source: 0.8.1/pb/bin/pb @ 198

Last change on this file since 198 was 198, checked in by Bruno Cornec, 13 years ago

Force mode on the Debian rules file in case it's not correct in the CMS

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