source: ProjectBuilder/0.8.1/pb/bin/pb@ 198

Last change on this file since 198 was 198, checked in by Bruno Cornec, 17 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
RevLine 
[5]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
[22]10# Syntax: see at end
[9]11
[18]12use strict 'vars';
[5]13use Getopt::Std;
[9]14use Data::Dumper;
15use English;
[16]16use AppConfig qw(:argcount :expand);
17use File::Basename;
[26]18use File::Copy;
[13]19use Time::localtime qw(localtime);
20use POSIX qw(strftime);
[5]21
[73]22# Global variables
[17]23use lib qw (lib);
[74]24use ProjectBuilder::Distribution qw (pb_distro_init);
25use ProjectBuilder::Version qw (pb_version_init);
[106]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);
[5]27
28my %opts; # CLI Options
[9]29my $action; # action to realize
30my $test = "FALSE";
31my $option = "";
32my @pkgs;
[95]33my $pbtag; # Global Tag variable
34my $pbver; # Global Version variable
[141]35my $pbscript; # Name of the script
[77]36my %pbver; # per package
37my %pbtag; # per package
[53]38my $pbrev; # Global REVISION variable
[16]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);
[112]41my $pbdatecvs = strftime("%Y-%m-%d %H:%M:%S", @date);
[108]42my $debug = 0;
[152]43my $pbaccount; # Login to use to connect to the VM
[162]44my $pbport; # Port to use to connect to the VM
[108]45my $LOG = \*STDOUT;
[5]46
[162]47getopts('a:hl:m:P:p:qr:s:tv',\%opts);
[5]48
[75]49my ($projectbuilderver,$projectbuilderrev) = pb_version_init();
[21]50if (defined $opts{'h'}) {
[74]51 pb_syntax();
[21]52 exit(0);
53}
54if (defined $opts{'v'}) {
55 $debug++;
56}
57if (defined $opts{'q'}) {
58 $debug=-1;
59}
[22]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 }
[9]65# Handles test option
66if (defined $opts{'t'}) {
67 $test = "TRUE";
68 # Works only for SVN
69 $option = "-r BASE";
70}
[5]71
[67]72# Handle root of the project if defined
73if (defined $opts{'r'}) {
74 $ENV{'PBROOT'} = $opts{'r'};
75}
[91]76# Handle virtual machines if any
77if (defined $opts{'m'}) {
78 $ENV{'PBVM'} = $opts{'m'};
79}
[141]80if (defined $opts{'s'}) {
81 $pbscript = $opts{'s'};
82}
[152]83if (defined $opts{'a'}) {
84 $pbaccount = $opts{'a'};
85}
[162]86if (defined $opts{'P'}) {
87 $pbport = $opts{'P'};
88}
[108]89
90# Get Action
91$action = shift @ARGV;
92die pb_syntax() if (not defined $action);
93
94my ($pbrc, $filteredfiles, $defpkgdir, $extpkgdir);
95
[59]96# Handles project name if any
[108]97# And get global params
[59]98if (defined $opts{'p'}) {
[107]99 ($ENV{'PBPROJ'},$debug,$LOG, $pbrc, $filteredfiles, $defpkgdir, $extpkgdir)
100 = pb_env_init($opts{'p'});
[59]101} else {
[107]102 ($ENV{'PBPROJ'},$debug,$LOG, $pbrc, $filteredfiles, $defpkgdir, $extpkgdir)
103 = pb_env_init();
[59]104}
105
[108]106print $LOG "Project: $ENV{'PBPROJ'}\n" if ($debug >= 0);
[22]107print $LOG "Action: $action\n" if ($debug >= 0);
[9]108
[91]109# Keep those project values to store them at the end each time
[83]110my $pbprojtag = $ENV{'PBTAG'};
111my $pbprojver = $ENV{'PBVER'};
112
[9]113# Act depending on action
114if ($action =~ /^cms2build$/) {
[77]115 pb_cms2build();
116} elsif ($action =~ /^build2pkg$/) {
117 pb_build2pkg();
118} elsif ($action =~ /^cms2pkg$/) {
119 pb_cms2build();
120 pb_build2pkg();
[88]121} elsif ($action =~ /^build2ssh$/) {
122 pb_build2ssh();
123} elsif ($action =~ /^pkg2ssh$/) {
124 pb_pkg2ssh();
[91]125} elsif ($action =~ /^build2vm$/) {
126 pb_build2vm();
127} elsif ($action =~ /^cms2vm$/) {
128 pb_cms2build();
129 pb_build2vm();
[141]130} elsif ($action =~ /^launchvm$/) {
[142]131 pb_launchvm($ENV{'PBVM'});
132} elsif ($action =~ /^script2vm$/) {
133 pb_script2vm($pbscript);
[106]134} elsif ($action =~ /^clean$/) {
[77]135} else {
136 print $LOG "'$action' is not available\n";
137 pb_syntax();
138}
139
140sub pb_cms2build {
141
[112]142 my $ptr = pb_get_pkg($defpkgdir,$extpkgdir);
[22]143 @pkgs = @$ptr;
[112]144 my $cms=pb_cms_init($ENV{'PBPROJ'});
[9]145
[98]146 my ($pkgv, $pkgt) = pb_conf_read("$ENV{'PBCONF'}/$ENV{'PBPROJ'}.pb","pkgver","pkgtag");
[174]147
148 # declare packager for filtering
149 my ($tmp) = pb_conf_get("packager");
150 my $pbpackager = $tmp->{$ENV{'PBPROJ'}};
151
[27]152 foreach my $pbpkg (@pkgs) {
[115]153 $ENV{'PBPKG'} = $pbpkg;
[98]154 if ((defined $pkgv) && (defined $pkgv->{$pbpkg})) {
155 $pbver = $pkgv->{$pbpkg};
[115]156 $ENV{'PBVER'} = $pbver;
[9]157 } else {
[16]158 $pbver = $ENV{'PBVER'};
[9]159 }
[98]160 if ((defined $pkgt) && (defined $pkgt->{$pbpkg})) {
161 $pbtag = $pkgt->{$pbpkg};
[115]162 $ENV{'PBTAG'} = $pbtag;
[9]163 } else {
[16]164 $pbtag = $ENV{'PBTAG'};
[9]165 }
[95]166
[16]167 $pbrev = $ENV{'PBREVISION'};
[112]168 print $LOG "\n";
169 print $LOG "Management of $pbpkg $pbver-$pbtag (rev $pbrev)\n";
[9]170 die "Unable to get env var PBDESTDIR" if (not defined $ENV{'PBDESTDIR'});
[16]171 # Clean up dest if necessary. The export will recreate it
[27]172 my $dest = "$ENV{'PBDESTDIR'}/$pbpkg-$pbver";
[74]173 pb_rm_rf($dest) if (-d $dest);
[9]174
175 # Export CMS tree for the concerned package to dest
176 # And generate some additional files
177 $OUTPUT_AUTOFLUSH=1;
[29]178
[9]179 # computes in which dir we have to work
[113]180 my $dir = $defpkgdir->{$pbpkg};
181 $dir = $extpkgdir->{$pbpkg} if (not defined $dir);
[114]182 print "def:".Dumper($defpkgdir)." ext: ".Dumper($extpkgdir)." \n" if ($debug >= 1);
[112]183 pb_cms_export($cms,$pbdatecvs,"$ENV{'PBROOT'}/$dir",$dest);
[9]184
185 # Extract cms log history and store it
[106]186 pb_cms_log($cms,"$ENV{'PBROOT'}/$dir","$dest/$ENV{'PBCMSLOGFILE'}");
[29]187
[21]188 my %build;
[91]189
190 my ($ptr) = pb_conf_get("vmlist");
191 foreach my $d (split(/,/,$ptr->{$ENV{'PBPROJ'}})) {
192 my ($name,$ver) = split(/_/,$d);
[11]193 chomp($ver);
[99]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);
[22]196 print $LOG "DEBUG Filtering PBDATE => $pbdate, PBTAG => $pbtag, PBVER => $pbver\n" if ($debug >= 1);
[13]197
[16]198 # Filter build files from the less precise up to the most with overloading
[13]199 # Filter all files found, keeping the name, and generating in dest
[16]200
201 # Find all build files first relatively to PBROOT
202 my %bfiles;
[27]203 print $LOG "DEBUG dir: $ENV{'PBCONF'}/$pbpkg\n" if ($debug >= 1);
[21]204 $build{"$ddir-$dver"} = "yes";
[27]205 if (-d "$ENV{'PBCONF'}/$pbpkg/$dtype") {
206 opendir(BDIR,"$ENV{'PBCONF'}/$pbpkg/$dtype") || die "Unable to open dir $ENV{'PBCONF'}/$pbpkg/$dtype: $!";
[16]207 foreach my $f (readdir(BDIR)) {
208 next if ($f =~ /^\./);
[27]209 $bfiles{$f} = "$ENV{'PBCONF'}/$pbpkg/$dtype/$f";
[16]210 $bfiles{$f} =~ s~$ENV{'PBROOT'}~~;
211 }
[13]212 closedir(BDIR);
[27]213 } elsif (-d "$ENV{'PBCONF'}/$pbpkg/$dfam") {
214 opendir(BDIR,"$ENV{'PBCONF'}/$pbpkg/$dfam") || die "Unable to open dir $ENV{'PBCONF'}/$pbpkg/$dfam: $!";
[16]215 foreach my $f (readdir(BDIR)) {
216 next if ($f =~ /^\./);
[27]217 $bfiles{$f} = "$ENV{'PBCONF'}/$pbpkg/$dfam/$f";
[16]218 $bfiles{$f} =~ s~$ENV{'PBROOT'}~~;
219 }
220 closedir(BDIR);
[27]221 } elsif (-d "$ENV{'PBCONF'}/$pbpkg/$ddir") {
222 opendir(BDIR,"$ENV{'PBCONF'}/$pbpkg/$ddir") || die "Unable to open dir $ENV{'PBCONF'}/$pbpkg/$ddir: $!";
[16]223 foreach my $f (readdir(BDIR)) {
224 next if ($f =~ /^\./);
[27]225 $bfiles{$f} = "$ENV{'PBCONF'}/$pbpkg/$ddir/$f";
[16]226 $bfiles{$f} =~ s~$ENV{'PBROOT'}~~;
227 }
[13]228 closedir(BDIR);
[27]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: $!";
[16]231 foreach my $f (readdir(BDIR)) {
232 next if ($f =~ /^\./);
[27]233 $bfiles{$f} = "$ENV{'PBCONF'}/$pbpkg/$ddir-$dver/$f";
[16]234 $bfiles{$f} =~ s~$ENV{'PBROOT'}~~;
235 }
[13]236 closedir(BDIR);
237 } else {
[21]238 $build{"$ddir-$dver"} = "no";
[13]239 next;
240 }
[22]241 print $LOG "DEBUG bfiles: ".Dumper(\%bfiles)."\n" if ($debug >= 1);
[13]242
[15]243 # Get all filters to apply
[77]244 my $ptr = pb_get_filters($pbpkg, $dtype, $dfam, $ddir, $dver);
[15]245
[19]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) {
[194]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);
[16]251 }
[113]252 if (defined $filteredfiles->{$pbpkg}) {
253 foreach my $f (split(/,/,$filteredfiles->{$pbpkg})) {
[174]254 pb_filter_file("$ENV{'PBROOT'}/$dir/$f",$ptr,"$dest/$f",$pbsuf,$pbpkg,$pbver,$pbtag,$pbrev,$pbdate,$pbpackager);
[61]255 }
[19]256 }
[15]257 }
[18]258 }
[21]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 }
[22]266 print $LOG "Build files generated for ".join(',',@found)."\n";
267 print $LOG "No Build files found for ".join(',',@notfound)."\n";
[21]268 }
[18]269 # Prepare the dest directory for archive
[60]270 if (-x "$ENV{'PBCONF'}/$pbpkg/pbinit") {
[108]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");
[11]274 }
[29]275
[18]276 # Archive dest dir
[69]277 chdir "$ENV{'PBDESTDIR'}" || die "Unable to change dir to $ENV{'PBDESTDIR'}";
[25]278 # Possibility to look at PBSRC to guess more the filename
[94]279 pb_system("tar cfz $pbpkg-$pbver.tar.gz $pbpkg-$pbver","Creating $pbpkg tar files compressed");
[31]280 print $LOG "Under $ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz\n" if ($debug >= 0);
[83]281
[70]282 # Keep track of what is generated for default
[113]283 open(LAST,"> $pbrc->{$ENV{'PBPROJ'}}") || die "Unable to create $pbrc->{$ENV{'PBPROJ'}}";
[83]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 }
[89]293 my ($pkg) = pb_conf_read("$ENV{'PBDESTDIR'}/$pbprojver-$pbprojtag.pb","pbpkg");
[83]294 $pkg = { } if (not defined $pkg);
[88]295 if ((not defined $pkg->{$pbpkg}) || ($pkg->{$pbpkg} ne "$pbver-$pbtag")) {
296 $pkg->{$pbpkg} = "$pbver-$pbtag";
[83]297 }
298
[88]299 print $LOG "DEBUG pkg: ".Dumper($pkg)."\n" if ($debug >= 1);
[83]300 open(PKG,"> $ENV{'PBDESTDIR'}/$pbprojver-$pbprojtag.pb") || die "Unable to create $ENV{'PBDESTDIR'}/$pbprojver-$pbprojtag.pb";
[88]301 foreach my $p (keys %$pkg) {
302 print PKG "pbpkg $p = $pkg->{$p}\n";
[83]303 }
304 close(PKG);
[9]305 }
[77]306}
[22]307
[77]308sub pb_build2pkg {
309
[22]310 # Get list of packages to build
[112]311 my $ptr = pb_get_pkg($defpkgdir,$extpkgdir);
[22]312 @pkgs = @$ptr;
313
314 # Get the running distro to build on
[99]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);
[22]317
[83]318 # Get content saved in cms2build
[89]319 my ($pkg) = pb_conf_read("$ENV{'PBDESTDIR'}/$pbprojver-$pbprojtag.pb","pbpkg");
[83]320 $pkg = { } if (not defined $pkg);
321
[174]322 # declare packager
323 my ($tmp) = pb_conf_get("packager");
324 my $pbpackager = $tmp->{$ENV{'PBPROJ'}};
325
[25]326 chdir "$ENV{'PBBUILDDIR'}";
[126]327 my $made = ""; # pkgs made during build
[27]328 foreach my $pbpkg (@pkgs) {
[88]329 my $vertag = $pkg->{$pbpkg};
[77]330 # get the version of the current package - maybe different
331 ($pbver,$pbtag) = split(/-/,$vertag);
332
[27]333 my $src="$ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz";
[188]334 # Suse < 10.2 forces tar.bz2 usage :-(
335 if ($ddir eq "suse") {
[191]336 print "SuSE needs bz2 type of packages so recompressing...\n";
[188]337 my $newsrc="$ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.bz2";
338 system "gzip -cd $src | bzip2 -c6 > $newsrc";
339 $src = $newsrc;
340 }
[67]341 print $LOG "Source file: $src\n" if ($debug >= 0);
[25]342
[149]343 print $LOG "Working directory: $ENV{'PBBUILDDIR'}\n" if ($debug >= 0);
[25]344 if ($dtype eq "rpm") {
345 foreach my $d ('RPMS','SRPMS','SPECS','SOURCES','BUILD') {
[28]346 if (! -d "$ENV{'PBBUILDDIR'}/$d") {
[96]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";
[28]348 }
[25]349 }
350
[188]351 symlink "$src","$ENV{'PBBUILDDIR'}/SOURCES/".basename($src) || die "Unable to symlink $src in $ENV{'PBBUILDDIR'}/SOURCES";
[25]352 # We need to first extract the spec file
[28]353 my @specfile;
[77]354 @specfile = pb_extract_build_files($src,"$pbpkg-$pbver/pbconf/$ddir-$dver/","$ENV{'PBBUILDDIR'}/SPECS");
[25]355
[28]356 print $LOG "specfile: ".Dumper(\@specfile)."\n" if ($debug >= 1);
[25]357 # set LANGUAGE to check for correct log messages
358 $ENV{'LANGUAGE'}="C";
[28]359 #system("ls -R $ENV{'PBBUILDDIR'}") if ($debug >= 1);
360 foreach my $f (@specfile) {
361 if ($f =~ /\.spec$/) {
[174]362 pb_system("rpmbuild --define \"packager $pbpackager\" --define \"_topdir $ENV{'PBBUILDDIR'}\" -ba $f","Building package with $f under $ENV{'PBBUILDDIR'}");
[28]363 last;
364 }
365 }
[136]366 $made="$made RPMS/*/$pbpkg-$pbver-$pbtag$pbsuf.*.rpm SRPMS/$pbpkg-$pbver-$pbtag$pbsuf.src.rpm";
[149]367 if (-f "/usr/bin/rpmlint") {
368 pb_system("rpmlint $made","Checking validity of rpms with rpmlint");
[150]369 }
[118]370 } elsif ($dtype eq "deb") {
[149]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";
[198]376 chmod 0755,"debian/rules";
[149]377 pb_system("dpkg-buildpackage -us -uc -rfakeroot","Building package");
[136]378 $made="$made $pbpkg"."_*.deb $pbpkg"."_*.dsc $pbpkg"."_*.tar.gz";
[87]379 } elsif ($dtype eq "ebuild") {
[149]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'};
[150]390 $pbbd =~ s|/|\\/|g;
[149]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";
[118]418 } elsif ($dtype eq "slackware") {
[136]419 $made="$made build-$pbpkg/$pbpkg-$pbver-*-$pbtag.tgz";
[118]420 pb_mkdir_p("$ENV{'PBBUILDDIR'}/install") if (! -d "$ENV{'PBBUILDDIR'}/install");
[87]421 } else {
[118]422 die "Unknown dtype format $dtype";
[87]423 }
424 }
[118]425 # Keep track of what is generated so that we can get them back from VMs
[129]426 open(KEEP,"> $ENV{'PBBUILDDIR'}/pbgen-$pbprojver-$pbprojtag") || die "Unable to create $ENV{'PBBUILDDIR'}/pbgen-$pbprojver-$pbprojtag";
[118]427 print KEEP "$made\n";
428 close(KEEP);
[87]429}
430
[88]431sub pb_build2ssh {
[90]432 pb_send2ssh("Sources");
433}
[87]434
[90]435sub pb_pkg2ssh {
436 pb_send2ssh("Packages");
437}
438
[108]439# By default deliver to the the public site hosting the
440# ftp structure (or whatever) or a VM
[90]441sub pb_send2ssh {
442
443 my $cmt = shift;
[118]444 my $vm = shift || undef;
[142]445 my $vmexist = shift || 0; # 0 is FALSE
[108]446 my $host = shift || "sshhost";
447 my $login = shift || "sshlogin";
448 my $dir = shift || "sshdir";
449 my $port = shift || "sshport";
[158]450 my $cmd = "";
[90]451
[87]452 # Get list of packages to build
[112]453 my $ptr = pb_get_pkg($defpkgdir,$extpkgdir);
[87]454 @pkgs = @$ptr;
455
[136]456 # Get the running distro to consider
[118]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);
[99]462 print $LOG "DEBUG: distro tuple: ".join(',',($ddir, $dver, $dfam, $dtype, $pbsuf))."\n" if ($debug >= 1);
[87]463
464 # Get content saved in cms2build
[89]465 my ($pkg) = pb_conf_read("$ENV{'PBDESTDIR'}/$pbprojver-$pbprojtag.pb","pbpkg");
[87]466 $pkg = { } if (not defined $pkg);
467
[118]468 my $src = "";
[87]469 chdir "$ENV{'PBBUILDDIR'}";
470 foreach my $pbpkg (@pkgs) {
[88]471 my $vertag = $pkg->{$pbpkg};
[87]472 # get the version of the current package - maybe different
473 ($pbver,$pbtag) = split(/-/,$vertag);
474
[118]475 if (($cmt eq "Sources") || ($cmt eq "VMs")) {
[158]476 $src = "$src $ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz";
[166]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 }
[118]482 }
483 }
484 if ($cmt eq "VMs") {
[132]485 $src="$src $ENV{'PBDESTDIR'}/pbscript $ENV{'PBCONF'}/$ENV{'PBPROJ'}.pb $ENV{'PBDESTDIR'}/$pbprojver-$pbprojtag.pb $ENV{'PBETC'}";
[142]486 } elsif ($cmt eq "Script") {
487 $src="$src $ENV{'PBDESTDIR'}/pbscript";
[118]488 } elsif ($cmt eq "Packages") {
489 # Get package list from file made during build2pkg
[129]490 open(KEEP,"$ENV{'PBBUILDDIR'}/pbgen-$pbprojver-$pbprojtag") || die "Unable to read $ENV{'PBBUILDDIR'}/pbgen-$pbprojver-$pbprojtag";
[126]491 $src = <KEEP>;
[118]492 chomp($src);
493 close(KEEP);
494 if ($dtype eq "rpm") {
495 # Also make a pbscript to generate yum/urpmi bases
[108]496 # $src = "$src $ENV{'PBDESTDIR'}/pbscript"
[118]497 } elsif ($dtype eq "deb") {
498 # Also make a pbscript to generate apt bases
499 # $src = "$src $ENV{'PBDESTDIR'}/pbscript"
[90]500 }
[87]501 }
[132]502 # Remove potential leading spaces (cause pb with basename)
503 $src =~ s/^ *//;
[129]504 my $basesrc = "";
[131]505 foreach my $i (split(/ +/,$src)) {
506 $basesrc .= " ".basename($i);
[130]507 }
[118]508
[128]509 print $LOG "Sources handled ($cmt): $src\n" if ($debug >= 0);
[108]510 my ($sshhost,$sshlogin,$sshdir,$sshport) = pb_conf_get($host,$login,$dir,$port);
[88]511 my $mac = "$sshlogin->{$ENV{'PBPROJ'}}\@$sshhost->{$ENV{'PBPROJ'}}";
[152]512 # Overwrite account value if passed as parameter
513 $mac = "$pbaccount\@$sshhost->{$ENV{'PBPROJ'}}" if (defined $pbaccount);
[162]514 $port = "$pbport" if (defined $pbport);
[108]515 my $tdir;
[136]516 my $bdir;
[142]517 if (($cmt eq "Sources") || ($cmt eq "Script")) {
[108]518 $tdir = "$sshdir->{$ENV{'PBPROJ'}}/src";
519 } elsif ($cmt eq "VMs") {
[136]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.+\}/||;
[90]524 } elsif ($cmt eq "Packages") {
[108]525 $tdir = "$sshdir->{$ENV{'PBPROJ'}}/$ddir/$dver";
[90]526 } else {
527 return;
[22]528 }
[136]529 # Remove a potential $ENV{'HOME'} as tdir should be relative to pb's home
[132]530 $tdir =~ s|\$ENV.+\}/||;
531
[111]532 $port = $sshport->{$ENV{'PBPROJ'}};
[158]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");
[136]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");
[108]536 if ($cmt eq "VMs") {
[128]537 # Get back info on pkg produced, compute their name and get them from the VM
[136]538 pb_system("scp -p -P $port $mac:$bdir/pbgen-$pbprojver-$pbprojtag $ENV{'PBBUILDDIR'} 2> /dev/null","Get package names in $tdir on $mac");
[129]539 open(KEEP,"$ENV{'PBBUILDDIR'}/pbgen-$pbprojver-$pbprojtag") || die "Unable to read $ENV{'PBBUILDDIR'}/pbgen-$pbprojver-$pbprojtag";
[118]540 my $src = <KEEP>;
541 chomp($src);
542 close(KEEP);
[131]543 $src =~ s/^ *//;
[136]544 pb_mkdir_p("$ENV{'PBBUILDDIR'}/$odir/$over");
[139]545 # Change pgben to make the next send2ssh happy
[143]546 my $made = "";
[139]547 open(KEEP,"> $ENV{'PBBUILDDIR'}/pbgen-$pbprojver-$pbprojtag") || die "Unable to write $ENV{'PBBUILDDIR'}/pbgen-$pbprojver-$pbprojtag";
[136]548 foreach my $p (split(/ +/,$src)) {
[139]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");
[144]551 $made="$made $odir/$over/$j" if (($dtype ne "rpm") || ($j !~ /.src.rpm$/));
[136]552 }
[143]553 print KEEP "$made\n";
[139]554 close(KEEP);
[144]555 pb_system("ssh -q -p $port $mac \"rm -rf $tdir\"","VM cleanup on $mac");
[142]556 if (! $vmexist) {
[145]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");
[142]558 }
[126]559 pb_send2ssh("Packages","$odir"."_"."$over");
[141]560 pb_rm_rf("$ENV{'PBBUILDDIR'}/$odir");
[108]561 }
[9]562}
[16]563
[142]564sub pb_script2vm {
565 my $pbscript=shift;
[141]566
567 # Prepare the script to be executed on the VM
568 # in $ENV{'PBDESTDIR'}/pbscript
[142]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 }
[141]573
[142]574 my ($vm,$all) = pb_get_vm();
575
[141]576 foreach my $v (@$vm) {
[142]577 # Launch the VM
578 my $vmexist = pb_launchvm($v);
579 if (! $vmexist) {
580 pb_system("sleep 300","Waiting for it to come up");
[141]581 }
582
[142]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");
[169]586
[142]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 }
[180]605 $vmport->{$ENV{'PBPROJ'}} = "$pbport" if (defined $pbport);
[142]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";
[141]618 } else {
[142]619 $qemucmd32 = "/usr/bin/qemu";
620 $qemucmd64 = "/usr/bin/qemu-system-x86_64";
[141]621 }
[142]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) {
[141]640 pb_system("$cmd &","Launching the VM");
641 }
[142]642 return($vmexist);
[141]643}
[142]644
[105]645sub pb_build2vm {
[108]646 # Prepare the script to be executed on the VM
647 # in $ENV{'PBDESTDIR'}/pbscript
[118]648 open(SCRIPT,"> $ENV{'PBDESTDIR'}/pbscript") || die "Unable to create $ENV{'PBDESTDIR'}/pbscript";
649 print SCRIPT "#!/bin/bash\n";
[126]650 print SCRIPT "echo ... Execution needed\n";
[132]651 print SCRIPT "# This is in directory delivery\n";
[118]652 print SCRIPT "# Setup the variables required for building\n";
653 print SCRIPT "export PBPROJ=$ENV{'PBPROJ'}\n";
[132]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";
[118]659 print SCRIPT "export PBROOT=\`pwd\`\n";
660 print SCRIPT "# Build\n";
[127]661 my $p = "";
662 $p = $ARGV[0] if (defined $ARGV[0]);
[132]663 print SCRIPT "echo Building packages on VM...\n";
[166]664 print SCRIPT "pb -p $ENV{'PBPROJ'} build2pkg $p\n";
[118]665 close(SCRIPT);
666 chmod 0755,"$ENV{'PBDESTDIR'}/pbscript";
667
[142]668 my ($vm,$all) = pb_get_vm();
669
[106]670 # Send tar files when we do a global generation
671 pb_build2ssh() if ($all == 1);
[118]672
673 foreach my $v (@$vm) {
[142]674 # Launch the VM
675 my $vmexist = pb_launchvm($v);
676 if (! $vmexist) {
677 pb_system("sleep 300","Waiting for it to come up");
[127]678 }
[118]679
[142]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");
[118]683 }
[105]684}
685
[77]686sub pb_get_pkg {
[16]687
[22]688my @pkgs;
[108]689my $defpkgdir = shift;
690my $extpkgdir = shift;
[22]691
692# Get packages list
693if (not defined $ARGV[0]) {
[112]694 @pkgs = keys %$defpkgdir;
[22]695} elsif ($ARGV[0] =~ /^all$/) {
[112]696 @pkgs = keys %$defpkgdir;
697 push(@pkgs, keys %$extpkgdir);
[22]698} else {
699 @pkgs = @ARGV;
700}
701print $LOG "Packages: ".join(',',@pkgs)."\n" if ($debug >= 0);
702return(\@pkgs);
703}
704
[105]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#
[91]710sub pb_get_vm {
711
712my @vm;
[105]713my $all = 0;
[91]714
715# Get VM list
[105]716if ((not defined $ENV{'PBVM'}) || ($ENV{'PBVM'} =~ /^all$/)) {
[108]717 my ($ptr) = pb_conf_get("vmlist");
[105]718 $ENV{'PBVM'} = $ptr->{$ENV{'PBPROJ'}};
719 $all = 1;
[91]720}
[105]721@vm = split(/,/,$ENV{'PBVM'});
[108]722print $LOG "VMs: ".join(',',@vm)."\n";
[105]723return(\@vm,$all);
[91]724}
725
[145]726# Returns the pid of a running VM command using a specific VM file
[142]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
[77]744sub pb_extract_build_files {
[25]745
746my $src=shift;
747my $dir=shift;
[26]748my $ddir=shift;
[28]749my @files;
[25]750
[188]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}
[25]758opendir(DIR,"$dir") || die "Unable to open directory $dir";
759foreach my $f (readdir(DIR)) {
760 next if ($f =~ /^\./);
[26]761 move("$dir/$f","$ddir") || die "Unable to move $dir/$f to $ddir";
[28]762 print $LOG "mv $dir/$f $ddir\n" if ($debug >= 1);
763 push @files,"$ddir/$f";
[25]764}
765closedir(DIR);
[26]766# Not enough but still a first cleanup
[74]767pb_rm_rf("$dir");
[28]768return(@files);
[25]769}
770
[74]771sub pb_syntax {
[21]772
[53]773 print "pb (aka project-builder) Version $projectbuilderver-$projectbuilderrev\n";
774 print "\n";
[169]775 print "Syntax: pb [-vhqt][-r pbroot][-p project][[-s script -a account -P port] -m \"mach-1[,...]\"] <action> [<pkg1>...]\n";
[21]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";
[142]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";
[91]784 print " (or use the env variable PBVM) \n";
[69]785 print "\n";
[141]786 print "-s script : Name of the script you want\n";
787 print " to execute on the related VMs.\n";
788 print "\n";
[152]789 print "-a account : Name of the account to use\n";
790 print " to connect on the related VMs.\n";
791 print "\n";
[21]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";
[91]795 print "-r pbroot : Path Name of project under the CMS \n";
796 print " (or use the env variable PBROOT) \n";
797 print "\n";
[21]798 print "<action> can be:\n";
799 print "\n";
[105]800 print "\tcms2build: Create tar files for the project under your CMS\n";
[21]801 print "\t CMS supported are SVN and CVS\n";
[22]802 print "\t parameters are packages to build\n";
803 print "\t if not using default list\n";
[21]804 print "\n";
805 print "\tbuild2pkg: Create packages for your running distribution \n";
806 print "\n";
[169]807 print "\tcms2pkg: cms2build + build2pkg\n";
808 print "\n";
[105]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";
[142]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";
[136]816 print "\n";
[169]817 print "\tcms2vm: cms2build + build2vm\n";
818 print "\n";
[142]819 print "\tlaunchvm: Launch one virtual machine\n";
[141]820 print "\n";
[142]821 print "\tscript2vm: Launch one virtual machine if needed \n";
822 print "\t and executes a script on it \n";
823 print "\n";
[21]824}
Note: See TracBrowser for help on using the repository browser.