source: ProjectBuilder/devel/pb/bin/pb@ 203

Last change on this file since 203 was 203, checked in by Bruno Cornec, 17 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.