source: devel/pb/bin/pb @ 203

Last change on this file since 203 was 203, checked in by Bruno Cornec, 12 years ago

use make and not the macro not portable
document Ubuntu 6.06 distribution detection hack
fix some VMs handling pb

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