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

Last change on this file since 162 was 162, checked in by Bruno Cornec, 17 years ago

Allow the usage of another port to communicate with the VM
Example script now mkdir /home if it doesn't exist

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