source: ProjectBuilder/devel/pb/bin/pb@ 1174

Last change on this file since 1174 was 1174, checked in by Bruno Cornec, 13 years ago
  • Fix ebuild test name generation (Report Francesco)
  • Fix project package generation from file URL
  • Introduce hpux entry (not working)
  • pb_cms_mod_http renamed pb_cms_mod_htftp and also now handles ftp protocol
  • Fix pb_cms_compliant for file URL build
  • Property svn:executable set to *
File size: 116.5 KB
Line 
1#!/usr/bin/perl -w
2#
3# Project Builder main application
4#
5# $Id$
6#
7# Copyright B. Cornec 2007
8# Provided under the GPL v2
9
10# Syntax: see at end
11
12use strict 'vars';
13
14# The modules mentioned here are required by pb when used both
15# locally or inside a VE/VM
16# Additional required modules only used locally are called with a require
17# in their respective section
18use Getopt::Long qw(:config auto_abbrev no_ignore_case);
19use Data::Dumper;
20use English;
21use File::Basename;
22use File::Copy;
23use File::stat;
24use File::Temp qw(tempdir);
25use File::Find;
26use Time::localtime qw(localtime);
27use POSIX qw(strftime);
28use lib qw (lib);
29use ProjectBuilder::Version;
30use ProjectBuilder::Base;
31use ProjectBuilder::Display;
32use ProjectBuilder::Conf;
33use ProjectBuilder::Distribution;
34use ProjectBuilder::CMS;
35use ProjectBuilder::Env;
36use ProjectBuilder::Filter;
37use ProjectBuilder::Changelog;
38
39# Global variables
40my %opts; # CLI Options
41my $action; # action to realize
42my $test = "FALSE"; # Not used
43my $pbforce = 0; # Force VE/VM rebuild
44my $pbsnap = 0; # Do not use snapshot mode for VM/VE by default
45my $option = ""; # Not used
46my @pkgs; # list of packages
47my $pbtag; # Global Tag variable
48my $pbver; # Global Version variable
49my $pbscript; # Name of the script
50my %pbver; # per package
51my %pbtag; # per package
52my $pbrev; # Global REVISION variable
53my $pbaccount; # Login to use to connect to the VM
54my $pbtarget; # Target os-ver-arch you want to build for
55my $pbport; # Port to use to connect to the VM
56my $newver; # New version to create
57my $iso = undef; # ISO image for the VM to create
58
59my @date = pb_get_date();
60my $pbdate = strftime("%Y-%m-%d", @date);
61
62=pod
63
64=head1 NAME
65
66pb, aka project-builder.org - builds packages for your projects
67
68=head1 DESCRIPTION
69
70pb helps you build various packages directly from your project sources.
71Those sources could be handled by a CMS (Configuration Management System)
72such as Subversion, CVS, Git, Mercurial... or being a simple reference to a compressed tar file.
73It's based on a set of configuration files, a set of provided macros to help
74you keeping build files as generic as possible. For example, a single .spec
75file should be required to generate for all rpm based distributions, even
76if you could also have multiple .spec files if required.
77
78=head1 SYNOPSIS
79
80pb [-vhSq][-r pbroot][-p project][[-s script -a account -P port][-t os-ver-arch][-m os-ver-arch[,...]]][-g][-i iso] <action> [<pkg1> ...]
81
82pb [--verbose][--help][--man][--quiet][--snapshot][--revision pbroot][--project project][[--script script --account account --port port][--target os-ver-arch][--machine os-ver-arch[,...]]][--nographic][--iso iso] <action> [<pkg1> ...]
83
84=head1 OPTIONS
85
86=over 4
87
88=item B<-v|--verbose>
89
90Print a brief help message and exits.
91
92=item B<-q|--quiet>
93
94Do not print any output.
95
96=item B<-h|--help>
97
98Print a brief help message and exits.
99
100=item B<-S|--snapshot>
101
102Use the snapshot mode of VMs or VEs
103
104=item B<--man>
105
106Prints the manual page and exits.
107
108=item B<-t|--target os-ver-arch>
109
110Name of the target system you want to build for.
111All if none precised.
112
113=item B<-m|--machine os-ver-arch[,os-ver-arch,...]>
114
115Name of the Virtual Machines (VM) or Virtual Environments (VE) you want to build on (coma separated).
116All if none precised (or use the env variable PBV).
117
118=item B<-s|--script script>
119
120Name of the script you want to execute on the related VMs or VEs.
121
122=item B<-g|--nographic>
123
124Do not launch VMs in graphical mode.
125
126=item B<-i|--iso iso_image>
127
128Name of the ISO image of the distribution you want to install on the related VMs.
129
130=item B<-a|--account account>
131
132Name of the account to use to connect on the related VMs.
133
134=item B<-P|--port port_number>
135
136Port number to use to connect on the related VMs.\n";
137
138=item B<-p|--project project_name>
139
140Name of the project you're working on (or use the env variable PBPROJ)
141
142=item B<-r|--revision revision>
143
144Path Name of the project revision under the CMS (or use the env variable PBROOT)
145
146=item B<-V|--version new_version>
147
148New version of the project to create based on the current one.
149
150=back
151
152=head1 ARGUMENTS
153
154<action> can be:
155
156=over 4
157
158=item B<sbx2build>
159
160Create tar files for the project under your CMS.
161Current state of the exported content is taken.
162CMS supported are SVN, SVK, CVS, Git and Mercurial
163parameters are packages to build
164if not using default list
165
166=item B<cms2build>
167
168Create tar files for the project under your CMS.
169Current state of the CMS is taken.
170CMS supported are SVN, SVK, CVS, Git and Mercurial
171parameters are packages to build
172if not using default list
173
174=item B<build2pkg>
175
176Create packages for your running distribution
177
178=item B<cms2pkg>
179
180cms2build + build2pkg
181
182=item B<sbx2pkg>
183
184sbx2build + build2pkg
185
186=item B<build2ssh>
187
188Send the tar files to a SSH host
189
190=item B<sbx2ssh>
191
192sbx2build + build2ssh
193
194=item B<cms2ssh>
195
196cms2build + build2ssh
197
198=item B<pkg2ssh>
199
200Send the packages built to a SSH host
201
202=item B<build2vm>
203
204Create packages in VMs, launching them if needed
205and send those packages to a SSH host once built
206VM type supported are QEMU
207
208=item B<build2ve>
209
210Create packages in VEs, creating it if needed
211and send those packages to a SSH host once built
212
213=item B<sbx2vm>
214
215sbx2build + build2vm
216
217=item B<sbx2ve>
218
219sbx2build + build2ve
220
221=item B<cms2vm>
222
223cms2build + build2vm
224
225=item B<cms2ve>
226
227cms2build + build2ve
228
229=item B<launchvm>
230
231Launch one virtual machine
232
233=item B<launchve>
234
235Launch one virtual environment
236
237=item B<script2vm>
238
239Launch one virtual machine if needed
240and executes a script on it
241
242=item B<script2ve>
243
244Execute a script in a virtual environment
245
246=item B<newvm>
247
248Create a new virtual machine
249
250=item B<newve>
251
252Create a new virtual environment
253
254=item B<setupvm>
255
256Setup a virtual machine for pb usage
257
258=item B<setupve>
259
260Setup a virtual environment for pb usage
261
262=item B<sbx2setupvm>
263
264Setup a virtual machine for pb usage using the sandbox version of pb instead of the latest stable
265Reserved to dev team.
266
267=item B<sbx2setupve>
268
269Setup a virtual environment for pb usage using the sandbox version of pb instead of the latest stable
270Reserved to dev team.
271
272=item B<snapvm>
273
274Snapshot a virtual machine for pb usage
275
276=item B<snapve>
277
278Snapshot a virtual environment for pb usage
279
280=item B<updatevm>
281
282Update the distribution in the virtual machine
283
284=item B<updateve>
285
286Update the distribution in the virtual environment
287
288=item B<test2pkg>
289
290Test a package locally
291
292=item B<test2vm>
293
294Test a package in a virtual machine
295
296=item B<test2ve>
297
298Test a package in a virtual environment
299
300=item B<newver>
301
302Create a new version of the project derived
303from the current one
304
305=item B<newproj>
306
307Create a new project and a template set of
308configuration files under pbconf
309
310=item B<announce>
311
312Announce the availability of the project through various means
313
314=item B<sbx2webssh>
315
316Create tar files for the website under your CMS.
317Current state of the exported content is taken.
318Deliver the content to the target server using ssh from the exported dir.
319
320=item B<cms2webssh>
321
322Create tar files for the website from your CMS.
323Deliver the content to the target server using ssh from the DVCS.
324
325=item B<sbx2webpkg>
326
327Create tar files for the website under your CMS.
328Current state of the exported content is taken.
329
330=item B<cms2webpkg>
331
332Create tar files for the website under your CMS.
333
334=item B<clean>
335
336Purge the build and delivery directories related to the current project
337
338=back
339
340<pkgs> can be a list of packages, the keyword 'all' or nothing, in which case the default list of packages is taken (corresponding to the defpkgdir list of arguments in the configuration file).
341
342=head1 WEB SITES
343
344The main Web site of the project is available at L<http://www.project-builder.org/>. Bug reports should be filled using the trac instance of the project at L<http://trac.project-builder.org/>.
345
346=head1 USER MAILING LIST
347
348None exists for the moment.
349
350=head1 CONFIGURATION FILES
351
352Each pb user may have a configuration in F<$HOME/.pbrc>. The values in this file may overwrite any other configuration file value.
353
354Here is an example of such a configuration file:
355
356 #
357 # Define for each project the URL of its pbconf repository
358 # No default option allowed here as they need to be all different
359 #
360 # URL of the pbconf content
361 # This is the format of a classical URL with the extension of additional schema such as
362 # svn+ssh, cvs+ssh, ...
363 #
364 pbconfurl linuxcoe = cvs+ssh://:ext:bcornec@linuxcoe.cvs.sourceforge.net:/cvsroot/linuxcoe/pbconf
365
366 # This is normaly defined in the project's configuration file
367 # Url of the project
368 #
369 pburl linuxcoe = cvs+ssh://:ext:bcornec@linuxcoe.cvs.sourceforge.net:/cvsroot/linuxcoe
370
371 # All these URLs needs to be defined here as the are the entry point
372 # for how to build packages for the project
373 #
374 pbconfurl pb = svn+ssh://svn.project-builder.org/mondo/svn/pb/pbconf
375 pbconfurl mondorescue = svn+ssh://svn.project-builder.org/mondo/svn/project-builder/mondorescue/pbconf
376 pbconfurl collectl = svn+ssh://bruno@svn.mondorescue.org/mondo/svn/project-builder/collectl/pbconf
377 pbconfurl netperf = svn+ssh://svn.mondorescue.org/mondo/svn/project-builder/netperf/pbconf
378
379 # Under that dir will take place everything related to pb
380 # If you want to use VMs/chroot/..., then use $ENV{'HOME'} to make it portable
381 # to your VMs/chroot/...
382 # if not defined then /var/cache
383 pbdefdir default = $ENV{'HOME'}/project-builder
384 pbdefdir pb = $ENV{'HOME'}
385 pbdefdir linuxcoe = $ENV{'HOME'}/LinuxCOE/cvs
386 pbdefdir mondorescue = $ENV{'HOME'}/mondo/svn
387
388 # pbconfdir points to the directory where the CMS content of the pbconfurl is checked out
389 # If not defined, pbconfdir is under pbdefdir/pbproj/pbconf
390 pbconfdir linuxcoe = $ENV{'HOME'}/LinuxCOE/cvs/pbconf
391 pbconfdir mondorescue = $ENV{'HOME'}/mondo/svn/pbconf
392
393 # pbdir points to the directory where the CMS content of the pburl is checked out
394 # If not defined, pbdir is under pbdefdir/pbproj
395 # Only defined if we have access to the dev of the project
396 pbdir linuxcoe = $ENV{'HOME'}/LinuxCOE/cvs
397 pbdir mondorescue = $ENV{'HOME'}/mondo/svn
398
399 # -daemonize doesn't work with qemu 0.8.2
400 vmopt default = -m 384
401
402=head1 AUTHORS
403
404The Project-Builder.org team L<http://trac.project-builder.org/> lead by Bruno Cornec L<mailto:bruno@project-builder.org>.
405
406=head1 COPYRIGHT
407
408Project-Builder.org is distributed under the GPL v2.0 license
409described in the file C<COPYING> included with the distribution.
410
411=cut
412
413# ---------------------------------------------------------------------------
414
415my ($projectbuilderver,$projectbuilderrev) = pb_version_init();
416my $appname = "pb";
417
418# Initialize the syntax string
419
420pb_syntax_init("$appname (aka project-builder.org) Version $projectbuilderver-$projectbuilderrev\n");
421
422GetOptions("help|?|h" => \$opts{'h'},
423 "man" => \$opts{'man'},
424 "verbose|v+" => \$opts{'v'},
425 "snapshot|S" => \$opts{'S'},
426 "quiet|q" => \$opts{'q'},
427 "log-files|l=s" => \$opts{'l'},
428 "force|f" => \$opts{'f'},
429 "account|a=s" => \$opts{'a'},
430 "revision|r=s" => \$opts{'r'},
431 "script|s=s" => \$opts{'s'},
432 "machines|mock|m=s" => \$opts{'m'},
433 "target|t=s" => \$opts{'t'},
434 "nographic|g" => \$opts{'g'},
435 "port|P=i" => \$opts{'P'},
436 "project|p=s" => \$opts{'p'},
437 "iso|i=s" => \$opts{'i'},
438 "version|V=s" => \$opts{'V'},
439) || pb_syntax(-1,0);
440
441if (defined $opts{'h'}) {
442 pb_syntax(0,1);
443}
444if (defined $opts{'man'}) {
445 pb_syntax(0,2);
446}
447if (defined $opts{'v'}) {
448 $pbdebug = $opts{'v'};
449}
450if (defined $opts{'f'}) {
451 $pbforce=1;
452}
453if (defined $opts{'q'}) {
454 $pbdebug=-1;
455}
456if (defined $opts{'S'}) {
457 $pbsnap=1;
458}
459if (defined $opts{'l'}) {
460 open(pbLOG,"> $opts{'l'}") || die "Unable to log to $opts{'l'}: $!";
461 $pbLOG = \*pbLOG;
462 $pbdebug = 0 if ($pbdebug == -1);
463 }
464pb_log_init($pbdebug, $pbLOG);
465pb_display_init("text","");
466
467# Handle root of the project if defined
468if (defined $opts{'r'}) {
469 $ENV{'PBROOTDIR'} = $opts{'r'};
470}
471# Handle virtual machines if any
472if (defined $opts{'m'}) {
473 $ENV{'PBV'} = $opts{'m'};
474}
475if (defined $opts{'s'}) {
476 $pbscript = $opts{'s'};
477}
478if (defined $opts{'a'}) {
479 $pbaccount = $opts{'a'};
480 die "option -a requires a -s script option" if (not defined $pbscript);
481}
482if (defined $opts{'P'}) {
483 $pbport = $opts{'P'};
484}
485if (defined $opts{'V'}) {
486 $newver = $opts{'V'};
487}
488if (defined $opts{'i'}) {
489 $iso = $opts{'i'};
490}
491if (defined $opts{'t'}) {
492 $pbtarget = $opts{'t'};
493}
494
495# Get Action
496$action = shift @ARGV;
497die pb_syntax(-1,1) if (not defined $action);
498
499my ($filteredfiles, $supfiles, $defpkgdir, $extpkgdir);
500my $pbinit = undef;
501$pbinit = 1 if ($action =~ /^newproj$/);
502
503# Handles project name if any
504# And get global params
505($filteredfiles, $supfiles, $defpkgdir, $extpkgdir) = pb_env_init($opts{'p'},$pbinit,$action);
506
507#
508# Check for command requirements
509#
510my ($req,$opt,$pbpara) = pb_conf_get_if("oscmd","oscmdopt","pbparallel");
511pb_check_requirements($req,$opt,$appname);
512
513#
514# Check if we can launch some actions in // with Parallel::ForkManager
515#
516my $pbparallel = $pbpara->{$appname} if (defined $pbpara);
517if (not defined $pbparallel) {
518 eval
519 {
520 require Sys::CPU;
521 Sys::CPU->import();
522 };
523 if ($@) {
524 # Sys::CPU not found, defaulting to 1
525 pb_log(1,"ADVISE: Install Sys::CPU to benefit from automatic parallelism optimization.\nOr use pbparallel in your pb.conf file\nOnly 1 process at a time for the moment\n");
526 $pbparallel = 1;
527 } else {
528 # Using the number of cores
529 $pbparallel = Sys::CPU::cpu_count();
530 pb_log(1,"Using parallel mode with $pbparallel processes\n");
531 }
532}
533
534eval
535{
536 require Parallel::ForkManager;
537 Parallel::ForkManager->import();
538};
539# Parallel::ForkManager not found so no // actions
540if ($@) {
541 $pbparallel = undef;
542 pb_log(1,"ADVISE: Install Parallel::ForkManager to benefit from automatic parallelism optimization.\nOnly 1 process at a time for the moment\n");
543}
544
545pb_log(0,"Project: $ENV{'PBPROJ'}\n");
546pb_log(0,"Action: $action\n");
547
548# Act depending on action
549if ($action =~ /^cms2build$/) {
550 pb_cms2build("CMS");
551} elsif ($action =~ /^sbx2build$/) {
552 pb_cms2build("SandBox");
553} elsif ($action =~ /^build2pkg$/) {
554 pb_build2pkg();
555} elsif ($action =~ /^cms2pkg$/) {
556 pb_cms2build("CMS");
557 pb_build2pkg();
558} elsif ($action =~ /^sbx2pkg$/) {
559 pb_cms2build("SandBox");
560 pb_build2pkg();
561} elsif ($action =~ /^build2ssh$/) {
562 pb_build2ssh();
563} elsif ($action =~ /^cms2ssh$/) {
564 pb_cms2build("CMS");
565 pb_build2ssh();
566} elsif ($action =~ /^sbx2ssh$/) {
567 pb_cms2build("SandBox");
568 pb_build2ssh();
569} elsif ($action =~ /^pkg2ssh$/) {
570 pb_pkg2ssh();
571} elsif ($action =~ /^build2ve$/) {
572 pb_build2v("ve","build");
573} elsif ($action =~ /^build2vm$/) {
574 pb_build2v("vm","build");
575} elsif ($action =~ /^cms2ve$/) {
576 pb_cms2build("CMS");
577 pb_build2v("ve","build");
578} elsif ($action =~ /^sbx2ve$/) {
579 pb_cms2build("SandBox");
580 pb_build2v("ve","build");
581} elsif ($action =~ /^cms2vm$/) {
582 pb_cms2build("CMS");
583 pb_build2v("vm","build");
584} elsif ($action =~ /^sbx2vm$/) {
585 pb_cms2build("SandBox");
586 pb_build2v("vm","build");
587} elsif ($action =~ /^launchvm$/) {
588 pb_launchv("vm",$ENV{'PBV'},0);
589} elsif ($action =~ /^launchve$/) {
590 pb_launchv("ve",$ENV{'PBV'},0);
591} elsif ($action =~ /^script2vm$/) {
592 pb_script2v($pbscript,"vm");
593} elsif ($action =~ /^script2ve$/) {
594 pb_script2v($pbscript,"ve");
595} elsif ($action =~ /^newver$/) {
596 pb_newver();
597} elsif ($action =~ /^newve$/) {
598 pb_launchv("ve",$ENV{'PBV'},1);
599} elsif ($action =~ /^newvm$/) {
600 pb_launchv("vm",$ENV{'PBV'},1);
601 pb_log(0, "Please ensure that sshd is running in your VM by default\n");
602 pb_log(0, "and that it allows remote root login (PermitRootLogin yes in /etc/ssh/sshd_config)\n");
603 pb_log(0, "Also ensure that network is up, firewalling correctly configured\n");
604 pb_log(0, "and perl, sudo, ntpdate and scp/ssh installed\n");
605 pb_log(0, "You should then be able to login with ssh -p VMPORT root\@localhost (if VM started with pb)\n");
606} elsif ($action =~ /^setupve$/) {
607 pb_setup2v("ve");
608} elsif ($action =~ /^setupvm$/) {
609 pb_setup2v("vm");
610} elsif ($action =~ /^sbx2setupve$/) {
611 die "This feature is limited to the pb project" if ($ENV{'PBPROJ'} ne $appname);
612 pb_cms2build("SandBox");
613 pb_setup2v("ve","SandBox");
614} elsif ($action =~ /^sbx2setupvm$/) {
615 die "This feature is limited to the pb project" if ($ENV{'PBPROJ'} ne $appname);
616 pb_cms2build("SandBox");
617 pb_setup2v("vm","SandBox");
618} elsif ($action =~ /^updateve$/) {
619 pb_update2v("ve");
620} elsif ($action =~ /^updatevm$/) {
621 pb_update2v("vm");
622} elsif ($action =~ /^snapve$/) {
623 pb_snap2v("ve");
624} elsif ($action =~ /^snapvm$/) {
625 pb_snap2v("vm");
626} elsif ($action =~ /^test2pkg$/) {
627 pb_test2pkg();
628} elsif ($action =~ /^test2ve$/) {
629 pb_build2v("ve","test");
630} elsif ($action =~ /^test2vm$/) {
631 pb_build2v("vm","test");
632} elsif ($action =~ /^newproj$/) {
633 # Nothing to do - already done in pb_env_init
634} elsif ($action =~ /^clean$/) {
635 pb_clean();
636} elsif ($action =~ /^announce$/) {
637 # For announce only. Require avoids the systematic load of these modules
638 require DBI;
639 require DBD::SQLite;
640
641 pb_announce();
642} elsif ($action =~ /^sbx2webpkg$/) {
643 require DBI;
644 require DBD::SQLite;
645
646 pb_cms2build("SandBox","Web");
647} elsif ($action =~ /^sbx2webssh$/) {
648 require DBI;
649 require DBD::SQLite;
650
651 pb_cms2build("SandBox","Web");
652 pb_send2target("Web");
653} elsif ($action =~ /^cms2webpkg$/) {
654 require DBI;
655 require DBD::SQLite;
656
657 pb_cms2build("CMS","Web");
658} elsif ($action =~ /^cms2webssh$/) {
659 require DBI;
660 require DBD::SQLite;
661
662 pb_cms2build("CMS","Web");
663 pb_send2target("Web");
664} else {
665 pb_log(0,"\'$action\' is not available\n");
666 pb_syntax(-2,1);
667}
668
669sub pb_cms2build {
670
671 my $param = shift || undef;
672 my $web = shift || undef;
673
674 my $pkg;
675 my @pkgs;
676 my $webdir;
677
678 my %pkgs;
679 my %pb; # Structure to store conf info
680
681 die "pb_cms2build requires a parameter: SandBox or CMS" if (not defined $param);
682
683 # If Website, then pkg is only the website
684 if (defined $web) {
685 ($webdir) = pb_conf_get("webdir");
686 pb_log(2,"webdir: ".Dumper($webdir)."\n");
687 $pkgs[0] = $webdir->{$ENV{'PBPROJ'}};
688 $extpkgdir = $webdir;
689 pb_log(0,"Package: $pkgs[0]\n");
690 } else {
691 $pkg = pb_cms_get_pkg($defpkgdir,$extpkgdir);
692 @pkgs = @$pkg;
693 }
694
695 my ($scheme, $uri) = pb_cms_init($pbinit,$param);
696
697 # We need 2 lines here
698 my ($pkgv, $pkgt, $testver) = pb_conf_get_if("pkgver","pkgtag","testver");
699
700 # declare packager and repo for filtering
701 # TODO: Is pbrepo needed so early in the process ?
702 my ($tmp1, $tmp2) = pb_conf_get("pbpackager","pbrepo");
703 $ENV{'PBPACKAGER'} = $tmp1->{$ENV{'PBPROJ'}};
704 $ENV{'PBREPO'} = $tmp2->{$ENV{'PBPROJ'}};
705
706 foreach my $pbpkg (@pkgs) {
707 $ENV{'PBPKG'} = $pbpkg;
708
709 if ((defined $pkgv) && (defined $pkgv->{$pbpkg})) {
710 $pbver = $pkgv->{$pbpkg};
711 } else {
712 $pbver = $ENV{'PBPROJVER'};
713 }
714 # If it's a test version, then tag == 0.date
715 if ((defined $testver) && (defined $testver->{$ENV{'PBPROJ'}}) && ($testver->{$ENV{'PBPROJ'}} =~ /true/i)) {
716 $pbtag = "0.".strftime("%Y%m%d%H%M%S", @date);
717 $ENV{'PBPROJTAG'} = $pbtag;
718 } elsif ((defined $pkgt) && (defined $pkgt->{$pbpkg})) {
719 $pbtag = $pkgt->{$pbpkg};
720 } else {
721 $pbtag = $ENV{'PBPROJTAG'};
722 }
723
724 $pbrev = $ENV{'PBREVISION'};
725 pb_log(0,"\n");
726 pb_log(0,"Management of $pbpkg $pbver-$pbtag (rev $pbrev)\n");
727 die "Unable to get env var PBDESTDIR" if (not defined $ENV{'PBDESTDIR'});
728
729 my $dest = "$ENV{'PBDESTDIR'}/$pbpkg-$pbver";
730 # Create the structure if needed
731 pb_mkdir_p($dest);
732 # Clean up dest if necessary. The export will recreate it
733 pb_rm_rf($dest) if (-d $dest);
734
735 # Export CMS tree for the concerned package to dest
736 # And generate some additional files
737 $OUTPUT_AUTOFLUSH=1;
738
739 # computes in which dir we have to work
740 my $dir = $defpkgdir->{$pbpkg};
741 $dir = $extpkgdir->{$pbpkg} if (not defined $dir);
742 $dir = $webdir->{$ENV{'PBPROJ'}} if (defined $web);
743 die "Variable \$dir not defined. Please report to dev team with log of a verbose run and this info ".Dumper($webdir) if (not defined $dir);
744 pb_log(2,"def:".Dumper($defpkgdir)." ext: ".Dumper($extpkgdir)." \n");
745
746 # Exporting content from CMS
747 my $sourcedir = undef;
748 my $sourceuri = $uri;
749 if ($param eq "SandBox") {
750 # Point to the local instance
751 $sourcedir = "$ENV{'PBDIR'}/$dir";
752 } else {
753 # Get it from a subdir of the URI with same version as localy but different root
754 # Only if using a real CMS
755 my ($scheme, $account, $host, $port, $path) = pb_get_uri($uri);
756 if (($scheme !~ /^file/) && ($scheme !~ /^(ht|f)tp/)) {
757 $sourceuri = "$ENV{'PBDIR'}/$dir";
758 $sourceuri =~ s|^$ENV{'PBPROJDIR'}/|$uri|;
759 }
760 }
761 my $preserve = pb_cms_export($sourceuri,$sourcedir,$dest);
762
763 # Generated fake content for test versions to speed up stuff
764 my $chglog;
765
766 # Get project info on authors and log file
767 $chglog = "$ENV{'PBROOTDIR'}/$pbpkg/pbcl";
768 $chglog = "$ENV{'PBROOTDIR'}/pbcl" if (! -f $chglog);
769 $chglog = undef if (! -f $chglog);
770
771 my $authors = "$ENV{'PBROOTDIR'}/$pbpkg/pbauthors";
772 $authors = "$ENV{'PBROOTDIR'}/pbauthors" if (! -f $authors);
773 $authors = "/dev/null" if (! -f $authors);
774
775 # Extract cms log history and store it
776 if ((defined $chglog) && (! -f "$dest/NEWS")) {
777 pb_log(2,"Generating NEWS file from $chglog\n");
778 copy($chglog,"$dest/NEWS") || die "Unable to create $dest/NEWS";
779 }
780 pb_cms_log($scheme,"$ENV{'PBDIR'}/$dir",$dest,$chglog,$authors,$testver);
781
782 my %build;
783 my %patches;
784 my %sources;
785 # We want to at least build for the underlying distro
786 # except if a target was given, in which case we only build for it
787 my ($tdir,$tver,$tarch);
788 ($tdir,$tver,$tarch) = split(/-/,$pbtarget) if (defined ($pbtarget));
789
790 my ($ddir, $dver, $dfam, $dtype, $dos, $pbsuf, $pbupd, $pbins, $arch) = pb_distro_init($tdir,$tver,$tarch);
791 my $tmpl = "$ddir-$dver-$arch,";
792
793 # Get list of distributions for which we need to generate build files if no target
794 if (not defined ($pbtarget)) {
795 my @pt = pb_conf_get_if("vmlist","velist");
796 if (defined $pt[0]->{$ENV{'PBPROJ'}}) {
797 $tmpl .= $pt[0]->{$ENV{'PBPROJ'}};
798 }
799 if (defined $pt[1]->{$ENV{'PBPROJ'}}) {
800 # The 2 lists needs to be grouped with a ',' separating them
801 if ($tmpl ne "") {
802 $tmpl .= ",";
803 }
804 $tmpl .= $pt[1]->{$ENV{'PBPROJ'}}
805 }
806 }
807
808 # Setup %pb structure to allow filtering later on, on files using that structure
809 $pb{'tag'} = $pbtag;
810 $pb{'rev'} = $pbrev;
811 $pb{'ver'} = $pbver;
812 $pb{'pkg'} = $pbpkg;
813 $pb{'realpkg'} = $pbpkg;
814 $pb{'date'} = $pbdate;
815 $pb{'defpkgdir'} = $defpkgdir;
816 $pb{'extpkgdir'} = $extpkgdir;
817 $pb{'chglog'} = $chglog;
818 $pb{'packager'} = $ENV{'PBPACKAGER'};
819 $pb{'proj'} = $ENV{'PBPROJ'};
820 $pb{'repo'} = $ENV{'PBREPO'};
821 $pb{'patches'} = \%patches;
822 $pb{'sources'} = \%sources;
823 pb_log(2,"DEBUG: pb: ".Dumper(%pb)."\n");
824
825 # Do not do that for website
826 if (not defined $web) {
827 pb_log(0,"Build files are being generated for ...\n");
828 my %virt;
829 # De-duplicate similar VM and VE
830 foreach my $d (split(/,/,$tmpl)) {
831 # skip ill-formatted vms (name-ver-arch)
832 next if ($d !~ /-/);
833 $virt{$d} = $d;
834 }
835
836 # Try to use // processing here
837 my $pm = new Parallel::ForkManager($pbparallel) if (defined $pbparallel);
838
839 foreach my $d (keys %virt) {
840 $pm->start and next if (defined $pbparallel);
841 my ($name,$ver,$arch) = split(/-/,$d);
842 pb_log(0,"Bad format for $d") if ((not defined $name) || (not defined $ver) || (not defined $arch)) ;
843 chomp($arch);
844 my ($ddir, $dver, $dfam);
845 ($ddir, $dver, $dfam, $pb{'dtype'}, $pb{'os'}, $pb{'suf'}, $pb{'upd'}, $pb{'arch'}) = pb_distro_init($name,$ver,$arch);
846 pb_log(2,"DEBUG: distro tuple: ".Dumper($ddir, $dver, $dfam, $pb{'dtype'}, $pb{'suf'})."\n");
847 pb_log(2,"DEBUG Filtering PBDATE => $pbdate, PBTAG => $pbtag, PBVER => $pbver\n");
848
849 # We need to compute the real name of the package
850 my $pbrealpkg = pb_cms_get_real_pkg($pbpkg,$pb{'dtype'});
851 $pb{'realpkg'} = $pbrealpkg;
852 pb_log(1,"Virtual package $pbpkg has a real package name of $pbrealpkg on $ddir-$dver\n") if ($pbrealpkg ne $pbpkg);
853
854 # Filter build files from the less precise up to the most with overloading
855 # Filter all files found, keeping the name, and generating in dest
856
857 # Find all build files first relatively to PBROOTDIR
858 # Find also all specific files referenced in the .pb conf file
859 my %bfiles = ();
860 my %pkgfiles = ();
861 $build{"$ddir-$dver-$arch"} = "yes";
862
863 if (-d "$ENV{'PBROOTDIR'}/$pbpkg/$pb{'dtype'}") {
864 pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$pb{'dtype'}",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
865 } elsif (-d "$ENV{'PBROOTDIR'}/$pbpkg/$dfam") {
866 pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$dfam",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
867 } elsif (-d "$ENV{'PBROOTDIR'}/$pbpkg/$ddir") {
868 pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$ddir",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
869 } elsif (-d "$ENV{'PBROOTDIR'}/$pbpkg/$ddir-$dver") {
870 pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$ddir-$dver",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
871 } elsif (-d "$ENV{'PBROOTDIR'}/$pbpkg/$ddir-$dver-$arch") {
872 pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$ddir-$dver-$arch",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
873 } else {
874 $build{"$ddir-$dver-$arch"} = "no";
875 next;
876 }
877 pb_log(2,"DEBUG bfiles: ".Dumper(\%bfiles)."\n");
878
879 # Get all filters to apply
880 my $ptr = pb_get_filters($pbpkg, $pb{'dtype'}, $dfam, $ddir, $dver);
881
882 # Apply now all the filters on all the files concerned
883 # destination dir depends on the type of file
884 if (defined $ptr) {
885 # For patch support
886 $pb{'tuple'} = "$ddir-$dver-$arch";
887 foreach my $f (values %bfiles,values %pkgfiles) {
888 pb_filter_file("$ENV{'PBROOTDIR'}/$f",$ptr,"$dest/pbconf/$ddir-$dver-$arch/".basename($f),\%pb);
889 }
890 }
891 pb_list_sfiles("$ENV{'PBROOTDIR'}/$pbpkg/pbpatch", \%patches, $pb{'dtype'}, $dfam, $ddir, $dver, $arch, "$ENV{'PBROOTDIR'}/$pbpkg/pbextpatch");
892 pb_list_sfiles("$ENV{'PBROOTDIR'}/$pbpkg/pbsrc", \%sources, $pb{'dtype'}, $dfam, $ddir, $dver, $arch, "$ENV{'PBROOTDIR'}/$pbpkg/pbextsrc");
893
894 $pm->finish if (defined $pbparallel);
895 }
896 $pm->wait_all_children if (defined $pbparallel);
897 my @found;
898 my @notfound;
899 foreach my $b (keys %build) {
900 push @found,$b if ($build{$b} =~ /yes/);
901 push @notfound,$b if ($build{$b} =~ /no/);
902 }
903 pb_log(0," ... ".join(',',sort(@found))."\n");
904 pb_log(0,"No Build files found for ".join(',',sort(@notfound))."\n") if (@notfound);
905 pb_log(2,"DEBUG: patches: ".Dumper(%patches)."\n");
906 pb_log(2,"DEBUG: sources: ".Dumper(%sources)."\n");
907 }
908
909 # Get the generic filter (all.pbf) and
910 # apply those to the non-build files including those
911 # generated by pbinit if applicable
912
913 # Get only all.pbf filter
914 my $ptr = pb_get_filters($pbpkg);
915
916 my $liste ="";
917 if (defined $filteredfiles->{$pbpkg}) {
918 foreach my $f (split(/,/,$filteredfiles->{$pbpkg})) {
919 pb_filter_file_inplace($ptr,"$dest/$f",\%pb);
920 $liste = "$f $liste";
921 }
922 }
923 pb_log(2,"Files ".$liste."have been filtered\n");
924
925 # Do not do that for website
926 if (not defined $web) {
927 my %tmp;
928 my $warnptcflag = 0;
929 my $warnsrcflag = 0;
930 # Filter potential patches (local + remote)
931 pb_log(0,"Delivering and compressing patches ");
932 foreach my $v (keys %patches) {
933 pb_mkdir_p("$dest/pbconf/$v/pbpatch");
934 foreach my $pf (split(/,/,$patches{$v})) {
935 my $pp = basename($pf);
936 if ($param eq "SandBox") {
937 $warnptcflag = 1;
938 }
939 pb_cms_export($pf,undef,"$dest/pbconf/$v/pbpatch");
940 pb_filter_file_inplace($ptr,"$dest/pbconf/$v/pbpatch/$pp",\%pb);
941 pb_system("gzip -9f $dest/pbconf/$v/pbpatch/$pp","","quiet");
942 $tmp{$pf} = "";
943 }
944 }
945 pb_log(0,"Delivering additional sources ");
946 foreach my $v (keys %sources) {
947 pb_mkdir_p("$dest/pbconf/$v/pbsrc");
948 foreach my $pf (split(/,/,$sources{$v})) {
949 my $pp = basename($pf);
950 if ($param eq "SandBox") {
951 $warnsrcflag = 1;
952 }
953 pb_cms_export($pf,undef,"$dest/pbconf/$v/pbsrc");
954 pb_filter_file_inplace($ptr,"$dest/pbconf/$v/pbsrc/$pp",\%pb);
955 $tmp{$pf} = "";
956 }
957 }
958 foreach my $v (keys %tmp) {
959 pb_log(0,"$v ");
960 }
961 pb_log(0,"\n");
962 pb_log(0,"WARNING: Patches are always taken from repository not local export\n") if ($warnptcflag == 1);
963 pb_log(0,"WARNING: Sources are always taken from repository not local export\n") if ($warnsrcflag == 1);
964 } else {
965 # Instead call News generation
966 pb_web_news2html($dest);
967 # And create an empty pbconf
968 pb_mkdir_p("$dest/pbconf");
969 # And prepare the pbscript to execute remotely
970 open(SCRIPT,"> $ENV{'PBTMP'}/pbscript") || die "Unable to create $ENV{'PBTMP'}/pbscript";
971 print SCRIPT "#!/bin/bash\n";
972 print SCRIPT "#set -x\n";
973 print SCRIPT "echo ... Extracting Website content\n";
974 print SCRIPT "find . -type f | grep -Ev '^./$pbpkg-$pbver.tar.gz|^./pbscript' | xargs rm -f non-existent\n";
975 print SCRIPT "find * -type d -depth | xargs rmdir 2> /dev/null \n";
976 print SCRIPT "tar xfz $pbpkg-$pbver.tar.gz\n";
977 print SCRIPT "mv $pbpkg-$pbver/* .\n";
978 print SCRIPT "rm -f $pbpkg-$pbver.tar.gz\n";
979 print SCRIPT "rmdir $pbpkg-$pbver\n";
980 close(SCRIPT);
981 chmod 0755,"$ENV{'PBTMP'}/pbscript";
982 }
983
984 # Prepare the dest directory for archive
985 if (-x "$ENV{'PBROOTDIR'}/$pbpkg/pbinit") {
986 pb_filter_file("$ENV{'PBROOTDIR'}/$pbpkg/pbinit",$ptr,"$ENV{'PBTMP'}/pbinit",\%pb);
987 chmod 0755,"$ENV{'PBTMP'}/pbinit";
988 pb_system("cd $dest ; $ENV{'PBTMP'}/pbinit","Executing init script from $ENV{'PBROOTDIR'}/$pbpkg/pbinit","verbose");
989 }
990
991 # Do we have additional script to run to prepare the environement for the project ?
992 # Then include it in the pbconf delivery
993 foreach my $pbvf (<$ENV{'PBROOTDIR'}/pbv*.pre>,<$ENV{'PBROOTDIR'}/pbv*.post>, <$ENV{'PBROOTDIR'}/pbtest*>) {
994 if (-x "$pbvf") {
995 my $target = "$ENV{'PBDESTDIR'}/".basename($pbvf);
996 pb_filter_file("$pbvf",$ptr,$target,\%pb);
997 chmod 0755,"$target";
998 }
999 }
1000
1001 # Archive dest dir
1002 chdir "$ENV{'PBDESTDIR'}" || die "Unable to change dir to $ENV{'PBDESTDIR'}";
1003 if (defined $preserve) {
1004 # In that case we want to preserve the original tar file for checksum purposes
1005 # The one created is btw equivalent in that case to this one
1006 # Maybe check basename of both to be sure they are the same ?
1007 pb_log(0,"Preserving original tar file ");
1008 move("$preserve","$pbpkg-$pbver.tar.gz");
1009 } else {
1010 # Possibility to look at PBSRC to guess more the filename
1011 pb_system("tar cfz $pbpkg-$pbver.tar.gz --exclude=$pbpkg-$pbver/pbconf $pbpkg-$pbver","Creating $pbpkg tar files compressed");
1012 }
1013 pb_log(0,"Under $ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz\n");
1014 pb_system("tar cfz $pbpkg-$pbver.pbconf.tar.gz $pbpkg-$pbver/pbconf","Creating pbconf tar files compressed");
1015 pb_log(0,"Under $ENV{'PBDESTDIR'}/$pbpkg-$pbver.pbconf.tar.gz\n");
1016
1017 # Keep track of version-tag per pkg
1018 $pkgs{$pbpkg} = "$pbver-$pbtag";
1019
1020 # Final cleanup
1021 pb_rm_rf($dest) if (-d $dest);
1022 }
1023
1024 # Keep track of per package version
1025 pb_log(2,"DEBUG pkgs: ".Dumper(%pkgs)."\n");
1026 open(PKG,"> $ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb") || die "Unable to create $ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb";
1027 foreach my $pbpkg (keys %pkgs) {
1028 print PKG "pbpkg $pbpkg = $pkgs{$pbpkg}\n";
1029 }
1030 close(PKG);
1031
1032 # Keep track of what is generated by default
1033 # We need to store the dir and info on version-tag
1034 # Base our content on the existing .pb file
1035 copy("$ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb","$ENV{'PBDESTDIR'}/pbrc");
1036 open(LAST,">> $ENV{'PBDESTDIR'}/pbrc") || die "Unable to create $ENV{'PBDESTDIR'}/pbrc";
1037 print LAST "pbroot $ENV{'PBPROJ'} = $ENV{'PBROOTDIR'}\n";
1038 print LAST "projver $ENV{'PBPROJ'} = $ENV{'PBPROJVER'}\n";
1039 print LAST "projtag $ENV{'PBPROJ'} = $ENV{'PBPROJTAG'}\n";
1040 print LAST "pbpackager $ENV{'PBPROJ'} = $ENV{'PBPACKAGER'}\n";
1041 close(LAST);
1042}
1043
1044sub pb_test2pkg {
1045 # Get the running distro to test on
1046 my ($ddir, $dver, $dfam, $dtype, $dos, $pbsuf, $pbupd, $pbins, $arch) = pb_distro_init();
1047 pb_log(2,"DEBUG: distro tuple: ".join(',',($ddir, $dver, $dfam, $dtype, $pbsuf, $pbupd, $pbins, $arch))."\n");
1048
1049 # Get list of packages to test
1050 # Get content saved in cms2build
1051 my $ptr = pb_get_pkg();
1052 @pkgs = @$ptr;
1053
1054 # Additional potential repo
1055 pb_distro_setuprepo($ddir,$dver,$arch,$dtype,$dfam,$dos);
1056 foreach my $pbpkg (@pkgs) {
1057 # We need to install the package to test, and deps brought with it
1058 pb_distro_installdeps(undef,$dtype,$pbins,$pbpkg);
1059 pb_system("$ENV{'PBDESTDIR'}/pbtest","Launching test for $pbpkg","verbose");
1060 }
1061}
1062
1063sub pb_build2pkg {
1064
1065 # Get the running distro to build on
1066 my ($ddir, $dver, $dfam, $dtype, $dos, $pbsuf, $pbupd, $pbins, $arch) = pb_distro_init();
1067 pb_log(2,"DEBUG: distro tuple: ".join(',',($ddir, $dver, $dfam, $dtype, $pbsuf, $pbupd, $pbins, $arch))."\n");
1068
1069 # If needed we may add repository to the build env
1070 pb_distro_setuprepo($ddir,$dver,$arch,$dtype,$dfam,$dos);
1071
1072 # Get list of packages to build
1073 my $ptr = pb_get_pkg();
1074 @pkgs = @$ptr;
1075
1076 # Get content saved in cms2build
1077 my ($pkg) = pb_conf_read("$ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb","pbpkg");
1078 $pkg = { } if (not defined $pkg);
1079
1080 chdir "$ENV{'PBBUILDDIR'}";
1081 my $made = ""; # pkgs made during build
1082 my $pm = new Parallel::ForkManager($pbparallel) if (defined $pbparallel);
1083
1084 # We need to communicate info back from the children if parallel so prepare a dir for that
1085 my $tmpd = "$ENV{'PBTMP'}/build.$$";
1086 pb_mkdir_p($tmpd) if (defined $pbparallel);
1087
1088 foreach my $pbpkg (@pkgs) {
1089 $pm->start and next if (defined $pbparallel);
1090
1091 my $vertag = $pkg->{$pbpkg};
1092 # get the version of the current package - maybe different
1093 ($pbver,$pbtag) = split(/-/,$vertag);
1094
1095 my $src="$ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz";
1096 my $src2="$ENV{'PBDESTDIR'}/$pbpkg-$pbver.pbconf.tar.gz";
1097 pb_log(2,"Source file: $src\n");
1098 pb_log(2,"Pbconf file: $src2\n");
1099
1100 pb_log(2,"Working directory: $ENV{'PBBUILDDIR'}\n");
1101 if ($dtype eq "rpm") {
1102 foreach my $d ('RPMS','SRPMS','SPECS','SOURCES','BUILD') {
1103 if (! -d "$ENV{'PBBUILDDIR'}/$d") {
1104 pb_mkdir_p("$ENV{'PBBUILDDIR'}/$d") || die "Please ensure that you can write into $ENV{'PBBUILDDIR'} to create $d\nchown the $ENV{'PBBUILDDIR'} directory to your uid";
1105 }
1106 }
1107
1108 # Remove in case a previous link/file was there
1109 unlink "$ENV{'PBBUILDDIR'}/SOURCES/".basename($src);
1110 symlink "$src","$ENV{'PBBUILDDIR'}/SOURCES/".basename($src) || die "Unable to symlink $src in $ENV{'PBBUILDDIR'}/SOURCES";
1111 # We need to first extract the spec file
1112 my @specfile = pb_extract_build_files($src2,"$pbpkg-$pbver/pbconf/$ddir-$dver-$arch/","$ENV{'PBBUILDDIR'}/SPECS","spec");
1113
1114 # We need to handle potential patches to upstream sources
1115 pb_extract_build_files($src2,"$pbpkg-$pbver/pbconf/$ddir-$dver-$arch/pbpatch/","$ENV{'PBBUILDDIR'}/SOURCES","patch");
1116
1117 pb_log(2,"specfile: ".Dumper(\@specfile)."\n");
1118 # set LANGUAGE to check for correct log messages
1119 $ENV{'LANGUAGE'}="C";
1120 # Older Redhat use _target_platform in %configure incorrectly
1121 my $specialdef = "";
1122 if (($ddir eq "redhat") || (($ddir eq "rhel") && ($dver eq "2.1"))) {
1123 $specialdef = "--define \'_target_platform \"\"\'";
1124 }
1125
1126 foreach my $f (@specfile) {
1127 if ($f =~ /\.spec$/) {
1128 # This could cause an issue in // mode
1129 pb_distro_installdeps($f,$dtype,$pbins);
1130 pb_system("rpmbuild $specialdef --define \"packager $ENV{'PBPACKAGER'}\" --define \"_topdir $ENV{'PBBUILDDIR'}\" -ba $f","Building package with $f under $ENV{'PBBUILDDIR'}","verbose");
1131 last;
1132 }
1133 }
1134 # Get the name of the generated packages
1135 open(LOG,"$ENV{'PBTMP'}/system.$$.log") || die "Unable to open $ENV{'PBTMP'}/system.$$.log";
1136 while (<LOG>) {
1137 chomp($_);
1138 next if ($_ !~ /^Wrote:/);
1139 s|.*/([S]*RPMS.*)|$1|;
1140 $made .=" $_";
1141 }
1142 close(LOG);
1143
1144 } elsif ($dtype eq "deb") {
1145 chdir "$ENV{'PBBUILDDIR'}" || die "Unable to chdir to $ENV{'PBBUILDDIR'}";
1146 pb_system("tar xfz $src","Extracting sources");
1147 pb_system("tar xfz $src2","Extracting pbconf");
1148
1149 chdir "$pbpkg-$pbver" || die "Unable to chdir to $pbpkg-$pbver";
1150 pb_rm_rf("debian");
1151 symlink "pbconf/$ddir-$dver-$arch","debian" || die "Unable to symlink to pbconf/$ddir-$dver-$arch";
1152 chmod 0755,"debian/rules";
1153
1154 pb_distro_installdeps("debian/control",$dtype,$pbins);
1155 pb_system("dpkg-buildpackage -us -uc -rfakeroot","Building package","verbose");
1156 # Get the name of the generated packages
1157 open(LOG,"$ENV{'PBTMP'}/system.$$.log") || die "Unable to open $ENV{'PBTMP'}/system.$$.log";
1158 while (<LOG>) {
1159 chomp();
1160 my $tmp = $_;
1161 next if ($tmp !~ /^dpkg-deb.*:/);
1162 $tmp =~ s|.*../(.*)_(.*).deb.*|$1|;
1163 $made="$made $tmp.dsc $tmp.tar.gz $tmp"."_*.deb $tmp"."_*.changes";
1164 }
1165 close(LOG);
1166 } elsif ($dtype eq "ebuild") {
1167 my @ebuildfile;
1168 # For gentoo we need to take pb as subsystem name
1169 # We put every apps here under sys-apps. hope it's correct
1170 # We use pb's home dir in order to have a single OVERLAY line
1171 my $tmpd = "$ENV{'HOME'}/portage/pb/sys-apps/$pbpkg";
1172 pb_mkdir_p($tmpd) if (! -d "$tmpd");
1173 pb_mkdir_p("$ENV{'HOME'}/portage/distfiles") if (! -d "$ENV{'HOME'}/portage/distfiles");
1174
1175 # We need to first extract the ebuild file
1176 @ebuildfile = pb_extract_build_files($src2,"$pbpkg-$pbver/pbconf/$ddir-$dver-$arch/","$tmpd","ebuild");
1177
1178 # Prepare the build env for gentoo
1179 my $found = 0;
1180 my $pbbd = $ENV{'HOME'};
1181 $pbbd =~ s|/|\\/|g;
1182 if (-r "/etc/make.conf") {
1183 open(MAKE,"/etc/make.conf");
1184 while (<MAKE>) {
1185 $found = 1 if (/$pbbd\/portage/);
1186 }
1187 close(MAKE);
1188 }
1189 if ($found == 0) {
1190 pb_system("sudo sh -c 'echo PORTDIR_OVERLAY=\"$ENV{'HOME'}/portage\" >> /etc/make.conf'");
1191 }
1192 #$found = 0;
1193 #if (-r "/etc/portage/package.keywords") {
1194 #open(KEYW,"/etc/portage/package.keywords");
1195 #while (<KEYW>) {
1196 #$found = 1 if (/portage\/pb/);
1197 #}
1198 #close(KEYW);
1199 #}
1200 #if ($found == 0) {
1201 #pb_system("sudo sh -c \"echo portage/pb >> /etc/portage/package.keywords\"");
1202 #}
1203
1204 # Build
1205 foreach my $f (@ebuildfile) {
1206 if ($f =~ /\.ebuild$/) {
1207 pb_distro_installdeps($f,$dtype,$pbins);
1208 move($f,"$tmpd/$pbpkg-$pbver.ebuild");
1209 pb_system("cd $tmpd ; ebuild $pbpkg-$pbver.ebuild clean ; ebuild $pbpkg-$pbver.ebuild digest ; ebuild $pbpkg-$pbver.ebuild package","verbose");
1210 # Now move it where pb expects it
1211 pb_mkdir_p("$ENV{'PBBUILDDIR'}/portage/pb/sys-apps/$pbpkg");
1212 if ($pbtag =~ /^0\./) {
1213 # This is a test version
1214 my $ntag = $pbtag;
1215 $ntag =~ s/^0\.//;
1216 move("$tmpd/$pbpkg-$pbver.ebuild","$ENV{'PBBUILDDIR'}/portage/pb/sys-apps/$pbpkg/$pbpkg-$pbver"."_p$ntag.ebuild");
1217 $made="$made portage/pb/sys-apps/$pbpkg/$pbpkg-$pbver"."_p$ntag.ebuild";
1218 } else {
1219 move("$tmpd/$pbpkg-$pbver.ebuild","$ENV{'PBBUILDDIR'}/portage/pb/sys-apps/$pbpkg/$pbpkg-$pbver-r$pbtag.ebuild");
1220 $made="$made portage/pb/sys-apps/$pbpkg/$pbpkg-$pbver-r$pbtag.ebuild";
1221 }
1222 }
1223 }
1224
1225 } elsif ($dtype eq "tgz") {
1226 # Slackware family
1227 $made="$made $pbpkg/$pbpkg-$pbver-*-$pbtag.tgz";
1228
1229 chdir "$ENV{'PBBUILDDIR'}" || die "Unable to chdir to $ENV{'PBBUILDDIR'}";
1230 pb_system("tar xfz $src","Extracting sources");
1231 pb_system("tar xfz $src2","Extracting pbconf");
1232 chdir "$pbpkg-$pbver" || die "Unable to chdir to $pbpkg-$pbver";
1233 symlink "pbconf/$ddir-$dver-$arch","install" || die "Unable to symlink to pbconf/$ddir-$dver-$arch";
1234 if (-x "install/pbslack") {
1235 pb_distro_installdeps("./install/pbslack",$dtype,$pbins);
1236 pb_system("./install/pbslack","Building software");
1237 pb_system("sudo /sbin/makepkg -p -l y -c y $pbpkg","Packaging $pbpkg","verbose");
1238 }
1239 } elsif ($dtype eq "pkg") {
1240 # Solaris
1241 $made="$made $pbpkg-$pbver-$pbtag.pkg.gz";
1242 my $pkgdestdir="$ENV{'PBBUILDDIR'}/install";
1243
1244 chdir "$ENV{'PBBUILDDIR'}" || die "Unable to chdir to $ENV{'PBBUILDDIR'}";
1245 # Will host resulting packages
1246 pb_mkdir_p("$dtype");
1247 pb_mkdir_p("$pkgdestdir/delivery");
1248 pb_system("tar xfz $src","Extracting sources under $ENV{'PBBUILDDIR'}");
1249 pb_system("tar xfz $src2","Extracting pbconf under $ENV{'PBBUILDDIR'}");
1250 chdir "$pbpkg-$pbver" || die "Unable to chdir to $pbpkg-$pbver";
1251 if (-f "pbconf/$ddir-$dver-$arch/pbbuild") {
1252 chmod 0755,"pbconf/$ddir-$dver-$arch/pbbuild";
1253 # pkginfo file is mandatory
1254 die "Unable to find pkginfo file in pbconf/$ddir-$dver-$arch" if (! -f "pbconf/$ddir-$dver-$arch/pkginfo");
1255 # Build
1256 pb_system("pbconf/$ddir-$dver-$arch/pbbuild $pkgdestdir/delivery","Building software and installing under $pkgdestdir/delivery");
1257 # Copy complementary files
1258 if (-f "pbconf/$ddir-$dver-$arch/prototype") {
1259 copy("pbconf/$ddir-$dver-$arch/prototype", $pkgdestdir)
1260 } else {
1261 # No prototype provided, calculating it
1262 open(PROTO,"> $pkgdestdir/prototype") || die "Unable to create prototype file";
1263 print PROTO "i pkginfo\n";
1264 print PROTO "i depend\n" if (-f "pbconf/$ddir-$dver-$arch/depend");
1265 $ENV{'PBSOLDESTDIR'} = "$pkgdestdir/delivery";
1266 find(\&create_solaris_prototype, "$pkgdestdir/delivery");
1267 }
1268 copy("pbconf/$ddir-$dver-$arch/depend", $pkgdestdir) if (-f "pbconf/$ddir-$dver-$arch/depend");
1269 copy("pbconf/$ddir-$dver-$arch/pkginfo", $pkgdestdir);
1270 pb_system("cd $pkgdestdir/delivery ; pkgmk -o -f ../prototype -r $pkgdestdir/delivery -d $ENV{'PBBUILDDIR'}/$dtype","Packaging $pbpkg","verbose");
1271 pb_system("cd $ENV{'PBBUILDDIR'}/$dtype ; echo \"\" | pkgtrans -o -n -s $ENV{'PBBUILDDIR'}/$dtype $ENV{'PBBUILDDIR'}/$pbpkg-$pbver-$pbtag.pkg all","Transforming $pbpkg","verbose");
1272 pb_system("cd $ENV{'PBBUILDDIR'} ; gzip -9f $pbpkg-$pbver-$pbtag.pkg","Compressing $pbpkg-$pbver-$pbtag.pkg","verbose");
1273 } else {
1274 pb_log(0,"No pbconf/$ddir-$dver-$arch/pbbuild file found for $pbpkg-$pbver in \n");
1275 }
1276 chdir ".." || die "Unable to chdir to parent dir";
1277 pb_system("rm -rf $pbpkg-$pbver $ENV{'PBBUILDDIR'}/$dtype $pkgdestdir", "Cleanup");
1278 } elsif ($dtype eq "hpux") {
1279 # HP-UX
1280 chdir "$ENV{'PBBUILDDIR'}" || die "Unable to chdir to $ENV{'PBBUILDDIR'}";
1281 pb_system("tar xfz $src","Extracting sources");
1282 pb_system("tar xfz $src2","Extracting pbconf");
1283
1284 chdir "$pbpkg-$pbver" || die "Unable to chdir to $pbpkg-$pbver";
1285 pb_system("buildpackage ","Building package","verbose");
1286 # Get the name of the generated packages
1287 open(LOG,"$ENV{'PBTMP'}/system.$$.log") || die "Unable to open $ENV{'PBTMP'}/system.$$.log";
1288 while (<LOG>) {
1289 chomp();
1290 my $tmp = $_;
1291 next if ($tmp !~ /^SD BUILD.*:/);
1292 $tmp =~ s|.*../(.*)_(.*).sd.*|$1|;
1293 $made="$made $tmp"."_*.sd";
1294 }
1295 close(LOG);
1296 $made="$made $pbpkg-$pbver-$pbtag.sd";
1297
1298 pb_system("rm -rf $pbpkg-$pbver", "Cleanup");
1299 } else {
1300 die "Unknown dtype format $dtype";
1301 }
1302 if (defined $pbparallel) {
1303 # Communicate results back to parent
1304 pb_set_content("$tmpd/$$",$made);
1305 $pm->finish;
1306 }
1307 }
1308 if (defined $pbparallel) {
1309 # In the parent, we need to get the result from the children
1310 $pm->wait_all_children;
1311 foreach my $f (<$tmpd/*>) {
1312 $made .= " ".pb_get_content($f);
1313 }
1314 pb_rm_rf($tmpd);
1315 }
1316
1317 # Find the appropriate check cmd/opts
1318 my ($oschkcmd,$oschkopt) = pb_conf_get_if("oschkcmd","oschkopt");
1319 my $chkcmd .= pb_distro_get_param($ddir,$dver,$arch,$oschkcmd,$dtype,$dfam,$dos);
1320 my $chkopt .= pb_distro_get_param($ddir,$dver,$arch,$oschkopt,$dtype,$dfam,$dos);
1321
1322 # Packages check if needed
1323 if ($dtype eq "rpm") {
1324 if (-x $chkcmd) {
1325 pb_system("$chkcmd $chkopt $made","Checking validity of rpms with $chkcmd","verbose");
1326 }
1327 my $rpms ="";
1328 my $srpms ="";
1329 foreach my $f (split(/ /,$made)) {
1330 $rpms .= "$ENV{'PBBUILDDIR'}/$f " if ($f =~ /^RPMS\//);
1331 $srpms .= "$ENV{'PBBUILDDIR'}/$f " if ($f =~ /^SRPMS\//);
1332 }
1333 pb_log(0,"SRPM packages generated: $srpms\n");
1334 pb_log(0,"RPM packages generated: $rpms\n");
1335 } elsif ($dtype eq "deb") {
1336 my $made2 = "";
1337 foreach my $f (split(/ /,$made)) {
1338 $made2 .= "../$f " if ($f =~ /\.deb$/);
1339 }
1340 if (-x $chkcmd) {
1341 pb_system("$chkcmd $chkopt $made2","Checking validity of debs with $chkcmd","verbose");
1342 } else {
1343 pb_log(0,"deb packages generated: $made2\n");
1344 }
1345 } else {
1346 pb_log(0,"No check done for $dtype yet\n");
1347 pb_log(0,"Packages generated: $made\n");
1348 }
1349
1350 # Keep track of what is generated so that we can get them back from VMs
1351 open(KEEP,"> $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}") || die "Unable to create $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}";
1352 print KEEP "$made\n";
1353 close(KEEP);
1354}
1355
1356sub create_solaris_prototype {
1357
1358 my $uidgid = "bin bin";
1359 my $pkgdestdir = $ENV{'PBSOLDESTDIR'};
1360
1361 return if ($_ =~ /^$pkgdestdir$/);
1362 if (-d $_) {
1363 my $n = $File::Find::name;
1364 $n =~ s~$pkgdestdir/~~;
1365 print PROTO "d none $n 0755 $uidgid\n";
1366 } elsif (-x $_) {
1367 my $n = $File::Find::name;
1368 $n =~ s~$pkgdestdir/~~;
1369 print PROTO "f none $n 0755 $uidgid\n";
1370 } elsif (-f $_) {
1371 my $n = $File::Find::name;
1372 $n =~ s~$pkgdestdir/~~;
1373 print PROTO "f none $n 0644 $uidgid\n";
1374 }
1375}
1376
1377sub pb_build2ssh {
1378 pb_send2target("Sources");
1379}
1380
1381sub pb_pkg2ssh {
1382 pb_send2target("Packages");
1383}
1384
1385# By default deliver to the the public site hosting the
1386# ftp structure (or whatever) or a VM/VE
1387sub pb_send2target {
1388
1389 my $cmt = shift;
1390 my $v = shift || undef;
1391 my $vmexist = shift || 0; # 0 is FALSE
1392 my $vmpid = shift || 0; # 0 is FALSE
1393 my $snapme = shift || 0; # 0 is FALSE
1394
1395 pb_log(2,"DEBUG: pb_send2target($cmt,".Dumper($v).",$vmexist,$vmpid)\n");
1396 my $host = "sshhost";
1397 my $login = "sshlogin";
1398 my $dir = "sshdir";
1399 my $port = "sshport";
1400 my $conf = "sshconf";
1401 my $tmout = undef;
1402 my $path = undef;
1403 if ($cmt =~ /^VM/) {
1404 $login = "vmlogin";
1405 $dir = "pbdefdir";
1406 # Specific VM
1407 $tmout = "vmtmout";
1408 $path = "vmpath";
1409 $host = "vmhost";
1410 $port = "vmport";
1411 } elsif ($cmt =~ /^VE/) {
1412 $login = "velogin";
1413 $dir = "pbdefdir";
1414 # Specific VE
1415 $path = "vepath";
1416 $conf = "rbsconf";
1417 } elsif ($cmt eq "Web") {
1418 $host = "websshhost";
1419 $login = "websshlogin";
1420 $dir = "websshdir";
1421 $port = "websshport";
1422 }
1423 my $cmd = "";
1424 my $src = "";
1425 my ($odir,$over,$oarch) = (undef, undef, undef);
1426 my ($ddir, $dver, $dfam, $dtype, $dos, $pbsuf, $pbupd, $pbins, $darch);
1427
1428 if ($cmt ne "Announce") {
1429 # Get list of packages to build
1430 my $ptr = pb_get_pkg();
1431 @pkgs = @$ptr;
1432
1433 # Get the running distro to consider
1434 if (defined $v) {
1435 ($odir,$over,$oarch) = split(/-/,$v);
1436 }
1437 ($ddir, $dver, $dfam, $dtype, $dos, $pbsuf, $pbupd, $pbins, $darch) = pb_distro_init($odir,$over,$oarch);
1438 pb_log(2,"DEBUG: distro tuple: ".join(',',($ddir, $dver, $dfam, $dtype, $pbsuf, $pbupd, $pbins, $darch))."\n");
1439
1440 # Get list of packages to build
1441 # Get content saved in cms2build
1442 my ($pkg) = pb_conf_read("$ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb","pbpkg");
1443 $pkg = { } if (not defined $pkg);
1444
1445 chdir "$ENV{'PBBUILDDIR'}";
1446 foreach my $pbpkg (@pkgs) {
1447 my $vertag = $pkg->{$pbpkg};
1448 # get the version of the current package - maybe different
1449 ($pbver,$pbtag) = split(/-/,$vertag);
1450
1451 if (($cmt eq "Sources") || ($cmt =~ /V[EM]build/)) {
1452 $src = "$src $ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz $ENV{'PBDESTDIR'}/$pbpkg-$pbver.pbconf.tar.gz";
1453 if ($cmd eq "") {
1454 $cmd = "ln -sf $pbpkg-$pbver.tar.gz $pbpkg-latest.tar.gz";
1455 } else {
1456 $cmd = "$cmd ; ln -sf $pbpkg-$pbver.tar.gz $pbpkg-latest.tar.gz";
1457 }
1458 } elsif ($cmt eq "Web") {
1459 $src = "$src $ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz"
1460 }
1461 }
1462 # Adds conf file for availability of conf elements
1463 pb_conf_add("$ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb");
1464 }
1465
1466 if ($cmt =~ /V[EM]build/) {
1467 $src="$src $ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb $ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb $ENV{'PBETC'} $ENV{'PBDESTDIR'}/pbrc $ENV{'PBDESTDIR'}/pbscript.$$";
1468 } elsif ($cmt =~ /V[EM]Script/) {
1469 $src="$src $ENV{'PBDESTDIR'}/pbscript.$$";
1470 } elsif ($cmt =~ /V[EM]test/) {
1471 $src="$src $ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb $ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb $ENV{'PBETC'} $ENV{'PBDESTDIR'}/pbrc $ENV{'PBDESTDIR'}/pbscript.$$ $ENV{'PBDESTDIR'}/pbtest";
1472 } elsif (($cmt eq "Announce") || ($cmt eq "Web")) {
1473 $src="$src $ENV{'PBTMP'}/pbscript";
1474 } elsif ($cmt eq "Packages") {
1475 # Get package list from file made during build2pkg
1476 open(KEEP,"$ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}") || die "Unable to read $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}";
1477 $src = <KEEP>;
1478 chomp($src);
1479 close(KEEP);
1480 $src="$src $ENV{'PBBUILDDIR'}/pbscript";
1481 }
1482 # Remove potential leading spaces (cause problem with basename)
1483 $src =~ s/^ *//;
1484 my $basesrc = "";
1485 foreach my $i (split(/ +/,$src)) {
1486 $basesrc .= " ".basename($i);
1487 }
1488
1489 pb_log(0,"Sources handled ($cmt): $src\n");
1490 pb_log(2,"values: ".Dumper(($host,$login,$dir,$port,$tmout,$path,$conf))."\n");
1491 my ($sshhost,$sshlogin,$sshdir,$sshport) = pb_conf_get($host,$login,$dir,$port);
1492 # Not mandatory...
1493 my ($rbsconf,$testver,$delivery) = pb_conf_get_if($conf,"testver","delivery");
1494 $delivery->{$ENV{'PBPROJ'}} = "" if (not defined $delivery->{$ENV{'PBPROJ'}});
1495 my ($vtmout,$vepath);
1496 # ...Except those in virtual context
1497 if ($cmt =~ /^VE/) {
1498 ($vepath) = pb_conf_get($path);
1499 }
1500 if ($cmt =~ /^VM/) {
1501 ($vtmout) = pb_conf_get($tmout);
1502 }
1503 pb_log(2,"ssh: ".Dumper(($sshhost,$sshlogin,$sshdir,$sshport,$vtmout,$vepath,$rbsconf))."\n");
1504
1505 my $mac;
1506 if ($cmt !~ /^VE/) {
1507 $mac = "$sshlogin->{$ENV{'PBPROJ'}}\@$sshhost->{$ENV{'PBPROJ'}}";
1508 # Overwrite account value if passed as parameter
1509 $mac = "$pbaccount\@$sshhost->{$ENV{'PBPROJ'}}" if (defined $pbaccount);
1510 pb_log(2, "DEBUG: pbaccount: $pbaccount => mac: $mac\n") if (defined $pbaccount);
1511 } else {
1512 # VE
1513 # Overwrite account value if passed as parameter (typically for setup2v)
1514 $mac = $sshlogin->{$ENV{'PBPROJ'}};
1515 $mac = $pbaccount if (defined $pbaccount);
1516 }
1517
1518 my $tdir;
1519 my $bdir;
1520 if (($cmt eq "Sources") || ($cmt =~ /V[EM]Script/)) {
1521 $tdir = "$sshdir->{$ENV{'PBPROJ'}}/$delivery->{$ENV{'PBPROJ'}}/src";
1522 } elsif (($cmt =~ /V[EM]build/) || ($cmt =~ /V[EM]test/)) {
1523 $tdir = $sshdir->{$ENV{'PBPROJ'}}."/$ENV{'PBPROJ'}/delivery";
1524 $bdir = $sshdir->{$ENV{'PBPROJ'}}."/$ENV{'PBPROJ'}/build";
1525 # Remove a potential $ENV{'HOME'} as bdir should be relative to pb's home
1526 $bdir =~ s|\$ENV.+\}/||;
1527 } elsif ($cmt eq "Announce") {
1528 $tdir = "$sshdir->{$ENV{'PBPROJ'}}/$delivery->{$ENV{'PBPROJ'}}";
1529 } elsif ($cmt eq "Web") {
1530 $tdir = "$sshdir->{$ENV{'PBPROJ'}}/$delivery->{$ENV{'PBPROJ'}}";
1531 } elsif ($cmt eq "Packages") {
1532 $tdir = "$sshdir->{$ENV{'PBPROJ'}}/$delivery->{$ENV{'PBPROJ'}}/$ddir/$dver/$darch";
1533
1534 my $repodir = $tdir;
1535 $repodir =~ s|^$sshdir->{$ENV{'PBPROJ'}}/||;
1536
1537 my ($pbrepo) = pb_conf_get("pbrepo");
1538
1539 # Repository management
1540 open(PBS,"> $ENV{'PBBUILDDIR'}/pbscript") || die "Unable to create $ENV{'PBBUILDDIR'}/pbscript";
1541 if ($dtype eq "rpm") {
1542 # Also make a pbscript to generate yum/urpmi bases
1543 print PBS << "EOF";
1544#!/bin/bash
1545# Prepare a script to ease yum setup
1546cat > $ENV{'PBPROJ'}.repo << EOT
1547[$ENV{'PBPROJ'}]
1548name=$ddir $dver $darch - $ENV{'PBPROJ'} Vanilla Packages
1549baseurl=$pbrepo->{$ENV{'PBPROJ'}}/$repodir
1550enabled=1
1551gpgcheck=0
1552EOT
1553chmod 644 $ENV{'PBPROJ'}.repo
1554
1555# Clean up old repo content
1556rm -rf headers/ repodata/
1557# Create yum repo
1558if [ -x /usr/bin/yum-arch ]; then
1559 yum-arch .
1560fi
1561# Create repodata
1562createrepo .
1563EOF
1564 if ($dfam eq "md") {
1565 # For Mandriva add urpmi management
1566 print PBS << "EOF";
1567# Prepare a script to ease urpmi setup
1568cat > $ENV{'PBPROJ'}.addmedia << EOT
1569urpmi.addmedia $ENV{'PBPROJ'} $pbrepo->{$ENV{'PBPROJ'}}/$repodir with media_info/hdlist.cz
1570EOT
1571chmod 755 $ENV{'PBPROJ'}.addmedia
1572
1573# Clean up old repo content
1574rm -f hdlist.cz synthesis.hdlist.cz
1575# Create urpmi repo
1576genhdlist2 --clean .
1577if [ \$\? -ne 0 ]; then
1578 genhdlist .
1579fi
1580EOF
1581 }
1582 if ($ddir eq "fedora") {
1583 # Extract the spec file to please Fedora maintainers :-(
1584 print PBS << "EOF";
1585for p in $basesrc; do
1586 echo \$p | grep -q 'src.rpm'
1587 if [ \$\? -eq 0 ]; then
1588 rpm2cpio \$p | cpio -ivdum --quiet '*.spec'
1589 fi
1590done
1591EOF
1592 }
1593 if ($dfam eq "novell") {
1594 # Add ymp scripts for one-click install on SuSE
1595 print PBS << "EOF";
1596# Prepare a script to ease SuSE one-click install
1597# Cf: http://de.opensuse.org/1-Klick-Installation/ISV
1598#
1599cat > $ENV{'PBPROJ'}.ymp << EOT
1600<?xml version="1.0" encoding="utf-8"?>
1601<!-- vim: set sw=2 ts=2 ai et: -->
1602<metapackage xmlns:os="http://opensuse.org/Standards/One_Click_Install" xmlns="http://opensuse.org/Standards/One_Click_Install">
1603 <group><!-- The group of software, typically one for project-builder.org -->
1604 <name>$ENV{'PBPROJ'} Bundle</name> <!-- Name of the software group -->
1605 <summary>Software bundle for the $ENV{'PBPROJ'} project</summary> <!--This message is shown to the user and should describe the whole bundle -->
1606 <description>This is the summary of the $ENV{'PBPROJ'} Project
1607
1608 Details are available on a per package basis below
1609
1610 </description><!--This is also shown to the user -->
1611 <remainSubscribed>false</remainSubscribed> <!-- Don't know what it mean -->
1612 <repositories><!-- List of needed repositories -->
1613 <repository>
1614 <name>$ENV{'PBPROJ'} Repository</name> <!-- Name of the repository -->
1615 <summary>This repository contains the $ENV{'PBPROJ'} project packages.</summary> <!-- Summary of the repository -->
1616 <description>This repository contains the $ENV{'PBPROJ'} project packages.</description><!-- This description is shown to the user -->
1617 <url>$pbrepo->{$ENV{'PBPROJ'}}/$repodir</url><!--URL of repository, which is added -->
1618 </repository>
1619 </repositories>
1620 <software><!-- A List of packages, which should be added through the one-click-installation -->
1621EOT
1622for p in $basesrc; do
1623 sum=`rpm -q --qf '%{SUMMARY}' \$p`
1624 name=`rpm -q --qf '%{NAME}' \$p`
1625 desc=`rpm -q --qf '%{description}' \$p`
1626 cat >> $ENV{'PBPROJ'}.ymp << EOT
1627 <item>
1628 <name>\$name</name><!-- Name of the package, is shown to the user and used to identify the package at the repository -->
1629 <summary>\$sum</summary> <!-- Summary of the package -->
1630 <description>\$desc</description> <!-- Description, is shown to the user -->
1631 </item>
1632EOT
1633done
1634cat >> $ENV{'PBPROJ'}.ymp << EOT
1635 </software>
1636 </group>
1637</metapackage>
1638EOT
1639chmod 644 $ENV{'PBPROJ'}.ymp
1640EOF
1641 }
1642 } elsif ($dtype eq "deb") {
1643 # Also make a pbscript to generate apt bases
1644 # Cf: http://www.debian.org/doc/manuals/repository-howto/repository-howto.fr.html
1645 # This dirname removes arch
1646 my $rpd = dirname("$pbrepo->{$ENV{'PBPROJ'}}/$repodir");
1647 # this one removes the ver
1648 $rpd = dirname($rpd);
1649 print PBS << "EOF";
1650#!/bin/bash
1651# Prepare a script to ease apt setup
1652cat > $ENV{'PBPROJ'}.sources.list << EOT
1653deb $rpd $dver contrib
1654deb-src $rpd $dver contrib
1655EOT
1656chmod 644 $ENV{'PBPROJ'}.sources.list
1657
1658# Up two levels to deal with the dist dir cross versions
1659cd ../..
1660mkdir -p dists/$dver/contrib/binary-$darch dists/$dver/contrib/source
1661
1662# Prepare a script to create apt info file
1663TMPD=`mktemp -d /tmp/pb.XXXXXXXXXX` || exit 1
1664mkdir -p \$TMPD
1665cat > \$TMPD/Release << EOT
1666Archive: unstable
1667Component: contrib
1668Origin: $ENV{'PBPROJ'}
1669Label: $ENV{'PBPROJ'} dev repository $pbrepo->{$ENV{'PBPROJ'}}
1670EOT
1671
1672echo "Creating Packages metadata ($darch)"
1673dpkg-scanpackages -a$darch $dver/$darch /dev/null | gzip -c9 > dists/$dver/contrib/binary-$darch/Packages.gz
1674dpkg-scanpackages -a$darch $dver/$darch /dev/null | bzip2 -c9 > dists/$dver/contrib/binary-$darch/Packages.bz2
1675echo "Creating Contents metadata ($darch)"
1676apt-ftparchive contents $dver | gzip -c9 > dists/$dver/Contents-$darch.gz
1677echo "Creating Release metadata ($darch)"
1678cat \$TMPD/Release > dists/$dver/contrib/binary-$darch/Release
1679echo "Architecture: $darch" >> dists/$dver/contrib/binary-$darch/Release
1680echo "Creating Source metadata"
1681dpkg-scansources $dver/$darch /dev/null | gzip -c9 > dists/$dver/contrib/source/Sources.gz
1682cat \$TMPD/Release > dists/$dver/contrib/source/Release
1683echo "Architecture: Source" >> dists/$dver/contrib/source/Release
1684echo "Creating Release metadata"
1685apt-ftparchive release dists/$dver > dists/$dver/Release
1686rm -rf \$TMPD
1687EOF
1688 } elsif ($dtype eq "ebuild") {
1689 # make a pbscript to generate links to latest version
1690 print PBS << "EOF";
1691#!/bin/bash
1692# Prepare a script to create correct links
1693for p in $src; do
1694 echo \$p | grep -q '.ebuild'
1695 if [ \$\? -eq 0 ]; then
1696 j=`basename \$p`
1697 pp=`echo \$j | cut -d'-' -f1`
1698 ln -sf \$j \$pp.ebuild
1699 fi
1700done
1701EOF
1702 }
1703 close(PBS);
1704 chmod 0755,"$ENV{'PBBUILDDIR'}/pbscript";
1705 } else {
1706 return;
1707 }
1708
1709 # Useless for VE
1710 my $nport = pb_get_port($sshport->{$ENV{'PBPROJ'}},$cmt) if ($cmt !~ /^VE/);
1711
1712 # Remove a potential $ENV{'HOME'} as tdir should be relative to pb's home
1713 $tdir =~ s|\$ENV.+\}/||;
1714
1715 my $tm = undef;
1716 if ($cmt =~ /^VM/) {
1717 $tm = $vtmout->{$ENV{'PBPROJ'}};
1718 }
1719
1720 # ssh communication if not VE
1721 # should use a hash instead...
1722 my ($shcmd,$cpcmd,$cptarget,$cp2target);
1723 if ($cmt !~ /^VE/) {
1724 my $keyfile = pb_ssh_get(0);
1725 $shcmd = "ssh -i $keyfile -q -o UserKnownHostsFile=/dev/null -p $nport $mac";
1726 $cpcmd = "scp -i $keyfile -p -o UserKnownHostsFile=/dev/null -P $nport";
1727 $cptarget = "$mac:$tdir";
1728 if ($cmt =~ /^VMbuild/) {
1729 $cp2target = "$mac:$bdir";
1730 }
1731 } else {
1732 my $tp = $vepath->{$ENV{'PBPROJ'}};
1733 ($odir,$over,$oarch) = split(/-/,$v);
1734 my $tpdir = "$tp/$odir/$over/$oarch";
1735 my ($ptr) = pb_conf_get("vetype");
1736 my $vetype = $ptr->{$ENV{'PBPROJ'}};
1737 if ($vetype eq "chroot") {
1738 $shcmd = "sudo chroot $tpdir /bin/su - $mac -c ";
1739 } elsif ($vetype eq "schroot") {
1740 $shcmd = "schroot $tp -u $mac -- ";
1741 }
1742 $cpcmd = "sudo cp -r ";
1743 # We need to get the home dir of the target account to deliver in the right place
1744 open(PASS,"$tpdir/etc/passwd") || die "Unable to open $tpdir/etc/passwd";
1745 my $homedir = "";
1746 while (<PASS>) {
1747 my ($c1,$c2,$c3,$c4,$c5,$c6,$c7) = split(/:/);
1748 $homedir = $c6 if ($c1 =~ /^$mac$/);
1749 pb_log(3,"Homedir: $homedir - account: $c6\n");
1750 }
1751 close(PASS);
1752 $cptarget = "$tpdir/$homedir/$tdir";
1753 if ($cmt eq "VEbuild") {
1754 $cp2target = "$tpdir/$homedir/$bdir";
1755 }
1756 pb_log(2,"On VE using $cptarget as target dir to copy to\n");
1757 }
1758
1759 my $logres = "";
1760 # Do not touch when just announcing
1761 if ($cmt ne "Announce") {
1762 pb_system("$shcmd \"mkdir -p $tdir ; cd $tdir ; echo \'for i in $basesrc; do if [ -f \$i ]; then rm -f \$i; fi; done\ ; $cmd' | bash\"","Preparing $tdir on $cptarget");
1763 } else {
1764 $logres = "> ";
1765 }
1766 pb_system("cd $ENV{'PBBUILDDIR'} ; $cpcmd $src $cptarget 2> /dev/null","$cmt delivery in $cptarget");
1767
1768 # For VE we need to change the owner manually
1769 if ($cmt =~ /^VE/) {
1770 pb_system("$shcmd \"sudo chown -R $mac $tdir\"","Adapt owner in $tdir to $mac");
1771 }
1772
1773 # Use the right script name depending on context
1774 my $pbscript;
1775 if ($cmt =~ /^V[EM]/) {
1776 $pbscript = "pbscript.$$";
1777 } else {
1778 $pbscript = "pbscript";
1779 }
1780
1781 pb_system("$shcmd \"echo \'cd $tdir ; if [ -x $pbscript ]; then ./$pbscript; fi ; rm -f ./$pbscript\' | bash\"","Executing pbscript on $cptarget if needed","verbose");
1782 if ($cmt =~ /^V[EM]build/) {
1783 # Get back info on pkg produced, compute their name and get them from the VM
1784 pb_system("$cpcmd $cp2target/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'} $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.$$ 2> /dev/null","Get package names in $cp2target");
1785 # For VE we need to change the owner manually
1786 if ($cmt eq "VEbuild") {
1787 pb_system("sudo chown $UID $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.$$","Adapt owner in $tdir to $UID");
1788 }
1789 if (not -f "$ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.$$") {
1790 pb_log(0,"Problem with VM $v on $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.$$");
1791 } else {
1792 open(KEEP,"$ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.$$") || die "Unable to read $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.$$";
1793 my $src = <KEEP>;
1794 chomp($src);
1795 close(KEEP);
1796 unlink("$ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.$$");
1797
1798 $src =~ s/^ *//;
1799 pb_mkdir_p("$ENV{'PBBUILDDIR'}/$odir/$over/$oarch");
1800 # Change pgben to make the next send2target happy
1801 my $made = "";
1802
1803 # For VM we don't want shell expansion to hapen locally but remotely
1804 my $delim = '\'';
1805 if ($cmt =~ /^VEbuild/) {
1806 # For VE we need to support shell expansion locally
1807 $delim = "";
1808 }
1809
1810 open(KEEP,"> $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}") || die "Unable to write $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}";
1811 foreach my $p (split(/ +/,$src)) {
1812 my $j = basename($p);
1813 pb_system("$cpcmd $cp2target/$delim$p$delim $ENV{'PBBUILDDIR'}/$odir/$over/$oarch 2> /dev/null","Recovery of package $j in $ENV{'PBBUILDDIR'}/$odir/$over/$oarch");
1814 $made="$made $odir/$over/$oarch/$j"; # if (($dtype ne "rpm") || ($j !~ /.src.rpm$/));
1815 }
1816 print KEEP "$made\n";
1817 close(KEEP);
1818 pb_system("$shcmd \"rm -rf $tdir $bdir\"","$cmt cleanup");
1819
1820 # Sign packages locally
1821 if ($dtype eq "rpm") {
1822 #pb_system("rpm --addsign --define \"_signature gpg\" --define \"_gpg_name $ENV{'PBPACKAGER'}\" --define \"__gpg_sign_cmd /usr/bin/gpg --batch --no-verbose --no-armor --no-tty --no-secmem-warning -sbo %{__signature_filename} %{__plaintext_filename} --use-agent\" $made","Signing RPM packages packages");
1823 } elsif ($dtype eq "deb") {
1824 #pb_system("debsign $made","Signing DEB packages");
1825 } else {
1826 pb_log(0,"I don't know yet how to sign packages for type $dtype.\nPlease give feedback to dev team\n");
1827 }
1828
1829 # We want to send them to the ssh account so overwrite what has been done before
1830 undef $pbaccount;
1831 pb_log(2,"Before sending pkgs, vmexist: $vmexist, vmpid: $vmpid\n");
1832 pb_send2target("Packages",$odir."-".$over."-".$oarch,$vmexist,$vmpid);
1833 pb_rm_rf("$ENV{'PBBUILDDIR'}/$odir/$over/$oarch");
1834 }
1835 }
1836 unlink("$ENV{'PBDESTDIR'}/pbscript.$$") if ($cmt =~ /^V[ME]/);
1837
1838 pb_log(2,"Before halt, vmexist: $vmexist, vmpid: $vmpid\n");
1839 if ((! $vmexist) && ($cmt =~ /^VM/)) {
1840 # If in setupvm then takes a snapshot just before halting
1841 if ($snapme != 0) {
1842 my ($vmmonport,$vmtype) = pb_conf_get("vmmonport","vmtype");
1843 # For monitoring control
1844 if ((($vmtype->{$ENV{'PBPROJ'}}) eq "kvm") || (($vmtype->{$ENV{'PBPROJ'}}) eq "qemu")) {
1845 eval
1846 {
1847 require Net::Telnet;
1848 Net::Telnet->import();
1849 };
1850 if ($@) {
1851 # Net::Telnet not found
1852 pb_log(1,"ADVISE: Install Net::Telnet to benefit from monitoring control and snapshot feature.\nWARNING: No snapshot created");
1853 } else {
1854 my $t = new Net::Telnet (Timeout => 120, Host => "localhost", Port => $vmmonport->{$ENV{'PBPROJ'}}) || die "Unable to dialog on the monitor";
1855 # move to monitor mode
1856 my @lines = $t->cmd("c");
1857 # Create a snapshot named pb
1858 @lines = $t->cmd("savevm pb");
1859 # Write the new status in the VM
1860 @lines = $t->cmd("commit all");
1861 # End
1862 @lines = $t->cmd("quit");
1863 }
1864 }
1865 }
1866 my $hoption = "-p";
1867 my $hpath = "/sbin";
1868 # Solaris doesn't support -h and has halt elsewhere
1869 if ($dtype eq "pkg") {
1870 $hoption = "" ;
1871 $hpath = "/usr/sbin";
1872 }
1873 pb_system("$shcmd \"sudo $hpath/halt $hoption \"; sleep $tm ; echo \'if [ -d /proc/$vmpid ]; then kill -9 $vmpid; fi \' | bash ; sleep 10","VM $v halt (pid $vmpid)");
1874 }
1875 if (($cmt =~ /^VE/) && ($snapme != 0)) {
1876 ($odir,$over,$oarch) = split(/-/,$v);
1877 my $tpdir = "$vepath->{$ENV{'PBPROJ'}}/$odir/$over/$oarch";
1878 pb_system("sudo tar cz -f $vepath->{$ENV{'PBPROJ'}}/$odir-$over-$oarch.tar.gz -C $tpdir .","Creating a snapshot of $tpdir");
1879 }
1880}
1881
1882sub pb_script2v {
1883 my $pbscript=shift;
1884 my $vtype=shift;
1885 my $pbforce=shift || 0; # Force stop of VM. Default not.
1886 my $vm1=shift || undef; # Only that VM to treat. Default all.
1887 my $snapme=shift || 0; # Do we have to create a snapshot. Default not.
1888 my $vm;
1889 my $all;
1890
1891 pb_log(2,"DEBUG: pb_script2v($pbscript,$vtype,$pbforce,".Dumper($vm1).",$snapme)\n");
1892 # Prepare the script to be executed on the VM
1893 # in $ENV{'PBDESTDIR'}/pbscript.$$
1894 if ((defined $pbscript ) && ($pbscript ne "$ENV{'PBDESTDIR'}/pbscript.$$")) {
1895 copy($pbscript,"$ENV{'PBDESTDIR'}/pbscript.$$") || die "Unable to create $ENV{'PBDESTDIR'}/pbscript.$$";
1896 chmod 0755,"$ENV{'PBDESTDIR'}/pbscript.$$";
1897 }
1898
1899 if (not defined $vm1) {
1900 ($vm,$all) = pb_get2v($vtype);
1901 } else {
1902 @$vm = ($vm1);
1903 }
1904 my ($vmexist,$vmpid) = (undef,undef);
1905
1906 foreach my $v (@$vm) {
1907 # Launch VM/VE
1908 ($vmexist,$vmpid) = pb_launchv($vtype,$v,0,$snapme,$pbsnap);
1909
1910 if ($vtype eq "vm") {
1911 pb_log(2,"DEBUG: After pb_launchv, vmexist: $vmexist, vmpid: $vmpid\n");
1912
1913 # Skip that VM if something went wrong
1914 next if (($vmpid == 0) && ($vmexist == 0));
1915
1916 # If force stopping the VM then reset vmexist
1917 if ($pbforce == 1) {
1918 $vmpid = $vmexist;
1919 $vmexist = 0;
1920 }
1921 } else {
1922 #VE
1923 $vmexist = 0;
1924 $vmpid = 0;
1925 }
1926
1927 # Gather all required files to send them to the VM
1928 # and launch the build through pbscript
1929 pb_log(2,"DEBUG: Before send2target, vmexist: $vmexist, vmpid: $vmpid\n");
1930 pb_send2target(uc($vtype)."Script","$v",$vmexist,$vmpid,$snapme);
1931
1932 }
1933}
1934
1935sub pb_launchv {
1936 my $vtype = shift;
1937 my $v = shift;
1938 my $create = shift || 0; # By default do not create a VM/VE
1939 my $snapme = shift || 0; # By default do not snap a VM/VE
1940 my $usesnap = shift || 1; # By default study the usage of the snapshot feature of VM/VE
1941
1942 # If creation or snapshot creation mode, no snapshot usable
1943 if (($create == 1) || ($snapme == 1)) {
1944 $usesnap = 0;
1945 }
1946
1947 pb_log(2,"DEBUG: pb_launchv($vtype,$v,$create,$snapme,$usesnap)\n");
1948 die "No VM/VE defined, unable to launch" if (not defined $v);
1949 # Keep only the first VM in case many were given
1950 $v =~ s/,.*//;
1951
1952 my $arch = pb_get_arch();
1953
1954 # Launch the VMs/VEs
1955 if ($vtype eq "vm") {
1956 die "-i iso parameter needed" if (((not defined $iso) || ($iso eq "")) && ($create != 0));
1957
1958 # TODO: vmmonport should be optional
1959 my ($ptr,$ptr2,$vmpath,$vmport,$vmsize,$vmmonport) = pb_conf_get("vmtype","vmcmd","vmpath","vmport","vmsize","vmmonport");
1960 my ($vmopt,$vmmem,$vmtmout,$vmsnap,$vmbuildtm) = pb_conf_get_if("vmopt","vmmem","vmtmout","vmsnap","vmbuildtm");
1961
1962 my $vmtype = $ptr->{$ENV{'PBPROJ'}};
1963 my $vmcmd = $ptr2->{$ENV{'PBPROJ'}};
1964
1965 if (defined $opts{'g'}) {
1966 if (($vmtype eq "kvm") || ($vmtype eq "qemu")) {
1967 $ENV{'PBVMOPT'} = "--nographic";
1968 }
1969 }
1970 if (not defined $ENV{'PBVMOPT'}) {
1971 $ENV{'PBVMOPT'} = "";
1972 }
1973 # Save the current status for later restoration
1974 $ENV{'PBOLDVMOPT'} = $ENV{'PBVMOPT'};
1975 # Set a default timeout of 2 minutes
1976 if (not defined $ENV{'PBVMTMOUT'}) {
1977 $ENV{'PBVMTMOUT'} = "120";
1978 }
1979 if (defined $vmopt->{$v}) {
1980 $ENV{'PBVMOPT'} .= " $vmopt->{$v}" if ($ENV{'PBVMOPT'} !~ / $vmopt->{$v}/);
1981 } elsif (defined $vmopt->{$ENV{'PBPROJ'}}) {
1982 $ENV{'PBVMOPT'} .= " $vmopt->{$ENV{'PBPROJ'}}" if ($ENV{'PBVMOPT'} !~ / $vmopt->{$ENV{'PBPROJ'}}/);
1983 }
1984
1985 # How much memory to allocate for VMs
1986 if (defined $vmmem->{$v}) {
1987 $ENV{'PBVMOPT'} .= " -m $vmmem->{$v}";
1988 } elsif (defined $vmmem->{$ENV{'PBPROJ'}}) {
1989 $ENV{'PBVMOPT'} .= " -m $vmmem->{$ENV{'PBPROJ'}}";
1990 }
1991
1992 # Are we allowed to use snapshot feature
1993 if ($usesnap == 1) {
1994 if ((defined $vmsnap->{$v}) && ($vmsnap->{$v} =~ /true/i)) {
1995 $ENV{'PBVMOPT'} .= " -snapshot";
1996 } elsif ((defined $vmsnap->{$ENV{'PBPROJ'}}) && ($vmsnap->{$ENV{'PBPROJ'}} =~ /true/i)) {
1997 $ENV{'PBVMOPT'} .= " -snapshot";
1998 } elsif ($pbsnap eq 1) {
1999 $ENV{'PBVMOPT'} .= " -snapshot";
2000 }
2001 }
2002 if ($snapme != 0) {
2003 if (($vmtype eq "kvm") || ($vmtype eq "qemu")) {
2004 # Configure the monitoring to automate the creation of the 'pb' snapshot
2005 $ENV{'PBVMOPT'} .= " -serial mon:telnet::$vmmonport->{$ENV{'PBPROJ'}},server,nowait";
2006 # In that case no snapshot call needed
2007 $ENV{'PBVMOPT'} =~ s/ -snapshot//;
2008 }
2009 }
2010 if (defined $vmtmout->{$v}) {
2011 $ENV{'PBVMTMOUT'} = $vmtmout->{$v};
2012 } elsif (defined $vmtmout->{$ENV{'PBPROJ'}}) {
2013 $ENV{'PBVMTMOUT'} = $vmtmout->{$ENV{'PBPROJ'}};
2014 }
2015 my $nport = pb_get_port($vmport->{$ENV{'PBPROJ'}});
2016
2017 my $cmd;
2018 my $vmm; # has to be used for pb_check_ps
2019 if (($vmtype eq "qemu") || ($vmtype eq "kvm")) {
2020 $vmm = "$vmpath->{$ENV{'PBPROJ'}}/$v.qemu";
2021 if (($create != 0) || (defined $iso)) {
2022 $ENV{'PBVMOPT'} .= " -cdrom $iso -boot d";
2023 }
2024 # Always redirect the network and always try to use a 'pb' snapshot
2025 $cmd = "$vmcmd $ENV{'PBVMOPT'} -redir tcp:$nport:10.0.2.15:22 -loadvm pb $vmm"
2026 } elsif ($vmtype eq "xen") {
2027 } elsif ($vmtype eq "vmware") {
2028 } else {
2029 die "VM of type $vmtype not supported. Report to the dev team";
2030 }
2031 # Restore the ENV VAR Value
2032 $ENV{'PBVMOPT'} = $ENV{'PBOLDVMOPT'};
2033
2034 my ($tmpcmd,$void) = split(/ +/,$cmd);
2035 my $vmexist = pb_check_ps($tmpcmd,$vmm);
2036 my $vmpid = 0;
2037 if (! $vmexist) {
2038 if ($create != 0) {
2039 die("Found an existing Virtual machine $vmm. Won't overwrite") if (-r $vmm);
2040 if (($vmtype eq "qemu") || ($vmtype eq "xen") || ($vmtype eq "kvm")) {
2041 my $command = pb_check_req("qemu-img",0);
2042 pb_system("$command create -f qcow2 $vmm $vmsize->{$ENV{'PBPROJ'}}","Creating the QEMU VM");
2043 } elsif ($vmtype eq "vmware") {
2044 } else {
2045 }
2046 }
2047 if (! -f "$vmm") {
2048 pb_log(0,"Unable to find VM $vmm\n");
2049 } else {
2050 # Is the SSH port free? if not kill the existing process using it after a build timeout period
2051 my $vmssh = pb_check_ps($tmpcmd,"tcp:$nport:10.0.2.15:22");
2052 if ($vmssh) {
2053 my $buildtm = $ENV{'PBVMTMOUT'};
2054 if (defined $vmbuildtm->{$v}) {
2055 $buildtm = $vmbuildtm->{$v};
2056 } elsif (defined $vmbuildtm->{$ENV{'PBPROJ'}}) {
2057 $buildtm = $vmbuildtm->{$ENV{'PBPROJ'}};
2058 }
2059
2060 sleep $buildtm;
2061 pb_log(0,"WARNING: Killing the process ($vmssh) using port $nport (previous failed VM ?)\n");
2062 kill 15,$vmssh;
2063 # Let it time to exit
2064 sleep 5;
2065 }
2066 pb_system("$cmd &","Launching the VM $vmm");
2067 # Using system allows to kill it externaly if needed
2068 pb_system("sleep $ENV{'PBVMTMOUT'}","Waiting $ENV{'PBVMTMOUT'} s for VM $v to come up");
2069 $vmpid = pb_check_ps($tmpcmd,$vmm);
2070 pb_log(0,"VM $vmm launched (pid $vmpid)\n");
2071 }
2072 } else {
2073 pb_log(0,"Found an existing VM $vmm (pid $vmexist)\n");
2074 }
2075 pb_log(2,"DEBUG: pb_launchv returns ($vmexist,$vmpid)\n");
2076 return($vmexist,$vmpid);
2077 # VE here
2078 } else {
2079 # Get distro context
2080 my ($name,$ver,$darch) = split(/-/,$v);
2081 chomp($darch);
2082 my ($ddir, $dver, $dfam, $dtype, $dos, $pbsuf) = pb_distro_init($name,$ver,$darch);
2083
2084 # Get VE context
2085 my ($ptr,$vepath) = pb_conf_get("vetype","vepath");
2086 my $vetype = $ptr->{$ENV{'PBPROJ'}};
2087
2088 # We can probably only get those params now we have the distro context
2089 my ($rbsb4pi,$rbspi,$vesnap,$oscodename,$osmindep,$verebuild,$rbsmirrorsrv) = pb_conf_get_if("rbsb4pi","rbspi","vesnap","oscodename","osmindep","verebuild","rbsmirrorsrv");
2090
2091 # We need to avoid umask propagation to the VE
2092 umask 0022;
2093
2094 if (($vetype eq "chroot") || ($vetype eq "schroot")) {
2095 # Architecture consistency
2096 if ($arch ne $darch) {
2097 die "Unable to launch a VE of architecture $darch on a $arch platform" if (($darch eq "x86_64") && ($arch =~ /i?86/));
2098 }
2099
2100 my ($verpmtype,$vedebtype) = pb_conf_get("verpmtype","vedebtype");
2101 if (($create != 0) || ((defined $verebuild) && ($verebuild->{$ENV{'PBPROJ'}} =~ /true/i)) || ($pbforce == 1)) {
2102 my ($rbsopt1) = pb_conf_get_if("rbsopt");
2103
2104 # We have to rebuild the chroot
2105 if ($dtype eq "rpm") {
2106
2107 # Which tool is used
2108 my $verpmstyle = $verpmtype->{$ENV{'PBPROJ'}};
2109
2110 # Get potential rbs option
2111 my $rbsopt = "";
2112 if (defined $rbsopt1) {
2113 if (defined $rbsopt1->{$verpmstyle}) {
2114 $rbsopt = $rbsopt1->{$verpmstyle};
2115 } elsif (defined $rbsopt1->{$ENV{'PBPROJ'}}) {
2116 $rbsopt = $rbsopt1->{$ENV{'PBPROJ'}};
2117 } else {
2118 $rbsopt = "";
2119 }
2120 }
2121
2122 my $postinstall = pb_get_postinstall($ddir,$dver,$darch,$rbspi,$verpmstyle);
2123 if ($verpmstyle eq "rinse") {
2124 # Need to reshape the mirrors generated with local before-post-install script
2125 my $b4post = "--before-post-install ";
2126 my $postparam = pb_distro_get_param($ddir,$dver,$darch,$rbsb4pi);
2127 if ($postparam eq "") {
2128 $b4post = "";
2129 } else {
2130 $b4post .= $postparam;
2131 }
2132
2133 # Need to reshape the package list for pb
2134 my $addpkgs;
2135 $postparam = "";
2136 $postparam .= pb_distro_get_param($ddir,$dver,$darch,$osmindep);
2137 if ($postparam eq "") {
2138 $addpkgs = "";
2139 } else {
2140 my $pkgfile = "$ENV{'PBTMP'}/addpkgs.lis";
2141 open(PKG,"> $pkgfile") || die "Unable to create $pkgfile";
2142 foreach my $p (split(/,/,$postparam)) {
2143 print PKG "$p\n";
2144 }
2145 close(PKG);
2146 $addpkgs = "--add-pkg-list $pkgfile";
2147 }
2148
2149 my $rinseverb = "";
2150 $rinseverb = "--verbose" if ($pbdebug gt 0);
2151 my ($rbsconf) = pb_conf_get("rbsconf");
2152
2153 my $command = pb_check_req("rinse",0);
2154 pb_system("sudo $command --directory \"$vepath->{$ENV{'PBPROJ'}}/$ddir/$dver/$darch\" --arch \"$darch\" --distribution \"$ddir-$dver\" --config \"$rbsconf->{$ENV{'PBPROJ'}}\" $b4post $postinstall $rbsopt $addpkgs $rinseverb","Creating the rinse VE for $ddir-$dver ($darch)", "verbose");
2155 } elsif ($verpmstyle eq "rpmbootstrap") {
2156 my $rbsverb = "";
2157 foreach my $i (1..$pbdebug) {
2158 $rbsverb .= " -v";
2159 }
2160 my $addpkgs = "";
2161 my $postparam = "";
2162 $postparam .= pb_distro_get_param($ddir,$dver,$darch,$osmindep);
2163 if ($postparam eq "") {
2164 $addpkgs = "";
2165 } else {
2166 $addpkgs = "-a $postparam";
2167 }
2168 my $command = pb_check_req("rpmbootstrap",0);
2169 pb_system("sudo $command $rbsopt $postinstall $addpkgs $ddir-$dver-$darch $rbsverb","Creating the rpmbootstrap VE for $ddir-$dver ($darch)", "verbose");
2170 } elsif ($verpmstyle eq "mock") {
2171 my ($rbsconf) = pb_conf_get("rbsconf");
2172 my $command = pb_check_req("mock",0);
2173 pb_system("sudo $command --init --resultdir=\"/tmp\" --configdir=\"$rbsconf->{$ENV{'PBPROJ'}}\" -r $v $rbsopt","Creating the mock VE for $ddir-$dver ($darch)");
2174 # Once setup we need to install some packages, the pb account, ...
2175 pb_system("sudo $command --install --configdir=\"$rbsconf->{$ENV{'PBPROJ'}}\" -r $v su","Configuring the mock VE");
2176 } else {
2177 die "Unknown verpmtype type $verpmstyle. Report to dev team";
2178 }
2179 } elsif ($dtype eq "deb") {
2180 my $vedebstyle = $vedebtype->{$ENV{'PBPROJ'}};
2181
2182 my $codename = pb_distro_get_param($ddir,$dver,$darch,$oscodename);
2183 my $postparam = "";
2184 my $addpkgs;
2185 $postparam .= pb_distro_get_param($ddir,$dver,$darch,$osmindep);
2186 if ($postparam eq "") {
2187 $addpkgs = "";
2188 } else {
2189 $addpkgs = "--include $postparam";
2190 }
2191 my $debmir = "";
2192 $debmir .= pb_distro_get_param($ddir,$dver,$darch,$rbsmirrorsrv);
2193
2194 # Get potential rbs option
2195 my $rbsopt = "";
2196 if (defined $rbsopt1) {
2197 if (defined $rbsopt1->{$vedebstyle}) {
2198 $rbsopt = $rbsopt1->{$vedebstyle};
2199 } elsif (defined $rbsopt1->{$ENV{'PBPROJ'}}) {
2200 $rbsopt = $rbsopt1->{$ENV{'PBPROJ'}};
2201 } else {
2202 $rbsopt = "";
2203 }
2204 }
2205
2206 # debootstrap works with amd64 not x86_64
2207 my $debarch = $darch;
2208 $debarch = "amd64" if ($darch eq "x86_64");
2209 if ($vedebstyle eq "debootstrap") {
2210 my $dbsverb = "";
2211 $dbsverb = "--verbose" if ($pbdebug gt 0);
2212
2213 # Some perl modules are in Universe on Ubuntu
2214 $rbsopt .= " --components=main,universe" if ($ddir eq "ubuntu");
2215
2216 pb_system("sudo /usr/sbin/debootstrap $dbsverb $rbsopt --arch=$debarch $addpkgs $codename \"$vepath->{$ENV{'PBPROJ'}}/$ddir/$dver/$darch\" $debmir","Creating the debootstrap VE for $ddir-$dver ($darch)", "verbose");
2217 # debootstrap doesn't create an /etc/hosts file
2218 if (! -f "$vepath->{$ENV{'PBPROJ'}}/$ddir/$dver/$darch/etc/hosts" ) {
2219 pb_system("sudo cp /etc/hosts $vepath->{$ENV{'PBPROJ'}}/$ddir/$dver/$darch/etc/hosts");
2220 }
2221 } else {
2222 die "Unknown vedebtype type $vedebstyle. Report to dev team";
2223 }
2224 } elsif ($dtype eq "ebuild") {
2225 die "Please teach the dev team how to build gentoo chroot";
2226 } else {
2227 die "Unknown distribution type $dtype. Report to dev team";
2228 }
2229 }
2230 # Fix modes to allow access to the VE for pb user
2231 pb_system("sudo chmod 755 $vepath->{$ENV{'PBPROJ'}}/$ddir $vepath->{$ENV{'PBPROJ'}}/$ddir/$dver $vepath->{$ENV{'PBPROJ'}}/$ddir/$dver/$darch","Fixing permissions");
2232
2233 # Test if an existing snapshot exists and use it if appropriate
2234 # And also use it of no local extracted VE is present
2235 if ((-f "$vepath->{$ENV{'PBPROJ'}}/$ddir-$dver-$darch.tar.gz") &&
2236 (((defined $vesnap->{$v}) && ($vesnap->{$v} =~ /true/i)) ||
2237 ((defined $vesnap->{$ENV{'PBPROJ'}}) && ($vesnap->{$ENV{'PBPROJ'}} =~ /true/i)) ||
2238 ($pbsnap eq 1) ||
2239 (! -d "$vepath->{$ENV{'PBPROJ'}}/$ddir/$dver/$darch"))) {
2240 pb_system("sudo rm -rf $vepath->{$ENV{'PBPROJ'}}/$ddir/$dver/$darch ; sudo mkdir -p $vepath->{$ENV{'PBPROJ'}}/$ddir/$dver/$darch ; sudo tar xz -C $vepath->{$ENV{'PBPROJ'}}/$ddir/$dver/$darch -f $vepath->{$ENV{'PBPROJ'}}/$ddir-$dver-$darch.tar.gz","Extracting snapshot of $ddir-$dver-$darch.tar.gz under $vepath->{$ENV{'PBPROJ'}}/$ddir/$dver/$darch");
2241 }
2242 # Nothing more to do for VE. No real launch
2243 } else {
2244 die "VE of type $vetype not supported. Report to the dev team";
2245 }
2246 }
2247}
2248
2249# Return string for date synchro
2250sub pb_date2v {
2251
2252my $vtype = shift;
2253my $v = shift;
2254
2255my ($ntp) = pb_conf_get_if($vtype."ntp");
2256my $vntp = $ntp->{$ENV{'PBPROJ'}} if (defined $ntp);
2257my $ntpline;
2258
2259if (defined $vntp) {
2260 my ($ntpcmd) = pb_conf_get($vtype."ntpcmd");
2261 my $vntpcmd;
2262 if (defined $ntpcmd->{$v}) {
2263 $vntpcmd = $ntpcmd->{$v};
2264 } elsif (defined $ntpcmd->{$ENV{'PBPROJ'}}) {
2265 $vntpcmd = $ntpcmd->{$ENV{'PBPROJ'}};
2266 } else {
2267 $vntpcmd = "/bin/true";
2268 }
2269 $ntpline = "sudo $vntpcmd $vntp";
2270} else {
2271 $ntpline = undef;
2272}
2273# Force new date to be in the future compared to the date
2274# of the host by adding 1 minute
2275my @date=pb_get_date();
2276$date[1]++;
2277my $upddate = strftime("%m%d%H%M%Y", @date);
2278my $dateline = "sudo date $upddate";
2279return($ntpline,$dateline);
2280}
2281
2282sub pb_build2v {
2283
2284my $vtype = shift;
2285my $action = shift || "build";
2286
2287my ($v,$all) = pb_get2v($vtype);
2288
2289# Send tar files when we do a global generation
2290pb_build2ssh() if (($all == 1) && ($action eq "build"));
2291
2292# Adapt // mode to memory size
2293$pbparallel = pb_set_parallel($vtype);
2294
2295my ($vmexist,$vmpid) = (undef,undef);
2296my $pm = new Parallel::ForkManager($pbparallel) if (defined $pbparallel);
2297
2298# Set which port the VM will use to communicate
2299$pm->run_on_start(\&pb_set_port);
2300
2301my $counter = 0;
2302foreach my $v (@$v) {
2303 $counter++;
2304 # Modulo 2 * pbparallel (to avoid synchronization problems)
2305 $counter = 1 if ($counter > 2 * $pbparallel);
2306 $pm->start($counter) and next if (defined $pbparallel);
2307 # Prepare the script to be executed on the VM/VE
2308 # in $ENV{'PBDESTDIR'}/pbscript.$$
2309 open(SCRIPT,"> $ENV{'PBDESTDIR'}/pbscript.$$") || die "Unable to create $ENV{'PBDESTDIR'}/pbscript.$$";
2310 print SCRIPT "#!/bin/bash\n";
2311
2312 # Transmit the verbosity level to the virtual env/mach.
2313 my $verbose = "";
2314 my $i = 0; # minimal debug level
2315 while ($i lt $pbdebug) {
2316 $verbose .= "-v ";
2317 $i++;
2318 }
2319 # Activate script verbosity if at least 2 for pbdebug
2320 print SCRIPT "set -x\n" if ($i gt 1);
2321 # Quiet if asked to be so on the original system
2322 $verbose = "-q" if ($pbdebug eq -1);
2323
2324 print SCRIPT "echo ... Execution needed\n";
2325 print SCRIPT "# This is in directory delivery\n";
2326 print SCRIPT "# Setup the variables required for building\n";
2327 print SCRIPT "export PBPROJ=$ENV{'PBPROJ'}\n";
2328
2329 if ($action eq "build") {
2330 print SCRIPT "# Preparation for pb\n";
2331 print SCRIPT "mv .pbrc \$HOME\n";
2332 print SCRIPT "cd ..\n";
2333 }
2334
2335 # VE needs a good /proc
2336 if ($vtype eq "ve") {
2337 print SCRIPT "sudo mount -t proc /proc /proc\n";
2338 }
2339
2340 my ($ntpline,$dateline) = pb_date2v($vtype,$v);
2341 print SCRIPT "# Time sync\n";
2342 print SCRIPT "echo 'setting up date with '";
2343 if (defined $ntpline) {
2344 print SCRIPT "echo $ntpline\n";
2345 print SCRIPT "$ntpline\n";
2346 } else {
2347 print SCRIPT "echo $dateline\n";
2348 print SCRIPT "$dateline\n";
2349 }
2350 # Use potential local proxy declaration in case we need it to download repo, pkgs, ...
2351 if (defined $ENV{'http_proxy'}) {
2352 print SCRIPT "export http_proxy=\"$ENV{'http_proxy'}\"\n";
2353 }
2354
2355 if (defined $ENV{'ftp_proxy'}) {
2356 print SCRIPT "export ftp_proxy=\"$ENV{'ftp_proxy'}\"\n";
2357 }
2358
2359 # Get list of packages to build/test and get some ENV vars as well
2360 my $ptr = pb_get_pkg();
2361 @pkgs = @$ptr;
2362 my $p = join(' ',@pkgs) if (@pkgs);
2363 print SCRIPT "export PBPROJVER=$ENV{'PBPROJVER'}\n";
2364 print SCRIPT "export PBPROJTAG=$ENV{'PBPROJTAG'}\n";
2365 print SCRIPT "export PBPACKAGER=\"$ENV{'PBPACKAGER'}\"\n";
2366
2367 # We may need to do some other tasks before building. Read a script here to finish setup
2368 if (-x "$ENV{'PBDESTDIR'}/pb$vtype".".pre") {
2369 print SCRIPT "# Special pre-instructions to be launched\n";
2370 print SCRIPT pb_get_content("$ENV{'PBDESTDIR'}/pb$vtype".".pre");
2371 }
2372
2373 if (-x "$ENV{'PBDESTDIR'}/pb$vtype"."$action.pre") {
2374 print SCRIPT "# Special pre-$action instructions to be launched\n";
2375 print SCRIPT pb_get_content("$ENV{'PBDESTDIR'}/pb$vtype"."$action.pre");
2376 }
2377
2378 print SCRIPT "# $action\n";
2379 print SCRIPT "echo $action"."ing packages on $vtype...\n";
2380
2381 if (($action eq "test") && (! -x "$ENV{'PBDESTDIR'}/pbtest")) {
2382 die "No test script ($ENV{'PBDESTDIR'}/pbtest) found when in test mode. Aborting ...";
2383 }
2384 print SCRIPT "pb $verbose -p $ENV{'PBPROJ'} $action"."2pkg $p\n";
2385
2386 if ($vtype eq "ve") {
2387 print SCRIPT "sudo umount /proc\n";
2388 }
2389
2390 # We may need to do some other tasks after building. Read a script here to exit properly
2391 if (-x "$ENV{'PBDESTDIR'}/pb$vtype"."$action.post") {
2392 print SCRIPT "# Special post-$action instructions to be launched\n";
2393 print SCRIPT pb_get_content("$ENV{'PBDESTDIR'}/pb$vtype"."$action.post");
2394 }
2395
2396 if (-x "$ENV{'PBDESTDIR'}/pb$vtype".".post") {
2397 print SCRIPT "# Special post-instructions to be launched\n";
2398 print SCRIPT pb_get_content("$ENV{'PBDESTDIR'}/pb$vtype".".post");
2399 }
2400
2401 close(SCRIPT);
2402 chmod 0755,"$ENV{'PBDESTDIR'}/pbscript.$$";
2403
2404 # Launch the VM/VE
2405 ($vmexist,$vmpid) = pb_launchv($vtype,$v,0);
2406
2407
2408 if ($vtype eq "vm") {
2409 # Skip that VM if something went wrong
2410 if (($vmpid == 0) && ($vmexist == 0)) {
2411 $pm->finish if (defined $pbparallel);
2412 next;
2413 }
2414 } else {
2415 # VE
2416 $vmexist = 0;
2417 $vmpid = 0;
2418 }
2419 # Gather all required files to send them to the VM/VE
2420 # and launch the build through pbscript
2421 pb_log(2,"Calling send2target $vtype,$v,$vmexist,$vmpid\n");
2422 pb_send2target(uc($vtype).$action,"$v",$vmexist,$vmpid);
2423 $pm->finish if (defined $pbparallel);
2424}
2425if (defined $pbparallel) {
2426 $pm->wait_all_children;
2427}
2428}
2429
2430
2431sub pb_clean {
2432
2433 my $sleep=10;
2434 die "Unable to get env var PBDESTDIR" if (not defined $ENV{'PBDESTDIR'});
2435 die "Unable to get env var PBBUILDDIR" if (not defined $ENV{'PBBUILDDIR'});
2436 pb_log(0,"We will now wait $sleep s before removing both directories\n$ENV{'PBDESTDIR'} and $ENV{'PBBUILDDIR'}.\nPlease break me if this is wrong\n");
2437 sleep $sleep;
2438 pb_rm_rf($ENV{'PBDESTDIR'});
2439 pb_rm_rf($ENV{'PBBUILDDIR'});
2440}
2441
2442sub pb_newver {
2443
2444 die "-V Version parameter needed" if ((not defined $newver) || ($newver eq ""));
2445
2446 # Need this call for PBDIR
2447 my ($scheme2,$uri) = pb_cms_init($pbinit);
2448
2449 my ($pbconf,$pburl) = pb_conf_get("pbconfurl","pburl");
2450 $uri = $pbconf->{$ENV{'PBPROJ'}};
2451 my ($scheme, $account, $host, $port, $path) = pb_get_uri($uri);
2452
2453 # Checking CMS repositories status
2454 ($scheme2, $account, $host, $port, $path) = pb_get_uri($pburl->{$ENV{'PBPROJ'}});
2455
2456 if ($scheme !~ /^svn/) {
2457 die "Only SVN is supported at the moment";
2458 }
2459
2460 my $res = pb_cms_isdiff($scheme,$ENV{'PBROOTDIR'});
2461 die "ERROR: No differences accepted in CMS for $ENV{'PBROOTDIR'} before creating a new version" if ($res != 0);
2462
2463 $res = pb_cms_isdiff($scheme2,$ENV{'PBDIR'});
2464 die "ERROR: No differences accepted in CMS for $ENV{'PBDIR'} before creating a new version" if ($res != 0);
2465
2466 # Tree identical between PBCONFDIR and PBROOTDIR. The delta is what
2467 # we want to get for the root of the new URL
2468
2469 my $tmp = $ENV{'PBROOTDIR'};
2470 $tmp =~ s|^$ENV{'PBCONFDIR'}||;
2471
2472 my $newurl = "$uri/".dirname($tmp)."/$newver";
2473 # Should probably use projver in the old file
2474 my $oldver= basename($tmp);
2475
2476 # Duplicate and extract project-builder part
2477 pb_log(2,"Copying $uri/$tmp to $newurl\n");
2478 pb_cms_copy($scheme,"$uri/$tmp",$newurl);
2479 pb_log(2,"Checkout $newurl to $ENV{'PBROOTDIR'}/../$newver\n");
2480 pb_cms_up($scheme,"$ENV{'PBCONFDIR'}/..");
2481
2482 # Duplicate and extract project
2483 my $newurl2 = "$pburl->{$ENV{'PBPROJ'}}/".dirname($tmp)."/$newver";
2484
2485 pb_log(2,"Copying $pburl->{$ENV{'PBPROJ'}}/$tmp to $newurl2\n");
2486 pb_cms_copy($scheme2,"$pburl->{$ENV{'PBPROJ'}}/$tmp",$newurl2);
2487 pb_log(2,"Checkout $newurl2 to $ENV{'PBDIR'}/../$newver\n");
2488 pb_cms_up($scheme2,"$ENV{'PBDIR'}/..");
2489
2490 # Update the .pb file
2491 open(FILE,"$ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb") || die "Unable to open $ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb";
2492 open(OUT,"> $ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb.new") || die "Unable to write to $ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb.new";
2493 while(<FILE>) {
2494 s/^projver\s+$ENV{'PBPROJ'}\s*=\s*$oldver/projver $ENV{'PBPROJ'} = $newver/;
2495 pb_log(0,"Changing projver from $oldver to $newver in $ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb\n") if (/^projver\s+$ENV{'PBPROJ'}\s*=\s*$oldver/);
2496 pb_log(0,"Commenting testver in $ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb\n") if (/^testver/);
2497 s/^testver/#testver/;
2498 print OUT $_;
2499 pb_log(0,"Please check delivery (".chomp($_).") in $ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb\n") if (/^delivery/);
2500 }
2501 close(FILE);
2502 close(OUT);
2503 rename("$ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb.new","$ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb");
2504
2505 # Checking pbcl files
2506 foreach my $f (<$ENV{'PBROOTDIR'}/*/pbcl>) {
2507 # Compute new pbcl file
2508 my $f2 = $f;
2509 $f2 =~ s|$ENV{'PBROOTDIR'}|$ENV{'PBROOTDIR'}/../$newver/|;
2510 open(PBCL,$f) || die "Unable to open $f";
2511 my $foundnew = 0;
2512 while (<PBCL>) {
2513 $foundnew = 1 if (/^$newver \(/);
2514 }
2515 close(PBCL);
2516 open(OUT,"> $f2") || die "Unable to write to $f2: $!";
2517 open(PBCL,$f) || die "Unable to open $f";
2518 while (<PBCL>) {
2519 print OUT "$_" if (not /^$oldver \(/);
2520 if ((/^$oldver \(/) && ($foundnew == 0)) {
2521 print OUT "$newver ($pbdate)\n";
2522 print OUT "- TBD\n";
2523 print OUT "\n";
2524 pb_log(0,"WARNING: version $newver not found in $f so added to $f2...\n") if ($foundnew == 0);
2525 }
2526 }
2527 close(OUT);
2528 close(PBCL);
2529 }
2530
2531 pb_log(2,"Checkin $ENV{'PBROOTDIR'}/../$newver\n");
2532 pb_cms_checkin($scheme,"$ENV{'PBROOTDIR'}/../$newver",undef);
2533}
2534
2535#
2536# Return the list of VMs/VEs we are working on
2537# $all is a flag to know if we return all of them
2538# or only some (if all we publish also tar files in addition to pkgs
2539#
2540sub pb_get2v {
2541
2542my $vtype = shift;
2543my @v;
2544my $all = 0;
2545my $vlist;
2546my $pbv = 'PBV';
2547
2548if ($vtype eq "vm") {
2549 $vlist = "vmlist";
2550} elsif ($vtype eq "ve") {
2551 $vlist = "velist";
2552}
2553# Get VM/VE list
2554if ((not defined $ENV{$pbv}) || ($ENV{$pbv} =~ /^all$/)) {
2555 my ($ptr) = pb_conf_get($vlist);
2556 $ENV{$pbv} = $ptr->{$ENV{'PBPROJ'}};
2557 $all = 1;
2558}
2559pb_log(2,"$vtype: $ENV{$pbv}\n");
2560@v = split(/,/,$ENV{$pbv});
2561return(\@v,$all);
2562}
2563
2564# Function to create a potentialy missing pb account on the VM/VE, and adds it to sudo
2565# Needs to use root account to connect to the VM/VE
2566# pb will take your local public SSH key to access
2567# the pb account in the VM later on if needed
2568sub pb_setup2v {
2569
2570my $vtype = shift;
2571my $sbx = shift || undef;
2572
2573my ($vm,$all) = pb_get2v($vtype);
2574
2575# Script generated
2576my $pbscript = "$ENV{'PBDESTDIR'}/setupv";
2577
2578# Adapt // mode to memory size
2579$pbparallel = pb_set_parallel($vtype);
2580
2581my $pm = new Parallel::ForkManager($pbparallel) if (defined $pbparallel);
2582
2583# Set which port the VM will use to communicate
2584$pm->run_on_start(\&pb_set_port);
2585
2586my $counter = 0;
2587foreach my $v (@$vm) {
2588 $counter++;
2589 # Modulo pbparallel
2590 $counter = 1 if ($counter > $pbparallel);
2591 $pm->start($counter) and next if (defined $pbparallel);
2592
2593 # Deal with date sync.
2594 my ($ntpline,$dateline) = pb_date2v($vtype,$v);
2595
2596 # Get distro context
2597 my ($name,$ver,$darch) = split(/-/,$v);
2598 chomp($darch);
2599 my ($ddir, $dver, $dfam, $dtype, $dos, $pbsuf, $pbupd, $pbins) = pb_distro_init($name,$ver,$darch);
2600
2601 # Name of the account to deal with for VM/VE
2602 # Do not use the one passed potentially with -a
2603 my ($pbac) = pb_conf_get($vtype."login");
2604 my ($key,$zero0,$zero1,$zero2);
2605 my ($vmexist,$vmpid);
2606
2607 # Prepare the script to be executed on the VM/VE
2608 # in $ENV{'PBDESTDIR'}/setupv
2609 open(SCRIPT,"> $pbscript") || die "Unable to create $pbscript";
2610
2611 print SCRIPT << 'EOF';
2612#!/usr/bin/perl -w
2613
2614use strict;
2615use File::Copy;
2616
2617# We should not need in this script more functions than what is provided
2618# by Base, Conf and Distribution to avoid problems at exec time.
2619# They are appended at the end.
2620
2621# Define mandatory global vars
2622our $pbdebug;
2623our $pbLOG;
2624our $pbsynmsg = "pbscript";
2625our $pbdisplaytype = "text";
2626our $pblocale = "";
2627pb_log_init($pbdebug, $pbLOG);
2628pb_temp_init();
2629
2630EOF
2631
2632 # Launch the VM/VE - Usage of snapshot disabled
2633 ($vmexist,$vmpid) = pb_launchv($vtype,$v,0,0,0);
2634
2635 my $keyfile;
2636 my $nport;
2637 my $vmhost;
2638
2639 if ($vtype eq "vm") {
2640 # Prepare the key to be used and transfered remotely
2641 $keyfile = pb_ssh_get(1);
2642
2643 my ($vmport,$vmntp);
2644 ($vmhost,$vmport,$vmntp) = pb_conf_get("vmhost","vmport","vmntp");
2645 $nport = pb_get_port($vmport->{$ENV{'PBPROJ'}});
2646
2647 # Skip that VM if something went wrong
2648 next if (($vmpid == 0) && ($vmexist == 0));
2649
2650 # Store the pub key part in a variable
2651 open(FILE,"$keyfile.pub") || die "Unable to open $keyfile.pub";
2652 ($zero0,$zero1,$zero2) = split(/ /,<FILE>);
2653 close(FILE);
2654
2655 $key = "\Q$zero1";
2656
2657 # We call true to avoid problems if SELinux is not activated, but chcon is present and returns in that case 1
2658 pb_system("cat $keyfile.pub | ssh -q -o UserKnownHostsFile=/dev/null -p $nport -i $keyfile root\@$vmhost->{$ENV{'PBPROJ'}} \"mkdir -p .ssh ; chmod 700 .ssh ; cat >> .ssh/authorized_keys ; chmod 600 .ssh/authorized_keys ; if [ -x /usr/bin/chcon ]; then /usr/bin/chcon -Rt home_ssh_t .ssh 2> /dev/null; /bin/true; fi\"","Copying local keys to $vtype. This may require the root password");
2659 # once this is done, we can do what we want on the VM remotely
2660 } elsif ($vtype eq "ve") {
2661 print SCRIPT << "EOF";
2662# For VE we need a good null dev
2663pb_system("rm -f /dev/null; mknod /dev/null c 1 3; chmod 777 /dev/null");
2664EOF
2665 print SCRIPT << "EOF";
2666# For VE we first need to mount some FS
2667pb_system("mount -t proc /proc /proc");
2668
2669EOF
2670 }
2671
2672if ($vtype eq "vm") {
2673 print SCRIPT << 'EOF';
2674# Removes duplicate in .ssh/authorized_keys of our key if needed
2675#
2676my $file1="$ENV{'HOME'}/.ssh/authorized_keys";
2677open(PBFILE,$file1) || die "Unable to open $file1";
2678open(PBOUT,"> $file1.new") || die "Unable to open $file1.new";
2679my $count = 0;
2680while (<PBFILE>) {
2681
2682EOF
2683 print SCRIPT << "EOF";
2684 if (/ $key /) {
2685 \$count++;
2686 }
2687print PBOUT \$_ if ((\$count <= 1) || (\$_ !~ / $key /));
2688}
2689close(PBFILE);
2690close(PBOUT);
2691rename("\$file1.new",\$file1);
2692chmod 0600,\$file1;
2693
2694# Sync date
2695EOF
2696 if (defined $ntpline) {
2697 print SCRIPT "pb_system(\"$ntpline\");\n";
2698 } else {
2699 print SCRIPT "pb_system(\"$dateline\");\n";
2700 }
2701 }
2702 print SCRIPT << 'EOF';
2703
2704# Adds $pbac->{$ENV{'PBPROJ'}} as an account if needed
2705#
2706my $file="/etc/passwd";
2707open(PBFILE,$file) || die "Unable to open $file";
2708my $found = 0;
2709while (<PBFILE>) {
2710EOF
2711 print SCRIPT << "EOF";
2712 \$found = 1 if (/^$pbac->{$ENV{'PBPROJ'}}:/);
2713EOF
2714
2715my $home = "/home";
2716# Solaris doesn't like that we use /home
2717$home = "/export/home" if ($dtype eq "pkg");
2718
2719 print SCRIPT << "EOF";
2720}
2721close(PBFILE);
2722
2723if ( \$found == 0 ) {
2724 if ( ! -d "$home" ) {
2725 pb_mkdir_p("$home");
2726 }
2727EOF
2728 print SCRIPT << "EOF";
2729pb_system("/usr/sbin/groupadd $pbac->{$ENV{'PBPROJ'}}","Adding group $pbac->{$ENV{'PBPROJ'}}");
2730pb_system("/usr/sbin/useradd -g $pbac->{$ENV{'PBPROJ'}} -m -d $home/$pbac->{$ENV{'PBPROJ'}} $pbac->{$ENV{'PBPROJ'}}","Adding user $pbac->{$ENV{'PBPROJ'}} (group $pbac->{$ENV{'PBPROJ'}} - home $home/$pbac->{$ENV{'PBPROJ'}})");
2731}
2732EOF
2733
2734 # Copy the content of our local conf file to the VM/VE
2735 my $content = pb_get_content(pb_distro_conffile());
2736 print SCRIPT << "EOF";
2737 #
2738 # Create a temporary local conf file for distribution support
2739 # This is created here before its use later. Its place is hardcoded, so no choice for the path
2740 #
2741 my \$tempconf = pb_distro_conffile();
2742 pb_mkdir_p(dirname(\$tempconf));
2743 open(CONF,"> \$tempconf") || die "Unable to create \$tempconf";
2744 print CONF q{$content};
2745 close(CONF);
2746EOF
2747
2748 if ($vtype eq "vm") {
2749 print SCRIPT << "EOF";
2750# allow ssh entry to build
2751#
2752mkdir "$home/$pbac->{$ENV{'PBPROJ'}}/.ssh",0700;
2753# Allow those accessing root to access the build account
2754copy("\$ENV{'HOME'}/.ssh/authorized_keys","$home/$pbac->{$ENV{'PBPROJ'}}/.ssh/authorized_keys");
2755chmod 0600,".ssh/authorized_keys";
2756pb_system("chown -R $pbac->{$ENV{'PBPROJ'}}:$pbac->{$ENV{'PBPROJ'}} $home/$pbac->{$ENV{'PBPROJ'}}","Finish setting up the account env for $pbac->{$ENV{'PBPROJ'}}");
2757
2758EOF
2759}
2760 print SCRIPT << 'EOF';
2761# No passwd for build account only keys
2762$file="/etc/shadow";
2763if (-f $file) {
2764 open(PBFILE,$file) || die "Unable to open $file";
2765 open(PBOUT,"> $file.new") || die "Unable to open $file.new";
2766 while (<PBFILE>) {
2767EOF
2768 print SCRIPT << "EOF";
2769 s/^$pbac->{$ENV{'PBPROJ'}}:\!\!:/$pbac->{$ENV{'PBPROJ'}}:*:/;
2770 s/^$pbac->{$ENV{'PBPROJ'}}:\!:/$pbac->{$ENV{'PBPROJ'}}:*:/; #SLES 9 e.g.
2771 s/^$pbac->{$ENV{'PBPROJ'}}:\\*LK\\*:/$pbac->{$ENV{'PBPROJ'}}:NP:/; #Solaris e.g.
2772EOF
2773 print SCRIPT << 'EOF';
2774 print PBOUT $_;
2775 }
2776 close(PBFILE);
2777 close(PBOUT);
2778 rename("$file.new",$file);
2779 chmod 0640,$file;
2780 }
2781
2782# Keep the VM in text mode
2783$file="/etc/inittab";
2784if (-f $file) {
2785 open(PBFILE,$file) || die "Unable to open $file";
2786 open(PBOUT,"> $file.new") || die "Unable to open $file.new";
2787 while (<PBFILE>) {
2788 s/^(..):5:initdefault:$/$1:3:initdefault:/;
2789 print PBOUT $_;
2790 }
2791 close(PBFILE);
2792 close(PBOUT);
2793 rename("$file.new",$file);
2794 chmod 0640,$file;
2795}
2796
2797# pb has to be added to portage group on gentoo
2798
2799# We need to have that pb_distro_init function
2800# Get it from Project-Builder::Distribution
2801# And we now need the conf file required for this to work created above
2802
2803my ($ddir, $dver, $dfam, $dtype, $dos, $pbsuf, $pbupd, $pbins, $darch) = pb_distro_init();
2804print "distro tuple: ".join(',',($ddir, $dver, $dfam, $dtype, $pbsuf, $pbupd, $pbins, $darch))."\n";
2805
2806# Adapt sudoers
2807# sudo is not default on Solaris and needs to be installed first
2808# from http://www.sunfreeware.com/programlistsparc10.html#sudo
2809if ($dtype eq "pkg") {
2810 $file="/usr/local/etc/sudoers";
2811} else {
2812 $file="/etc/sudoers";
2813}
2814open(PBFILE,$file) || die "Unable to open $file";
2815open(PBOUT,"> $file.new") || die "Unable to open $file.new";
2816while (<PBFILE>) {
2817EOF
2818 print SCRIPT << "EOF";
2819 next if (/^$pbac->{$ENV{'PBPROJ'}} /);
2820EOF
2821 print SCRIPT << 'EOF';
2822 s/Defaults[ \t]+requiretty//;
2823 print PBOUT $_;
2824}
2825close(PBFILE);
2826EOF
2827 print SCRIPT << "EOF";
2828# Some distro force requiretty at compile time, so disable here
2829print PBOUT "Defaults:$pbac->{$ENV{'PBPROJ'}} !requiretty\n";
2830print PBOUT "Defaults:root !requiretty\n";
2831# This is needed in order to be able to halt the machine from the $pbac->{$ENV{'PBPROJ'}} account at least
2832print PBOUT "Defaults:$pbac->{$ENV{'PBPROJ'}} env_keep += \\\"http_proxy ftp_proxy\\\"\n";
2833print PBOUT "$pbac->{$ENV{'PBPROJ'}} ALL=(ALL) NOPASSWD:ALL\n";
2834EOF
2835 print SCRIPT << 'EOF';
2836close(PBOUT);
2837rename("$file.new",$file);
2838chmod 0440,$file;
2839
2840EOF
2841
2842 # We may need a proxy configuration. Get it from the local env
2843
2844 if (defined $ENV{'http_proxy'}) {
2845 print SCRIPT "\$ENV\{'http_proxy'\}=\"$ENV{'http_proxy'}\";\n";
2846 }
2847
2848 if (defined $ENV{'ftp_proxy'}) {
2849 print SCRIPT "\$ENV\{'ftp_proxy'\}=\"$ENV{'ftp_proxy'}\";\n";
2850 }
2851
2852 print SCRIPT << 'EOF';
2853
2854# Suse wants sudoers as 640
2855if ((($ddir eq "sles") && (($dver =~ /10/) || ($dver =~ /9/))) || (($ddir eq "opensuse") && ($dver =~ /10.[012]/))) {
2856 chmod 0640,$file;
2857}
2858
2859# First install all required packages
2860pb_system("yum clean all","Cleaning yum env") if (($ddir eq "fedora") || ($ddir eq "asianux") || ($ddir eq "rhel"));
2861my ($ospkgdep) = pb_conf_get_if("ospkgdep");
2862
2863my $pkgdep = pb_distro_get_param($ddir,$dver,$darch,$ospkgdep,$dfam,$dtype,$dos);
2864pb_distro_installdeps(undef,$dtype,$pbins,pb_distro_only_deps_needed($dtype,join(' ',split(/,/,$pkgdep))));
2865
2866EOF
2867 my ($instype) = pb_conf_get("pbinstalltype");
2868 my $itype = pb_distro_get_param($ddir,$dver,$darch,$instype,$dfam,$dtype,$dos);
2869 if (defined $sbx) {
2870 # Install from sandbox mean a file base install
2871 $itype = "file";
2872 }
2873 if ($itype =~ /^file/) {
2874 my $cmdget;
2875 if (defined $sbx) {
2876 # Install from sandbox mean using the result of the just passed sbx2build command
2877 # Get content saved in cms2build
2878 my ($pkg) = pb_conf_read("$ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb","pbpkg");
2879 die "Unable to get package list" if (not defined $pkg);
2880
2881 # We consider 2 specific packages
2882 my $vertag1 = $pkg->{"ProjectBuilder"};
2883 my $vertag2 = $pkg->{"project-builder"};
2884 # get the version of the current package - maybe different
2885 my ($pbver1,$tmp1) = split(/-/,$vertag1);
2886 my ($pbver2,$tmp2) = split(/-/,$vertag2);
2887 # Copy inside the VE
2888 if ($vtype eq "ve") {
2889 my ($vepath) = pb_conf_get("vepath");
2890 copy("$ENV{'PBDESTDIR'}/ProjectBuilder-$pbver1.tar.gz","$vepath->{$ENV{'PBPROJ'}}/$ddir/$dver/$darch/tmp");
2891 copy("$ENV{'PBDESTDIR'}/project-builder-$pbver2.tar.gz","$vepath->{$ENV{'PBPROJ'}}/$ddir/$dver/$darch/tmp");
2892 } else {
2893 pb_system("scp -i $keyfile -p -o UserKnownHostsFile=/dev/null -P $nport $ENV{'PBDESTDIR'}/ProjectBuilder-$pbver1.tar.gz $ENV{'PBDESTDIR'}/project-builder-$pbver2.tar.gz root\@$vmhost->{$ENV{'PBPROJ'}}:/tmp","Copying local project files to $vtype.");
2894 }
2895 $cmdget = "mv /tmp/ProjectBuilder-$pbver1.tar.gz ProjectBuilder-latest.tar.gz ; mv /tmp/project-builder-$pbver2.tar.gz project-builder-latest.tar.gz";
2896 } else {
2897 $cmdget = "wget --passive-ftp ftp://ftp.project-builder.org/src/ProjectBuilder-latest.tar.gz; wget --passive-ftp ftp://ftp.project-builder.org/src/project-builder-latest.tar.gz";
2898 }
2899 print SCRIPT << 'EOF';
2900# Then install manually the missing perl modules
2901my ($osperldep,$osperlver) = pb_conf_get_if("osperldep","osperlver");
2902
2903my $perldep = pb_distro_get_param($ddir,$dver,$darch,$osperldep,$dfam,$dtype,$dos);
2904foreach my $m (split(/,/,$perldep)) {
2905 # Skip empty deps
2906 next if ($m =~ /^\s*$/);
2907 my $dir = $m;
2908 $dir =~ s/-.*//;
2909 pb_system("echo \"rm -rf $m* ; wget http://search.cpan.org/CPAN/modules/by-module/$dir/$m-$osperlver->{$m}.tar.gz ; gzip -cd $m-$osperlver->{$m}.tar.gz | tar xf - ; cd $m* ; if [ -f Build.PL ]; then perl Build.PL; ./Build ; ./Build install ; else perl Makefile.PL; make ; make install ; fi; cd .. ; rm -rf $m*\" | bash" ,"Installing perl module $m-$osperlver->{$m}");
2910}
2911EOF
2912
2913 print SCRIPT << "EOF";
2914pb_system("rm -rf ProjectBuilder-* ; rm -rf project-builder-* ; $cmdget ; gzip -cd ProjectBuilder-latest.tar.gz | tar xf - ; cd ProjectBuilder-* ; perl Makefile.PL ; make ; make install ; cd .. ; rm -rf ProjectBuilder-* ; gzip -cd project-builder-latest.tar.gz | tar xf - ; cd project-builder-* ; perl Makefile.PL ; make ; make install ; cd .. ; rm -rf project-builder-* ;","Building Project-Builder");
2915EOF
2916 } elsif ($itype =~ /^pkg/) {
2917 # pkg based install. We need to point to the project-builder.org repository
2918 print SCRIPT << 'EOF';
2919my ($ospkg) = pb_conf_get_if("ospkg");
2920
2921my $pkgforpb = pb_distro_get_param($ddir,$dver,$darch,$ospkg,$dfam,$dtype,$dos);
2922pb_distro_setuposrepo($ddir,$dver,$darch,$dtype,$dfam,$dos);
2923pb_distro_installdeps(undef,$dtype,$pbins,pb_distro_only_deps_needed($dtype,join(' ',split(/,/,$pkgforpb))));
2924EOF
2925 } else {
2926 # Unknown install type
2927 die("Unknown install type $itype->{$ENV{'PBPROJ'}} for param pbinstalltype");
2928 }
2929 print SCRIPT << 'EOF';
2930pb_system("pb 2>&1 | head -5",undef,"verbose");
2931EOF
2932 if ($vtype eq "ve") {
2933 print SCRIPT << 'EOF';
2934# For VE we need to umount some FS at the end
2935
2936pb_system("umount /proc");
2937
2938# Create a basic network file if not already there
2939
2940my $nf="/etc/sysconfig/network";
2941if ((! -f $nf) && ($dtype eq "rpm")) {
2942 open(NF,"> $nf") || die "Unable to create $nf";
2943 print NF "NETWORKING=yes\n";
2944 print NF "HOSTNAME=localhost\n";
2945 close(NF);
2946}
2947chmod 0755,$nf;
2948EOF
2949 }
2950
2951 # Adds pb_distro_init and all functions needed from ProjectBuilder::Distribution, Conf and Base
2952 foreach my $d (@INC) {
2953 my @f = ("$d/ProjectBuilder/Base.pm","$d/ProjectBuilder/Distribution.pm","$d/ProjectBuilder/Conf.pm");
2954 foreach my $f (@f) {
2955 if (-f "$f") {
2956 open(PBD,"$f") || die "Unable to open $f";
2957 while (<PBD>) {
2958 next if (/^package/);
2959 next if (/^use Exporter/);
2960 next if (/^use ProjectBuilder::/);
2961 next if (/^our /);
2962 print SCRIPT $_;
2963 }
2964 close(PBD);
2965 }
2966 }
2967 }
2968 # Use a fake pb_version_init version here
2969 print SCRIPT << "EOF";
2970sub pb_version_init {
2971
2972return("$projectbuilderver","$projectbuilderrev");
2973}
29741;
2975EOF
2976 close(SCRIPT);
2977 chmod 0755,"$pbscript";
2978
2979 # That build script needs to be run as root and force stop of VM at end
2980 $pbaccount = "root";
2981
2982 # Force shutdown of VM except if it was already launched
2983 my $pbforce = 0;
2984 if ((! $vmexist) && ($vtype eq "vm")) {
2985 $pbforce = 1;
2986 }
2987
2988 pb_script2v($pbscript,$vtype,$pbforce,$v);
2989 $pm->finish if (defined $pbparallel);
2990}
2991if (defined $pbparallel) {
2992 $pm->wait_all_children;
2993}
2994return;
2995}
2996
2997# Function to create a snapshot named 'pb' for VMs and a compressed tar for VEs
2998sub pb_snap2v {
2999
3000my $vtype = shift;
3001
3002my ($vm,$all) = pb_get2v($vtype);
3003
3004# Script generated
3005my $pbscript = "$ENV{'PBDESTDIR'}/snapv";
3006
3007my ($pbac) = pb_conf_get($vtype."login");
3008
3009foreach my $v (@$vm) {
3010 if ($vtype eq "ve") {
3011 # Get distro context
3012 my ($name,$ver,$darch) = split(/-/,$v);
3013 chomp($darch);
3014 my ($ddir, $dver, $dfam, $dtype, $dos, $pbsuf) = pb_distro_init($name,$ver,$darch);
3015 my ($vepath) = pb_conf_get("vepath");
3016
3017 # Test if an existing snapshot exists and remove it if there is a VE
3018 if ((-f "$vepath->{$ENV{'PBPROJ'}}/$ddir-$dver-$darch.tar.gz") &&
3019 (! -d "$vepath->{$ENV{'PBPROJ'}}/$ddir/$dver/$darch")) {
3020 pb_system("sudo rm -f $vepath->{$ENV{'PBPROJ'}}/$ddir-$dver-$darch.tar.gz","Removing previous snapshot $ddir-$dver-$darch.tar.gz");
3021 }
3022 }
3023
3024 # Prepare the script to be executed on the VM/VE
3025 open(SCRIPT,"> $pbscript") || die "Unable to create $pbscript";
3026 print SCRIPT << 'EOF';
3027 #!/bin/bash
3028 sleep 2
3029EOF
3030 close(SCRIPT);
3031 chmod 0755,"$pbscript";
3032
3033 # Force shutdown of VM/VE
3034 # Force snapshot of VM/VE
3035 pb_script2v($pbscript,$vtype,1,$v,1);
3036}
3037return;
3038}
3039
3040# Function to update a VMs or VEs with the latest distribution content
3041sub pb_update2v {
3042
3043my $vtype = shift;
3044
3045my ($vm,$all) = pb_get2v($vtype);
3046
3047# Script generated
3048my $pbscript = "$ENV{'PBDESTDIR'}/updatev";
3049
3050my ($pbac) = pb_conf_get($vtype."login");
3051
3052foreach my $v (@$vm) {
3053 # Get distro context
3054 my ($name,$ver,$darch) = split(/-/,$v);
3055 chomp($darch);
3056 my ($ddir, $dver, $dfam, $dtype, $dos, $pbsuf, $pbupd, $pbins) = pb_distro_init($name,$ver,$darch);
3057
3058 # Prepare the script to be executed on the VM/VE
3059 # in $ENV{'PBDESTDIR'}/updatev
3060 open(SCRIPT,"> $pbscript") || die "Unable to create $pbscript";
3061
3062 print SCRIPT << 'EOF';
3063 #!/bin/bash
3064 sleep 2
3065EOF
3066 # VE needs a good /proc
3067 if ($vtype eq "ve") {
3068 print SCRIPT "sudo mount -t proc /proc /proc\n";
3069 }
3070 print SCRIPT "$pbupd\n";
3071 if ($vtype eq "ve") {
3072 print SCRIPT "sudo umount /proc\n";
3073 }
3074 close(SCRIPT);
3075 chmod 0755,"$pbscript";
3076
3077 # Force shutdown of VM except
3078 pb_script2v($pbscript,$vtype,1,$v);
3079}
3080return;
3081}
3082
3083sub pb_announce {
3084
3085 # Get all required parameters
3086 my ($pbpackager,$pbrepo,$pbml,$pbsmtp) = pb_conf_get("pbpackager","pbrepo","pbml","pbsmtp");
3087 my ($pkgv, $pkgt, $testver) = pb_conf_get_if("pkgver","pkgtag","testver");
3088 my $pkg = pb_cms_get_pkg($defpkgdir,$extpkgdir);
3089 my @pkgs = @$pkg;
3090 my %pkgs;
3091 my $first = 0;
3092
3093 # Command to find packages on repo
3094 my $findstr = "find . ";
3095 # Generated announce files
3096 my @files;
3097
3098 foreach my $pbpkg (@pkgs) {
3099 if ($first != 0) {
3100 $findstr .= "-o ";
3101 }
3102 $first++;
3103 if ((defined $pkgv) && (defined $pkgv->{$pbpkg})) {
3104 $pbver = $pkgv->{$pbpkg};
3105 } else {
3106 $pbver = $ENV{'PBPROJVER'};
3107 }
3108 if ((defined $pkgt) && (defined $pkgt->{$pbpkg})) {
3109 $pbtag = $pkgt->{$pbpkg};
3110 } else {
3111 $pbtag = $ENV{'PBPROJTAG'};
3112 }
3113
3114 # TODO: use virtual/real names here now
3115 $findstr .= "-name \'$pbpkg-$pbver-$pbtag\.*.rpm\' -o -name \'$pbpkg"."_$pbver*\.deb\' -o -name \'$pbpkg-$pbver*\.ebuild\' ";
3116
3117 my $chglog;
3118
3119 # Get project info on log file and generate tmp files used later on
3120 pb_cms_init($pbinit);
3121 $chglog = "$ENV{'PBROOTDIR'}/$pbpkg/pbcl";
3122 $chglog = "$ENV{'PBROOTDIR'}/pbcl" if (! -f $chglog);
3123 $chglog = undef if (! -f $chglog);
3124
3125 open(OUT,"> $ENV{'PBTMP'}/$pbpkg.ann") || die "Unable to create $ENV{'PBTMP'}/$pbpkg.ann: $!";
3126 my %pb;
3127 $pb{'dtype'} = "announce";
3128 $pb{'realpkg'} = $pbpkg;
3129 $pb{'ver'} = $pbver;
3130 $pb{'tag'} = $pbtag;
3131 $pb{'suf'} = "N/A"; # Should not be empty even if unused
3132 $pb{'date'} = $pbdate;
3133 $pb{'chglog'} = $chglog;
3134 $pb{'packager'} = $pbpackager;
3135 $pb{'proj'} = $ENV{'PBPROJ'};
3136 $pb{'repo'} = $pbrepo;
3137 pb_changelog(\%pb,\*OUT,"yes");
3138 close(OUT);
3139 push(@files,"$ENV{'PBTMP'}/$pbpkg.ann");
3140 }
3141 $findstr .= " | grep -Ev \'src.rpm\'";
3142
3143 # Prepare the command to run and execute it
3144 open(PBS,"> $ENV{'PBTMP'}/pbscript") || die "Unable to create $ENV{'PBTMP'}/pbscript";
3145 print PBS "$findstr\n";
3146 close(PBS);
3147 chmod 0755,"$ENV{'PBTMP'}/pbscript";
3148 pb_send2target("Announce");
3149
3150 # Get subject line
3151 my $sl = "Project $ENV{'PBPROJ'} version $ENV{'PBPROJVER'} is now available";
3152 pb_log(0,"Please enter the title of your announce\n");
3153 pb_log(0,"(By default: $sl)\n");
3154 my $sl2 = <STDIN>;
3155 $sl = $sl2 if ($sl2 !~ /^$/);
3156
3157 # Prepare a template of announce
3158 open(ANN,"> $ENV{'PBTMP'}/announce.html") || die "Unable to create $ENV{'PBTMP'}/announce.html: $!";
3159 print ANN << "EOF";
3160$sl</p>
3161
3162<p>The project team is happy to announce the availability of a newest version of $ENV{'PBPROJ'} $ENV{'PBPROJVER'}. Enjoy it as usual!</p>
3163<p>
3164Now available at <a href="$pbrepo->{$ENV{'PBPROJ'}}">$pbrepo->{$ENV{'PBPROJ'}}</a>
3165</p>
3166<p>
3167EOF
3168 open(LOG,"$ENV{'PBTMP'}/system.$$.log") || die "Unable to read $ENV{'PBTMP'}/system.$$.log: $!";
3169 my $col = 2;
3170 my $i = 1;
3171 print ANN << 'EOF';
3172<TABLE WIDTH="700" CELLPADDING="0" CELLSPACING="0" BORDER="0">
3173<TR>
3174EOF
3175 while (<LOG>) {
3176 print ANN "<TD><A HREF=\"$pbrepo->{$ENV{'PBPROJ'}}/$_\">$_</A></TD>";
3177 $i++;
3178 if ($i > $col) {
3179 print ANN "</TR>\n<TR>";
3180 $i = 1;
3181 }
3182 }
3183 close(LOG);
3184 print ANN << "EOF";
3185</TR>
3186</TABLE>
3187</p>
3188
3189<p>As usual source packages are also available in the same directory.</p>
3190
3191<p>
3192Changes are :
3193</p>
3194<p>
3195EOF
3196 # Get each package changelog content
3197 foreach my $f (sort(@files)) {
3198 open(IN,"$f") || die "Unable to read $f:$!";
3199 while (<IN>) {
3200 print ANN $_;
3201 }
3202 close(IN);
3203 print ANN "</p><p>\n";
3204 }
3205 print ANN "</p>\n";
3206 close(ANN);
3207
3208 # Allow for modification
3209 my $editor = "vi";
3210 $editor = $ENV{'EDITOR'} if (defined $ENV{'EDITOR'});
3211 pb_system("$editor $ENV{'PBTMP'}/announce.html","Allowing modification of the announce","noredir");
3212
3213 # Store it in DB for external usage (Web pages generation)
3214 my $db = "$ENV{'PBCONFDIR'}/announces3.sql";
3215
3216 my $precmd = "";
3217 if (! -f $db) {
3218 $precmd = "CREATE TABLE announces (id INTEGER PRIMARY KEY AUTOINCREMENT, date DATE, announce VARCHAR[65535])";
3219 }
3220
3221 my $dbh = DBI->connect("dbi:SQLite:dbname=$db","","",
3222 { RaiseError => 1, AutoCommit => 1 })
3223 || die "Unable to connect to $db";
3224
3225 if ($precmd ne "") {
3226 my $sth = $dbh->prepare(qq{$precmd})
3227 || die "Unable to create table into $db";
3228 $sth->execute();
3229 }
3230
3231 # To read whole file
3232 local $/;
3233 open(ANN,"$ENV{'PBTMP'}/announce.html") || die "Unable to read $ENV{'PBTMP'}/announce.html: $!";
3234 my $announce = <ANN>;
3235 close(ANN);
3236
3237 pb_log(2,"INSERT INTO announces VALUES (NULL, $pbdate, $announce)");
3238 my $sth = $dbh->prepare(qq{INSERT INTO announces VALUES (NULL,?,?)})
3239 || die "Unable to insert into $db";
3240 $sth->execute($pbdate, $announce);
3241 $sth->finish();
3242 $dbh->disconnect;
3243
3244 # Then deliver it on the Web
3245 # $TOOLHOME/livwww www
3246
3247 # Mail it to project's ML
3248 open(ML,"| w3m -dump -T text/html > $ENV{'PBTMP'}/announce.txt") || die "Unable to create $ENV{'PBTMP'}/announce.txt: $!";
3249 print ML << 'EOF';
3250<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/x html1/DTD/xhtml1-strict.dtd">
3251
3252<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" xml:lang="en" lang="en">
3253 <head>
3254 </head>
3255 <body>
3256 <p>
3257EOF
3258 open(ANN,"$ENV{'PBTMP'}/announce.html") || die "Unable to read $ENV{'PBTMP'}/announce.html: $!";
3259 while(<ANN>) {
3260 print ML $_;
3261 }
3262 print ML << 'EOF';
3263</body>
3264</html>
3265EOF
3266 close(ML);
3267
3268 # To read whole file
3269 local $/;
3270 open(ANN,"$ENV{'PBTMP'}/announce.txt") || die "Unable to read $ENV{'PBTMP'}/announce.txt: $!";
3271 my $msg = <ANN>;
3272 close(ANN);
3273
3274 # Preparation of headers
3275 eval
3276 {
3277 require Mail::Sendmail;
3278 Mail::Sendmail->import();
3279 };
3280 if ($@) {
3281 # Mail::Sendmail not found not sending mail !
3282 pb_log(0,"No Mail::Sendmail module found so not sending any mail !\n");
3283 } else {
3284 my %mail = (
3285 To => $pbml->{$ENV{'PBPROJ'}},
3286 From => $pbpackager->{$ENV{'PBPROJ'}},
3287 Smtp => $pbsmtp->{$ENV{'PBPROJ'}},
3288 Body => $msg,
3289 Subject => "[ANNOUNCE] $sl",
3290 );
3291
3292 # Send mail
3293 if (! sendmail(%mail)) {
3294 if ((defined $Mail::Sendmail::error) and (defined $Mail::Sendmail::log)) {
3295 die "Unable to send mail ($Mail::Sendmail::error): $Mail::Sendmail::log";
3296 }
3297 }
3298 }
3299}
3300
3301#
3302# Creates a set of HTML file containing the news for the project
3303# based on what has been generated by the pb_announce function
3304#
3305sub pb_web_news2html {
3306
3307 my $dest = shift || $ENV{'PBTMP'};
3308
3309 # Get all required parameters
3310 my ($pkgv, $pkgt) = pb_conf_get_if("pkgver","pkgtag");
3311
3312 # DB of announces for external usage (Web pages generation)
3313 my $db = "$ENV{'PBCONFDIR'}/announces3.sql";
3314
3315 my $dbh = DBI->connect("dbi:SQLite:dbname=$db","","",
3316 { RaiseError => 1, AutoCommit => 1 })
3317 || die "Unable to connect to $db";
3318 # For date handling
3319 $ENV{LANGUAGE}="C";
3320 my $firstjan = strftime("%Y-%m-%d", 0, 0, 0, 1, 0, localtime->year(), 0, 0, -1);
3321 my $oldfirst = strftime("%Y-%m-%d", 0, 0, 0, 1, 0, localtime->year()-1, 0, 0, -1);
3322 pb_log(2,"firstjan: $firstjan, oldfirst: $oldfirst, pbdate:$pbdate\n");
3323 my $all = $dbh->selectall_arrayref("SELECT id,date,announce FROM announces ORDER BY date DESC");
3324 my %news;
3325 $news{"cy"} = ""; # current year's news
3326 $news{"ly"} = ""; # last year news
3327 $news{"py"} = ""; # previous years news
3328 $news{"fp"} = ""; # first page news
3329 my $cpt = 4; # how many news for first page
3330 # Extract info from DB
3331 foreach my $row (@$all) {
3332 my ($id, $date, $announce) = @$row;
3333 $news{"cy"} = $news{"cy"}."<p><B>$date</B> $announce\n" if ((($date cmp $pbdate) le 0) && (($firstjan cmp $date) le 0));
3334 $news{"ly"} = $news{"ly"}."<p><B>$date</B> $announce\n" if ((($date cmp $firstjan) le 0) && (($oldfirst cmp $date) le 0));
3335 $news{"py"} = $news{"py"}."<p><B>$date</B> $announce\n" if (($date cmp $oldfirst) le 0);
3336 $news{"fp"} = $news{"fp"}."<p><B>$date</B> $announce\n" if ($cpt > 0);
3337 $cpt--;
3338 }
3339 pb_log(1,"news{fp}: ".$news{"fp"}."\n");
3340 $dbh->disconnect;
3341
3342 # Generate the HTML content
3343 foreach my $pref (keys %news) {
3344 open(NEWS,"> $dest/pb_web_$pref"."news.html") || die "Unable to create $dest/pb_web_$pref"."news.html: $!";
3345 print NEWS "$news{$pref}";
3346 close(NEWS);
3347 }
3348}
3349
3350
3351# Return the SSH key file to use
3352# Potentially create it if needed
3353
3354sub pb_ssh_get {
3355
3356my $create = shift || 0; # Do not create keys by default
3357
3358# Check the SSH environment
3359my $keyfile = undef;
3360
3361# We have specific keys by default
3362$keyfile = "$ENV{'HOME'}/.ssh/pb_dsa";
3363if (!(-e $keyfile) && ($create eq 1)) {
3364 pb_system("ssh-keygen -q -b 1024 -N '' -f $keyfile -t dsa","Generating SSH keys for pb");
3365}
3366
3367$keyfile = "$ENV{'HOME'}/.ssh/id_rsa" if (-s "$ENV{'HOME'}/.ssh/id_rsa");
3368$keyfile = "$ENV{'HOME'}/.ssh/id_dsa" if (-s "$ENV{'HOME'}/.ssh/id_dsa");
3369$keyfile = "$ENV{'HOME'}/.ssh/pb_dsa" if (-s "$ENV{'HOME'}/.ssh/pb_dsa");
3370die "Unable to find your public ssh key under $keyfile" if (not defined $keyfile);
3371return($keyfile);
3372}
3373
3374
3375# Returns the pid of a running VM command using a specific VM file
3376sub pb_check_ps {
3377 my $vmcmd = shift;
3378 my $vmm = shift;
3379 my $vmexist = 0; # FALSE by default
3380
3381 open(PS, "ps auxhww|") || die "Unable to call ps";
3382 while (<PS>) {
3383 next if (! /$vmcmd/);
3384 next if (! /$vmm/);
3385 my ($void1, $void2);
3386 ($void1, $vmexist, $void2) = split(/ +/);
3387 last;
3388 }
3389 return($vmexist);
3390}
3391
3392
3393sub pb_extract_build_files {
3394
3395my $src=shift;
3396my $dir=shift;
3397my $ddir=shift;
3398my $mandatory=shift || "spec";
3399my @files;
3400
3401my $flag = "mayfail" if ($mandatory eq "patch");
3402my $res;
3403
3404if ($src =~ /tar\.gz$/) {
3405 $res = pb_system("tar xfpz $src $dir","Extracting $mandatory files from $src",$flag);
3406} elsif ($src =~ /tar\.bz2$/) {
3407 $res = pb_system("tar xfpj $src $dir","Extracting $mandatory files from $src",$flag);
3408} else {
3409 die "Unknown compression algorithm for $src";
3410}
3411# If not mandatory return now
3412return() if (($res != 0) and ($mandatory eq "patch"));
3413opendir(DIR,"$dir") || die "Unable to open directory $dir";
3414foreach my $f (readdir(DIR)) {
3415 next if ($f =~ /^\./);
3416 # Skip potential patch dir
3417 next if ($f =~ /^pbpatch/);
3418 move("$dir/$f","$ddir") || die "Unable to move $dir/$f to $ddir";
3419 pb_log(2,"mv $dir/$f $ddir\n");
3420 push @files,"$ddir/$f";
3421}
3422closedir(DIR);
3423# Not enough but still a first cleanup
3424pb_rm_rf("$dir");
3425return(@files);
3426}
3427
3428sub pb_list_bfiles {
3429
3430my $dir = shift;
3431my $pbpkg = shift;
3432my $bfiles = shift;
3433my $pkgfiles = shift;
3434my $supfiles = shift;
3435
3436opendir(BDIR,"$dir") || die "Unable to open dir $dir: $!";
3437foreach my $f (readdir(BDIR)) {
3438 next if ($f =~ /^\./);
3439 if (-d $f) {
3440 # Recurse for directories (Debian 3.0 format e.g.)
3441 pb_list_bfiles($f,$pbpkg,$bfiles,$pkgfiles,$supfiles);
3442 next;
3443 }
3444 $bfiles->{$f} = "$dir/$f";
3445 $bfiles->{$f} =~ s~$ENV{'PBROOTDIR'}~~;
3446 if (defined $supfiles->{$pbpkg}) {
3447 $pkgfiles->{$f} = "$dir/$f" if ($f =~ /$supfiles->{$pbpkg}/);
3448 }
3449}
3450closedir(BDIR);
3451}
3452
3453sub pb_list_sfiles {
3454
3455my $sdir = shift;
3456my $sources = shift;
3457my $dtype = shift;
3458my $dfam = shift;
3459my $ddir = shift;
3460my $dver = shift;
3461my $arch = shift;
3462my $extdir = shift;
3463
3464# Prepare local sources for this distro - They are always applied first - May be a problem one day
3465# This function works for both patches and additional sources
3466foreach my $p (sort(<$sdir/*>)) {
3467 $sources->{"$ddir-$dver-$arch"} .= "," if ((defined $sources->{"$ddir-$dver-$arch"}) and ($p =~ /\.all$/));
3468 $sources->{"$ddir-$dver-$arch"} .= "file://$p" if ($p =~ /\.all$/);
3469 $sources->{"$ddir-$dver-$arch"} .= "," if ((defined $sources->{"$ddir-$dver-$arch"}) and ($p =~ /\.$dtype$/));
3470 $sources->{"$ddir-$dver-$arch"} .= "file://$p" if ($p =~ /\.$dtype$/);
3471 $sources->{"$ddir-$dver-$arch"} .= "," if ((defined $sources->{"$ddir-$dver-$arch"}) and ($p =~ /\.$dfam$/));
3472 $sources->{"$ddir-$dver-$arch"} .= "file://$p" if ($p =~ /\.$dfam$/);
3473 $sources->{"$ddir-$dver-$arch"} .= "," if ((defined $sources->{"$ddir-$dver-$arch"}) and ($p =~ /\.$ddir$/));
3474 $sources->{"$ddir-$dver-$arch"} .= "file://$p" if ($p =~ /\.$ddir$/);
3475 $sources->{"$ddir-$dver-$arch"} .= "," if ((defined $sources->{"$ddir-$dver-$arch"}) and ($p =~ /\.$ddir-$dver$/));
3476 $sources->{"$ddir-$dver-$arch"} .= "file://$p" if ($p =~ /\.$ddir-$dver$/);
3477 $sources->{"$ddir-$dver-$arch"} .= "," if ((defined $sources->{"$ddir-$dver-$arch"}) and ($p =~ /\.$ddir-$dver-$arch$/));
3478 $sources->{"$ddir-$dver-$arch"} .= "file://$p" if ($p =~ /\.$ddir-$dver-$arch$/);
3479}
3480
3481# Prepare also remote sources to be included - Applied after the local ones
3482foreach my $p ("all","$dtype","$dfam","$ddir","$ddir-$dver","$ddir-$dver-$arch") {
3483 my $f = "$extdir.".".$p";
3484 next if (not -f $f);
3485 if (not open(PATCH,$f)) {
3486 pb_display("Unable to open existing external source file content $f\n");
3487 next;
3488 }
3489 while (<PATCH>) {
3490 chomp();
3491 $sources->{"$ddir-$dver-$arch"} .= "," if (defined $sources->{"$ddir-$dver-$arch"});
3492 $sources->{"$ddir-$dver-$arch"} .= "$_";
3493 }
3494 close(PATCH);
3495}
3496pb_log(2,"DEBUG: sources: ".Dumper($sources)."\n");
3497}
3498
3499#
3500# Return the list of packages we are working on in a non CMS action
3501#
3502sub pb_get_pkg {
3503
3504my @pkgs = ();
3505
3506my ($var) = pb_conf_read("$ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb","pbpkg");
3507@pkgs = keys %$var;
3508
3509pb_log(0,"Packages: ".join(',',@pkgs)."\n");
3510return(\@pkgs);
3511}
3512
3513#
3514# Return the postinstall line if needed
3515#
3516
3517sub pb_get_postinstall {
3518
3519my $ddir = shift;
3520my $dver = shift;
3521my $darch = shift;
3522my $rbspi = shift;
3523my $vestyle = shift;
3524my $post = "";
3525
3526# Do we have a local post-install script
3527if ($vestyle eq "rinse") {
3528 $post = "--post-install ";
3529} elsif ($vestyle eq "rpmbootstrap") {
3530 $post = "-s ";
3531}
3532
3533my $postparam = pb_distro_get_param($ddir,$dver,$darch,$rbspi);
3534if ($postparam eq "") {
3535 $post = "";
3536} else {
3537 $post .= $postparam;
3538}
3539return($post);
3540}
3541
3542# Manages VM SSH port communication
3543sub pb_get_port {
3544
3545my $port = shift;
3546my $cmt = shift;
3547
3548die "No port passed in parameter. Report to dev team\n" if (not defined $port);
3549pb_log(2,"pb_get_port with $port\n");
3550my $nport = $port;
3551# Maybe a port was given as parameter so overwrite
3552$nport = "$pbport" if (defined $pbport);
3553# Maybe in // mode so use the env var set up as an offset to the base port, except when called from send2target for Packages
3554if ((not defined $cmt) || ($cmt ne "Packages")) {
3555 $nport += $ENV{'PBVMPORT'} if ((defined $pbparallel) && (defined $ENV{'PBVMPORT'}));
3556}
3557pb_log(2,"pb_get_port returns $nport\n");
3558return($nport);
3559}
3560
3561sub pb_set_port {
3562
3563my ($pid,$ident) = @_;
3564pb_log(2,"pb_set_port for VM ($pid), id $ident\n");
3565$ENV{'PBVMPORT'} = $ident;
3566pb_log(2,"pb_set_port sets PBVMPORT in env to $ENV{'PBVMPORT'}\n");
3567}
3568
3569sub pb_set_parallel {
3570
3571my $vtype = shift;
3572
3573pb_log(2,"pb_set_parallel vtype: $vtype\n");
3574# Take care of memory size if VM, parallel mode and more than 1 action
3575if ((defined $pbparallel) && ($pbparallel ne 1) && ($vtype eq "vm")) {
3576 eval
3577 {
3578 require Linux::SysInfo;
3579 Linux::SysInfo->import();
3580 };
3581 if ($@) {
3582 # Linux::SysInfo not found
3583 pb_log(1,"ADVISE: Install Linux::SysInfo to benefit from automatic parallelism optimization.\nOr optimize manually pbparallel in your pb.conf file\nUsing $pbparallel processes max at a time for the moment\nWARNING: This may consume too much memory for your system");
3584 } else {
3585 # Using the memory size
3586 my $si = Linux::SysInfo::sysinfo();
3587 if (not defined $si) {
3588 pb_log(1,"ADVISE: Install Linux::SysInfo to benefit from automatic parallelism optimization.\nOr optimize manually pbparallel in your pb.conf file\nUsing $pbparallel processes max at a time for the moment\nWARNING: This may consume too much memory for your system");
3589 } else {
3590 # Keep the number of VM whose memory can be allocated
3591 my $ram = $si->{"totalram"}-$si->{"sharedram"}-$si->{"bufferram"};
3592 my $ram2;
3593 my ($vmmem) = pb_conf_get_if("vmmem");
3594
3595 my $v = "default";
3596 if ((defined $vmmem) and (defined $vmmem->{$v})) {
3597 $ram2 = $vmmem->{$v};
3598 } else {
3599 # Default for KVM/QEMU
3600 $ram2 = 128;
3601 }
3602 $pbparallel = sprintf("%d",$ram/$ram2);
3603 }
3604 pb_log(1,"Using $pbparallel processes at a time\n");
3605 }
3606}
3607pb_log(2,"pb_set_parallel returns: $pbparallel\n");
3608return($pbparallel);
3609}
3610
3611
36121;
Note: See TracBrowser for help on using the repository browser.