source: devel/pb/bin/pb @ 792

Revision 792, 91.4 KB checked in by bruno, 4 years ago (diff)

If passing the -i parameter then the VM is launched with the according CD attached

  • Property svn:executable set to *
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';
13use Getopt::Long qw(:config auto_abbrev no_ignore_case);
14use Data::Dumper;
15use English;
16use File::Basename;
17use File::Copy;
18use File::stat;
19use File::Temp qw(tempdir);
20use Time::localtime qw(localtime);
21use POSIX qw(strftime);
22use lib qw (lib);
23use ProjectBuilder::Version;
24use ProjectBuilder::Base;
25use ProjectBuilder::Display;
26use ProjectBuilder::Conf;
27use ProjectBuilder::Distribution;
28use ProjectBuilder::CMS;
29use ProjectBuilder::Env;
30use ProjectBuilder::Filter;
31use ProjectBuilder::Changelog;
32use Mail::Sendmail;
33
34# Global variables
35my %opts;                                       # CLI Options
36my $action;                                     # action to realize
37my $test = "FALSE";                     # Not used
38my $pbforce = 0;                        # Force VE/VM rebuild
39my $pbsnap = 0;                         # Use snapshot mode for VM/VE
40my $option = "";                        # Not used
41my @pkgs;                                       # list of packages
42my $pbtag;                                      # Global Tag variable
43my $pbver;                                      # Global Version variable
44my $pbscript;                           # Name of the script
45my %pbver;                                      # per package
46my %pbtag;                                      # per package
47my $pbrev;                                      # Global REVISION variable
48my $pbaccount;                          # Login to use to connect to the VM
49my $pbport;                                     # Port to use to connect to the VM
50my $newver;                                     # New version to create
51my $iso = undef;                        # ISO image for the VM to create
52
53my @date = pb_get_date();
54my $pbdate = strftime("%Y-%m-%d", @date);
55
56=pod
57
58=head1 NAME
59
60pb, aka project-builder.org - builds packages for your projects
61
62=head1 DESCRIPTION
63
64pb helps you build various packages directly from your project sources.
65Those sources could be handled by a CMS (Configuration Management System)
66such as Subversion, CVS, Git, Mercurial... or being a simple reference to a compressed tar file.
67It's based on a set of configuration files, a set of provided macros to help
68you keeping build files as generic as possible. For example, a single .spec
69file should be required to generate for all rpm based distributions, even
70if you could also have multiple .spec files if required.
71
72=head1 SYNOPSIS
73
74pb [-vhSq][-r pbroot][-p project][[-s script -a account -P port][-m mach-1[,...]]][-i iso] <action> [<pkg1> ...]
75
76pb [--verbose][--help][--man][--quiet][--snapshot][--revision pbroot][--project project][[--script script --account account --port port][--machine mach-1[,...]]][--iso iso] <action> [<pkg1> ...]
77
78=head1 OPTIONS
79
80=over 4
81
82=item B<-v|--verbose>
83
84Print a brief help message and exits.
85
86=item B<-q|--quiet>
87
88Do not print any output.
89
90=item B<-h|--help>
91
92Print a brief help message and exits.
93
94=item B<-S|--snapshot>
95
96Use the snapshot mode of VMs or VEs
97
98=item B<--man>
99
100Prints the manual page and exits.
101
102=item B<-m|--machine machine1[,machine2,...]>
103
104Name of the Virtual Machines (VM) or Virtual Environments (VE) you want to build on (coma separated).
105All if none precised (or use the env variable PBV).
106
107=item B<-s|--script script>
108
109Name of the script you want to execute on the related VMs or VEs.
110
111=item B<-i|--iso iso_image>
112
113Name of the ISO image of the distribution you want to install on the related VMs.
114
115=item B<-a|--account account>
116
117Name of the account to use to connect on the related VMs.
118
119=item B<-P|--port port_number>
120
121Port number to use to connect on the related VMs.\n";
122
123=item B<-p|--project project_name>
124
125Name of the project you're working on (or use the env variable PBPROJ)
126
127=item B<-r|--revision revision>
128
129Path Name of the project revision under the CMS (or use the env variable PBROOT)
130
131=item B<-V|--version new_version>
132
133New version of the project to create based on the current one.
134
135=back
136
137=head1 ARGUMENTS
138
139<action> can be:
140
141=over 4
142
143=item B<cms2build>
144
145Create tar files for the project under your CMS.
146CMS supported are SVN, CVS and Mercurial
147parameters are packages to build
148if not using default list
149
150=item B<build2pkg>
151
152Create packages for your running distribution
153
154=item B<cms2pkg>
155
156cms2build + build2pkg
157
158=item B<build2ssh>
159
160Send the tar files to a SSH host
161
162=item B<cms2ssh>
163
164cms2build + build2ssh
165
166=item B<pkg2ssh>
167
168Send the packages built to a SSH host
169
170=item B<build2vm>
171
172Create packages in VMs, launching them if needed
173and send those packages to a SSH host once built
174VM type supported are QEMU
175
176=item B<build2ve>
177
178Create packages in VEs, creating it if needed
179and send those packages to a SSH host once built
180
181=item B<cms2vm>
182
183cms2build + build2vm
184
185=item B<cms2ve>
186
187cms2build + build2ve
188
189=item B<launchvm>
190
191Launch one virtual machine
192
193=item B<launchve>
194
195Launch one virtual environment
196
197=item B<script2vm>
198
199Launch one virtual machine if needed
200and executes a script on it
201
202=item B<script2ve>
203
204Execute a script in a virtual environment
205
206=item B<newvm>
207
208Create a new virtual machine
209
210=item B<newve>
211
212Create a new virtual environment
213
214=item B<setupvm>
215
216Setup a virtual machine for pb usage
217
218=item B<setupve>
219
220Setup a virtual environment for pb usage
221
222=item B<snapvm>
223
224Snapshot a virtual machine for pb usage
225
226=item B<snapve>
227
228Snapshot a virtual environment for pb usage
229
230=item B<test2pkg>
231
232Test a package locally
233
234=item B<test2vm>
235
236Test a package in a virtual machine
237
238=item B<test2ve>
239
240Test a package in a virtual environment
241
242=item B<newver>
243
244Create a new version of the project derived
245from the current one
246
247=item B<newproj>
248
249Create a new project and a template set of
250configuration files under pbconf
251
252=item B<announce>
253
254Announce the availability of the project through various means
255
256=item B<web2ssh>
257
258Deliver the Web site content to the target server using ssh.
259
260=item B<clean>
261
262Purge the build and delivery directories related to the current project
263
264=back
265
266<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).
267
268=head1 WEB SITES
269
270The 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/>.
271
272=head1 USER MAILING LIST
273
274None exists for the moment.
275
276=head1 CONFIGURATION FILES
277
278Each pb user may have a configuration in F<$HOME/.pbrc>. The values in this file may overwrite any other configuration file value.
279
280Here is an example of such a configuration file:
281
282 #
283 # Define for each project the URL of its pbconf repository
284 # No default option allowed here as they need to be all different
285 #
286 # URL of the pbconf content
287 # This is the format of a classical URL with the extension of additional schema such as
288 # svn+ssh, cvs+ssh, ...
289 #
290 pbconfurl linuxcoe = cvs+ssh://:ext:bcornec@linuxcoe.cvs.sourceforge.net:/cvsroot/linuxcoe/pbconf
291
292 # This is normaly defined in the project's configuration file
293 # Url of the project
294 #
295 pburl linuxcoe = cvs+ssh://:ext:bcornec@linuxcoe.cvs.sourceforge.net:/cvsroot/linuxcoe
296 
297 # All these URLs needs to be defined here as the are the entry point
298 # for how to build packages for the project
299 #
300 pbconfurl pb = svn+ssh://svn.project-builder.org/mondo/svn/pb/pbconf
301 pbconfurl mondorescue = svn+ssh://svn.project-builder.org/mondo/svn/project-builder/mondorescue/pbconf
302 pbconfurl collectl = svn+ssh://bruno@svn.mondorescue.org/mondo/svn/project-builder/collectl/pbconf
303 pbconfurl netperf = svn+ssh://svn.mondorescue.org/mondo/svn/project-builder/netperf/pbconf
304 
305 # Under that dir will take place everything related to pb
306 # If you want to use VMs/chroot/..., then use $ENV{'HOME'} to make it portable
307 # to your VMs/chroot/...
308 # if not defined then /var/cache
309 pbdefdir default = $ENV{'HOME'}/project-builder
310 pbdefdir pb = $ENV{'HOME'}
311 pbdefdir linuxcoe = $ENV{'HOME'}/LinuxCOE/cvs
312 pbdefdir mondorescue = $ENV{'HOME'}/mondo/svn
313 
314 # pbconfdir points to the directory where the CMS content of the pbconfurl is checked out
315 # If not defined, pbconfdir is under pbdefdir/pbproj/pbconf
316 pbconfdir linuxcoe = $ENV{'HOME'}/LinuxCOE/cvs/pbconf
317 pbconfdir mondorescue = $ENV{'HOME'}/mondo/svn/pbconf
318 
319 # pbdir points to the directory where the CMS content of the pburl is checked out
320 # If not defined, pbdir is under pbdefdir/pbproj
321 # Only defined if we have access to the dev of the project
322 pbdir linuxcoe = $ENV{'HOME'}/LinuxCOE/cvs
323 pbdir mondorescue = $ENV{'HOME'}/mondo/svn
324 
325 # -daemonize doesn't work with qemu 0.8.2
326 vmopt default = -m 384
327
328=head1 AUTHORS
329
330The Project-Builder.org team L<http://trac.project-builder.org/> lead by Bruno Cornec L<mailto:bruno@project-builder.org>.
331
332=head1 COPYRIGHT
333
334Project-Builder.org is distributed under the GPL v2.0 license
335described in the file C<COPYING> included with the distribution.
336
337=cut
338
339# ---------------------------------------------------------------------------
340
341my ($projectbuilderver,$projectbuilderrev) = pb_version_init();
342
343# Initialize the syntax string
344
345pb_syntax_init("pb (aka project-builder.org) Version $projectbuilderver-$projectbuilderrev\n");
346
347GetOptions("help|?|h" => \$opts{'h'}, 
348                "man" => \$opts{'man'},
349                "verbose|v+" => \$opts{'v'},
350                "snapshot|S" => \$opts{'S'},
351                "quiet|q" => \$opts{'q'},
352                "log-files|l=s" => \$opts{'l'},
353                "force|f" => \$opts{'f'},
354                "account|a=s" => \$opts{'a'},
355                "revision|r=s" => \$opts{'r'},
356                "script|s=s" => \$opts{'s'},
357                "machines|mock|m=s" => \$opts{'m'},
358                "port|P=i" => \$opts{'P'},
359                "project|p=s" => \$opts{'p'},
360                "iso|i=s" => \$opts{'i'},
361                "version|V=s" => \$opts{'V'},
362) || pb_syntax(-1,0);
363
364if (defined $opts{'h'}) {
365        pb_syntax(0,1);
366}
367if (defined $opts{'man'}) {
368        pb_syntax(0,2);
369}
370if (defined $opts{'v'}) {
371        $pbdebug = $opts{'v'};
372}
373if (defined $opts{'f'}) {
374        $pbforce=1;
375}
376if (defined $opts{'q'}) {
377        $pbdebug=-1;
378}
379if (defined $opts{'S'}) {
380        $pbsnap=1;
381}
382if (defined $opts{'l'}) {
383        open(pbLOG,"> $opts{'l'}") || die "Unable to log to $opts{'l'}: $!";
384        $pbLOG = \*pbLOG;
385        $pbdebug = 0  if ($pbdebug == -1);
386        }
387pb_log_init($pbdebug, $pbLOG);
388pb_display_init("text","");
389
390# Handle root of the project if defined
391if (defined $opts{'r'}) {
392        $ENV{'PBROOTDIR'} = $opts{'r'};
393}
394# Handle virtual machines if any
395if (defined $opts{'m'}) {
396        $ENV{'PBV'} = $opts{'m'};
397}
398if (defined $opts{'s'}) {
399        $pbscript = $opts{'s'};
400}
401if (defined $opts{'a'}) {
402        $pbaccount = $opts{'a'};
403        die "option -a requires a -s script option" if (not defined $pbscript);
404}
405if (defined $opts{'P'}) {
406        $pbport = $opts{'P'};
407}
408if (defined $opts{'V'}) {
409        $newver = $opts{'V'};
410}
411if (defined $opts{'i'}) {
412        $iso = $opts{'i'};
413}
414
415# Get Action
416$action = shift @ARGV;
417die pb_syntax(-1,1) if (not defined $action);
418
419my ($filteredfiles, $supfiles, $defpkgdir, $extpkgdir);
420my $pbinit = undef;
421$pbinit = 1 if ($action =~ /^newproj$/);
422
423# Handles project name if any
424# And get global params
425($filteredfiles, $supfiles, $defpkgdir, $extpkgdir) = pb_env_init($opts{'p'},$pbinit,$action);
426
427pb_log(0,"Project: $ENV{'PBPROJ'}\n");
428pb_log(0,"Action: $action\n");
429
430# Act depending on action
431if ($action =~ /^cms2build$/) {
432        pb_cms2build();
433} elsif ($action =~ /^build2pkg$/) {
434        pb_build2pkg();
435} elsif ($action =~ /^cms2pkg$/) {
436        pb_cms2build();
437        pb_build2pkg();
438} elsif ($action =~ /^build2ssh$/) {
439        pb_build2ssh();
440} elsif ($action =~ /^cms2ssh$/) {
441        pb_cms2build();
442        pb_build2ssh();
443} elsif ($action =~ /^pkg2ssh$/) {
444        pb_pkg2ssh();
445} elsif ($action =~ /^build2ve$/) {
446        pb_build2v("ve","build");
447} elsif ($action =~ /^build2vm$/) {
448        pb_build2v("vm","build");
449} elsif ($action =~ /^cms2ve$/) {
450        pb_cms2build();
451        pb_build2v("ve","build");
452} elsif ($action =~ /^cms2vm$/) {
453        pb_cms2build();
454        pb_build2v("vm","build");
455} elsif ($action =~ /^launchvm$/) {
456        pb_launchv("vm",$ENV{'PBV'},0);
457} elsif ($action =~ /^launchve$/) {
458        pb_launchv("ve",$ENV{'PBV'},0);
459} elsif ($action =~ /^script2vm$/) {
460        pb_script2v($pbscript,"vm");
461} elsif ($action =~ /^script2ve$/) {
462        pb_script2v($pbscript,"ve");
463} elsif ($action =~ /^newver$/) {
464        pb_newver();
465} elsif ($action =~ /^newve$/) {
466        pb_launchv("ve",$ENV{'PBV'},1);
467} elsif ($action =~ /^newvm$/) {
468        pb_launchv("vm",$ENV{'PBV'},1);
469} elsif ($action =~ /^setupve$/) {
470        pb_setup2v("ve");
471} elsif ($action =~ /^setupvm$/) {
472        pb_setup2v("vm");
473} elsif ($action =~ /^snapve$/) {
474        pb_snap2v("ve");
475} elsif ($action =~ /^snapvm$/) {
476        pb_snap2v("vm");
477} elsif ($action =~ /^test2pkg$/) {
478        pb_test2pkg();
479} elsif ($action =~ /^test2ve$/) {
480        pb_build2v("ve","test");
481} elsif ($action =~ /^test2vm$/) {
482        pb_build2v("vm","test");
483} elsif ($action =~ /^newproj$/) {
484        # Nothing to do - already done in pb_env_init
485} elsif ($action =~ /^clean$/) {
486        pb_clean();
487} elsif ($action =~ /^announce$/) {
488        # For announce only. Require avoids the systematic load of these modules
489        require DBI;
490        require DBD::SQLite;
491
492        pb_announce();
493} elsif ($action =~ /^web2ssh$/) {
494        require DBI;
495        require DBD::SQLite;
496
497        pb_cms2build("Web");
498        pb_send2target("Web");
499} else {
500        pb_log(0,"\'$action\' is not available\n");
501        pb_syntax(-2,1);
502}
503
504sub pb_cms2build {
505
506        my $param = shift || undef;
507
508        my $pkg;
509        my @pkgs;
510        my $webdir;
511
512        my %pkgs;
513        my %pb;                         # Structure to store conf info
514
515        # If Website, then pkg is only the website
516        if ((defined $param) && ($param eq "Web")) {
517                ($webdir) = pb_conf_get("webdir");
518                pb_log(2,"webdir: ".Dumper($webdir)."\n");
519                $pkgs[0] = $webdir->{$ENV{'PBPROJ'}};
520                $extpkgdir = $webdir;
521                pb_log(0,"Package: $pkgs[0]\n");
522        } else {
523                $pkg = pb_cms_get_pkg($defpkgdir,$extpkgdir);
524                @pkgs = @$pkg;
525        }
526
527        my ($scheme, $uri) = pb_cms_init($pbinit);
528
529        my ($pkgv, $pkgt) = pb_conf_get_if("pkgver","pkgtag");
530
531        # declare packager and repo for filtering
532        my ($tmp1, $tmp2) = pb_conf_get("pbpackager","pbrepo");
533        $ENV{'PBPACKAGER'} = $tmp1->{$ENV{'PBPROJ'}};
534        $ENV{'PBREPO'} = $tmp2->{$ENV{'PBPROJ'}};
535
536        foreach my $pbpkg (@pkgs) {
537                my ($testver) = pb_conf_get_if("testver");
538                $ENV{'PBPKG'} = $pbpkg;
539
540                if ((defined $pkgv) && (defined $pkgv->{$pbpkg})) {
541                        $pbver = $pkgv->{$pbpkg};
542                } else {
543                        $pbver = $ENV{'PBPROJVER'};
544                }
545                # If it's a test version, then tag == 0.date
546                if (defined $testver->{$ENV{'PBPROJ'}}) {
547                        $pbtag = "0.".strftime("%Y%m%d%H%M%S", @date);
548                        $ENV{'PBPROJTAG'} = $pbtag;
549                } elsif ((defined $pkgt) && (defined $pkgt->{$pbpkg})) {
550                        $pbtag = $pkgt->{$pbpkg};
551                } else {
552                        $pbtag = $ENV{'PBPROJTAG'};
553                }
554
555                $pbrev = $ENV{'PBREVISION'};
556                pb_log(0,"\n");
557                pb_log(0,"Management of $pbpkg $pbver-$pbtag (rev $pbrev)\n");
558                die "Unable to get env var PBDESTDIR" if (not defined $ENV{'PBDESTDIR'});
559
560                # Clean up dest if necessary. The export will recreate it
561                my $dest = "$ENV{'PBDESTDIR'}/$pbpkg-$pbver";
562                pb_rm_rf($dest) if (-d $dest);
563
564                # Export CMS tree for the concerned package to dest
565                # And generate some additional files
566                $OUTPUT_AUTOFLUSH=1;
567
568                # computes in which dir we have to work
569                my $dir = $defpkgdir->{$pbpkg};
570                $dir = $extpkgdir->{$pbpkg} if (not defined $dir);
571                $dir = $webdir->{$ENV{'PBPROJ'}} if ((defined $param) && ($param eq "Web"));
572                pb_log(2,"def:".Dumper($defpkgdir)." ext: ".Dumper($extpkgdir)." \n");
573
574                # Exporting content from CMS
575                my $preserve = pb_cms_export($uri,"$ENV{'PBDIR'}/$dir",$dest);
576
577                # Generated fake content for test versions to speed up stuff
578                my $chglog;
579
580                # Get project info on authors and log file
581                $chglog = "$ENV{'PBROOTDIR'}/$pbpkg/pbcl";
582                $chglog = "$ENV{'PBROOTDIR'}/pbcl" if (! -f $chglog);
583                $chglog = undef if (! -f $chglog);
584
585                my $authors = "$ENV{'PBROOTDIR'}/$pbpkg/pbauthors";
586                $authors = "$ENV{'PBROOTDIR'}/pbauthors" if (! -f $authors);
587                $authors = "/dev/null" if (! -f $authors);
588
589                # Extract cms log history and store it
590                if ((defined $chglog) && (! -f "$dest/NEWS")) {
591                        pb_log(2,"Generating NEWS file from $chglog\n");
592                        copy($chglog,"$dest/NEWS") || die "Unable to create $dest/NEWS";
593                }
594                pb_cms_log($scheme,"$ENV{'PBDIR'}/$dir",$dest,$chglog,$authors,$testver);
595
596                my %build;
597                my @pt;
598                my $tmpl = "";
599                my %patches;
600
601                @pt = pb_conf_get_if("vmlist","velist");
602                if (defined $pt[0]->{$ENV{'PBPROJ'}}) {
603                        $tmpl .= $pt[0]->{$ENV{'PBPROJ'}};
604                }
605                if (defined $pt[1]->{$ENV{'PBPROJ'}}) {
606                        # the 2 lists needs to be grouped with a ',' separating them
607                        if ($tmpl ne "") {
608                                $tmpl .= ",";
609                        }
610                        $tmpl .= $pt[1]->{$ENV{'PBPROJ'}} 
611                }
612       
613                # Setup %pb structure to allow filtering later on, on files using that structure
614                $pb{'tag'} = $pbtag;
615                $pb{'rev'} = $pbrev;
616                $pb{'ver'} = $pbver;
617                $pb{'pkg'} = $pbpkg;
618                $pb{'date'} = $pbdate;
619                $pb{'defpkgdir'} = $defpkgdir;
620                $pb{'extpkgdir'} = $extpkgdir;
621                $pb{'chglog'} = $chglog;
622                $pb{'packager'} = $ENV{'PBPACKAGER'};
623                $pb{'proj'} = $ENV{'PBPROJ'};
624                $pb{'repo'} = $ENV{'PBREPO'};
625                $pb{'patches'} = \%patches;
626                pb_log(2,"DEBUG: pb: ".Dumper(%pb)."\n");
627       
628                # Do not do that for website
629                if ((not defined $param) || ($param ne "Web")) {
630                        my %virt;
631                        # De-duplicate similar VM and VE
632                        foreach my $d (split(/,/,$tmpl)) {
633                                # skip ill-formatted vms (name-ver-arch)
634                                next if ($d !~ /-/);
635                                $virt{$d} = $d;
636                        }
637
638                        foreach my $d (keys %virt) {
639                                my ($name,$ver,$arch) = split(/-/,$d);
640                                pb_log(0,"Bad format for $d") if ((not defined $name) || (not defined $ver) || (not defined $arch)) ;
641                                chomp($arch);
642                                my ($ddir, $dver, $dfam);
643                                ($ddir, $dver, $dfam, $pb{'dtype'}, $pb{'suf'}, $pb{'upd'}, $pb{'arch'}) = pb_distro_init($name,$ver,$arch);
644                                pb_log(2,"DEBUG: distro tuple: ".Dumper($ddir, $dver, $dfam, $pb{'dtype'}, $pb{'suf'})."\n");
645                                pb_log(2,"DEBUG Filtering PBDATE => $pbdate, PBTAG => $pbtag, PBVER => $pbver\n");
646       
647                                # We need to compute the real name of the package
648                                my $pbrealpkg = pb_cms_get_real_pkg($pbpkg,$pb{'dtype'});
649                                $pb{'realpkg'} = $pbrealpkg;
650                                pb_log(1,"Virtual package $pbpkg has a real package name of $pbrealpkg on $ddir-$dver\n") if ($pbrealpkg ne $pbpkg);
651       
652                                # Filter build files from the less precise up to the most with overloading
653                                # Filter all files found, keeping the name, and generating in dest
654       
655                                # Find all build files first relatively to PBROOTDIR
656                                # Find also all specific files referenced in the .pb conf file
657                                my %bfiles = ();
658                                my %pkgfiles = ();
659                                $build{"$ddir-$dver-$arch"} = "yes";
660       
661                                if (-d "$ENV{'PBROOTDIR'}/$pbpkg/$pb{'dtype'}") {
662                                        pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$pb{'dtype'}",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
663                                } elsif (-d "$ENV{'PBROOTDIR'}/$pbpkg/$dfam") {
664                                        pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$dfam",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
665                                } elsif (-d "$ENV{'PBROOTDIR'}/$pbpkg/$ddir") {
666                                        pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$ddir",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
667                                } elsif (-d "$ENV{'PBROOTDIR'}/$pbpkg/$ddir-$dver") {
668                                        pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$ddir-$dver",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
669                                } elsif (-d "$ENV{'PBROOTDIR'}/$pbpkg/$ddir-$dver-$arch") {
670                                        pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$ddir-$dver-$arch",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
671                                } else {
672                                        $build{"$ddir-$dver-$arch"} = "no";
673                                        next;
674                                }
675                                pb_log(2,"DEBUG bfiles: ".Dumper(\%bfiles)."\n");
676       
677                                # Get all filters to apply
678                                my $ptr = pb_get_filters($pbpkg, $pb{'dtype'}, $dfam, $ddir, $dver);
679       
680                                # Prepare local patches for this distro - They are always applied first - May be a problem one day
681                                foreach my $p (sort(<$ENV{'PBROOTDIR'}/$pbpkg/pbpatch/*>)) {
682                                        $patches{"$ddir-$dver-$arch"} .= "," if ((defined $patches{"$ddir-$dver-$arch"}) and ($p =~ /\.all$/));
683                                        $patches{"$ddir-$dver-$arch"} .= "file://$p" if ($p =~ /\.all$/);
684                                        $patches{"$ddir-$dver-$arch"} .= "," if ((defined $patches{"$ddir-$dver-$arch"}) and ($p =~ /\.$pb{'dtype'}$/));
685                                        $patches{"$ddir-$dver-$arch"} .= "file://$p" if ($p =~ /\.$pb{'dtype'}$/);
686                                        $patches{"$ddir-$dver-$arch"} .= "," if ((defined $patches{"$ddir-$dver-$arch"}) and ($p =~ /\.$dfam$/));
687                                        $patches{"$ddir-$dver-$arch"} .= "file://$p" if ($p =~ /\.$dfam$/);
688                                        $patches{"$ddir-$dver-$arch"} .= "," if ((defined $patches{"$ddir-$dver-$arch"}) and ($p =~ /\.$ddir$/));
689                                        $patches{"$ddir-$dver-$arch"} .= "file://$p" if ($p =~ /\.$ddir$/);
690                                        $patches{"$ddir-$dver-$arch"} .= "," if ((defined $patches{"$ddir-$dver-$arch"}) and ($p =~ /\.$ddir-$dver$/));
691                                        $patches{"$ddir-$dver-$arch"} .= "file://$p" if ($p =~ /\.$ddir-$dver$/);
692                                        $patches{"$ddir-$dver-$arch"} .= "," if ((defined $patches{"$ddir-$dver-$arch"}) and ($p =~ /\.$ddir-$dver-$arch$/));
693                                        $patches{"$ddir-$dver-$arch"} .= "file://$p" if ($p =~ /\.$ddir-$dver-$arch$/);
694                                }
695       
696                                # Prepare also remote patches to be included - Applied after the local ones
697                                foreach my $p ("all","$pb{'dtype'}","$dfam","$ddir","$ddir-$dver","$ddir-$dver-$arch") {
698                                        my $f = "$ENV{'PBROOTDIR'}/$pbpkg/pbextpatch.$p";
699                                        next if (not -f $f);
700                                        if (not open(PATCH,$f)) {
701                                                pb_display("Unable to open existing external patch file content $f\n");
702                                                next;
703                                        }
704                                        while (<PATCH>) {
705                                                chomp();
706                                                $patches{"$ddir-$dver-$arch"} .= "," if (defined $patches{"$ddir-$dver-$arch"});
707                                                $patches{"$ddir-$dver-$arch"} .= "$_";
708                                        }
709                                        close(PATCH);
710                                }
711                                pb_log(2,"DEBUG: pb->patches: ".Dumper($pb{'patches'})."\n");
712       
713                                # Apply now all the filters on all the files concerned
714                                # destination dir depends on the type of file
715                                if (defined $ptr) {
716                                        # For patch support
717                                        $pb{'tuple'} = "$ddir-$dver-$arch";
718                                        foreach my $f (values %bfiles,values %pkgfiles) {
719                                                pb_filter_file("$ENV{'PBROOTDIR'}/$f",$ptr,"$dest/pbconf/$ddir-$dver-$arch/".basename($f),\%pb);
720                                        }
721                                }
722                        }
723                        my @found;
724                        my @notfound;
725                        foreach my $b (keys %build) {
726                                push @found,$b if ($build{$b} =~ /yes/);
727                                push @notfound,$b if ($build{$b} =~ /no/);
728                        }
729                        pb_log(0,"Build files generated for ".join(',',sort(@found))."\n");
730                        pb_log(0,"No Build files found for ".join(',',sort(@notfound))."\n") if (@notfound);
731                        pb_log(2,"DEBUG: patches: ".Dumper(%patches)."\n");
732                }
733
734                # Get the generic filter (all.pbf) and
735                # apply those to the non-build files including those
736                # generated by pbinit if applicable
737
738                # Get only all.pbf filter
739                my $ptr = pb_get_filters($pbpkg);
740
741                my $liste ="";
742                if (defined $filteredfiles->{$pbpkg}) {
743                        foreach my $f (split(/,/,$filteredfiles->{$pbpkg})) {
744                                pb_filter_file_inplace($ptr,"$dest/$f",\%pb);
745                                $liste = "$f $liste";
746                        }
747                }
748                pb_log(2,"Files ".$liste."have been filtered\n");
749
750                # Do not do that for website
751                if ((not defined $param) || ($param ne "Web")) {
752                        my %tmp;
753                        # Filter potential patches (local + remote)
754                        pb_log(0,"Delivering and compressing patches ");
755                        foreach my $v (keys %patches) {
756                                pb_mkdir_p("$dest/pbconf/$v/pbpatch");
757                                foreach my $pf (split(/,/,$patches{$v})) {
758                                        my $pp = basename($pf);
759                                        pb_cms_export($pf,undef,"$dest/pbconf/$v/pbpatch");
760                                        pb_filter_file_inplace($ptr,"$dest/pbconf/$v/pbpatch/$pp",\%pb);
761                                        pb_system("gzip -9f $dest/pbconf/$v/pbpatch/$pp","","quiet");
762                                        $tmp{$pf} = "";
763                                }
764                        }
765                        foreach my $v (keys %tmp) {
766                                pb_log(0,"$v ");
767                        }
768                        pb_log(0,"\n");
769                } else {
770                        # Instead call News generation
771                        pb_web_news2html($dest);
772                        # And create an empty pbconf
773                        pb_mkdir_p("$dest/pbconf");
774                        # And prepare the pbscript to execute remotely
775                        open(SCRIPT,"> $ENV{'PBDESTDIR'}/pbscript") || die "Unable to create $ENV{'PBDESTDIR'}/pbscript";
776                        print SCRIPT "#!/bin/bash\n";
777                        print SCRIPT "#set -x\n";
778                        print SCRIPT "echo ... Extracting Website content\n";
779                        print SCRIPT "find . -type f | grep -Ev '^./$pbpkg-$pbver.tar.gz|^./pbscript' | xargs rm -f non-existent\n";
780                        print SCRIPT "find * -type d -depth | xargs rmdir 2> /dev/null \n";
781                        print SCRIPT "tar xfz $pbpkg-$pbver.tar.gz\n";
782                        print SCRIPT "mv $pbpkg-$pbver/* .\n";
783                        print SCRIPT "rm -f $pbpkg-$pbver.tar.gz\n";
784                        print SCRIPT "rmdir $pbpkg-$pbver\n";
785                        close(SCRIPT);
786                }
787
788                # Prepare the dest directory for archive
789                if (-x "$ENV{'PBROOTDIR'}/$pbpkg/pbinit") {
790                        pb_filter_file("$ENV{'PBROOTDIR'}/$pbpkg/pbinit",$ptr,"$ENV{'PBTMP'}/pbinit",\%pb);
791                        chmod 0755,"$ENV{'PBTMP'}/pbinit";
792                        pb_system("cd $dest ; $ENV{'PBTMP'}/pbinit","Executing init script from $ENV{'PBROOTDIR'}/$pbpkg/pbinit","verbose");
793                }
794
795                # Do we have additional script to run to prepare the environement for the project ?
796                # Then include it in the pbconf delivery
797                foreach my $pbvf (<$ENV{'PBROOTDIR'}/pbv*.pre>,<$ENV{'PBROOTDIR'}/pbv*.post>, <$ENV{'PBROOTDIR'}/pbtest*>) {
798                        if (-x "$pbvf") {
799                                my $target = "$ENV{'PBDESTDIR'}/".basename($pbvf);
800                                pb_filter_file("$pbvf",$ptr,$target,\%pb);
801                                chmod 0755,"$target";
802                        }
803                }
804
805                # Archive dest dir
806                chdir "$ENV{'PBDESTDIR'}" || die "Unable to change dir to $ENV{'PBDESTDIR'}";
807                if (defined $preserve) {
808                        # In that case we want to preserve the original tar file for checksum purposes
809                        # The one created is btw equivalent in that case to this one
810                        # Maybe check basename of both to be sure they are the same ?
811                        pb_log(0,"Preserving original tar file ");
812                        move("$preserve","$pbpkg-$pbver.tar.gz");
813                } else {
814                        # Possibility to look at PBSRC to guess more the filename
815                        pb_system("tar cfz $pbpkg-$pbver.tar.gz --exclude=$pbpkg-$pbver/pbconf $pbpkg-$pbver","Creating $pbpkg tar files compressed");
816                }
817                pb_log(0,"Under $ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz\n");
818                pb_system("tar cfz $pbpkg-$pbver.pbconf.tar.gz $pbpkg-$pbver/pbconf","Creating pbconf tar files compressed");
819                pb_log(0,"Under $ENV{'PBDESTDIR'}/$pbpkg-$pbver.pbconf.tar.gz\n");
820
821                # Keep track of version-tag per pkg
822                $pkgs{$pbpkg} = "$pbver-$pbtag";
823
824                # Final cleanup
825                pb_rm_rf($dest) if (-d $dest);
826        }
827
828        # Keep track of per package version
829        pb_log(2,"DEBUG pkgs: ".Dumper(%pkgs)."\n");
830        open(PKG,"> $ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb") || die "Unable to create $ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb";
831        foreach my $pbpkg (keys %pkgs) {
832                print PKG "pbpkg $pbpkg = $pkgs{$pbpkg}\n";
833        }
834        close(PKG);
835
836        # Keep track of what is generated by default
837        # We need to store the dir and info on version-tag
838        # Base our content on the existing .pb file
839        copy("$ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb","$ENV{'PBDESTDIR'}/pbrc");
840        open(LAST,">> $ENV{'PBDESTDIR'}/pbrc") || die "Unable to create $ENV{'PBDESTDIR'}/pbrc";
841        print LAST "pbroot $ENV{'PBPROJ'} = $ENV{'PBROOTDIR'}\n";
842        print LAST "projver $ENV{'PBPROJ'} = $ENV{'PBPROJVER'}\n";
843        print LAST "projtag $ENV{'PBPROJ'} = $ENV{'PBPROJTAG'}\n";
844        print LAST "pbpackager $ENV{'PBPROJ'} = $ENV{'PBPACKAGER'}\n";
845        close(LAST);
846}
847
848sub pb_test2pkg {
849        # Get the running distro to test on
850        my ($ddir, $dver, $dfam, $dtype, $pbsuf, $pbupd, $arch) = pb_distro_init();
851        pb_log(2,"DEBUG: distro tuple: ".join(',',($ddir, $dver, $dfam, $dtype, $pbsuf, $pbupd, $arch))."\n");
852
853        # Get list of packages to test
854        # Get content saved in cms2build
855        my $ptr = pb_get_pkg();
856        @pkgs = @$ptr;
857
858        # Additional potential repo
859        pb_distro_setuprepo($ddir,$dver,$arch,$dtype);
860        foreach my $pbpkg (@pkgs) {
861                # We need to install the package to test, and deps brought with it
862                pb_distro_installdeps(undef,$dtype,$pbupd,$pbpkg);
863                pb_system("$ENV{'PBDESTDIR'}/pbtest","Launching test for $pbpkg","verbose");
864        }
865}
866
867sub pb_build2pkg {
868
869        # Get the running distro to build on
870        my ($ddir, $dver, $dfam, $dtype, $pbsuf, $pbupd, $arch) = pb_distro_init();
871        pb_log(2,"DEBUG: distro tuple: ".join(',',($ddir, $dver, $dfam, $dtype, $pbsuf, $pbupd, $arch))."\n");
872
873        # Get list of packages to build
874        # Get content saved in cms2build
875        my $ptr = pb_get_pkg();
876        @pkgs = @$ptr;
877
878        my ($pkg) = pb_conf_read("$ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb","pbpkg");
879        $pkg = { } if (not defined $pkg);
880
881        chdir "$ENV{'PBBUILDDIR'}";
882        my $made = ""; # pkgs made during build
883        foreach my $pbpkg (@pkgs) {
884                my $vertag = $pkg->{$pbpkg};
885                # get the version of the current package - maybe different
886                ($pbver,$pbtag) = split(/-/,$vertag);
887
888                my $src="$ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz";
889                my $src2="$ENV{'PBDESTDIR'}/$pbpkg-$pbver.pbconf.tar.gz";
890                pb_log(2,"Source file: $src\n");
891                pb_log(2,"Pbconf file: $src2\n");
892
893                pb_log(2,"Working directory: $ENV{'PBBUILDDIR'}\n");
894                if ($dtype eq "rpm") {
895                        foreach my $d ('RPMS','SRPMS','SPECS','SOURCES','BUILD') {
896                                if (! -d "$ENV{'PBBUILDDIR'}/$d") {
897                                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";
898                                }
899                        }
900
901                        # Remove in case a previous link/file was there
902                        unlink "$ENV{'PBBUILDDIR'}/SOURCES/".basename($src);
903                        symlink "$src","$ENV{'PBBUILDDIR'}/SOURCES/".basename($src) || die "Unable to symlink $src in $ENV{'PBBUILDDIR'}/SOURCES";
904                        # We need to first extract the spec file
905                        my @specfile = pb_extract_build_files($src2,"$pbpkg-$pbver/pbconf/$ddir-$dver-$arch/","$ENV{'PBBUILDDIR'}/SPECS","spec");
906
907                        # We need to handle potential patches to upstream sources
908                        pb_extract_build_files($src2,"$pbpkg-$pbver/pbconf/$ddir-$dver-$arch/pbpatch/","$ENV{'PBBUILDDIR'}/SOURCES","patch");
909
910                        pb_log(2,"specfile: ".Dumper(\@specfile)."\n");
911                        # set LANGUAGE to check for correct log messages
912                        $ENV{'LANGUAGE'}="C";
913                        # Older Redhat use _target_platform in %configure incorrectly
914                        my $specialdef = "";
915                        if (($ddir eq "redhat") || (($ddir eq "rhel") && ($dver eq "2.1"))) {
916                                $specialdef = "--define \'_target_platform \"\"\'";
917                        }
918
919                        # If needed we may add repository to the build env
920                        pb_distro_setuprepo($ddir,$dver,$arch,$dtype);
921                        foreach my $f (@specfile) {
922                                if ($f =~ /\.spec$/) {
923                                        pb_distro_installdeps("$f",$dtype,$pbupd);
924                                        pb_system("rpmbuild $specialdef --define \'packager $ENV{'PBPACKAGER'}\' --define \"_topdir $ENV{'PBBUILDDIR'}\" -ba $f","Building package with $f under $ENV{'PBBUILDDIR'}","verbose");
925                                        last;
926                                }
927                        }
928                        # Get the name of the generated packages
929                        open(LOG,"$ENV{'PBTMP'}/system.log") || die "Unable to open $ENV{'PBTMP'}/system.log";
930                        while (<LOG>) {
931                                chomp($_);
932                                next if ($_ !~ /^Wrote:/);
933                                s|.*/([S]*RPMS.*)|$1|;
934                                $made .=" $_";
935                        }
936                        close(LOG);
937
938                } elsif ($dtype eq "deb") {
939                        chdir "$ENV{'PBBUILDDIR'}" || die "Unable to chdir to $ENV{'PBBUILDDIR'}";
940                        pb_system("tar xfz $src","Extracting sources");
941                        pb_system("tar xfz $src2","Extracting pbconf");
942
943                        chdir "$pbpkg-$pbver" || die "Unable to chdir to $pbpkg-$pbver";
944                        pb_rm_rf("debian");
945                        symlink "pbconf/$ddir-$dver-$arch","debian" || die "Unable to symlink to pbconf/$ddir-$dver-$arch";
946                        chmod 0755,"debian/rules";
947
948                        pb_distro_setuprepo($ddir,$dver,$arch,$dtype);
949                        pb_distro_installdeps("debian/control",$dtype,$pbupd);
950                        pb_system("dpkg-buildpackage -us -uc -rfakeroot","Building package","verbose");
951                        # Get the name of the generated packages
952                        open(LOG,"$ENV{'PBTMP'}/system.log") || die "Unable to open $ENV{'PBTMP'}/system.log";
953                        while (<LOG>) {
954                                chomp();
955                                my $tmp = $_;
956                                next if ($tmp !~ /^dpkg-deb.*:/);
957                                $tmp =~ s|.*../(.*)_(.*).deb.*|$1|;
958                                $made="$made $tmp.dsc $tmp.tar.gz $tmp"."_*.deb $tmp"."_*.changes";
959                        }
960                        close(LOG);
961                } elsif ($dtype eq "ebuild") {
962                        my @ebuildfile;
963                        # For gentoo we need to take pb as subsystem name
964                        # We put every apps here under sys-apps. hope it's correct
965                        # We use pb's home dir in order to have a single OVERLAY line
966                        my $tmpd = "$ENV{'HOME'}/portage/pb/sys-apps/$pbpkg";
967                        pb_mkdir_p($tmpd) if (! -d "$tmpd");
968                        pb_mkdir_p("$ENV{'HOME'}/portage/distfiles") if (! -d "$ENV{'HOME'}/portage/distfiles");
969
970                        # We need to first extract the ebuild file
971                        @ebuildfile = pb_extract_build_files($src2,"$pbpkg-$pbver/pbconf/$ddir-$dver-$arch/","$tmpd","ebuild");
972
973                        # Prepare the build env for gentoo
974                        my $found = 0;
975                        my $pbbd = $ENV{'HOME'};
976                        $pbbd =~ s|/|\\/|g;
977                        if (-r "/etc/make.conf") {
978                                open(MAKE,"/etc/make.conf");
979                                while (<MAKE>) {
980                                        $found = 1 if (/$pbbd\/portage/);
981                                }
982                                close(MAKE);
983                        }
984                        if ($found == 0) {
985                                pb_system("sudo sh -c 'echo PORTDIR_OVERLAY=\"$ENV{'HOME'}/portage\" >> /etc/make.conf'");
986                        }
987                        #$found = 0;
988                        #if (-r "/etc/portage/package.keywords") {
989                        #open(KEYW,"/etc/portage/package.keywords");
990                        #while (<KEYW>) {
991                        #$found = 1 if (/portage\/pb/);
992                        #}
993                        #close(KEYW);
994                        #}
995                        #if ($found == 0) {
996                        #pb_system("sudo sh -c \"echo portage/pb >> /etc/portage/package.keywords\"");
997                        #}
998
999                        # Build
1000                        foreach my $f (@ebuildfile) {
1001                                if ($f =~ /\.ebuild$/) {
1002                                        pb_distro_installdeps("$f",$dtype,$pbupd);
1003                                        move($f,"$tmpd/$pbpkg-$pbver.ebuild");
1004                                        pb_system("cd $tmpd ; ebuild $pbpkg-$pbver.ebuild clean ; ebuild $pbpkg-$pbver.ebuild digest ; ebuild $pbpkg-$pbver.ebuild package","verbose");
1005                                        # Now move it where pb expects it
1006                                        pb_mkdir_p("$ENV{'PBBUILDDIR'}/portage/pb/sys-apps/$pbpkg");
1007                                        move("$tmpd/$pbpkg-$pbver.ebuild","$ENV{'PBBUILDDIR'}/portage/pb/sys-apps/$pbpkg");
1008                                }
1009                        }
1010
1011                        $made="$made portage/pb/sys-apps/$pbpkg/$pbpkg-$pbver.ebuild";
1012                } elsif ($dtype eq "tgz") {
1013                        # Slackware family
1014                        $made="$made $pbpkg/$pbpkg-$pbver-*-$pbtag.tgz";
1015
1016                        chdir "$ENV{'PBBUILDDIR'}" || die "Unable to chdir to $ENV{'PBBUILDDIR'}";
1017                        pb_system("tar xfz $src","Extracting sources");
1018                        pb_system("tar xfz $src2","Extracting pbconf");
1019                        chdir "$pbpkg-$pbver" || die "Unable to chdir to $pbpkg-$pbver";
1020                        symlink "pbconf/$ddir-$dver-$arch","install" || die "Unable to symlink to pbconf/$ddir-$dver-$arch";
1021                        if (-x "install/pbslack") {
1022                                pb_distro_installdeps("./install/pbslack",$dtype,$pbupd);
1023                                pb_system("./install/pbslack","Building package");
1024                                pb_system("sudo /sbin/makepkg -p -l y -c y $pbpkg","Packaging $pbpkg","verbose");
1025                        }
1026                } else {
1027                        die "Unknown dtype format $dtype";
1028                }
1029        }
1030        # Packages check if needed
1031        if ($dtype eq "rpm") {
1032                if (-f "/usr/bin/rpmlint") {
1033                        pb_system("rpmlint $made","Checking validity of rpms with rpmlint","verbose");
1034                } else {
1035                        pb_log(0,"rpm packages generated: $made\n");
1036                }
1037        } elsif ($dtype eq "deb") {
1038                my $made2 = "";
1039                if (-f "/usr/bin/lintian") {
1040                        foreach my $f (split(/ /,$made)) {
1041                                $made2 .= "../$f " if ($f =~ /\.changes$/);
1042                        }
1043                        pb_system("lintian $made2","Checking validity of debs with lintian","verbose");
1044                } else {
1045                        pb_log(0,"deb packages generated: $made2\n");
1046                }
1047        } else {
1048                pb_log(0,"No check done for $dtype yet\n");
1049                pb_log(0,"Packages generated: $made\n");
1050        }
1051
1052        # Keep track of what is generated so that we can get them back from VMs
1053        open(KEEP,"> $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}") || die "Unable to create $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}";
1054        print KEEP "$made\n";
1055        close(KEEP);
1056}
1057
1058sub pb_build2ssh {
1059        pb_send2target("Sources");
1060}
1061
1062sub pb_pkg2ssh {
1063        pb_send2target("Packages");
1064}
1065
1066# By default deliver to the the public site hosting the
1067# ftp structure (or whatever) or a VM/VE
1068sub pb_send2target {
1069
1070        my $cmt = shift;
1071        my $v = shift || undef;
1072        my $vmexist = shift || 0;                       # 0 is FALSE
1073        my $vmpid = shift || 0;                         # 0 is FALSE
1074        my $snapme = shift || 0;                        # 0 is FALSE
1075
1076        pb_log(2,"DEBUG: pb_send2target($cmt,".Dumper($v).",$vmexist,$vmpid)\n");
1077        my $host = "sshhost";
1078        my $login = "sshlogin";
1079        my $dir = "sshdir";
1080        my $port = "sshport";
1081        my $conf = "sshconf";
1082        my $rebuild = "sshrebuild";
1083        my $tmout = "vmtmout";
1084        my $path = "vmpath";
1085        if ($cmt =~ /^VM/) {
1086                $login = "vmlogin";
1087                $dir = "pbdefdir";
1088                $tmout = "vmtmout";
1089                $rebuild = "vmrebuild";
1090                # Specific VM
1091                $host = "vmhost";
1092                $port = "vmport";
1093        } elsif ($cmt =~ /^VE/) {
1094                $login = "velogin";
1095                $dir = "pbdefdir";
1096                # Specific VE
1097                $path = "vepath";
1098                $conf = "veconf";
1099                $rebuild = "verebuild";
1100        } elsif ($cmt eq "Web") {
1101                $host = "websshhost";
1102                $login = "websshlogin";
1103                $dir = "websshdir";
1104                $port = "websshport";
1105        }
1106        my $cmd = "";
1107        my $src = "";
1108        my ($odir,$over,$oarch) = (undef, undef, undef);
1109        my ($ddir, $dver, $dfam, $dtype, $pbsuf);
1110
1111        if ($cmt ne "Announce") {
1112                my $ptr = pb_get_pkg();
1113                @pkgs = @$ptr;
1114
1115                # Get the running distro to consider
1116                if (defined $v) {
1117                        ($odir,$over,$oarch) = split(/-/,$v);
1118                }
1119                ($ddir, $dver, $dfam, $dtype, $pbsuf) = pb_distro_init($odir,$over,$oarch);
1120                pb_log(2,"DEBUG: distro tuple: ".join(',',($ddir, $dver, $dfam, $dtype, $pbsuf))."\n");
1121
1122                # Get list of packages to build
1123                # Get content saved in cms2build
1124                my ($pkg) = pb_conf_read("$ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb","pbpkg");
1125                $pkg = { } if (not defined $pkg);
1126
1127                chdir "$ENV{'PBBUILDDIR'}";
1128                foreach my $pbpkg (@pkgs) {
1129                        my $vertag = $pkg->{$pbpkg};
1130                        # get the version of the current package - maybe different
1131                        ($pbver,$pbtag) = split(/-/,$vertag);
1132
1133                        if (($cmt eq "Sources") || ($cmt =~ /V[EM]build/)) {
1134                                $src = "$src $ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz $ENV{'PBDESTDIR'}/$pbpkg-$pbver.pbconf.tar.gz";
1135                                if ($cmd eq "") {
1136                                        $cmd = "ln -sf $pbpkg-$pbver.tar.gz $pbpkg-latest.tar.gz";
1137                                } else {
1138                                        $cmd = "$cmd ; ln -sf $pbpkg-$pbver.tar.gz $pbpkg-latest.tar.gz";
1139                                }
1140                        } elsif ($cmt eq "Web") {
1141                                $src = "$src $ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz"
1142                        }
1143                }
1144                # Adds conf file for availability of conf elements
1145                pb_conf_add("$ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb");
1146        }
1147
1148        if ($cmt =~ /V[EM]build/) {
1149                $src="$src $ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb $ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb $ENV{'PBETC'} $ENV{'PBDESTDIR'}/pbrc $ENV{'PBDESTDIR'}/pbscript";
1150        } elsif (($cmt =~ /V[EM]Script/) || ($cmt eq "Web")) {
1151                $src="$src $ENV{'PBDESTDIR'}/pbscript";
1152        } elsif ($cmt =~ /V[EM]test/) {
1153                $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";
1154        } elsif ($cmt eq "Announce") {
1155                $src="$src $ENV{'PBTMP'}/pbscript";
1156        } elsif ($cmt eq "Packages") {
1157                # Get package list from file made during build2pkg
1158                open(KEEP,"$ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}") || die "Unable to read $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}";
1159                $src = <KEEP>;
1160                chomp($src);
1161                close(KEEP);
1162                $src="$src $ENV{'PBBUILDDIR'}/pbscript";
1163        }
1164        # Remove potential leading spaces (cause problem with basename)
1165        $src =~ s/^ *//;
1166        my $basesrc = "";
1167        foreach my $i (split(/ +/,$src)) {
1168                $basesrc .= " ".basename($i);
1169        }
1170
1171        pb_log(0,"Sources handled ($cmt): $src\n");
1172        pb_log(2,"values: ".Dumper(($host,$login,$dir,$port,$tmout,$rebuild,$path,$conf))."\n");
1173        my ($sshhost,$sshlogin,$sshdir,$sshport,$vtmout,$vepath) = pb_conf_get($host,$login,$dir,$port,$tmout,$path);
1174        # Not mandatory
1175        my ($vrebuild,$veconf,$testver) = pb_conf_get_if($rebuild,$conf,"testver");
1176        pb_log(2,"ssh: ".Dumper(($sshhost,$sshlogin,$sshdir,$sshport,$vtmout,$vrebuild,$vepath,$veconf))."\n");
1177
1178        my $mac;
1179        if ($cmt !~ /^VE/) {
1180                $mac = "$sshlogin->{$ENV{'PBPROJ'}}\@$sshhost->{$ENV{'PBPROJ'}}";
1181                # Overwrite account value if passed as parameter
1182                $mac = "$pbaccount\@$sshhost->{$ENV{'PBPROJ'}}" if (defined $pbaccount);
1183                pb_log(2, "DEBUG: pbaccount: $pbaccount => mac: $mac\n") if (defined $pbaccount);
1184        } else {
1185                # VE
1186                # Overwrite account value if passed as parameter (typically for setup2ve)
1187                $mac = $sshlogin->{$ENV{'PBPROJ'}};
1188                $mac = $pbaccount if (defined $pbaccount);
1189        }
1190
1191        my $tdir;
1192        my $bdir;
1193        if (($cmt eq "Sources") || ($cmt =~ /V[EM]Script/)) {
1194                $tdir = $sshdir->{$ENV{'PBPROJ'}}."/src";
1195                if ((defined $testver) && (defined $testver->{$ENV{'PBPROJ'}}) && ($testver->{$ENV{'PBPROJ'}} =~ /true/i)) {
1196                        # This is a test pkg => target dir is under test
1197                        $tdir = $sshdir->{$ENV{'PBPROJ'}}."/test/src";
1198                }
1199        } elsif (($cmt =~ /V[EM]build/)  || ($cmt =~ /V[EM]test/)) {
1200                $tdir = $sshdir->{$ENV{'PBPROJ'}}."/$ENV{'PBPROJ'}/delivery";
1201                $bdir = $sshdir->{$ENV{'PBPROJ'}}."/$ENV{'PBPROJ'}/build";
1202                # Remove a potential $ENV{'HOME'} as bdir should be relative to pb's home
1203                $bdir =~ s|\$ENV.+\}/||;
1204        } elsif ($cmt eq "Announce") {
1205                $tdir = "$sshdir->{$ENV{'PBPROJ'}}";
1206                if ((defined $testver) && (defined $testver->{$ENV{'PBPROJ'}}) && ($testver->{$ENV{'PBPROJ'}} =~ /true/i)) {
1207                        # This is a test pkg => target dir is under test
1208                        $tdir = $sshdir->{$ENV{'PBPROJ'}}."/test";
1209                }
1210        } elsif ($cmt eq "Web") {
1211                $tdir = "$sshdir->{$ENV{'PBPROJ'}}";
1212                if ((defined $testver) && (defined $testver->{$ENV{'PBPROJ'}}) && ($testver->{$ENV{'PBPROJ'}} =~ /true/i)) {
1213                        # This is a test website => target dir is under test
1214                        $tdir = $sshdir->{$ENV{'PBPROJ'}}."/../test";
1215                }
1216        } elsif ($cmt eq "Packages") {
1217                $tdir = $sshdir->{$ENV{'PBPROJ'}}."/$ddir/$dver";
1218
1219                if ((defined $testver) && (defined $testver->{$ENV{'PBPROJ'}}) && ($testver->{$ENV{'PBPROJ'}} =~ /true/i)) {
1220                        # This is a test pkg => target dir is under test
1221                        $tdir = $sshdir->{$ENV{'PBPROJ'}}."/test/$ddir/$dver";
1222                }
1223
1224                my $repodir = $tdir;
1225                $repodir =~ s|^$sshdir->{$ENV{'PBPROJ'}}/||;
1226
1227                my ($pbrepo) = pb_conf_get("pbrepo");
1228
1229                # Repository management
1230                open(PBS,"> $ENV{'PBBUILDDIR'}/pbscript") || die "Unable to create $ENV{'PBBUILDDIR'}/pbscript";
1231                if ($dtype eq "rpm") {
1232                        # Also make a pbscript to generate yum/urpmi bases
1233                        print PBS << "EOF";
1234#!/bin/bash
1235# Prepare a script to ease yum setup
1236cat > $ENV{'PBPROJ'}.repo << EOT
1237[$ENV{'PBPROJ'}]
1238name=$ddir $dver - $ENV{'PBPROJ'} Vanilla Packages
1239baseurl=$pbrepo->{$ENV{'PBPROJ'}}/$repodir
1240enabled=1
1241gpgcheck=0
1242EOT
1243chmod 644 $ENV{'PBPROJ'}.repo
1244
1245# Clean up old repo content
1246rm -rf headers/ repodata/
1247# Create yum repo
1248yum-arch .
1249# Create repodata
1250createrepo .
1251EOF
1252                        if ($dfam eq "md") {
1253                                # For Mandriva add urpmi management
1254                                print PBS << "EOF";
1255# Prepare a script to ease urpmi setup
1256cat > $ENV{'PBPROJ'}.addmedia << EOT
1257urpmi.addmedia $ENV{'PBPROJ'} $pbrepo->{$ENV{'PBPROJ'}}/$repodir with hdlist.cz
1258EOT
1259chmod 755 $ENV{'PBPROJ'}.addmedia
1260
1261# Clean up old repo content
1262rm -f hdlist.cz synthesis.hdlist.cz
1263# Create urpmi repo
1264genhdlist .
1265EOF
1266                        }
1267                        if ($ddir eq "fedora") {
1268                                # Extract the spec file to please Fedora maintainers :-(
1269                                print PBS << "EOF";
1270for p in $basesrc; do
1271        echo \$p | grep -q 'src.rpm'
1272        if [ \$\? -eq 0 ]; then
1273                rpm2cpio \$p | cpio -ivdum --quiet '*.spec'
1274        fi
1275done
1276EOF
1277                        }
1278                } elsif ($dtype eq "deb") {
1279                        # Also make a pbscript to generate apt bases
1280                        # Cf: http://www.debian.org/doc/manuals/repository-howto/repository-howto.fr.html
1281                        my $rpd = dirname("$pbrepo->{$ENV{'PBPROJ'}}/$repodir");
1282                        print PBS << "EOF";
1283#!/bin/bash
1284# Prepare a script to ease apt setup
1285cat > $ENV{'PBPROJ'}.sources.list << EOT
1286deb $rpd $dver contrib
1287deb-src $rpd $dver contrib
1288EOT
1289chmod 644 $ENV{'PBPROJ'}.sources.list
1290
1291# Prepare a script to create apt info file
1292(cd .. ; for a in i386 amd64 ia64; do mkdir -p dists/$dver/contrib/binary-\$a; dpkg-scanpackages -a\$a $dver /dev/null | gzip -c9 > dists/$dver/contrib/binary-\$a/Packages.gz; done; mkdir -p dists/$dver/contrib/source; dpkg-scansources $dver /dev/null | gzip -c9 > dists/$dver/contrib/source/Sources.gz)
1293#(cd .. ; rm -f dists/$dver/Release ; apt-ftparchive release dists/$dver > dists/$dver/Release; gpg --sign -ba -o dists/$dver/Release.gpg dists/$dver/Release)
1294EOF
1295                } elsif ($dtype eq "ebuild") {
1296                        # make a pbscript to generate links to latest version
1297                        print PBS << "EOF";
1298#!/bin/bash
1299# Prepare a script to create correct links
1300for p in $src; do
1301        echo \$p | grep -q '.ebuild'
1302        if [ \$\? -eq 0 ]; then
1303                j=`basename \$p`
1304                pp=`echo \$j | cut -d'-' -f1`
1305                ln -sf \$j \$pp.ebuild
1306        fi
1307done
1308EOF
1309                }
1310                close(PBS);
1311                chmod 0755,"$ENV{'PBBUILDDIR'}/pbscript";
1312        } else {
1313                return;
1314        }
1315
1316        # Useless for VE
1317        my $nport;
1318        if ($cmt !~ /^VE/) {
1319                $nport = $sshport->{$ENV{'PBPROJ'}};
1320                $nport = "$pbport" if (defined $pbport);
1321        }
1322
1323        # Remove a potential $ENV{'HOME'} as tdir should be relative to pb's home
1324        $tdir =~ s|\$ENV.+\}/||;
1325
1326        my $tm = $vtmout->{$ENV{'PBPROJ'}};
1327
1328        # ssh communication if not VE
1329        # should use a hash instead...
1330        my ($shcmd,$cpcmd,$cptarget,$cp2target);
1331        if ($cmt !~ /^VE/) {
1332                my $keyfile = pb_ssh_get(0);
1333                $shcmd = "ssh -i $keyfile -q -o UserKnownHostsFile=/dev/null -p $nport $mac";
1334                $cpcmd = "scp -i $keyfile -p -o UserKnownHostsFile=/dev/null -P $nport";
1335                $cptarget = "$mac:$tdir";
1336                if ($cmt =~ /^VMbuild/) {
1337                        $cp2target = "$mac:$bdir";
1338                }
1339        } else {
1340                my $tp = $vepath->{$ENV{'PBPROJ'}};
1341                ($odir,$over,$oarch) = split(/-/,$v);
1342                my $tpdir = "$tp/$odir/$over/$oarch";
1343                my ($ptr) = pb_conf_get("vetype");
1344                my $vetype = $ptr->{$ENV{'PBPROJ'}};
1345                if ($vetype eq "chroot") {
1346                        $shcmd = "sudo chroot $tpdir /bin/su - $mac -c ";
1347                        $cpcmd = "sudo cp -r ";
1348                } elsif ($vetype eq "schroot") {
1349                        $shcmd = "schroot $tp -u $mac -- ";
1350                        $cpcmd = "sudo cp -r ";
1351                }
1352                # We need to get the home dir of the target account to deliver in the right place
1353                open(PASS,"$tpdir/etc/passwd") || die "Unable to open $tpdir/etc/passwd";
1354                my $homedir = "";
1355                while (<PASS>) {
1356                        my ($c1,$c2,$c3,$c4,$c5,$c6,$c7) = split(/:/);
1357                        $homedir = $c6 if ($c1 =~ /^$mac$/);
1358                        pb_log(3,"Homedir: $homedir - account: $c6\n");
1359                }
1360                close(PASS);
1361                $cptarget = "$tpdir/$homedir/$tdir";
1362                if ($cmt eq "VEbuild") {
1363                        $cp2target = "$tpdir/$homedir/$bdir";
1364                }
1365                pb_log(2,"On VE using $cptarget as target dir to copy to\n");
1366        }
1367
1368        my $logres = "";
1369        # Do not touch when just announcing
1370        if ($cmt ne "Announce") {
1371                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");
1372        } else {
1373                $logres = "> ";
1374        }
1375        pb_system("cd $ENV{'PBBUILDDIR'} ; $cpcmd $src $cptarget 2> /dev/null","$cmt delivery in $cptarget");
1376
1377        # For VE we need to change the owner manually
1378        if ($cmt =~ /^VE/) {
1379                pb_system("$shcmd \"sudo chown -R $mac $tdir\"","Adapt owner in $tdir to $mac");
1380        }
1381
1382        pb_system("$shcmd \"echo \'cd $tdir ; if [ -x pbscript ]; then ./pbscript; fi ; rm -f ./pbscript\' | bash\"","Executing pbscript on $cptarget if needed","verbose");
1383        if ($cmt =~ /^V[EM]build/) {
1384                # Get back info on pkg produced, compute their name and get them from the VM
1385                pb_system("$cpcmd $cp2target/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'} $ENV{'PBBUILDDIR'} 2> /dev/null","Get package names in $cp2target");
1386                # For VE we need to change the owner manually
1387                if ($cmt eq "VEbuild") {
1388                        pb_system("sudo chown $UID $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}","Adapt owner in $tdir to $UID");
1389                }
1390                # return here to avoid breaking the load on VMs/VEs in case of a bad one
1391                if (not -f "$ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}") {
1392                        pb_log(0,"Problem with VM $v on $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}");
1393                        return;
1394                }
1395                open(KEEP,"$ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}") || die "Unable to read $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}";
1396                my $src = <KEEP>;
1397                chomp($src);
1398                close(KEEP);
1399                $src =~ s/^ *//;
1400                pb_mkdir_p("$ENV{'PBBUILDDIR'}/$odir/$over");
1401                # Change pgben to make the next send2target happy
1402                my $made = "";
1403                open(KEEP,"> $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}") || die "Unable to write $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}";
1404                foreach my $p (split(/ +/,$src)) {
1405                        my $j = basename($p);
1406                        pb_system("$cpcmd $cp2target/\'$p\' $ENV{'PBBUILDDIR'}/$odir/$over 2> /dev/null","Package recovery of $j in $cp2target");
1407                        $made="$made $odir/$over/$j"; # if (($dtype ne "rpm") || ($j !~ /.src.rpm$/));
1408                }
1409                print KEEP "$made\n";
1410                close(KEEP);
1411                pb_system("$shcmd \"rm -rf $tdir $bdir\"","$cmt cleanup");
1412
1413                # Sign packages locally
1414                if ($dtype eq "rpm") {
1415                                #pb_system("rpm --addsign --define \'_signature gpg\' --define \'__gpg_sign_cmd /usr/bin/gpg --batch --no-verbose --no-armor --no-secmem-warning -u \"$ENV{'PBPACKAGER'}\" -sbo %{__signature_filename} %{__plaintext_filename} --use-agent\' $made","Signing RPM packages packages");
1416                } elsif ($dtype eq "deb") {
1417                                #pb_system("debsign $made","Signing DEB packages");
1418                } else {
1419                        pb_log(0,"I don't know yet how to sign packages for type $dtype. Please give feedback to dev team");
1420                }
1421
1422                # We want to send them to the ssh account so overwrite what has been done before
1423                undef $pbaccount;
1424                pb_log(2,"Before sending pkgs, vmexist: $vmexist, vmpid: $vmpid\n");
1425                pb_send2target("Packages",$odir."-".$over."-".$oarch,$vmexist,$vmpid);
1426                pb_rm_rf("$ENV{'PBBUILDDIR'}/$odir");
1427        }
1428        pb_log(2,"Before halt, vmexist: $vmexist, vmpid: $vmpid\n");
1429        if ((! $vmexist) && ($cmt =~ /^VM/)) {
1430                # If in setupvm then takes a snapshot just before halting
1431                if ($snapme != 0) {
1432                        my ($vmmonport,$vmtype) = pb_conf_get("vmmonport","vmtype");
1433                        # For monitoring control
1434                        if ((($vmtype->{$ENV{'PBPROJ'}}) eq "kvm") || (($vmtype->{$ENV{'PBPROJ'}}) eq "qemu")) {
1435                                use Net::Telnet;
1436                                my $t = new Net::Telnet (Timeout => 120, Host => "localhost", Port => $vmmonport->{$ENV{'PBPROJ'}}) || die "Unable to dialog on the monitor";
1437                                # move to monitor mode
1438                                my @lines = $t->cmd("c");
1439                                # Create a snapshot named pb
1440                                @lines = $t->cmd("savevm pb");
1441                                # Write the new status in the VM
1442                                @lines = $t->cmd("commit all");
1443                                # End
1444                                @lines = $t->cmd("quit");
1445                        }
1446                }
1447                pb_system("$shcmd \"sudo /sbin/halt -p \"; sleep $tm ; echo \'if [ -d /proc/$vmpid ]; then kill -9 $vmpid; fi \' | bash ; sleep 10","VM $v halt (pid $vmpid)");
1448        }
1449        if (($cmt =~ /^VE/) && ($snapme != 0)) {
1450                ($odir,$over,$oarch) = split(/-/,$v);
1451                my $tpdir = "$vepath->{$ENV{'PBPROJ'}}/$odir/$over/$oarch";
1452                pb_system("sudo tar cz -f $vepath->{$ENV{'PBPROJ'}}/$odir-$over-$oarch.tar.gz -C $tpdir .","Creating a snapshot of $tpdir");
1453        }
1454}
1455
1456sub pb_script2v {
1457        my $pbscript=shift;
1458        my $vtype=shift;
1459        my $pbforce=shift || 0; # Force stop of VM. Default not
1460        my $vm1=shift || undef; # Only that VM to treat
1461        my $snapme=shift || 0;  # Do we have to create a snapshot
1462        my $vm;
1463        my $all;
1464
1465        pb_log(2,"DEBUG: pb_script2v($pbscript,$vtype,$pbforce,".Dumper($vm1).",$snapme)\n");
1466        # Prepare the script to be executed on the VM
1467        # in $ENV{'PBDESTDIR'}/pbscript
1468        if ((defined $pbscript ) && ($pbscript ne "$ENV{'PBDESTDIR'}/pbscript")) {
1469                copy($pbscript,"$ENV{'PBDESTDIR'}/pbscript") || die "Unable to create $ENV{'PBDESTDIR'}/pbscript";
1470                chmod 0755,"$ENV{'PBDESTDIR'}/pbscript";
1471        }
1472
1473        if (not defined $vm1) {
1474                ($vm,$all) = pb_get2v($vtype);
1475        } else {
1476                @$vm = ($vm1);
1477        }
1478        my ($vmexist,$vmpid) = (undef,undef);
1479
1480        foreach my $v (@$vm) {
1481                # Launch VM/VE - Usage of snapshot disabled
1482                ($vmexist,$vmpid) = pb_launchv($vtype,$v,0,$snapme,0);
1483
1484                if ($vtype eq "vm") {
1485                        pb_log(2,"DEBUG: After pb_launchv, vmexist: $vmexist, vmpid: $vmpid\n");
1486
1487                        # Skip that VM if something went wrong
1488                        next if (($vmpid == 0) && ($vmexist == 0));
1489
1490                        # If force stopping the VM then reset vmexist
1491                        if ($pbforce == 1) {
1492                                $vmpid = $vmexist;
1493                                $vmexist = 0;
1494                        }
1495                } else {
1496                        #VE
1497                        $vmexist = 0;
1498                        $vmpid = 0;
1499                }
1500
1501                # Gather all required files to send them to the VM
1502                # and launch the build through pbscript
1503                pb_log(2,"DEBUG: Before send2target, vmexist: $vmexist, vmpid: $vmpid\n");
1504                pb_send2target(uc($vtype)."Script","$v",$vmexist,$vmpid,$snapme);
1505
1506        }
1507}
1508
1509sub pb_launchv {
1510        my $vtype = shift;
1511        my $v = shift;
1512        my $create = shift || 0;                # By default do not create a VM/VE
1513        my $snapme = shift || 0;                # By default do not snap a VM/VE
1514        my $usesnap = shift || 1;               # By default study the usage of the snapshot feature of VM/VE
1515
1516        # If creation or snapshot creation mode, no snapshot usable
1517        if (($create == 1) || ($snapme == 1)) {
1518                $usesnap = 0;
1519        }
1520
1521        pb_log(2,"DEBUG: pb_launchv($vtype,$v,$create,$snapme,$usesnap)\n");
1522        die "No VM/VE defined, unable to launch" if (not defined $v);
1523        # Keep only the first VM in case many were given
1524        $v =~ s/,.*//;
1525
1526        my $arch = pb_get_arch();
1527
1528        # Launch the VMs/VEs
1529        if ($vtype eq "vm") {
1530                die "-i iso parameter needed" if (((not defined $iso) || ($iso eq "")) && ($create != 0));
1531
1532                my ($ptr,$vmpath,$vmport,$vmsize,$vmmonport) = pb_conf_get("vmtype","vmpath","vmport","vmsize","vmmonport");
1533                my ($vmopt,$vmtmout,$vmsnap) = pb_conf_get_if("vmopt","vmtmout","vmsnap");
1534
1535                my $vmtype = $ptr->{$ENV{'PBPROJ'}};
1536                if (not defined $ENV{'PBVMOPT'}) {
1537                        $ENV{'PBVMOPT'} = "";
1538                }
1539                # Save the current status for later restoration
1540                $ENV{'PBOLDVMOPT'} = $ENV{'PBVMOPT'};
1541                # Set a default timeout of 2 minutes
1542                if (not defined $ENV{'PBVMTMOUT'}) {
1543                        $ENV{'PBVMTMOUT'} = "120";
1544                }
1545                if (defined $vmopt->{$v}) {
1546                        $ENV{'PBVMOPT'} .= " $vmopt->{$v}" if ($ENV{'PBVMOPT'} !~ / $vmopt->{$v}/);
1547                } elsif (defined $vmopt->{$ENV{'PBPROJ'}}) {
1548                        $ENV{'PBVMOPT'} .= " $vmopt->{$ENV{'PBPROJ'}}" if ($ENV{'PBVMOPT'} !~ / $vmopt->{$ENV{'PBPROJ'}}/);
1549                }
1550
1551                # Are we allowed to use snapshot feature
1552                if ($usesnap == 1) {
1553                        if ((defined $vmsnap->{$v}) && ($vmsnap->{$v} =~ /true/i)) {
1554                                $ENV{'PBVMOPT'} .= "-snapshot ";
1555                        } elsif ((defined $vmsnap->{$ENV{'PBPROJ'}}) && ($vmsnap->{$ENV{'PBPROJ'}} =~ /true/i)) {
1556                                $ENV{'PBVMOPT'} .= "-snapshot ";
1557                        } elsif ($pbsnap eq 1) {
1558                                $ENV{'PBVMOPT'} .= "-snapshot ";
1559                        }
1560                } 
1561                if ($snapme != 0) {
1562                        if (($vmtype eq "kvm") || ($vmtype eq "qemu")) {
1563                                # Configure the monitoring to automize the creation of the 'pb' snapshot
1564                                $ENV{'PBVMOPT'} .= "-serial mon:telnet::$vmmonport->{$ENV{'PBPROJ'}},server,nowait ";
1565                                # In that case no snapshot call needed
1566                                $ENV{'PBVMOPT'} =~ s/-snapshot //;
1567                        }
1568                }
1569                if (defined $vmtmout->{$v}) {
1570                        $ENV{'PBVMTMOUT'} = $vmtmout->{$v};
1571                } elsif (defined $vmtmout->{$ENV{'PBPROJ'}}) {
1572                        $ENV{'PBVMTMOUT'} = $vmtmout->{$ENV{'PBPROJ'}};
1573                }
1574                my $nport = $vmport->{$ENV{'PBPROJ'}};
1575                $nport = "$pbport" if (defined $pbport);
1576       
1577                my $cmd;
1578                my $vmcmd;              # has to be used for pb_check_ps
1579                my $vmm;                # has to be used for pb_check_ps
1580                if (($vmtype eq "qemu") || ($vmtype eq "kvm")) {
1581                        my $qemucmd32;
1582                        my $qemucmd64;
1583                        if ($arch eq "x86_64") {
1584                                $qemucmd32 = "/usr/bin/qemu-system-i386";
1585                                $qemucmd64 = "/usr/bin/qemu";
1586                        } else {
1587                                $qemucmd32 = "/usr/bin/qemu";
1588                                $qemucmd64 = "/usr/bin/qemu-system-x86_64";
1589                        }
1590                        if ($v =~ /x86_64/) {
1591                                        $vmcmd = "$qemucmd64";
1592                                } else {
1593                                        $vmcmd = "$qemucmd32";
1594                                }
1595                        if ($vmtype eq "kvm") {
1596                                $vmcmd = "/usr/bin/kvm";
1597                                }
1598                        $vmm = "$vmpath->{$ENV{'PBPROJ'}}/$v.qemu";
1599                        if (($create != 0) || (defined $iso)) {
1600                                $ENV{'PBVMOPT'} .= " -cdrom $iso -boot d";
1601                        }
1602                        # Always redirect the network and always try to use a 'pb' snapshot
1603                        $cmd = "$vmcmd $ENV{'PBVMOPT'} -redir tcp:$nport:10.0.2.15:22 -loadvm pb $vmm"
1604                } elsif ($vmtype eq "xen") {
1605                } elsif ($vmtype eq "vmware") {
1606                } else {
1607                        die "VM of type $vmtype not supported. Report to the dev team";
1608                }
1609                # Restore the ENV VAR Value
1610                $ENV{'PBVMOPT'} = $ENV{'PBOLDVMOPT'};
1611
1612                my ($tmpcmd,$void) = split(/ +/,$cmd);
1613                my $vmexist = pb_check_ps($tmpcmd,$vmm);
1614                my $vmpid = 0;
1615                if (! $vmexist) {
1616                        if ($create != 0) {
1617                                die("Found an existing Virtual machine $vmm. Won't overwrite") if (-r $vmm);
1618                                if (($vmtype eq "qemu") || ($vmtype eq "xen") || ($vmtype eq "kvm")) {
1619                                        pb_system("/usr/bin/qemu-img create -f qcow2 $vmm $vmsize->{$ENV{'PBPROJ'}}","Creating the QEMU VM");
1620                                } elsif ($vmtype eq "vmware") {
1621                                } else {
1622                                }
1623                        }
1624                        if (! -f "$vmm") {
1625                                pb_log(0,"Unable to find VM $vmm\n");
1626                        } else {
1627                                pb_system("$cmd &","Launching the VM $vmm");
1628                                pb_system("sleep $ENV{'PBVMTMOUT'}","Waiting $ENV{'PBVMTMOUT'} s for VM $v to come up");
1629                                $vmpid = pb_check_ps($tmpcmd,$vmm);
1630                                pb_log(0,"VM $vmm launched (pid $vmpid)\n");
1631                        }
1632                } else {
1633                        pb_log(0,"Found an existing VM $vmm (pid $vmexist)\n");
1634                }
1635                pb_log(2,"DEBUG: pb_launchv returns ($vmexist,$vmpid)\n");
1636                return($vmexist,$vmpid);
1637        # VE here
1638        } else {
1639                # Get VE context
1640                my ($ptr,$vetmout,$vepath,$verebuild,$veconf,$vepostinstall) = pb_conf_get("vetype","vetmout","vepath","verebuild","veconf");
1641                my ($veb4pi,$vepi,$vepkglist,$vesnap) = pb_conf_get_if("veb4pi","vepi","vepkglist","vesnap");
1642                my $vetype = $ptr->{$ENV{'PBPROJ'}};
1643
1644                # Get distro context
1645                my ($name,$ver,$darch) = split(/-/,$v);
1646                chomp($darch);
1647                my ($ddir, $dver, $dfam, $dtype, $pbsuf) = pb_distro_init($name,$ver,$darch);
1648
1649                if (($vetype eq "chroot") || ($vetype eq "schroot")) {
1650                        # Architecture consistency
1651                        if ($arch ne $darch) {
1652                                die "Unable to launch a VE of architecture $darch on a $arch platform" if (($darch eq "x86_64") && ($arch =~ /i?86/));
1653                        }
1654
1655                        my ($verpmtype) = pb_conf_get("verpmtype");
1656                        if (($create != 0) || ($verebuild->{$ENV{'PBPROJ'}} eq "true") || ($pbforce == 1)) {
1657                                # We have to rebuild the chroot
1658                                if ($dtype eq "rpm") {
1659
1660                                        my $verpmstyle = pb_distro_get_param($ddir,$dver,$darch,$verpmtype);
1661                                        if ($verpmstyle eq "rinse") {
1662                                                # Need to reshape the mirrors generated with local before-post-install script
1663                                                my $b4post = "--before-post-install ";
1664                                                my $postparam = pb_distro_get_param($ddir,$dver,$darch,$veb4pi);
1665                                                if ($postparam eq "") {
1666                                                        $b4post = "";
1667                                                } else {
1668                                                        $b4post .= $postparam;
1669                                                }
1670                                                # Do we have a local post-install script
1671                                                my $post = "--post-install ";
1672                                                $postparam = pb_distro_get_param($ddir,$dver,$darch,$vepi);
1673                                                if ($postparam eq "") {
1674                                                        $post = "";
1675                                                } else {
1676                                                        $post .= $postparam;
1677                                                }
1678
1679                                                # Need to reshape the package list for pb
1680                                                my $addpkgs;
1681                                                $postparam = pb_distro_get_param($ddir,$dver,$darch,$vepkglist);
1682                                                if ($postparam eq "") {
1683                                                        $addpkgs = "";
1684                                                } else {
1685                                                        my $pkgfile = "$ENV{'PBTMP'}/addpkgs.lis";
1686                                                        open(PKG,"> $pkgfile") || die "Unable to create $pkgfile";
1687                                                        foreach my $p (split(/,/,$postparam)) {
1688                                                                print PKG "$p\n";
1689                                                        }
1690                                                        close(PKG);
1691                                                        $addpkgs = "--add-pkg-list $pkgfile";
1692                                                }
1693                                                my $rinseverb = "";
1694                                                $rinseverb = "--verbose" if ($pbdebug gt 0);
1695
1696                                                pb_system("sudo /usr/sbin/rinse --directory \"$vepath->{$ENV{'PBPROJ'}}/$ddir/$dver/$darch\" --arch \"$darch\" --distribution \"$ddir-$dver\" --config \"$veconf->{$ENV{'PBPROJ'}}\" $b4post $post $addpkgs $rinseverb","Creating the rinse VE for $ddir-$dver ($darch)", "verbose");
1697                                        } elsif ($verpmstyle eq "mock") {
1698                                                pb_system("sudo /usr/sbin/mock --init --resultdir=\"/tmp\" --configdir=\"$veconf->{$ENV{'PBPROJ'}}\" -r $v","Creating the mock VE for $ddir-$dver ($darch)");
1699                                                # Once setup we need to install some packages, the pb account, ...
1700                                                pb_system("sudo /usr/sbin/mock --install --configdir=\"$veconf->{$ENV{'PBPROJ'}}\" -r $v su","Configuring the mock VE");
1701                                        }
1702                                } elsif ($dtype eq "deb") {
1703                                        pb_system("","Creating the pbuilder VE TBD");
1704                                } elsif ($dtype eq "ebuild") {
1705                                        die "Please teach the dev team how to build gentoo chroot";
1706                                } else {
1707                                        die "Unknown distribution type $dtype. Report to dev team";
1708                                }
1709                        }
1710                        # Test if an existing snapshot exists and use it if appropriate
1711                        # And also use it of no local extracted VE is present
1712                        if ((-f "$vepath->{$ENV{'PBPROJ'}}/$ddir-$dver-$darch.tar.gz") &&
1713                                (((defined $vesnap->{$v}) && ($vesnap->{$v} =~ /true/i)) ||
1714                                        ((defined $vesnap->{$ENV{'PBPROJ'}}) && ($vesnap->{$ENV{'PBPROJ'}} =~ /true/i)) ||
1715                                        ($pbsnap eq 1) ||
1716                                        (! -d "$vepath->{$ENV{'PBPROJ'}}/$ddir/$dver/$darch"))) {
1717                                                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");
1718                        }
1719                        # Nothing more to do for VE. No real launch
1720                } else {
1721                        die "VE of type $vetype not supported. Report to the dev team";
1722                }
1723        }
1724}
1725
1726# Return string for date synchro
1727sub pb_date2v {
1728
1729my $vtype = shift;
1730my $v = shift;
1731
1732my ($ntp) = pb_conf_get($vtype."ntp");
1733my $vntp = $ntp->{$ENV{'PBPROJ'}};
1734my $ntpline;
1735
1736if (defined $vntp) {
1737        my ($ntpcmd) = pb_conf_get($vtype."ntpcmd");
1738        my $vntpcmd;
1739        if (defined $ntpcmd->{$v}) {
1740                $vntpcmd = $ntpcmd->{$v};
1741        } elsif (defined $ntpcmd->{$ENV{'PBPROJ'}}) {
1742                $vntpcmd = $ntpcmd->{$ENV{'PBPROJ'}};
1743        } else {
1744                $vntpcmd = "/bin/true";
1745        }
1746        $ntpline = "sudo $vntpcmd $vntp";
1747} else {
1748        $ntpline = undef;
1749}
1750# Force new date to be in the future compared to the date
1751# of the host by adding 1 minute
1752my @date=pb_get_date();
1753$date[1]++;
1754my $upddate = strftime("%m%d%H%M%Y", @date);
1755my $dateline = "sudo date $upddate";
1756return($ntpline,$dateline);
1757}
1758
1759sub pb_build2v {
1760
1761my $vtype = shift;
1762my $action = shift || "build";
1763
1764my ($v,$all) = pb_get2v($vtype);
1765
1766# Send tar files when we do a global generation
1767pb_build2ssh() if (($all == 1) && ($action eq "build"));
1768
1769my ($vmexist,$vmpid) = (undef,undef);
1770
1771foreach my $v (@$v) {
1772        # Prepare the script to be executed on the VM/VE
1773        # in $ENV{'PBDESTDIR'}/pbscript
1774        open(SCRIPT,"> $ENV{'PBDESTDIR'}/pbscript") || die "Unable to create $ENV{'PBDESTDIR'}/pbscript";
1775        print SCRIPT "#!/bin/bash\n";
1776
1777        # Transmit the verbosity level to the virtual env/mach.
1778        my $verbose = "";
1779        my $i = 0;                                                      # minimal debug level
1780        while ($i lt $pbdebug) {
1781                $verbose .= "-v ";
1782                $i++;
1783        }
1784        # Activate script verbosity if at least 2 for pbdebug
1785        print SCRIPT "set -x\n" if ($i gt 1);
1786        # Quiet if asked to be so on the original system
1787        $verbose = "-q" if ($pbdebug eq -1);
1788
1789        print SCRIPT "echo ... Execution needed\n";
1790        print SCRIPT "# This is in directory delivery\n";
1791        print SCRIPT "# Setup the variables required for building\n";
1792        print SCRIPT "export PBPROJ=$ENV{'PBPROJ'}\n";
1793
1794        if ($action eq "build") {
1795                print SCRIPT "# Preparation for pb\n";
1796                print SCRIPT "mv .pbrc \$HOME\n";
1797                print SCRIPT "cd ..\n";
1798        }
1799
1800        # VE needs a good /proc
1801        if ($vtype eq "ve") {
1802                print SCRIPT "sudo mount -t proc /proc /proc\n";
1803        }
1804
1805        my ($ntpline,$dateline) = pb_date2v($vtype,$v);
1806        print SCRIPT "# Time sync\n";
1807        print SCRIPT "echo 'setting up date with '";
1808        if (defined $ntpline) {
1809                print SCRIPT "echo $ntpline\n";
1810                print SCRIPT "$ntpline\n";
1811        } else {
1812                print SCRIPT "echo $dateline\n";
1813                print SCRIPT "$dateline\n";
1814        }
1815        # Use potential local proxy declaration in case we need it to download repo, pkgs, ...
1816        if (defined $ENV{'http_proxy'}) {
1817                print SCRIPT "export http_proxy=\"$ENV{'http_proxy'}\"\n";
1818        }
1819
1820        if (defined $ENV{'ftp_proxy'}) {
1821                print SCRIPT "export ftp_proxy=\"$ENV{'ftp_proxy'}\"\n";
1822        }
1823
1824        # Get list of packages to build/test and get some ENV vars as well
1825        my $ptr = pb_get_pkg();
1826        @pkgs = @$ptr;
1827        my $p = join(' ',@pkgs) if (@pkgs);
1828        print SCRIPT "export PBPROJVER=$ENV{'PBPROJVER'}\n";
1829        print SCRIPT "export PBPROJTAG=$ENV{'PBPROJTAG'}\n";
1830        print SCRIPT "export PBPACKAGER=\"$ENV{'PBPACKAGER'}\"\n";
1831
1832        # We may need to do some other tasks before building. Read a script here to finish setup
1833        if (-x "$ENV{'PBDESTDIR'}/pb$vtype".".pre") {
1834                print SCRIPT "# Special pre-instructions to be launched\n";
1835                print SCRIPT pb_get_content("$ENV{'PBDESTDIR'}/pb$vtype".".pre");
1836        }
1837
1838        if (-x "$ENV{'PBDESTDIR'}/pb$vtype"."$action.pre") {
1839                print SCRIPT "# Special pre-$action instructions to be launched\n";
1840                print SCRIPT pb_get_content("$ENV{'PBDESTDIR'}/pb$vtype"."$action.pre");
1841        }
1842
1843        print SCRIPT "# $action\n";
1844        print SCRIPT "echo $action"."ing packages on $vtype...\n";
1845
1846        if (($action eq "test") && (! -x "$ENV{'PBDESTDIR'}/pbtest")) {
1847                        die "No test script ($ENV{'PBDESTDIR'}/pbtest) found when in test mode. Aborting ...";
1848        }
1849        print SCRIPT "pb $verbose -p $ENV{'PBPROJ'} $action"."2pkg $p\n";
1850
1851        if ($vtype eq "ve") {
1852                print SCRIPT "sudo umount /proc\n";
1853        }
1854
1855        # We may need to do some other tasks after building. Read a script here to exit properly
1856        if (-x "$ENV{'PBDESTDIR'}/pb$vtype"."$action.post") {
1857                print SCRIPT "# Special post-$action instructions to be launched\n";
1858                print SCRIPT pb_get_content("$ENV{'PBDESTDIR'}/pb$vtype"."$action.post");
1859        }
1860
1861        if (-x "$ENV{'PBDESTDIR'}/pb$vtype".".post") {
1862                print SCRIPT "# Special post-instructions to be launched\n";
1863                print SCRIPT pb_get_content("$ENV{'PBDESTDIR'}/pb$vtype".".post");
1864        }
1865
1866        close(SCRIPT);
1867        chmod 0755,"$ENV{'PBDESTDIR'}/pbscript";
1868       
1869        # Launch the VM/VE
1870        ($vmexist,$vmpid) = pb_launchv($vtype,$v,0);
1871
1872        if ($vtype eq "vm") {
1873                # Skip that VM if it something went wrong
1874                next if (($vmpid == 0) && ($vmexist == 0));
1875        } else {
1876                # VE
1877                $vmexist = 0;
1878                $vmpid = 0;
1879        }
1880        # Gather all required files to send them to the VM/VE
1881        # and launch the build through pbscript
1882        pb_log(2,"Calling send2target $vtype,$v,$vmexist,$vmpid\n");
1883        pb_send2target(uc($vtype).$action,"$v",$vmexist,$vmpid);
1884}
1885}
1886
1887
1888sub pb_clean {
1889
1890        my $sleep=10;
1891        die "Unable to get env var PBDESTDIR" if (not defined $ENV{'PBDESTDIR'});
1892        die "Unable to get env var PBBUILDDIR" if (not defined $ENV{'PBBUILDDIR'});
1893        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");
1894        sleep $sleep;
1895        pb_rm_rf($ENV{'PBDESTDIR'});
1896        pb_rm_rf($ENV{'PBBUILDDIR'});
1897}
1898
1899sub pb_newver {
1900
1901        die "-V Version parameter needed" if ((not defined $newver) || ($newver eq ""));
1902
1903        # Need this call for PBDIR
1904        my ($scheme2,$uri) = pb_cms_init($pbinit);
1905
1906        my ($pbconf) = pb_conf_get("pbconfurl");
1907        $uri = $pbconf->{$ENV{'PBPROJ'}};
1908        my ($scheme, $account, $host, $port, $path) = pb_get_uri($uri);
1909
1910        # Checking CMS repositories status
1911        my ($pburl) = pb_conf_get("pburl");
1912        ($scheme2, $account, $host, $port, $path) = pb_get_uri($pburl->{$ENV{'PBPROJ'}});
1913
1914        if ($scheme !~ /^svn/) {
1915                die "Only SVN is supported at the moment";
1916        }
1917
1918        my $res = pb_cms_isdiff($scheme,$ENV{'PBROOTDIR'});
1919        die "ERROR: No differences accepted in CMS for $ENV{'PBROOTDIR'} before creating a new version" if ($res != 0);
1920
1921        $res = pb_cms_isdiff($scheme2,$ENV{'PBDIR'});
1922        die "ERROR: No differences accepted in CMS for $ENV{'PBDIR'} before creating a new version" if ($res != 0);
1923
1924        # Tree identical between PBCONFDIR and PBROOTDIR. The delta is what
1925        # we want to get for the root of the new URL
1926
1927        my $tmp = $ENV{'PBROOTDIR'};
1928        $tmp =~ s|^$ENV{'PBCONFDIR'}||;
1929
1930        my $newurl = "$uri/".dirname($tmp)."/$newver";
1931        # Should probably use projver in the old file
1932        my $oldver= basename($tmp);
1933
1934        # Duplicate and extract project-builder part
1935        pb_log(2,"Copying $uri/$tmp to $newurl\n");
1936        pb_cms_copy($scheme,"$uri/$tmp",$newurl);
1937        pb_log(2,"Checkout $newurl to $ENV{'PBROOTDIR'}/../$newver\n");
1938        pb_cms_up($scheme,"$ENV{'PBCONFDIR'}/..");
1939
1940        # Duplicate and extract project
1941        my $newurl2 = "$pburl->{$ENV{'PBPROJ'}}/".dirname($tmp)."/$newver";
1942
1943        pb_log(2,"Copying $pburl->{$ENV{'PBPROJ'}}/$tmp to $newurl2\n");
1944        pb_cms_copy($scheme2,"$pburl->{$ENV{'PBPROJ'}}/$tmp",$newurl2);
1945        pb_log(2,"Checkout $newurl2 to $ENV{'PBDIR'}/../$newver\n");
1946        pb_cms_up($scheme2,"$ENV{'PBDIR'}/..");
1947
1948        # Update the .pb file
1949        open(FILE,"$ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb") || die "Unable to open $ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb";
1950        open(OUT,"> $ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb.new") || die "Unable to write to $ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb.new";
1951        while(<FILE>) {
1952                s/^projver\s+$ENV{'PBPROJ'}\s*=\s*$oldver/projver $ENV{'PBPROJ'} = $newver/;
1953                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/);
1954                s/^testver/#testver/;
1955                pb_log(0,"Commenting testver in $ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb\n") if (/^testver/);
1956                print OUT $_;
1957        }
1958        close(FILE);
1959        close(OUT);
1960        rename("$ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb.new","$ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb");
1961
1962        # Checking pbcl files
1963        foreach my $f (<$ENV{'PBROOTDIR'}/*/pbcl>) {
1964                # Compute new pbcl file
1965                my $f2 = $f;
1966                $f2 =~ s|$ENV{'PBROOTDIR'}|$ENV{'PBROOTDIR'}/../$newver/|;
1967                open(PBCL,$f) || die "Unable to open $f";
1968                my $foundnew = 0;
1969                while (<PBCL>) {
1970                        $foundnew = 1 if (/^$newver \(/);
1971                }
1972                close(PBCL);
1973                open(OUT,"> $f2") || die "Unable to write to $f2: $!";
1974                open(PBCL,$f) || die "Unable to open $f";
1975                while (<PBCL>) {
1976                        print OUT "$_" if (not /^$oldver \(/);
1977                        if ((/^$oldver \(/) && ($foundnew == 0)) {
1978                                print OUT "$newver ($pbdate)\n";
1979                                print OUT "- TBD\n";
1980                                print OUT "\n";
1981                                pb_log(0,"WARNING: version $newver not found in $f so added to $f2...\n") if ($foundnew == 0);
1982                        }
1983                }
1984                close(OUT);
1985                close(PBCL);
1986        }
1987
1988        pb_log(2,"Checkin $ENV{'PBROOTDIR'}/../$newver\n");
1989        pb_cms_checkin($scheme,"$ENV{'PBROOTDIR'}/../$newver",undef);
1990}
1991
1992#
1993# Return the list of VMs/VEs we are working on
1994# $all is a flag to know if we return all of them
1995# or only some (if all we publish also tar files in addition to pkgs
1996#
1997sub pb_get2v {
1998
1999my $vtype = shift;
2000my @v;
2001my $all = 0;
2002my $vlist;
2003my $pbv = 'PBV';
2004
2005if ($vtype eq "vm") {
2006        $vlist = "vmlist";
2007} elsif ($vtype eq "ve") {
2008        $vlist = "velist";
2009}
2010# Get VM/VE list
2011if ((not defined $ENV{$pbv}) || ($ENV{$pbv} =~ /^all$/)) {
2012        my ($ptr) = pb_conf_get($vlist);
2013        $ENV{$pbv} = $ptr->{$ENV{'PBPROJ'}};
2014        $all = 1;
2015}
2016pb_log(2,"$vtype: $ENV{$pbv}\n");
2017@v = split(/,/,$ENV{$pbv});
2018return(\@v,$all);
2019}
2020
2021# Function to create a potentialy missing pb account on the VM/VE, and adds it to sudo
2022# Needs to use root account to connect to the VM/VE
2023# pb will take your local public SSH key to access
2024# the pb account in the VM later on if needed
2025sub pb_setup2v {
2026
2027my $vtype = shift;
2028
2029my ($vm,$all) = pb_get2v($vtype);
2030
2031# Script generated
2032my $pbscript = "$ENV{'PBDESTDIR'}/setupv";
2033
2034foreach my $v (@$vm) {
2035        # Deal with date sync.
2036        my ($ntpline,$dateline) = pb_date2v($vtype,$v);
2037
2038        # Name of the account to deal with for VM/VE
2039        # Do not use the one passed potentially with -a
2040        my ($pbac) = pb_conf_get($vtype."login");
2041        my ($key,$zero0,$zero1,$zero2);
2042        my ($vmexist,$vmpid);
2043
2044        # Prepare the script to be executed on the VM/VE
2045        # in $ENV{'PBDESTDIR'}/setupv
2046        open(SCRIPT,"> $pbscript") || die "Unable to create $pbscript";
2047       
2048        print SCRIPT << 'EOF';
2049#!/usr/bin/perl -w
2050
2051use strict;
2052use File::Copy;
2053
2054# We should not need in this script more functions than what is provided
2055# by Base and Distribution to avoid problems at exec time.
2056# They are appended at the end.
2057
2058our $pbdebug;
2059our $pbLOG;
2060our $pbsynmsg = "pbscript";
2061our $pbdisplaytype = "text";
2062our $pblocale = "";
2063pb_log_init($pbdebug, $pbLOG);
2064pb_temp_init();
2065
2066EOF
2067
2068        # Launch the VM/VE - Usage of snapshot disabled
2069        ($vmexist,$vmpid) = pb_launchv($vtype,$v,0,0,0);
2070
2071        if ($vtype eq "vm") {
2072                # Prepare the key to be used and transfered remotely
2073                my $keyfile = pb_ssh_get(1);
2074               
2075                my ($vmhost,$vmport,$vmntp) = pb_conf_get("vmhost","vmport","vmntp");
2076                my $nport = $vmport->{$ENV{'PBPROJ'}};
2077                $nport = "$pbport" if (defined $pbport);
2078       
2079                # Skip that VM if something went wrong
2080                next if (($vmpid == 0) && ($vmexist == 0));
2081       
2082                # Store the pub key part in a variable
2083                open(FILE,"$keyfile.pub") || die "Unable to open $keyfile.pub";
2084                ($zero0,$zero1,$zero2) = split(/ /,<FILE>);
2085                close(FILE);
2086
2087                $key = "\Q$zero1";
2088
2089                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\"","Copying local keys to $vtype. This may require the root password");
2090                # once this is done, we can do what we want on the VM remotely
2091        } elsif ($vtype eq "ve") {
2092                # We need to finish the setup of packages needed in the VE if needed
2093                # rinse at least needs it
2094                my ($vepkglist) = pb_conf_get_if("vepkglist");
2095
2096                if (defined $vepkglist) {
2097                        # Get distro context
2098                        my ($name,$ver,$darch) = split(/-/,$v);
2099                        chomp($darch);
2100                        my ($ddir, $dver, $dfam, $dtype, $pbsuf, $pbupd) = pb_distro_init($name,$ver,$darch);
2101       
2102                        my $postparam = pb_distro_get_param($ddir,$dver,$darch,$vepkglist);
2103                        # Change the list of pkg in to a space separated list
2104                        $postparam =~ s/,/ /g;
2105                        # remove potential sudo from the update command for this time,
2106                        # as this will be run as root anyway, and if not we will have
2107                        # a problem with tty
2108                        $pbupd =~ s/sudo //g;
2109
2110                        print SCRIPT << "EOF";
2111# For VE we first need to mount some FS
2112pb_system("mount -t proc /proc /proc");
2113
2114# For VE we need a good null dev
2115pb_system("rm -f /dev/null; mknod /dev/null c 1 3; chmod 777 /dev/null");
2116
2117# For VE we need some additional packages that are not there yet
2118pb_system("$pbupd $postparam");
2119
2120EOF
2121                }
2122        }
2123        if ($vtype eq "vm") {
2124                print SCRIPT << 'EOF';
2125# Removes duplicate in .ssh/authorized_keys of our key if needed
2126#
2127my $file1="$ENV{'HOME'}/.ssh/authorized_keys";
2128open(PBFILE,$file1) || die "Unable to open $file1";
2129open(PBOUT,"> $file1.new") || die "Unable to open $file1.new";
2130my $count = 0;
2131while (<PBFILE>) {
2132
2133EOF
2134                print SCRIPT << "EOF";
2135        if (/ $key /) {
2136                \$count++;
2137        }
2138print PBOUT \$_ if ((\$count <= 1) || (\$_ !~ / $key /));
2139}
2140close(PBFILE);
2141close(PBOUT);
2142rename("\$file1.new",\$file1);
2143chmod 0600,\$file1;
2144
2145# Sync date
2146EOF
2147                if (defined $ntpline) {
2148                        print SCRIPT "system(\"$ntpline\");\n";
2149                } else {
2150                        print SCRIPT "system(\"$dateline\");\n";
2151                }
2152        }
2153        print SCRIPT << 'EOF';
2154
2155# Adds $pbac->{$ENV{'PBPROJ'}} as an account if needed
2156#
2157my $file="/etc/passwd";
2158open(PBFILE,$file) || die "Unable to open $file";
2159my $found = 0;
2160while (<PBFILE>) {
2161EOF
2162        print SCRIPT << "EOF";
2163        \$found = 1 if (/^$pbac->{$ENV{'PBPROJ'}}:/);
2164EOF
2165        print SCRIPT << 'EOF';
2166}
2167close(PBFILE);
2168
2169if ( $found == 0 ) {
2170        if ( ! -d "/home" ) {
2171                pb_mkdir("/home");
2172        }
2173EOF
2174        print SCRIPT << "EOF";
2175pb_system("groupadd $pbac->{$ENV{'PBPROJ'}}","Adding group $pbac->{$ENV{'PBPROJ'}}");
2176pb_system("useradd $pbac->{$ENV{'PBPROJ'}} -g $pbac->{$ENV{'PBPROJ'}} -m -d /home/$pbac->{$ENV{'PBPROJ'}}","Adding user $pbac->{$ENV{'PBPROJ'}} (group $pbac->{$ENV{'PBPROJ'}} - home /home/$pbac->{$ENV{'PBPROJ'}}");
2177}
2178EOF
2179
2180        if ($vtype eq "vm") {
2181                print SCRIPT << "EOF";
2182# allow ssh entry to build
2183#
2184mkdir "/home/$pbac->{$ENV{'PBPROJ'}}/.ssh",0700;
2185# Allow those accessing root to access the build account
2186copy("\$ENV{'HOME'}/.ssh/authorized_keys","/home/$pbac->{$ENV{'PBPROJ'}}/.ssh/authorized_keys");
2187chmod 0600,".ssh/authorized_keys";
2188pb_system("chown -R $pbac->{$ENV{'PBPROJ'}}:$pbac->{$ENV{'PBPROJ'}} /home/$pbac->{$ENV{'PBPROJ'}}","Finish setting up the account env for $pbac->{$ENV{'PBPROJ'}}");
2189
2190EOF
2191}
2192        print SCRIPT << 'EOF';
2193# No passwd for build account only keys
2194$file="/etc/shadow";
2195if (-f $file) {
2196        open(PBFILE,$file) || die "Unable to open $file";
2197        open(PBOUT,"> $file.new") || die "Unable to open $file.new";
2198        while (<PBFILE>) {
2199EOF
2200        print SCRIPT << "EOF";
2201                s/^$pbac->{$ENV{'PBPROJ'}}:\!\!:/$pbac->{$ENV{'PBPROJ'}}:*:/;
2202                s/^$pbac->{$ENV{'PBPROJ'}}:\!:/$pbac->{$ENV{'PBPROJ'}}:*:/;     #SLES 9 e.g.
2203EOF
2204                print SCRIPT << 'EOF';
2205                print PBOUT $_;
2206        }
2207        close(PBFILE);
2208        close(PBOUT);
2209        rename("$file.new",$file);
2210        chmod 0640,$file;
2211        }
2212
2213# Keep the VM in text mode
2214$file="/etc/inittab";
2215if (-f $file) {
2216        open(PBFILE,$file) || die "Unable to open $file";
2217        open(PBOUT,"> $file.new") || die "Unable to open $file.new";
2218        while (<PBFILE>) {
2219                s/^(..):5:initdefault:$/$1:3:initdefault:/;
2220                print PBOUT $_;
2221        }
2222        close(PBFILE);
2223        close(PBOUT);
2224        rename("$file.new",$file);
2225        chmod 0640,$file;
2226}
2227
2228# pb has to be added to portage group on gentoo
2229
2230# Adapt sudoers
2231$file="/etc/sudoers";
2232open(PBFILE,$file) || die "Unable to open $file";
2233open(PBOUT,"> $file.new") || die "Unable to open $file.new";
2234while (<PBFILE>) {
2235EOF
2236        print SCRIPT << "EOF";
2237        next if (/^$pbac->{$ENV{'PBPROJ'}}   /);
2238EOF
2239        print SCRIPT << 'EOF';
2240        s/Defaults[ \t]+requiretty//;
2241        print PBOUT $_;
2242}
2243close(PBFILE);
2244EOF
2245        print SCRIPT << "EOF";
2246# This is needed in order to be able to halt the machine from the $pbac->{$ENV{'PBPROJ'}} account at least
2247print PBOUT "Defaults:pb env_keep += \\\"http_proxy ftp_proxy\\\"\n";
2248print PBOUT "$pbac->{$ENV{'PBPROJ'}}   ALL=(ALL) NOPASSWD:ALL\n";
2249EOF
2250        print SCRIPT << 'EOF';
2251close(PBOUT);
2252rename("$file.new",$file);
2253chmod 0440,$file;
2254
2255EOF
2256               
2257        my $SCRIPT = \*SCRIPT;
2258       
2259        pb_install_deps($SCRIPT);
2260       
2261        print SCRIPT << 'EOF';
2262# Suse wants sudoers as 640
2263if (($ddir eq "sles") || (($ddir eq "opensuse") && ($dver =~ /10.[012]/))) {
2264        chmod 0640,$file;
2265}
2266
2267pb_system("rm -rf ProjectBuilder-* ; wget --passive-ftp ftp://ftp.mondorescue.org/src/ProjectBuilder-latest.tar.gz ; tar xvfz ProjectBuilder-latest.tar.gz ; cd ProjectBuilder-* ; perl Makefile.PL ; make ; make install ; cd .. ; rm -rf ProjectBuilder-* ; rm -rf project-builder-* ; wget --passive-ftp ftp://ftp.mondorescue.org/src/project-builder-latest.tar.gz ; tar xvfz project-builder-latest.tar.gz ; cd project-builder-* ; perl Makefile.PL ; make ; make install ; cd .. ; rm -rf project-builder-* ;","Building Project-Builder");
2268system "pb 2>&1 | head -5";
2269EOF
2270        if ($vtype eq "ve") {
2271                        print SCRIPT << 'EOF';
2272# For VE we need to umount some FS at the end
2273
2274pb_system("umount /proc");
2275
2276# Create a basic network file if not already there
2277
2278my $nf="/etc/sysconfig/network";
2279if (! -f $nf) {
2280        open(NF,"> $nf") || die "Unable to create $nf";
2281        print NF "NETWORKING=yes\n";
2282        print NF "HOSTNAME=localhost\n";
2283        close(NF);
2284}
2285chmod 0755,$nf;
2286EOF
2287        }
2288
2289        # Adds pb_distro_init from ProjectBuilder::Distribution and Base
2290        foreach my $d (@INC) {
2291                my @f = ("$d/ProjectBuilder/Base.pm","$d/ProjectBuilder/Distribution.pm");
2292                foreach my $f (@f) {
2293                        if (-f "$f") {
2294                                open(PBD,"$f") || die "Unable to open $f";
2295                                while (<PBD>) {
2296                                                next if (/^package/);
2297                                                next if (/^use Exporter/);
2298                                                next if (/^use ProjectBuilder::/);
2299                                                next if (/^our /);
2300                                        print SCRIPT $_;
2301                                }
2302                                close(PBD);
2303                        }
2304                }
2305        }
2306        close(SCRIPT);
2307        chmod 0755,"$pbscript";
2308
2309        # That build script needs to be run as root and force stop of VM at end
2310        $pbaccount = "root";
2311
2312        # Force shutdown of VM exept if it was already launched
2313        my $pbforce = 0;
2314        if ((! $vmexist) && ($vtype eq "vm")) {
2315                $pbforce = 1;
2316        }
2317       
2318        pb_script2v($pbscript,$vtype,$pbforce,$v);
2319}
2320return;
2321}
2322
2323# Function to create a snapshot named 'pb' for VMs and a compressed tar for VEs
2324sub pb_snap2v {
2325
2326my $vtype = shift;
2327
2328my ($vm,$all) = pb_get2v($vtype);
2329
2330# Script generated
2331my $pbscript = "$ENV{'PBDESTDIR'}/snapv";
2332
2333foreach my $v (@$vm) {
2334        # Name of the account to deal with for VM/VE
2335        # Do not use the one passed potentially with -a
2336        my ($pbac) = pb_conf_get($vtype."login");
2337        my ($vmexist,$vmpid);
2338
2339        # Prepare the script to be executed on the VM/VE
2340        # in $ENV{'PBDESTDIR'}/setupv
2341        open(SCRIPT,"> $pbscript") || die "Unable to create $pbscript";
2342       
2343        print SCRIPT << 'EOF';
2344        #!/bin/bash
2345        sleep 2
2346EOF
2347        close(SCRIPT);
2348        chmod 0755,"$pbscript";
2349
2350        # Force shutdown of VM/VE
2351        # Force snapshot of VM/VE
2352        pb_script2v($pbscript,$vtype,1,$v,1);
2353}
2354return;
2355}
2356
2357sub pb_install_deps {
2358
2359my $SCRIPT = shift;
2360
2361print {$SCRIPT} << 'EOF';
2362# We need to have that pb_distro_init function
2363# Get it from Project-Builder::Distribution
2364my ($ddir, $dver, $dfam, $dtype, $pbsuf, $pbupd, $arch) = pb_distro_init(); 
2365print "distro tuple: ".join(',',($ddir, $dver, $dfam, $dtype, $pbsuf, $arch))."\n";
2366
2367# We may need a proxy configuration. Get it from the local env
2368EOF
2369
2370if (defined $ENV{'http_proxy'}) {
2371        print SCRIPT "\$ENV\{'http_proxy'\}=\"$ENV{'http_proxy'}\";\n";
2372}
2373
2374if (defined $ENV{'ftp_proxy'}) {
2375        print SCRIPT "\$ENV\{'ftp_proxy'\}=\"$ENV{'ftp_proxy'}\";\n";
2376}
2377
2378print {$SCRIPT} << 'EOF';
2379# Get and install pb
2380my $insdm = "rm -rf Date-Manip* ; wget http://search.cpan.org/CPAN/authors/id/S/SB/SBECK/Date-Manip-5.54.tar.gz ; tar xvfz Date-Manip-5.54.tar.gz ; cd Date-Manip* ; perl Makefile.PL ; make ; make install ; cd .. ; rm -rf Date-Manip*";
2381my $insmb = "rm -rf Module-Build* ; wget http://search.cpan.org/CPAN/authors/id/K/KW/KWILLIAMS/Module-Build-0.2808.tar.gz ; tar xvfz Module-Build-0.2808.tar.gz ; cd Module-Build* ; perl Makefile.PL ; make ; make install ; cd .. ; rm -rf Module-Build*";
2382my $insfm = "rm -rf File-MimeInfo* ; wget http://search.cpan.org/CPAN/authors/id/P/PA/PARDUS/File-MimeInfo/File-MimeInfo-0.15.tar.gz ; tar xvfz File-MimeInfo-0.15.tar.gz ; cd File-MimeInfo* ; perl Makefile.PL ; make ; make install ; cd .. ; rm -rf File-MimeInfo*";
2383my $insfb = "rm -rf File-Basedir* ; wget http://search.cpan.org/CPAN/authors/id/P/PA/PARDUS/File-BaseDir-0.03.tar.gz ; tar xvfz File-BaseDir-0.03.tar.gz ; cd File-BaseDir* ; perl Makefile.PL ; make ; make install ; cd .. ; rm -rf File-BaseDir*";
2384my $insms = "rm -rf Mail-Sendmail* ; wget http://search.cpan.org/CPAN/authors/id/M/MI/MIVKOVIC/Mail-Sendmail-0.79.tar.gz ; tar xvfz Mail-Sendmail-0.79.tar.gz ; cd Mail-Sendmail* ; perl Makefile.PL ; make ; make install ; cd .. ; rm -rf Mail-Sendmail*";
2385my $cmtdm = "Installing Date-Manip perl module";
2386my $cmtmb = "Installing Module-Build perl module";
2387my $cmtfm = "Installing File-MimeInfo perl module";
2388my $cmtfb = "Installing File-Basedir perl module";
2389my $cmtms = "Installing Perl-Sendmail perl module";
2390my $cmtall = "Installing required modules";
2391
2392if ( $ddir eq "fedora" ) {
2393        pb_system("yum clean all","Cleaning yum env");
2394        if ($dver == 4) {
2395                pb_distro_installdeps(undef,$dtype,$pbupd,pb_distro_only_deps_needed($dtype,"rpm-build wget patch ntp sudo perl-DateManip perl-ExtUtils-MakeMaker"));
2396                pb_system("$insmb","$cmtmb");
2397                pb_system("$insfm","$cmtfm");
2398                pb_system("$insfb","$cmtfb");
2399                pb_system("$insms","$cmtms");
2400        } else {
2401                pb_distro_installdeps(undef,$dtype,$pbupd,pb_distro_only_deps_needed($dtype,"rpm-build wget patch ntp sudo perl-DateManip perl-ExtUtils-MakeMaker perl-File-MimeInfo perl-Mail-Sendmail"));
2402        }
2403} elsif ($ddir eq "asianux") {
2404        pb_system("yum clean all","Cleaning yum env");
2405        pb_distro_installdeps(undef,$dtype,$pbupd,pb_distro_only_deps_needed($dtype,"rpm-build wget patch ntp sudo perl-DateManip"));
2406        pb_system("$insmb","$cmtmb");
2407        pb_system("$insfm","$cmtfm");
2408        pb_system("$insfb","$cmtfb");
2409        pb_system("$insms","$cmtms");
2410} elsif (( $dfam eq "rh" ) || ($ddir eq "suse") || ($ddir eq "sles") || (($ddir eq "opensuse") && (($dver eq "10.1") || ($dver eq "10.0"))) || ($ddir eq "slackware")) {
2411        # Suppose pkg are installed already as no online mirror available
2412        pb_system("rpm -e lsb 2>&1 > /dev/null","Removing lsb package");
2413        pb_system("$insdm","$cmtdm");
2414        pb_system("$insmb","$cmtmb");
2415        pb_system("$insfm","$cmtfm");
2416        pb_system("$insfb","$cmtfb");
2417        pb_system("$insms","$cmtms");
2418} elsif ($ddir eq "opensuse") { 
2419        # New OpenSuSE
2420        pb_distro_installdeps(undef,$dtype,$pbupd,pb_distro_only_deps_needed($dtype,"make wget patch sudo ntp"));
2421        pb_system("$insmb","$cmtmb");
2422        pb_system("$insfm","$cmtfm");
2423        pb_system("$insfb","$cmtfb");
2424        pb_distro_installdeps(undef,$dtype,$pbupd,pb_distro_only_deps_needed($dtype,"perl-Date-Manip perl-File-HomeDir perl-Mail-Sendmail"));
2425        if ($dver < 11) {
2426                pb_distro_installdeps(undef,$dtype,$pbupd,pb_distro_only_deps_needed($dtype,"ntp"));
2427        } else {
2428                pb_distro_installdeps(undef,$dtype,$pbupd,pb_distro_only_deps_needed($dtype,"sntp"));
2429        }
2430} elsif ( $dfam eq "md" ) {
2431                my $addp = "";
2432                if (($ddir eq "mandrake") && ($dver eq "10.1")) {
2433                        pb_system("$insdm","$cmtdm");
2434                } else {
2435                        $addp ="perl-DateManip";
2436                }
2437                pb_distro_installdeps(undef,$dtype,$pbupd,pb_distro_only_deps_needed($dtype,"rpm-build wget sudo patch ntp-client perl-File-MimeInfo perl-Mail-Sendmail $addp"));
2438} elsif ( $dfam eq "du" ) {
2439        if (( $dver eq "3.1" ) && ($ddir eq "debian")) {
2440                pb_system("$insfb","$cmtfb");
2441                pb_system("$insfm","$cmtfm");
2442                pb_distro_installdeps(undef,$dtype,$pbupd,pb_distro_only_deps_needed($dtype,"wget patch ssh sudo debian-builder dh-make fakeroot ntpdate libmodule-build-perl libdate-manip-perl libmail-sendmail-perl"));
2443        } else  {
2444                pb_distro_installdeps(undef,$dtype,$pbupd,pb_distro_only_deps_needed($dtype,"wget patch openssh-server dpkg-dev sudo debian-builder dh-make fakeroot ntpdate libfile-mimeinfo-perl libmodule-build-perl libdate-manip-perl libmail-sendmail-perl"));
2445        }
2446} elsif ( $dfam eq "gen" ) {
2447                #system "emerge -u system";
2448                pb_distro_installdeps(undef,$dtype,$pbupd,pb_distro_only_deps_needed($dtype,"wget sudo ntp DateManip File-MimeInfo Mail-Sendmail"));
2449} else {
2450        pb_log(0,"No pkg to install\n");
2451}
2452EOF
2453}
2454
2455sub pb_announce {
2456
2457        # Get all required parameters
2458        my ($pbpackager,$pbrepo,$pbml,$pbsmtp) = pb_conf_get("pbpackager","pbrepo","pbml","pbsmtp");
2459        my ($pkgv, $pkgt, $testver) = pb_conf_get_if("pkgver","pkgtag","testver");
2460        my $pkg = pb_cms_get_pkg($defpkgdir,$extpkgdir);
2461        my @pkgs = @$pkg;
2462        my %pkgs;
2463        my $first = 0;
2464
2465        # Command to find packages on repo
2466        my $findstr = "find . ";
2467        # Generated announce files
2468        my @files;
2469
2470        foreach my $pbpkg (@pkgs) {
2471                if ($first != 0) {
2472                        $findstr .= "-o ";
2473                }
2474                $first++;
2475                if ((defined $pkgv) && (defined $pkgv->{$pbpkg})) {
2476                        $pbver = $pkgv->{$pbpkg};
2477                } else {
2478                        $pbver = $ENV{'PBPROJVER'};
2479                }
2480                if ((defined $pkgt) && (defined $pkgt->{$pbpkg})) {
2481                        $pbtag = $pkgt->{$pbpkg};
2482                } else {
2483                        $pbtag = $ENV{'PBPROJTAG'};
2484                }
2485
2486                # TODO: use virtual/real names here now
2487                $findstr .= "-name \'$pbpkg-$pbver-$pbtag\.*.rpm\' -o -name \'$pbpkg"."_$pbver*\.deb\' -o -name \'$pbpkg-$pbver\.ebuild\' ";
2488
2489                my $chglog;
2490
2491                # Get project info on log file and generate tmp files used later on
2492                pb_cms_init($pbinit);
2493                $chglog = "$ENV{'PBROOTDIR'}/$pbpkg/pbcl";
2494                $chglog = "$ENV{'PBROOTDIR'}/pbcl" if (! -f $chglog);
2495                $chglog = undef if (! -f $chglog);
2496
2497                open(OUT,"> $ENV{'PBTMP'}/$pbpkg.ann") || die "Unable to create $ENV{'PBTMP'}/$pbpkg.ann: $!";
2498                my %pb;
2499                $pb{'dtype'} = "announce";
2500                $pb{'realpkg'} = $pbpkg;
2501                $pb{'ver'} = $pbver;
2502                $pb{'tag'} = $pbtag;
2503                $pb{'suf'} = "N/A";             # Should not be empty even if unused
2504                $pb{'date'} = $pbdate;
2505                $pb{'chglog'} = $chglog;
2506                $pb{'packager'} = $pbpackager;
2507                $pb{'proj'} = $ENV{'PBPROJ'};
2508                $pb{'repo'} = $pbrepo;
2509                pb_changelog(\%pb,\*OUT,"yes");
2510                close(OUT);
2511                push(@files,"$ENV{'PBTMP'}/$pbpkg.ann");
2512        }
2513        $findstr .= " | grep -Ev \'src.rpm\'";
2514        if ((not defined $testver) || (not defined $testver->{$ENV{'PBPROJ'}}) || ($testver->{$ENV{'PBPROJ'}} !~ /true/i)) {
2515                $findstr .= " | grep -v ./test/";
2516        }
2517
2518        # Prepare the command to run and execute it
2519        open(PBS,"> $ENV{'PBTMP'}/pbscript") || die "Unable to create $ENV{'PBTMP'}/pbscript";
2520        print PBS "$findstr\n";
2521        close(PBS);
2522        chmod 0755,"$ENV{'PBTMP'}/pbscript";
2523        pb_send2target("Announce");
2524
2525        # Get subject line
2526        my $sl = "Project $ENV{'PBPROJ'} version $ENV{'PBPROJVER'} is now available";
2527        pb_log(0,"Please enter the title of your announce\n");
2528        pb_log(0,"(By default: $sl)\n");
2529        my $sl2 = <STDIN>;
2530        $sl = $sl2 if ($sl2 !~ /^$/);
2531
2532        # Prepare a template of announce
2533        open(ANN,"> $ENV{'PBTMP'}/announce.html") || die "Unable to create $ENV{'PBTMP'}/announce.html: $!";
2534        print ANN << "EOF";
2535$sl</p>
2536
2537<p>The project team is happy to announce the availability of a newest version of $ENV{'PBPROJ'} $ENV{'PBPROJVER'}. Enjoy it as usual!</p>
2538<p>
2539Now available at <a href="$pbrepo->{$ENV{'PBPROJ'}}">$pbrepo->{$ENV{'PBPROJ'}}</a>
2540</p>
2541<p>
2542EOF
2543        open(LOG,"$ENV{'PBTMP'}/system.log") || die "Unable to read $ENV{'PBTMP'}/system.log: $!";
2544        my $col = 2;
2545        my $i = 1;
2546        print ANN << 'EOF';
2547<TABLE WIDTH="700" CELLPADDING="0" CELLSPACING="0" BORDER="0">
2548<TR>
2549EOF
2550        while (<LOG>) {
2551                print ANN "<TD><A HREF=\"$pbrepo->{$ENV{'PBPROJ'}}/$_\">$_</A></TD>";
2552                $i++;
2553                if ($i > $col) {
2554                        print ANN "</TR>\n<TR>";
2555                        $i = 1;
2556                }
2557        }
2558        close(LOG);
2559        print ANN << "EOF";
2560</TR>
2561</TABLE>
2562</p>
2563
2564<p>As usual source packages are also available in the same directory.</p>
2565
2566<p>
2567Changes are :
2568</p>
2569<p>
2570EOF
2571        # Get each package changelog content
2572        foreach my $f (sort(@files)) {
2573                open(IN,"$f") || die "Unable to read $f:$!";
2574                while (<IN>) {
2575                        print ANN $_;
2576                }
2577                close(IN);
2578                print ANN "</p><p>\n";
2579        }
2580        print ANN "</p>\n";
2581        close(ANN);
2582
2583        # Allow for modification
2584        pb_system("vi $ENV{'PBTMP'}/announce.html","Allowing modification of the announce","noredir");
2585
2586        # Store it in DB for external usage (Web pages generation)
2587        my $db = "$ENV{'PBCONFDIR'}/announces3.sql";
2588
2589        my $precmd = "";
2590        if (! -f $db) {
2591                $precmd = "CREATE TABLE announces (id INTEGER PRIMARY KEY AUTOINCREMENT, date DATE, announce VARCHAR[65535])";
2592        }
2593
2594        my $dbh = DBI->connect("dbi:SQLite:dbname=$db","","",
2595                        { RaiseError => 1, AutoCommit => 1 })
2596                        || die "Unable to connect to $db";
2597
2598        if ($precmd ne "") {
2599                my $sth = $dbh->prepare(qq{$precmd})
2600                        || die "Unable to create table into $db";
2601                $sth->execute();
2602        }
2603
2604        # To read whole file
2605        local $/;
2606        open(ANN,"$ENV{'PBTMP'}/announce.html") || die "Unable to read $ENV{'PBTMP'}/announce.html: $!";
2607        my $announce = <ANN>;
2608        close(ANN);
2609       
2610        pb_log(2,"INSERT INTO announces VALUES (NULL, $pbdate, $announce)");
2611        my $sth = $dbh->prepare(qq{INSERT INTO announces VALUES (NULL,?,?)})
2612                        || die "Unable to insert into $db";
2613        $sth->execute($pbdate, $announce);
2614        $sth->finish();
2615        $dbh->disconnect;
2616
2617        # Then deliver it on the Web
2618        # $TOOLHOME/livwww www
2619
2620        # Mail it to project's ML
2621        open(ML,"| w3m -dump -T text/html > $ENV{'PBTMP'}/announce.txt") || die "Unable to create $ENV{'PBTMP'}/announce.txt: $!";
2622        print ML << 'EOF';
2623<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/x html1/DTD/xhtml1-strict.dtd">
2624
2625<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" xml:lang="en" lang="en">
2626  <head>
2627  </head>
2628  <body>
2629  <p>
2630EOF
2631        open(ANN,"$ENV{'PBTMP'}/announce.html") || die "Unable to read $ENV{'PBTMP'}/announce.html: $!";
2632        while(<ANN>) {
2633                print ML $_;
2634        }
2635        print ML << 'EOF';
2636</body>
2637</html>
2638EOF
2639        close(ML);
2640
2641        # To read whole file
2642        local $/;
2643        open(ANN,"$ENV{'PBTMP'}/announce.txt") || die "Unable to read $ENV{'PBTMP'}/announce.txt: $!";
2644        my $msg = <ANN>;
2645        close(ANN);
2646       
2647        # Preparation of headers
2648
2649        my %mail = (   
2650                        To                      =>      $pbml->{$ENV{'PBPROJ'}},
2651                        From            =>      $pbpackager->{$ENV{'PBPROJ'}},
2652                        Smtp            =>      $pbsmtp->{$ENV{'PBPROJ'}},
2653                        Body            =>      $msg,
2654                        Subject         =>      "[ANNOUNCE] $sl",
2655                );
2656                       
2657        # Send mail
2658        sendmail(%mail) or die "Unable to send mail ($Mail::Sendmail::error): $Mail::Sendmail::log";
2659}
2660
2661#
2662# Creates a set of HTML file containing the news for the project
2663# based on what has been generated by the pb_announce function
2664#
2665sub pb_web_news2html {
2666
2667        my $dest = shift || $ENV{'PBTMP'};
2668
2669        # Get all required parameters
2670        my ($pkgv, $pkgt, $testver) = pb_conf_get_if("pkgver","pkgtag","testver");
2671
2672        # DB of announces for external usage (Web pages generation)
2673        my $db = "$ENV{'PBCONFDIR'}/announces3.sql";
2674
2675        my $dbh = DBI->connect("dbi:SQLite:dbname=$db","","",
2676                        { RaiseError => 1, AutoCommit => 1 })
2677                        || die "Unable to connect to $db";
2678        # For date handling
2679        $ENV{LANGUAGE}="C";
2680        my $firstjan = strftime("%Y-%m-%d", 0, 0, 0, 1, 0, localtime->year(), 0, 0, -1);
2681        my $oldfirst = strftime("%Y-%m-%d", 0, 0, 0, 1, 0, localtime->year()-1, 0, 0, -1);
2682        pb_log(2,"firstjan: $firstjan, oldfirst: $oldfirst, pbdate:$pbdate\n");
2683        my $all = $dbh->selectall_arrayref("SELECT id,date,announce FROM announces ORDER BY date DESC");
2684        my %news;
2685        $news{"cy"} = "";       # current year's news
2686        $news{"ly"} = "";       # last year news
2687        $news{"py"} = "";       # previous years news
2688        $news{"fp"} = "";       # first page news
2689        my $cpt = 4;            # how many news for first page
2690        # Extract info from DB
2691        foreach my $row (@$all) {
2692                my ($id, $date, $announce) = @$row;
2693                $news{"cy"} = $news{"cy"}."<p><B>$date</B> $announce\n" if ((($date cmp $pbdate) le 0) && (($firstjan cmp $date) le 0));
2694                $news{"ly"} = $news{"ly"}."<p><B>$date</B> $announce\n" if ((($date cmp $firstjan) le 0) && (($oldfirst cmp $date) le 0));
2695                $news{"py"} = $news{"py"}."<p><B>$date</B> $announce\n" if (($date cmp $oldfirst) le 0);
2696                $news{"fp"} = $news{"fp"}."<p><B>$date</B> $announce\n" if ($cpt > 0);
2697                $cpt--;
2698        }
2699        pb_log(1,"news{fp}: ".$news{"fp"}."\n");
2700        $dbh->disconnect;
2701
2702        # Generate the HTML content
2703        foreach my $pref (keys %news) {
2704                open(NEWS,"> $dest/pb_web_$pref"."news.html") || die "Unable to create $dest/pb_web_$pref"."news.html: $!";
2705                print NEWS "$news{$pref}";
2706                close(NEWS);
2707        }
2708}
2709
2710
2711# Return the SSH key file to use
2712# Potentially create it if needed
2713
2714sub pb_ssh_get {
2715
2716my $create = shift || 0;        # Do not create keys by default
2717
2718# Check the SSH environment
2719my $keyfile = undef;
2720
2721# We have specific keys by default
2722$keyfile = "$ENV{'HOME'}/.ssh/pb_dsa";
2723if (!(-e $keyfile) && ($create eq 1)) {
2724        pb_system("ssh-keygen -q -b 1024 -N '' -f $keyfile -t dsa","Generating SSH keys for pb");
2725}
2726
2727$keyfile = "$ENV{'HOME'}/.ssh/id_rsa" if (-s "$ENV{'HOME'}/.ssh/id_rsa");
2728$keyfile = "$ENV{'HOME'}/.ssh/id_dsa" if (-s "$ENV{'HOME'}/.ssh/id_dsa");
2729$keyfile = "$ENV{'HOME'}/.ssh/pb_dsa" if (-s "$ENV{'HOME'}/.ssh/pb_dsa");
2730die "Unable to find your public ssh key under $keyfile" if (not defined $keyfile);
2731return($keyfile);
2732}
2733
2734
2735# Returns the pid of a running VM command using a specific VM file
2736sub pb_check_ps {
2737        my $vmcmd = shift;
2738        my $vmm = shift;
2739        my $vmexist = 0;                # FALSE by default
2740
2741        open(PS, "ps auxhww|") || die "Unable to call ps";
2742        while (<PS>) {
2743                next if (! /$vmcmd/);
2744                next if (! /$vmm/);
2745                my ($void1, $void2);
2746                ($void1, $vmexist, $void2) = split(/ +/);
2747                last;
2748        }
2749        return($vmexist);
2750}
2751
2752
2753sub pb_extract_build_files {
2754
2755my $src=shift;
2756my $dir=shift;
2757my $ddir=shift;
2758my $mandatory=shift || "spec";
2759my @files;
2760
2761my $flag = "mayfail" if ($mandatory eq "patch");
2762my $res;
2763
2764if ($src =~ /tar\.gz$/) {
2765        $res = pb_system("tar xfpz $src $dir","Extracting $mandatory files from $src",$flag);
2766} elsif ($src =~ /tar\.bz2$/) {
2767        $res = pb_system("tar xfpj $src $dir","Extracting $mandatory files from $src",$flag);
2768} else {
2769        die "Unknown compression algorithm for $src";
2770}
2771# If not mandatory return now
2772return() if (($res != 0) and ($mandatory eq "patch"));
2773opendir(DIR,"$dir") || die "Unable to open directory $dir";
2774foreach my $f (readdir(DIR)) {
2775        next if ($f =~ /^\./);
2776        # Skip potential patch dir
2777        next if ($f =~ /^pbpatch/);
2778        move("$dir/$f","$ddir") || die "Unable to move $dir/$f to $ddir";
2779        pb_log(2,"mv $dir/$f $ddir\n");
2780        push @files,"$ddir/$f";
2781}
2782closedir(DIR);
2783# Not enough but still a first cleanup
2784pb_rm_rf("$dir");
2785return(@files);
2786}
2787
2788sub pb_list_bfiles {
2789
2790my $dir = shift;
2791my $pbpkg = shift;
2792my $bfiles = shift;
2793my $pkgfiles = shift;
2794my $supfiles = shift;
2795
2796opendir(BDIR,"$dir") || die "Unable to open dir $dir: $!";
2797foreach my $f (readdir(BDIR)) {
2798        next if ($f =~ /^\./);
2799        $bfiles->{$f} = "$dir/$f";
2800        $bfiles->{$f} =~ s~$ENV{'PBROOTDIR'}~~;
2801        if (defined $supfiles->{$pbpkg}) {
2802                $pkgfiles->{$f} = "$dir/$f" if ($f =~ /$supfiles->{$pbpkg}/);
2803        }
2804}
2805closedir(BDIR);
2806}
2807
2808
2809#
2810# Return the list of packages we are working on in a non CMS action
2811#
2812sub pb_get_pkg {
2813
2814my @pkgs = ();
2815
2816my ($var) = pb_conf_read("$ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb","pbpkg");
2817@pkgs = keys %$var;
2818
2819pb_log(0,"Packages: ".join(',',@pkgs)."\n");
2820return(\@pkgs);
2821}
2822
28231;
Note: See TracBrowser for help on using the repository browser.