source: devel/pb/bin/pb @ 163

Last change on this file since 163 was 163, checked in by bruno, 12 years ago

Sets date in the VM to avoid build problem with configure
Improve the example script for VM

  • Property svn:executable set to *
File size: 26.3 KB
Line 
1#!/usr/bin/perl -w
2#
3# Project Builder main application
4#
5# $Id$
6#
7# Copyright B. Cornec 2007
8# Provided under the GPL v2
9
10# Syntax: see at end
11
12use strict 'vars';
13use Getopt::Std;
14use Data::Dumper;
15use English;
16use AppConfig qw(:argcount :expand);
17use File::Basename;
18use File::Copy;
19use Time::localtime qw(localtime);
20use POSIX qw(strftime);
21
22# Global variables
23use lib qw (lib);
24use ProjectBuilder::Distribution qw (pb_distro_init);
25use ProjectBuilder::Changelog qw (pb_changelog);
26use ProjectBuilder::Version qw (pb_version_init);
27use ProjectBuilder::Base qw (pb_conf_read pb_conf_get pb_cms_init pb_mkdir_p pb_system pb_rm_rf pb_get_filters pb_filter_file pb_filter_file_pb pb_cms_export pb_cms_log);
28
29my %opts;                   # CLI Options
30my $action;                 # action to realize
31my $test = "FALSE";
32my $option = "";
33my @pkgs;
34my $pbtag;                  # Global Tag variable
35my $pbver;                  # Global Version variable
36my $pbscript;               # Name of the script
37my %pbver;                  # per package
38my %pbtag;                  # per package
39my $pbrev;                  # Global REVISION variable
40my @date=(localtime->sec(), localtime->min(), localtime->hour(), localtime->mday(), localtime->mon(), localtime->year(), localtime->wday(), localtime->yday(), localtime->isdst());
41my $pbdate = strftime("%Y-%m-%d", @date);
42my $pbdatecvs = strftime("%Y-%m-%d %H:%M:%S", @date);
43my $debug = 0;
44my $pbaccount;              # Login to use to connect to the VM
45my $pbport;                 # Port to use to connect to the VM
46my $LOG = \*STDOUT;
47
48getopts('a:hl:m:P:p:qr:s:tv',\%opts);
49
50my ($projectbuilderver,$projectbuilderrev) = pb_version_init();
51if (defined $opts{'h'}) {
52    pb_syntax();
53    exit(0);
54}
55if (defined $opts{'v'}) {
56    $debug++;
57}
58if (defined $opts{'q'}) {
59    $debug=-1;
60}
61if (defined $opts{'l'}) {
62    open(LOG,"> $opts{'l'}") || die "Unable to log to $opts{'l'}: $!";
63    $LOG = *LOG;
64    $debug = 0  if ($debug == -1);
65    }
66# Handles test option
67if (defined $opts{'t'}) {
68    $test = "TRUE";
69    # Works only for SVN
70    $option = "-r BASE";
71}
72
73# Handle root of the project if defined
74if (defined $opts{'r'}) {
75    $ENV{'PBROOT'} = $opts{'r'};
76}
77# Handle virtual machines if any
78if (defined $opts{'m'}) {
79    $ENV{'PBVM'} = $opts{'m'};
80}
81if (defined $opts{'s'}) {
82    $pbscript = $opts{'s'};
83}
84if (defined $opts{'a'}) {
85    $pbaccount = $opts{'a'};
86}
87if (defined $opts{'P'}) {
88    $pbport = $opts{'P'};
89}
90
91# Get Action
92$action = shift @ARGV;
93die pb_syntax() if (not defined $action);
94
95my ($pbrc, $filteredfiles, $defpkgdir, $extpkgdir);
96
97# Handles project name if any
98# And get global params
99if (defined $opts{'p'}) {
100    ($ENV{'PBPROJ'},$debug,$LOG, $pbrc, $filteredfiles, $defpkgdir, $extpkgdir) 
101    = pb_env_init($opts{'p'});
102} else {
103    ($ENV{'PBPROJ'},$debug,$LOG, $pbrc, $filteredfiles, $defpkgdir, $extpkgdir) 
104    = pb_env_init();
105}
106
107print $LOG "Project: $ENV{'PBPROJ'}\n" if ($debug >= 0);
108print $LOG "Action: $action\n" if ($debug >= 0);
109
110# Keep those project values to store them at the end each time
111my $pbprojtag = $ENV{'PBTAG'};
112my $pbprojver = $ENV{'PBVER'};
113
114# Act depending on action
115if ($action =~ /^cms2build$/) {
116    pb_cms2build();
117} elsif ($action =~ /^build2pkg$/) {
118    pb_build2pkg();
119} elsif ($action =~ /^cms2pkg$/) {
120    pb_cms2build();
121    pb_build2pkg();
122} elsif ($action =~ /^build2ssh$/) {
123    pb_build2ssh();
124} elsif ($action =~ /^pkg2ssh$/) {
125    pb_pkg2ssh();
126} elsif ($action =~ /^build2vm$/) {
127    pb_build2vm();
128} elsif ($action =~ /^cms2vm$/) {
129    pb_cms2build();
130    pb_build2vm();
131} elsif ($action =~ /^launchvm$/) {
132    pb_launchvm($ENV{'PBVM'});
133} elsif ($action =~ /^script2vm$/) {
134    pb_script2vm($pbscript);
135} elsif ($action =~ /^clean$/) {
136} else {
137    print $LOG "'$action' is not available\n";
138    pb_syntax();
139}
140
141sub pb_cms2build {
142
143    my $ptr = pb_get_pkg($defpkgdir,$extpkgdir);
144    @pkgs = @$ptr;
145    my $cms=pb_cms_init($ENV{'PBPROJ'});
146
147    my ($pkgv, $pkgt) = pb_conf_read("$ENV{'PBCONF'}/$ENV{'PBPROJ'}.pb","pkgver","pkgtag");
148    foreach my $pbpkg (@pkgs) {
149        $ENV{'PBPKG'} = $pbpkg;
150        if ((defined $pkgv) && (defined $pkgv->{$pbpkg})) {
151            $pbver = $pkgv->{$pbpkg};
152            $ENV{'PBVER'} = $pbver;
153        } else {
154            $pbver = $ENV{'PBVER'};
155        }
156        if ((defined $pkgt) && (defined $pkgt->{$pbpkg})) {
157            $pbtag = $pkgt->{$pbpkg};
158            $ENV{'PBTAG'} = $pbtag;
159        } else {
160            $pbtag = $ENV{'PBTAG'};
161        }
162
163        $pbrev = $ENV{'PBREVISION'};
164        print $LOG "\n";
165        print $LOG "Management of $pbpkg $pbver-$pbtag (rev $pbrev)\n";
166        die "Unable to get env var PBDESTDIR" if (not defined $ENV{'PBDESTDIR'});
167        # Clean up dest if necessary. The export will recreate it
168        my $dest = "$ENV{'PBDESTDIR'}/$pbpkg-$pbver";
169        pb_rm_rf($dest) if (-d $dest);
170
171        # Export CMS tree for the concerned package to dest
172        # And generate some additional files
173        $OUTPUT_AUTOFLUSH=1;
174
175        # computes in which dir we have to work
176        my $dir = $defpkgdir->{$pbpkg};
177        $dir = $extpkgdir->{$pbpkg} if (not defined $dir);
178        print "def:".Dumper($defpkgdir)." ext: ".Dumper($extpkgdir)." \n" if ($debug >= 1);
179        pb_cms_export($cms,$pbdatecvs,"$ENV{'PBROOT'}/$dir",$dest);
180
181        # Extract cms log history and store it
182        pb_cms_log($cms,"$ENV{'PBROOT'}/$dir","$dest/$ENV{'PBCMSLOGFILE'}");
183
184        my %build;
185
186        my ($ptr) = pb_conf_get("vmlist");
187        foreach my $d (split(/,/,$ptr->{$ENV{'PBPROJ'}})) {
188            my ($name,$ver) = split(/_/,$d);
189            chomp($ver);
190            my ($ddir, $dver, $dfam, $dtype, $pbsuf) = pb_distro_init($name,$ver);
191            print $LOG "DEBUG: distro tuple: ".Dumper($ddir, $dver, $dfam, $dtype, $pbsuf)."\n" if ($debug >= 1);
192            print $LOG "DEBUG Filtering PBDATE => $pbdate, PBTAG => $pbtag, PBVER => $pbver\n" if ($debug >= 1);
193
194            # Filter build files from the less precise up to the most with overloading
195            # Filter all files found, keeping the name, and generating in dest
196
197            # Find all build files first relatively to PBROOT
198            my %bfiles;
199            print $LOG "DEBUG dir: $ENV{'PBCONF'}/$pbpkg\n" if ($debug >= 1);
200            $build{"$ddir-$dver"} = "yes";
201            if (-d "$ENV{'PBCONF'}/$pbpkg/$dtype") {
202                opendir(BDIR,"$ENV{'PBCONF'}/$pbpkg/$dtype") || die "Unable to open dir $ENV{'PBCONF'}/$pbpkg/$dtype: $!";
203                foreach my $f (readdir(BDIR)) {
204                    next if ($f =~ /^\./);
205                    $bfiles{$f} = "$ENV{'PBCONF'}/$pbpkg/$dtype/$f";
206                    $bfiles{$f} =~ s~$ENV{'PBROOT'}~~;
207                }
208                closedir(BDIR);
209            } elsif (-d "$ENV{'PBCONF'}/$pbpkg/$dfam") {
210                opendir(BDIR,"$ENV{'PBCONF'}/$pbpkg/$dfam") || die "Unable to open dir $ENV{'PBCONF'}/$pbpkg/$dfam: $!";
211                foreach my $f (readdir(BDIR)) {
212                    next if ($f =~ /^\./);
213                    $bfiles{$f} = "$ENV{'PBCONF'}/$pbpkg/$dfam/$f";
214                    $bfiles{$f} =~ s~$ENV{'PBROOT'}~~;
215                }
216                closedir(BDIR);
217            } elsif (-d "$ENV{'PBCONF'}/$pbpkg/$ddir") {
218                opendir(BDIR,"$ENV{'PBCONF'}/$pbpkg/$ddir") || die "Unable to open dir $ENV{'PBCONF'}/$pbpkg/$ddir: $!";
219                foreach my $f (readdir(BDIR)) {
220                    next if ($f =~ /^\./);
221                    $bfiles{$f} = "$ENV{'PBCONF'}/$pbpkg/$ddir/$f";
222                    $bfiles{$f} =~ s~$ENV{'PBROOT'}~~;
223                }
224                closedir(BDIR);
225            } elsif (-d "$ENV{'PBCONF'}/$pbpkg/$ddir-$dver") {
226                opendir(BDIR,"$ENV{'PBCONF'}/$pbpkg/$ddir-$dver") || die "Unable to open dir $ENV{'PBCONF'}/$pbpkg/$ddir-$dver: $!";
227                foreach my $f (readdir(BDIR)) {
228                    next if ($f =~ /^\./);
229                    $bfiles{$f} = "$ENV{'PBCONF'}/$pbpkg/$ddir-$dver/$f";
230                    $bfiles{$f} =~ s~$ENV{'PBROOT'}~~;
231                }
232                closedir(BDIR);
233            } else {
234                $build{"$ddir-$dver"} = "no";
235                next;
236            }
237            print $LOG "DEBUG bfiles: ".Dumper(\%bfiles)."\n" if ($debug >= 1);
238
239            # Get all filters to apply
240            my $ptr = pb_get_filters($pbpkg, $dtype, $dfam, $ddir, $dver);
241
242            # Apply now all the filters on all the files concerned
243            # destination dir depends on the type of file
244            if (defined $ptr) {
245                foreach my $f (values %bfiles) {
246                    pb_filter_file_pb("$ENV{'PBROOT'}/$f",$ptr,"$dest/pbconf/$ddir-$dver/".basename($f),$dtype,$pbsuf,$pbpkg,$pbver,$pbtag,$pbrev,$pbdate,$defpkgdir,$extpkgdir);
247                }
248                if (defined $filteredfiles->{$pbpkg}) {
249                    foreach my $f (split(/,/,$filteredfiles->{$pbpkg})) {
250                        pb_filter_file("$ENV{'PBROOT'}/$dir/$f",$ptr,"$dest/$f",$pbsuf,$pbpkg,$pbver,$pbtag,$pbrev,$pbdate);
251                    }
252                }
253            }
254        }
255        if ($debug >= 0) {
256            my @found;
257            my @notfound;
258            foreach my $b (keys %build) {
259                push @found,$b if ($build{$b} =~ /yes/);
260                push @notfound,$b if ($build{$b} =~ /no/);
261            }
262            print $LOG "Build files generated for ".join(',',@found)."\n";
263            print $LOG "No Build files found for ".join(',',@notfound)."\n";
264        }
265        # Prepare the dest directory for archive
266        if (-x "$ENV{'PBCONF'}/$pbpkg/pbinit") {
267            #pb_system("cd $dest ; $ENV{'PBCONF'}/$pbpkg/pbinit","Executing init script $ENV{'PBCONF'}/$pbpkg/pbinit");
268            print $LOG "Executing init script $ENV{'PBCONF'}/$pbpkg/pbinit\n";
269            system("cd $dest ; $ENV{'PBCONF'}/$pbpkg/pbinit");
270        }
271
272        # Archive dest dir
273        chdir "$ENV{'PBDESTDIR'}" || die "Unable to change dir to $ENV{'PBDESTDIR'}";
274        # Possibility to look at PBSRC to guess more the filename
275        pb_system("tar cfz $pbpkg-$pbver.tar.gz $pbpkg-$pbver","Creating $pbpkg tar files compressed");
276        print $LOG "Under $ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz\n" if ($debug >= 0);
277
278        # Keep track of what is generated for default
279        open(LAST,"> $pbrc->{$ENV{'PBPROJ'}}") || die "Unable to create $pbrc->{$ENV{'PBPROJ'}}";
280        print LAST "pbroot $pbprojver-$pbprojtag = $ENV{'PBROOT'}\n";
281        close(LAST);
282
283        # Keep track of per package version
284        if (! -f "$ENV{'PBDESTDIR'}/$pbprojver-$pbprojtag.pb") {
285            open(PKG,">$ENV{'PBDESTDIR'}/$pbprojver-$pbprojtag.pb") || die "Unable to create $ENV{'PBDESTDIR'}/$pbprojver-$pbprojtag.pb";
286            print PKG "# Empty\n";
287            close(PKG);
288        }
289        my ($pkg) = pb_conf_read("$ENV{'PBDESTDIR'}/$pbprojver-$pbprojtag.pb","pbpkg");
290        $pkg = { } if (not defined $pkg);
291        if ((not defined $pkg->{$pbpkg}) || ($pkg->{$pbpkg} ne "$pbver-$pbtag")) {
292            $pkg->{$pbpkg} = "$pbver-$pbtag";
293        }
294
295        print $LOG "DEBUG pkg: ".Dumper($pkg)."\n" if ($debug >= 1);
296        open(PKG,"> $ENV{'PBDESTDIR'}/$pbprojver-$pbprojtag.pb") || die "Unable to create $ENV{'PBDESTDIR'}/$pbprojver-$pbprojtag.pb";
297        foreach my $p (keys %$pkg) {
298            print PKG "pbpkg $p = $pkg->{$p}\n";
299        }
300        close(PKG);
301    }
302}
303
304sub pb_build2pkg {
305
306    # Get list of packages to build
307    my $ptr = pb_get_pkg($defpkgdir,$extpkgdir);
308    @pkgs = @$ptr;
309
310    # Get the running distro to build on
311    my ($ddir, $dver, $dfam, $dtype, $pbsuf) = pb_distro_init();
312    print $LOG "DEBUG: distro tuple: ".join(',',($ddir, $dver, $dfam, $dtype, $pbsuf))."\n" if ($debug >= 1);
313
314    # Get content saved in cms2build
315    my ($pkg) = pb_conf_read("$ENV{'PBDESTDIR'}/$pbprojver-$pbprojtag.pb","pbpkg");
316    $pkg = { } if (not defined $pkg);
317
318    chdir "$ENV{'PBBUILDDIR'}";
319    my $made = ""; # pkgs made during build
320    foreach my $pbpkg (@pkgs) {
321        my $vertag = $pkg->{$pbpkg};
322        # get the version of the current package - maybe different
323        ($pbver,$pbtag) = split(/-/,$vertag);
324
325        my $src="$ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz";
326        print $LOG "Source file: $src\n" if ($debug >= 0);
327
328        print $LOG "Working directory: $ENV{'PBBUILDDIR'}\n" if ($debug >= 0);
329        if ($dtype eq "rpm") {
330            foreach my $d ('RPMS','SRPMS','SPECS','SOURCES','BUILD') {
331                if (! -d "$ENV{'PBBUILDDIR'}/$d") {
332                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";
333                }
334            }
335
336            # We need to first extract the spec file
337            symlink "$src","$ENV{'PBBUILDDIR'}/SOURCES/".basename($src) || die "Unable to symlink $src in $ENV{'PBBUILDDIR'}/SOURCES";
338            my @specfile;
339            @specfile = pb_extract_build_files($src,"$pbpkg-$pbver/pbconf/$ddir-$dver/","$ENV{'PBBUILDDIR'}/SPECS");
340
341            print $LOG "specfile: ".Dumper(\@specfile)."\n" if ($debug >= 1);
342            # set LANGUAGE to check for correct log messages
343            $ENV{'LANGUAGE'}="C";
344            #system("ls -R $ENV{'PBBUILDDIR'}") if ($debug >= 1);
345            foreach my $f (@specfile) {
346                if ($f =~ /\.spec$/) {
347                    pb_system("rpmbuild --define \"_topdir $ENV{'PBBUILDDIR'}\" -ba $f","Building package with $f under $ENV{'PBBUILDDIR'}");
348                    last;
349                }
350            }
351            $made="$made RPMS/*/$pbpkg-$pbver-$pbtag$pbsuf.*.rpm SRPMS/$pbpkg-$pbver-$pbtag$pbsuf.src.rpm";
352            if (-f "/usr/bin/rpmlint") {
353                pb_system("rpmlint $made","Checking validity of rpms with rpmlint");
354            }
355        } elsif ($dtype eq "deb") {
356            chdir "$ENV{'PBBUILDDIR'}" || die "Unable to chdir to $ENV{'PBBUILDDIR'}";
357            pb_system("tar xfz $src","Extracting sources");
358
359            chdir "$pbpkg-$pbver" || die "Unable to chdir to $pbpkg-$pbver";
360            symlink "pbconf/$ddir-$dver","debian" || die "Unable to symlink to pbconf/$ddir-$dver";
361            pb_system("dpkg-buildpackage -us -uc -rfakeroot","Building package");
362            $made="$made $pbpkg"."_*.deb $pbpkg"."_*.dsc $pbpkg"."_*.tar.gz";
363        } elsif ($dtype eq "ebuild") {
364            my @ebuildfile;
365            # For gentoo we need to take pb as subsystem name
366            pb_mkdir_p("$ENV{'PBBUILDDIR'}/portage/pb/$pbpkg") if (! -d "$ENV{'PBBUILDDIR'}/portage/pb/$pbpkg");
367
368            # We need to first extract the ebuild file
369            @ebuildfile = pb_extract_build_files($src,"$pbpkg-$pbver/pbconf/$ddir-$dver/","$ENV{'PBBUILDDIR'}/portage/pb/$pbpkg");
370
371            # Prepare the build env for gentoo
372            my $found = 0;
373            my $pbbd = $ENV{'PBBUILDDIR'};
374            $pbbd =~ s|/|\\/|g;
375            open(MAKE,"/etc/make.conf") || die "Unable to open /etc/make.conf";
376            while (<MAKE>) {
377                $found = 1 if (/$pbbd\/portage/);
378            }
379            close(MAKE);
380            if ($found == 0) {
381                pb_system("sudo \'echo \"$ENV{'PBBUILDDIR'}/portage\" >> /etc/make.conf\'");
382            }
383            $found = 0;
384            open(KEYW,"/etc/portage/package.keywords") || die "Unable to open /etc/portage/package.keywords";
385            while (<KEYW>) {
386                $found = 1 if (/portage\/pb/);
387            }
388            close(KEYW);
389            if ($found == 0) {
390                pb_system("sudo \'echo \"portage/pb\" >> /etc/portage/package.keywords\'");
391            }
392
393            # Build
394            foreach my $f (@ebuildfile) {
395                if ($f =~ /\.ebuild$/) {
396                    pb_system("ebuild $f digest ; ebuild $f package");
397                }
398            }
399            print $LOG "ebuild file: ".Dumper(\@ebuildfile)."\n" if ($debug >= 1);
400
401            $made="$made portage/pb/$pbpkg/$pbpkg-$pbver.ebuild";
402        } elsif ($dtype eq "slackware") {
403            $made="$made build-$pbpkg/$pbpkg-$pbver-*-$pbtag.tgz";
404            pb_mkdir_p("$ENV{'PBBUILDDIR'}/install") if (! -d "$ENV{'PBBUILDDIR'}/install");
405        } else {
406            die "Unknown dtype format $dtype";
407        }
408    }
409    # Keep track of what is generated so that we can get them back from VMs
410    open(KEEP,"> $ENV{'PBBUILDDIR'}/pbgen-$pbprojver-$pbprojtag") || die "Unable to create $ENV{'PBBUILDDIR'}/pbgen-$pbprojver-$pbprojtag";
411    print KEEP "$made\n";
412    close(KEEP);
413}
414
415sub pb_build2ssh {
416    pb_send2ssh("Sources");
417}
418
419sub pb_pkg2ssh {
420    pb_send2ssh("Packages");
421}
422
423# By default deliver to the the public site hosting the
424# ftp structure (or whatever) or a VM
425sub pb_send2ssh {
426
427    my $cmt = shift;
428    my $vm = shift || undef;
429    my $vmexist = shift || 0;           # 0 is FALSE
430    my $host = shift || "sshhost";
431    my $login = shift || "sshlogin";
432    my $dir = shift || "sshdir";
433    my $port = shift || "sshport";
434    my $cmd = "";
435
436    # Get list of packages to build
437    my $ptr = pb_get_pkg($defpkgdir,$extpkgdir);
438    @pkgs = @$ptr;
439
440    # Get the running distro to consider
441    my ($odir,$over) = (undef, undef);
442    if (defined $vm) {
443        ($odir,$over) = split(/_/,$vm);
444    }
445    my ($ddir, $dver, $dfam, $dtype, $pbsuf) = pb_distro_init($odir,$over);
446    print $LOG "DEBUG: distro tuple: ".join(',',($ddir, $dver, $dfam, $dtype, $pbsuf))."\n" if ($debug >= 1);
447
448    # Get content saved in cms2build
449    my ($pkg) = pb_conf_read("$ENV{'PBDESTDIR'}/$pbprojver-$pbprojtag.pb","pbpkg");
450    $pkg = { } if (not defined $pkg);
451
452    my $src = "";
453    chdir "$ENV{'PBBUILDDIR'}";
454    foreach my $pbpkg (@pkgs) {
455        my $vertag = $pkg->{$pbpkg};
456        # get the version of the current package - maybe different
457        ($pbver,$pbtag) = split(/-/,$vertag);
458
459        if (($cmt eq "Sources") || ($cmt eq "VMs")) {
460            $src = "$src $ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz";
461            $cmd = "$cmd ; ln -sf $pbpkg-$pbver.tar.gz $pbpkg-latest.tar.gz";
462        }
463    }
464    if ($cmt eq "VMs") {
465        $src="$src $ENV{'PBDESTDIR'}/pbscript $ENV{'PBCONF'}/$ENV{'PBPROJ'}.pb $ENV{'PBDESTDIR'}/$pbprojver-$pbprojtag.pb $ENV{'PBETC'}";
466    } elsif ($cmt eq "Script") {
467        $src="$src $ENV{'PBDESTDIR'}/pbscript";
468    } elsif ($cmt eq "Packages") {
469        # Get package list from file made during build2pkg
470        open(KEEP,"$ENV{'PBBUILDDIR'}/pbgen-$pbprojver-$pbprojtag") || die "Unable to read $ENV{'PBBUILDDIR'}/pbgen-$pbprojver-$pbprojtag";
471        $src = <KEEP>;
472        chomp($src);
473        close(KEEP);
474        if ($dtype eq "rpm") {
475            # Also make a pbscript to generate yum/urpmi bases
476            # $src = "$src $ENV{'PBDESTDIR'}/pbscript"
477        } elsif ($dtype eq "deb") {
478            # Also make a pbscript to generate apt bases
479            # $src = "$src $ENV{'PBDESTDIR'}/pbscript"
480        }
481    }
482    # Remove potential leading spaces (cause pb with basename)
483    $src =~ s/^ *//;
484    my $basesrc = "";
485    foreach my $i (split(/ +/,$src)) {
486        $basesrc .= " ".basename($i);
487    }
488
489    print $LOG "Sources handled ($cmt): $src\n" if ($debug >= 0);
490    my ($sshhost,$sshlogin,$sshdir,$sshport) = pb_conf_get($host,$login,$dir,$port);
491    my $mac = "$sshlogin->{$ENV{'PBPROJ'}}\@$sshhost->{$ENV{'PBPROJ'}}";
492    # Overwrite account value if passed as parameter
493    $mac = "$pbaccount\@$sshhost->{$ENV{'PBPROJ'}}" if (defined $pbaccount);
494    $port = "$pbport" if (defined $pbport);
495    my $tdir;
496    my $bdir;
497    if (($cmt eq "Sources") || ($cmt eq "Script")) {
498        $tdir = "$sshdir->{$ENV{'PBPROJ'}}/src";
499    } elsif ($cmt eq "VMs") {
500        $tdir = dirname("$sshdir->{$ENV{'PBPROJ'}}")."/delivery";
501        $bdir = dirname("$sshdir->{$ENV{'PBPROJ'}}")."/build";
502        # Remove a potential $ENV{'HOME'} as bdir should be relative to pb's home
503        $bdir =~ s|\$ENV.+\}/||;
504    } elsif ($cmt eq "Packages") {
505        $tdir = "$sshdir->{$ENV{'PBPROJ'}}/$ddir/$dver";
506    } else {
507        return;
508    }
509    # Remove a potential $ENV{'HOME'} as tdir should be relative to pb's home
510    $tdir =~ s|\$ENV.+\}/||;
511
512    $port = $sshport->{$ENV{'PBPROJ'}};
513    pb_system("ssh -q -p $port $mac \"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 $mac");
514    pb_system("cd $ENV{'PBBUILDDIR'} ; scp -p -P $port $src $mac:$tdir 2> /dev/null","$cmt delivery in $tdir on $mac");
515    pb_system("ssh -q -p $port $mac \"echo \'cd $tdir ; if [ -f pbscript ]; then ./pbscript; fi\' | bash\"","Executing pbscript on $mac  if needed");
516    if ($cmt eq "VMs") {
517        # Get back info on pkg produced, compute their name and get them from the VM
518        pb_system("scp -p -P $port $mac:$bdir/pbgen-$pbprojver-$pbprojtag $ENV{'PBBUILDDIR'} 2> /dev/null","Get package names in $tdir on $mac");
519        open(KEEP,"$ENV{'PBBUILDDIR'}/pbgen-$pbprojver-$pbprojtag") || die "Unable to read $ENV{'PBBUILDDIR'}/pbgen-$pbprojver-$pbprojtag";
520        my $src = <KEEP>;
521        chomp($src);
522        close(KEEP);
523        $src =~ s/^ *//;
524        pb_mkdir_p("$ENV{'PBBUILDDIR'}/$odir/$over");
525        # Change pgben to make the next send2ssh happy
526        my $made = "";
527        open(KEEP,"> $ENV{'PBBUILDDIR'}/pbgen-$pbprojver-$pbprojtag") || die "Unable to write $ENV{'PBBUILDDIR'}/pbgen-$pbprojver-$pbprojtag";
528        foreach my $p (split(/ +/,$src)) {
529            my $j = basename($p);
530            pb_system("scp -p -P $port $mac:\'$bdir/$p\' $ENV{'PBBUILDDIR'}/$odir/$over 2> /dev/null","Package recovery of $j in $tdir from $mac");
531            $made="$made $odir/$over/$j" if (($dtype ne "rpm") || ($j !~ /.src.rpm$/));
532        }
533        print KEEP "$made\n";
534        close(KEEP);
535        pb_system("ssh -q -p $port $mac \"rm -rf $tdir\"","VM cleanup on $mac");
536        if (! $vmexist) {
537            pb_system("ssh -q -p $port $mac \"sudo /usr/bin/poweroff \"; sleep 120 ; echo \'if [ -d /proc/$vmexist ]; then kill $vmexist; fi \' | bash ; sleep 10","VM halt on $mac");
538        }
539        pb_send2ssh("Packages","$odir"."_"."$over");
540        pb_rm_rf("$ENV{'PBBUILDDIR'}/$odir");
541    }
542}
543
544sub pb_script2vm {
545    my $pbscript=shift;
546
547    # Prepare the script to be executed on the VM
548    # in $ENV{'PBDESTDIR'}/pbscript
549    if ((defined $pbscript ) && ($pbscript ne "$ENV{'PBDESTDIR'}/pbscript")) {
550        copy($pbscript,"$ENV{'PBDESTDIR'}/pbscript") || die "Unable to create $ENV{'PBDESTDIR'}/pbscript";
551        chmod 0755,"$ENV{'PBDESTDIR'}/pbscript";
552    }
553
554    my ($vm,$all) = pb_get_vm();
555
556    foreach my $v (@$vm) {
557        # Launch the VM
558        my $vmexist = pb_launchvm($v);
559        if (! $vmexist) {
560            pb_system("sleep 300","Waiting for it to come up");
561        }
562
563        # Gather all required files to send them to the VM
564        # and launch the build thourgh pbscript
565        pb_send2ssh("Script","$v",$vmexist,"vmhost","vmlogin","pbrc","vmport");
566    }
567}
568
569sub pb_launchvm {
570    my $vm = shift;
571
572    die "No VM defined, unable to launch" if (not defined $vm);
573    # Keep only the first VM in case many were given
574    $vm =~ s/,.*//;
575
576    # Launch the VMs
577    my ($ptr,$vmopt,$vmport,$vmpath) = pb_conf_get("vmtype","vmopt","vmport","vmpath");
578    my $vmtype = $ptr->{$ENV{'PBPROJ'}};
579    if (defined $vmopt->{$ENV{'PBPROJ'}}) {
580        $ENV{'PBVMOPT'} = $vmopt->{$ENV{'PBPROJ'}};
581    } else {
582        $ENV{'PBVMOPT'} = "";
583    }
584
585    my $cmd;
586    my $vmcmd;      # has to be used for pb_check_ps
587    my $vmm;        # has to be used for pb_check_ps
588    if ($vmtype eq "qemu") {
589        my $arch = `uname -m`;
590        chomp($arch);
591        my $qemucmd32;
592        my $qemucmd64;
593        if ($arch eq "x86_64") {
594            $qemucmd32 = "/usr/bin/qemu-system-i386";
595            $qemucmd64 = "/usr/bin/qemu";
596        } else {
597            $qemucmd32 = "/usr/bin/qemu";
598            $qemucmd64 = "/usr/bin/qemu-system-x86_64";
599        }
600        if ($vm =~ /_64/) {
601            $vmcmd = "$qemucmd64 -no-kqemu";
602        } else {
603            $vmcmd = "$qemucmd32";
604        }
605        $vmm = "$vmpath->{$ENV{'PBPROJ'}}/$vm.qemu";
606        if (! -f "$vmm") {
607            print "Unable to find VM $vmm";
608            return;
609        }
610        $cmd = "$vmcmd $ENV{'PBVMOPT'} -redir tcp:$vmport->{$ENV{'PBPROJ'}}:10.0.2.15:22 $vmm"
611    } elsif ($vmtype eq "xen") {
612    } elsif ($vmtype eq "vmware") {
613    } else {
614        die "VM of type $vmtype not supported. Report to the dev team";
615    }
616    my $vmexist = pb_check_ps($vmcmd,$vmm);
617    if (! $vmexist) {
618        pb_system("$cmd &","Launching the VM");
619    }
620    return($vmexist);
621}
622
623sub pb_build2vm {
624    # Prepare the script to be executed on the VM
625    # in $ENV{'PBDESTDIR'}/pbscript
626    open(SCRIPT,"> $ENV{'PBDESTDIR'}/pbscript") || die "Unable to create $ENV{'PBDESTDIR'}/pbscript";
627    print SCRIPT "#!/bin/bash\n";
628    print SCRIPT "echo ... Execution needed\n";
629    print SCRIPT "# This is in directory delivery\n";
630    print SCRIPT "# Setup the variables required for building\n";
631    print SCRIPT "export PBPROJ=$ENV{'PBPROJ'}\n";
632    print SCRIPT "# Preparation for pb\n";
633    print SCRIPT "mkdir -p ../pbconf\n";
634    print SCRIPT "mv $ENV{'PBPROJ'}.pb ../pbconf\n";
635    print SCRIPT "mv .pbrc \$HOME\n";
636    print SCRIPT "cd ..\n";
637    print SCRIPT "export PBROOT=\`pwd\`\n";
638    print SCRIPT "#Sync date\n";
639    my $syncdate = strftime("%m%d%H%M", @date);
640    print SCRIPT "sudo date $syncdate\n";
641    print SCRIPT "# Build\n";
642    my $p = "";
643    $p = $ARGV[0] if (defined $ARGV[0]);
644    print SCRIPT "echo Building packages on VM...\n";
645    print SCRIPT "pb build2pkg $p\n";
646    close(SCRIPT);
647    chmod 0755,"$ENV{'PBDESTDIR'}/pbscript";
648
649    my ($vm,$all) = pb_get_vm();
650
651    # Send tar files when we do a global generation
652    pb_build2ssh() if ($all == 1);
653
654    foreach my $v (@$vm) {
655        # Launch the VM
656        my $vmexist = pb_launchvm($v);
657        if (! $vmexist) {
658            pb_system("sleep 300","Waiting for it to come up");
659        }
660
661        # Gather all required files to send them to the VM
662        # and launch the build thourgh pbscript
663        pb_send2ssh("VMs","$v",$vmexist,"vmhost","vmlogin","pbrc","vmport");
664    }
665}
666
667sub pb_get_pkg {
668
669my @pkgs;
670my $defpkgdir = shift;
671my $extpkgdir = shift;
672
673# Get packages list
674if (not defined $ARGV[0]) {
675    @pkgs = keys %$defpkgdir;
676} elsif ($ARGV[0] =~ /^all$/) {
677    @pkgs = keys %$defpkgdir;
678    push(@pkgs, keys %$extpkgdir);
679} else {
680    @pkgs = @ARGV;
681}
682print $LOG "Packages: ".join(',',@pkgs)."\n" if ($debug >= 0);
683return(\@pkgs);
684}
685
686#
687# Return the list of VMs we are working on
688# $all is a flag to know if we return all of them
689# or only some (if all we publish also tar files in addition to pkgs
690#
691sub pb_get_vm {
692
693my @vm;
694my $all = 0;
695
696# Get VM list
697if ((not defined $ENV{'PBVM'}) || ($ENV{'PBVM'} =~ /^all$/)) {
698    my ($ptr) = pb_conf_get("vmlist");
699    $ENV{'PBVM'} = $ptr->{$ENV{'PBPROJ'}};
700    $all = 1;
701}
702@vm = split(/,/,$ENV{'PBVM'});
703print $LOG "VMs: ".join(',',@vm)."\n";
704return(\@vm,$all);
705}
706
707# Returns the pid of a running VM command using a specific VM file
708sub pb_check_ps {
709    my $vmcmd = shift;
710    my $vmm = shift;
711    my $vmexist = 0;        # FALSE by default
712
713    open(PS, "ps auxhww|") || die "Unable to call ps";
714    while (<PS>) {
715        next if (! /$vmcmd/);
716        next if (! /$vmm/);
717        my ($void1, $void2);
718        ($void1, $vmexist, $void2) = split(/ +/);
719        last;
720    }
721    return($vmexist);
722}
723
724
725sub pb_extract_build_files {
726
727my $src=shift;
728my $dir=shift;
729my $ddir=shift;
730my @files;
731
732pb_system("tar xfpz $src $dir","Extracting build files");
733opendir(DIR,"$dir") || die "Unable to open directory $dir";
734foreach my $f (readdir(DIR)) {
735    next if ($f =~ /^\./);
736    move("$dir/$f","$ddir") || die "Unable to move $dir/$f to $ddir";
737    print $LOG "mv $dir/$f $ddir\n" if ($debug >= 1);
738    push @files,"$ddir/$f";
739}
740closedir(DIR);
741# Not enough but still a first cleanup
742pb_rm_rf("$dir");
743return(@files);
744}
745
746sub pb_syntax {
747
748    print "pb (aka project-builder) Version $projectbuilderver-$projectbuilderrev\n";
749    print "\n";
750    print "Syntax: pb [-vhqt][-r pbroot][-p project][[-s script -a account] -m \"mach-1[,...]\"] <action> [<pkg1>...]\n";
751    print "\n";
752    print "-h : This help file\n";
753    print "-q : Quiet mode\n";
754    print "-t : Test mode (not done yet)\n";
755    print "-v : Verbose mode\n";
756    print "\n";
757    print "-m machine : Name of the Virtual Machines (VM) you want\n";
758    print "             to build on (coma separated). All if none precised\n";
759    print "             (or use the env variable PBVM)       \n";
760    print "\n";
761    print "-s script  : Name of the script you want\n";
762    print "             to execute on the related VMs.\n";
763    print "\n";
764    print "-a account : Name of the account to use\n";
765    print "             to connect on the related VMs.\n";
766    print "\n";
767    print "-p project : Name of the project you're working on\n";
768    print "             (or use the env variable PBPROJ)     \n";
769    print "\n";
770    print "-r pbroot  : Path Name of project under the CMS \n";
771    print "             (or use the env variable PBROOT)   \n";
772    print "\n";
773    print "<action> can be:\n";
774    print "\n";
775    print "\tcms2build: Create tar files for the project under your CMS\n";
776    print "\t           CMS supported are SVN and CVS\n";
777    print "\t           parameters are packages to build\n";
778    print "\t           if not using default list\n";
779    print "\n";
780    print "\tbuild2pkg: Create packages for your running distribution  \n";
781    print "\n";
782    print "\tbuild2ssh: Send the tar files to a SSH host               \n";
783    print "\n";
784    print "\tpkg2ssh:   Send the packages built to a SSH host          \n";
785    print "\n";
786    print "\tcms2pkg:   cms2build + build2pkg\n";
787    print "\n";
788    print "\tbuild2vm:  Create packages in VMs, launching them if needed\n";
789    print "\t           and send those packages to a SSH host once built\n";
790    print "\t           VM type supported are QEMU            \n";
791    print "\n";
792    print "\tlaunchvm:  Launch one virtual machine\n";
793    print "\n";
794    print "\tscript2vm: Launch one virtual machine if needed        \n";
795    print "\t           and executes a script on it                 \n";
796    print "\n";
797    print "\tcms2vm:    cms2build + build2vm\n";
798    print "\n";
799}
Note: See TracBrowser for help on using the repository browser.