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

Last change on this file since 341 was 341, checked in by Bruno Cornec, 16 years ago

Fix some merging issues

  • Property svn:executable set to *
File size: 43.7 KB
Line 
1#!/usr/bin/perl -w
2
3eval 'exec /usr/bin/perl -w -S $0 ${1+"$@"}'
4 if 0; # not running under some shell
5#
6# Project Builder main application
7#
8# $Id$
9#
10# Copyright B. Cornec 2007
11# Provided under the GPL v2
12
13# Syntax: see at end
14
15use strict 'vars';
16use Getopt::Long qw(:config auto_abbrev no_ignore_case);
17use Pod::Usage;
18use Data::Dumper;
19use English;
20use File::Basename;
21use File::Copy;
22use Time::localtime qw(localtime);
23use POSIX qw(strftime);
24
25# Global variables
26use lib qw (lib);
27use ProjectBuilder::Distribution;
28use ProjectBuilder::Version;
29use ProjectBuilder::Base;
30
31my %opts; # CLI Options
32my $action; # action to realize
33my $test = "FALSE"; # Not used
34my $force = 0; # Force VE/VM rebuild
35my $option = ""; # Not used
36my @pkgs; # list of packages
37my $pbtag; # Global Tag variable
38my $pbver; # Global Version variable
39my $pbscript; # Name of the script
40my %pbver; # per package
41my %pbtag; # per package
42my $pbrev; # Global REVISION variable
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 $iso; # ISO image for the VM to create
47
48my @date = pb_get_date();
49my $pbdate = strftime("%Y-%m-%d", @date);
50
51=pod
52
53=head1 NAME
54
55pb, aka project-builder.org - builds packages for your projects
56
57=head1 DESCRIPTION
58
59pb helps you build various packages directly from your project sources.
60Those sources could be handled by a CMS (Configuration Management System)
61such as Subversion, CVS, ... or being a simple reference to a compressed tar file.
62It's based on a set of configuration files, a set of provided macros to help
63you keeping build files as generic as possible. For example, a single .spec
64file should be required to generate for all rpm based distributions, even
65if you could also have multiple .spec files if required.
66
67=head1 SYNOPSIS
68
69pb [-vhq][-r pbroot][-p project][[-s script -a account -P port][-m mach-1[,...]]][-i iso] <action> [<pkg1> ...]
70
71pb [--verbose][--help][--man][--quiet][--revision pbroot][--project project][[--script script --account account --port port][--machine mach-1[,...]]][--iso iso] <action> [<pkg1> ...]
72
73=head1 OPTIONS
74
75=over 4
76
77=item B<-v|--verbose>
78
79Print a brief help message and exits.
80
81=item B<-q|--quiet>
82
83Do not print any output.
84
85=item B<-h|--help>
86
87Print a brief help message and exits.
88
89=item B<--man>
90
91Prints the manual page and exits.
92
93=item B<-m|--machine machine1[,machine2,...]>
94
95Name of the Virtual Machines (VM) or Virtual Environments (VE) you want to build on (coma separated).
96All if none precised (or use the env variable PBV).
97
98=item B<-s|--script script>
99
100Name of the script you want to execute on the related VMs or VEs.
101
102=item B<-i|--iso iso_image>
103
104Name of the ISO image of the distribution you want to install on the related VMs.
105
106=item B<-a|--account account>
107
108Name of the account to use to connect on the related VMs.
109
110=item B<-P|--port port_number>
111
112Port number to use to connect on the related VMs.\n";
113
114=item B<-p|--project project_name>
115
116Name of the project you're working on (or use the env variable PBPROJ)
117
118=item B<-r|--revision revision>
119
120Path Name of the project revision under the CMS (or use the env variable PBROOT)
121
122=item B<-V|--version new_version>
123
124New version of the project to create based on the current one.
125
126=back
127
128=head1 ARGUMENTS
129
130<action> can be:
131
132=over 4
133
134=item B<cms2build>
135
136Create tar files for the project under your CMS.
137CMS supported are SVN and CVS
138parameters are packages to build
139if not using default list
140
141=item B<build2pkg>
142
143Create packages for your running distribution
144
145=item B<cms2pkg>
146
147cms2build + build2pkg
148
149=item B<build2ssh>
150
151Send the tar files to a SSH host
152
153=item B<cms2ssh>
154
155cms2build + build2ssh
156
157=item B<pkg2ssh>
158
159Send the packages built to a SSH host
160
161=item B<build2vm>
162
163Create packages in VMs, launching them if needed
164and send those packages to a SSH host once built
165VM type supported are QEMU
166
167=item B<build2ve>
168
169Create packages in VEs, creating it if needed
170and send those packages to a SSH host once built
171
172=item B<cms2vm>
173
174cms2build + build2vm
175
176=item B<cms2ve>
177
178cms2build + build2ve
179
180=item B<launchvm>
181
182Launch one virtual machine
183
184=item B<launchve>
185
186Launch one virtual environment
187
188=item B<script2vm>
189
190Launch one virtual machine if needed
191and executes a script on it
192
193=item B<script2ve>
194
195Execute a script in a virtual environment
196
197=item B<newvm>
198
199Create a new virtual machine
200
201=item B<newve>
202
203Create a new virtual environment
204
205=item B<newver>
206
207Create a new version of the project derived
208from the current one
209
210=item B<newproj>
211
212Create a new project and a template set of
213configuration files under pbconf
214
215=back
216
217<pkgs> can be a list of packages, the keyword 'all' or nothing, in which case the default list of packages is taken (corresponding to the defpkgdir list of arguments in the configuration file).
218
219=head1 WEB SITES
220
221The main Web site of the project is available at L<http://www.project-builder.org/>. Bug reports should be filled using the trac instance of the project at L<http://trac.project-builder.org/>.
222
223=head1 USER MAILING LIST
224
225None exists for the moment.
226
227=head1 CONFIGURATION FILES
228
229Each pb user may have a configuration in F<$HOME/.pbrc>. The values in this file may overwrite any other configuration file value.
230
231Here is an example of such a configuration file:
232
233 #
234 # Define for each project the URL of its pbconf repository
235 # No default option allowed here as they need to be all different
236 #
237 # URL of the pbconf content
238 # This is the format of a classical URL with the extension of additional schema such as
239 # svn+ssh, cvs+ssh, ...
240 #
241 pbconfurl linuxcoe = cvs+ssh://:ext:bcornec@linuxcoe.cvs.sourceforge.net:/cvsroot/linuxcoe/pbconf
242
243 # This is normaly defined in the project's configuration file
244 # Url of the project
245 #
246 pburl linuxcoe = cvs+ssh://:ext:bcornec@linuxcoe.cvs.sourceforge.net:/cvsroot/linuxcoe
247
248 # All these URLs needs to be defined here as the are the entry point
249 # for how to build packages for the project
250 #
251 pbconfurl pb = svn+ssh://svn.project-builder.org/mondo/svn/pb/pbconf
252 pbconfurl mondorescue = svn+ssh://svn.project-builder.org/mondo/svn/project-builder/mondorescue/pbconf
253 pbconfurl collectl = svn+ssh://bruno@svn.mondorescue.org/mondo/svn/project-builder/collectl/pbconf
254 pbconfurl netperf = svn+ssh://svn.mondorescue.org/mondo/svn/project-builder/netperf/pbconf
255
256 # Under that dir will take place everything related to pb
257 # If you want to use VMs/chroot/..., then use $ENV{'HOME'} to make it portable
258 # to your VMs/chroot/...
259 # if not defined then /var/cache
260 pbdefdir default = $ENV{'HOME'}/project-builder
261 pbdefdir pb = $ENV{'HOME'}
262 pbdefdir linuxcoe = $ENV{'HOME'}/LinuxCOE/cvs
263 pbdefdir mondorescue = $ENV{'HOME'}/mondo/svn
264
265 # pbconfdir points to the directory where the CMS content of the pbconfurl is checked out
266 # If not defined, pbconfdir is under pbdefdir/pbproj/pbconf
267 pbconfdir linuxcoe = $ENV{'HOME'}/LinuxCOE/cvs/pbconf
268 pbconfdir mondorescue = $ENV{'HOME'}/mondo/svn/pbconf
269
270 # pbdir points to the directory where the CMS content of the pburl is checked out
271 # If not defined, pbdir is under pbdefdir/pbproj
272 # Only defined if we have access to the dev of the project
273 pbdir linuxcoe = $ENV{'HOME'}/LinuxCOE/cvs
274 pbdir mondorescue = $ENV{'HOME'}/mondo/svn
275
276 # -daemonize doesn't work with qemu 0.8.2
277 vmopt default = -m 384
278
279=head1 AUTHORS
280
281The Project-Builder.org team L<http://trac.project-builder.org/> lead by Bruno Cornec L<mailto:bruno@project-builder.org>.
282
283=head1 COPYRIGHT
284
285Project-Builder.org is distributed under the GPL v2.0 license
286described in the file C<COPYING> included with the distribution.
287
288=cut
289
290# ---------------------------------------------------------------------------
291
292# Old syntax
293#getopts('a:fhi:l:m:P:p:qr:s:vV:',\%opts);
294
295my ($projectbuilderver,$projectbuilderrev) = pb_version_init();
296
297GetOptions("help|?|h" => \$opts{'h'},
298 "man" => \$opts{'man'},
299 "verbose|v+" => \$opts{'v'},
300 "quiet|q" => \$opts{'q'},
301 "log-files|l=s" => \$opts{'l'},
302 "force|f" => \$opts{'f'},
303 "account|a=s" => \$opts{'a'},
304 "revision|r=s" => \$opts{'r'},
305 "script|s=s" => \$opts{'s'},
306 "machines|mock|m=s" => \$opts{'m'},
307 "port|P=i" => \$opts{'P'},
308 "project|p=s" => \$opts{'p'},
309 "iso|i=s" => \$opts{'i'},
310 "version|V=s" => \$opts{'V'},
311) || pb_syntax(-1,0);
312
313if (defined $opts{'h'}) {
314 pb_syntax(0,1);
315}
316if (defined $opts{'man'}) {
317 pb_syntax(0,2);
318}
319if (defined $opts{'v'}) {
320 $debug = $opts{'v'};
321 pb_log(0,"Debug value: $debug\n");
322}
323if (defined $opts{'f'}) {
324 $force=1;
325}
326if (defined $opts{'q'}) {
327 $debug=-1;
328}
329if (defined $opts{'l'}) {
330 open(LOG,"> $opts{'l'}") || die "Unable to log to $opts{'l'}: $!";
331 $LOG = *LOG;
332 $debug = 0 if ($debug == -1);
333 }
334pb_log_init($debug, $LOG);
335
336# Handle root of the project if defined
337if (defined $opts{'r'}) {
338 $ENV{'PBROOTDIR'} = $opts{'r'};
339}
340# Handle virtual machines if any
341if (defined $opts{'m'}) {
342 $ENV{'PBV'} = $opts{'m'};
343}
344if (defined $opts{'s'}) {
345 $pbscript = $opts{'s'};
346}
347if (defined $opts{'a'}) {
348 $pbaccount = $opts{'a'};
349}
350if (defined $opts{'P'}) {
351 $pbport = $opts{'P'};
352}
353if (defined $opts{'V'}) {
354 $newver = $opts{'V'};
355}
356if (defined $opts{'i'}) {
357 $iso = $opts{'i'};
358}
359
360# Get Action
361$action = shift @ARGV;
362die pb_syntax(-1,1) if (not defined $action);
363
364my ($filteredfiles, $supfiles, $defpkgdir, $extpkgdir);
365my $pbinit = undef;
366$pbinit = 1 if ($action =~ /^newproj$/);
367
368# Handles project name if any
369# And get global params
370if (defined $opts{'p'}) {
371 ($filteredfiles, $supfiles, $defpkgdir, $extpkgdir)
372 = pb_env_init($opts{'p'},$pbinit);
373} else {
374 ($filteredfiles, $supfiles, $defpkgdir, $extpkgdir)
375 = pb_env_init(undef,$pbinit);
376}
377
378pb_log(0,"Project: $ENV{'PBPROJ'}\n");
379pb_log(0,"Action: $action\n");
380
381# Keep those project values to store them at the end each time
382my $pbprojtag = $ENV{'PBTAG'};
383my $pbprojver = $ENV{'PBVER'};
384
385# Act depending on action
386if ($action =~ /^cms2build$/) {
387 pb_cms2build();
388} elsif ($action =~ /^build2pkg$/) {
389 pb_build2pkg();
390} elsif ($action =~ /^cms2pkg$/) {
391 pb_cms2build();
392 pb_build2pkg();
393} elsif ($action =~ /^build2ssh$/) {
394 pb_build2ssh();
395} elsif ($action =~ /^cms2ssh$/) {
396 pb_cms2build();
397 pb_build2ssh();
398} elsif ($action =~ /^pkg2ssh$/) {
399 pb_pkg2ssh();
400} elsif ($action =~ /^build2ve$/) {
401 pb_build2v("ve");
402} elsif ($action =~ /^build2vm$/) {
403 pb_build2v("vm");
404} elsif ($action =~ /^cms2ve$/) {
405 pb_cms2build();
406 pb_build2v("ve");
407} elsif ($action =~ /^cms2vm$/) {
408 pb_cms2build();
409 pb_build2v("vm");
410} elsif ($action =~ /^launchvm$/) {
411 pb_launchv("vm",$ENV{'PBV'},0);
412} elsif ($action =~ /^launchve$/) {
413 pb_launchv("ve",$ENV{'PBV'},0);
414} elsif ($action =~ /^script2vm$/) {
415 pb_script2v($pbscript,"vm");
416} elsif ($action =~ /^script2ve$/) {
417 pb_script2v($pbscript,"ve");
418} elsif ($action =~ /^newver$/) {
419 pb_newver();
420} elsif ($action =~ /^newve$/) {
421 pb_launchv("ve",$ENV{'PBV'},1);
422} elsif ($action =~ /^newvm$/) {
423 pb_launchv("vm",$ENV{'PBV'},1);
424} elsif ($action =~ /^newproj$/) {
425 # Nothing to do - already done in pb_env_init
426} elsif ($action =~ /^clean$/) {
427} else {
428 pb_log(0,"\'$action\' is not available\n");
429 pb_syntax(-2,1);
430}
431
432sub pb_cms2build {
433
434 my $ptr = pb_get_pkg($defpkgdir,$extpkgdir);
435 @pkgs = @$ptr;
436
437 my ($scheme, $uri) = pb_cms_init($pbinit);
438
439 my ($pkgv, $pkgt) = pb_conf_get_if("pkgver","pkgtag");
440
441 # declare packager for filtering
442 my ($tmp) = pb_conf_get("pbpackager");
443 my $pbpackager = $tmp->{$ENV{'PBPROJ'}};
444
445 foreach my $pbpkg (@pkgs) {
446 $ENV{'PBPKG'} = $pbpkg;
447 $ENV{'PBVER'} = $pbprojver;
448 $ENV{'PBTAG'} = $pbprojtag;
449 if ((defined $pkgv) && (defined $pkgv->{$pbpkg})) {
450 $pbver = $pkgv->{$pbpkg};
451 $ENV{'PBVER'} = $pbver;
452 } else {
453 $pbver = $ENV{'PBVER'};
454 }
455 if ((defined $pkgt) && (defined $pkgt->{$pbpkg})) {
456 $pbtag = $pkgt->{$pbpkg};
457 $ENV{'PBTAG'} = $pbtag;
458 } else {
459 $pbtag = $ENV{'PBTAG'};
460 }
461
462 $pbrev = $ENV{'PBREVISION'};
463 pb_log(0,"\n");
464 pb_log(0,"Management of $pbpkg $pbver-$pbtag (rev $pbrev)\n");
465 die "Unable to get env var PBDESTDIR" if (not defined $ENV{'PBDESTDIR'});
466 # Clean up dest if necessary. The export will recreate it
467 my $dest = "$ENV{'PBDESTDIR'}/$pbpkg-$pbver";
468 pb_rm_rf($dest) if (-d $dest);
469
470 # Export CMS tree for the concerned package to dest
471 # And generate some additional files
472 $OUTPUT_AUTOFLUSH=1;
473
474 # computes in which dir we have to work
475 my $dir = $defpkgdir->{$pbpkg};
476 $dir = $extpkgdir->{$pbpkg} if (not defined $dir);
477 pb_log(2,"def:".Dumper($defpkgdir)." ext: ".Dumper($extpkgdir)." \n");
478
479 # Exporting from CMS
480 pb_cms_export($uri,"$ENV{'PBDIR'}/$dir",$dest);
481
482 # Get project info on authors and log file
483 my $chglog = "$ENV{'PBROOTDIR'}/$pbpkg/pbcl";
484 $chglog = "$ENV{'PBROOTDIR'}/pbcl" if (! -f $chglog);
485 $chglog = undef if (! -f $chglog);
486
487 my $authors = "$ENV{'PBROOTDIR'}/$pbpkg/pbauthors";
488 $authors = "$ENV{'PBROOTDIR'}/pbauthors" if (! -f $authors);
489 $authors = "/dev/null" if (! -f $authors);
490
491 # Extract cms log history and store it
492 if ((defined $chglog) && (! -f "$dest/NEWS")) {
493 pb_log(2,"Generating NEWS file from $chglog\n");
494 copy($chglog,"$dest/NEWS") || die "Unable to create $dest/NEWS";
495 }
496 pb_cms_log($scheme,"$ENV{'PBDIR'}/$dir",$dest,$chglog,$authors);
497
498 my %build;
499
500 my @pt;
501 @pt = pb_conf_get_if("vmlist","velist");
502 my $tmpl = "";
503 if (defined $pt[0]->{$ENV{'PBPROJ'}}) {
504 $tmpl .= $pt[0]->{$ENV{'PBPROJ'}};
505 }
506 if (defined $pt[1]->{$ENV{'PBPROJ'}}) {
507 # the 2 lists needs to be grouped with a ',' separated them
508 if ($tmpl ne "") {
509 $tmpl .= ",";
510 }
511 $tmpl .= $pt[1]->{$ENV{'PBPROJ'}}
512 }
513 foreach my $d (split(/,/,$tmpl)) {
514 my ($name,$ver,$arch) = split(/-/,$d);
515 chomp($arch);
516 my ($ddir, $dver, $dfam, $dtype, $pbsuf) = pb_distro_init($name,$ver);
517 pb_log(2,"DEBUG: distro tuple: ".Dumper($ddir, $dver, $dfam, $dtype, $pbsuf)."\n");
518 pb_log(2,"DEBUG Filtering PBDATE => $pbdate, PBTAG => $pbtag, PBVER => $pbver\n");
519
520 # Filter build files from the less precise up to the most with overloading
521 # Filter all files found, keeping the name, and generating in dest
522
523 # Find all build files first relatively to PBROOTDIR
524 # Find also all specific files referenced in the .pb conf file
525 my %bfiles = ();
526 my %pkgfiles = ();
527 $build{"$ddir-$dver"} = "yes";
528
529 if (-d "$ENV{'PBROOTDIR'}/$pbpkg/$dtype") {
530 pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$dtype",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
531 } elsif (-d "$ENV{'PBROOTDIR'}/$pbpkg/$dfam") {
532 pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$dfam",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
533 } elsif (-d "$ENV{'PBROOTDIR'}/$pbpkg/$ddir") {
534 pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$ddir",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
535 } elsif (-d "$ENV{'PBROOTDIR'}/$pbpkg/$ddir-$dver") {
536 pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$ddir-$dver",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
537 } else {
538 $build{"$ddir-$dver"} = "no";
539 next;
540 }
541 pb_log(2,"DEBUG bfiles: ".Dumper(\%bfiles)."\n");
542
543 # Get all filters to apply
544 my $ptr = pb_get_filters($pbpkg, $dtype, $dfam, $ddir, $dver);
545
546 # Apply now all the filters on all the files concerned
547 # destination dir depends on the type of file
548 if (defined $ptr) {
549 foreach my $f (values %bfiles,values %pkgfiles) {
550 pb_filter_file_pb("$ENV{'PBROOTDIR'}/$f",$ptr,"$dest/pbconf/$ddir-$dver/".basename($f),$dtype,$pbsuf,$ENV{'PBPROJ'},$pbpkg,$pbver,$pbtag,$pbrev,$pbdate,$defpkgdir,$extpkgdir,$pbpackager,$chglog);
551 }
552 }
553 }
554 my @found;
555 my @notfound;
556 foreach my $b (keys %build) {
557 push @found,$b if ($build{$b} =~ /yes/);
558 push @notfound,$b if ($build{$b} =~ /no/);
559 }
560 pb_log(0,"Build files generated for ".join(',',@found)."\n");
561 pb_log(0,"No Build files found for ".join(',',@notfound)."\n") if (@notfound);
562 # Get the generic filter (all.pbf) and
563 # apply those to the non-build files including those
564 # generated by pbinit if applicable
565
566 # Get only all.pbf filter
567 $ptr = pb_get_filters($pbpkg);
568
569 my $liste ="";
570 if (defined $filteredfiles->{$pbpkg}) {
571 foreach my $f (split(/,/,$filteredfiles->{$pbpkg})) {
572 pb_filter_file_inplace($ptr,"$dest/$f",$ENV{'PBPROJ'},$pbpkg,$pbver,$pbtag,$pbrev,$pbdate,$pbpackager);
573 $liste = "$f $liste";
574 }
575 }
576 pb_log(2,"Files ".$liste."have been filtered\n");
577
578 # Prepare the dest directory for archive
579 if (-x "$ENV{'PBROOTDIR'}/$pbpkg/pbinit") {
580 pb_filter_file("$ENV{'PBROOTDIR'}/$pbpkg/pbinit",$ptr,"$ENV{'PBTMP'}/pbinit",$ENV{'PBPROJ'},$pbpkg,$pbver,$pbtag,$pbrev,$pbdate,$pbpackager);
581 chmod 0755,"$ENV{'PBTMP'}/pbinit";
582 pb_system("cd $dest ; $ENV{'PBTMP'}/pbinit","Executing init script from $ENV{'PBROOTDIR'}/$pbpkg/pbinit");
583 }
584
585 # Archive dest dir
586 chdir "$ENV{'PBDESTDIR'}" || die "Unable to change dir to $ENV{'PBDESTDIR'}";
587 # Possibility to look at PBSRC to guess more the filename
588 pb_system("tar cfz $pbpkg-$pbver.tar.gz $pbpkg-$pbver","Creating $pbpkg tar files compressed");
589 pb_log(2,"Under $ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz\n");
590
591 # Keep track of what is generated by default
592 open(LAST,"> $ENV{'PBDESTDIR'}/pbrc") || die "Unable to create $ENV{'PBDESTDIR'}/pbrc";
593 #print LAST "pbroot $pbprojver-$pbprojtag = $ENV{'PBROOTDIR'}\n";
594 # Why not use pbproj ?
595 print LAST "pbroot $ENV{'PBPROJ'} = $ENV{'PBROOTDIR'}\n";
596 close(LAST);
597
598 # Keep track of per package version
599 my ($pkg) = pb_conf_read_if("$ENV{'PBDESTDIR'}/$pbprojver-$pbprojtag.pb","pbpkg");
600 $pkg = { } if (not defined $pkg);
601 if ((not defined $pkg->{$pbpkg}) || ($pkg->{$pbpkg} ne "$pbver-$pbtag")) {
602 $pkg->{$pbpkg} = "$pbver-$pbtag";
603 }
604
605 pb_log(2,"DEBUG pkg: ".Dumper($pkg)."\n");
606 open(PKG,"> $ENV{'PBDESTDIR'}/$pbprojver-$pbprojtag.pb") || die "Unable to create $ENV{'PBDESTDIR'}/$pbprojver-$pbprojtag.pb";
607 foreach my $p (keys %$pkg) {
608 print PKG "pbpkg $p = $pkg->{$p}\n";
609 }
610 close(PKG);
611
612 # Final cleanup
613 pb_rm_rf($dest) if (-d $dest);
614 }
615}
616
617sub pb_build2pkg {
618
619 # Get list of packages to build
620 my $ptr = pb_get_pkg($defpkgdir,$extpkgdir);
621 @pkgs = @$ptr;
622
623 # Get the running distro to build on
624 my ($ddir, $dver, $dfam, $dtype, $pbsuf) = pb_distro_init();
625 pb_log(2,"DEBUG: distro tuple: ".join(',',($ddir, $dver, $dfam, $dtype, $pbsuf))."\n");
626
627 # Get content saved in cms2build
628 my ($pkg) = pb_conf_read("$ENV{'PBDESTDIR'}/$pbprojver-$pbprojtag.pb","pbpkg");
629 $pkg = { } if (not defined $pkg);
630
631 # declare packager (via env var in VM/VE
632 my $pbpackager;
633 if (not defined $ENV{'PBPACKAGER'}) {
634 my ($tmp) = pb_conf_get("pbpackager");
635 $pbpackager = $tmp->{$ENV{'PBPROJ'}};
636 } else {
637 $pbpackager = $ENV{'PBPACKAGER'};
638 }
639
640 chdir "$ENV{'PBBUILDDIR'}";
641 my $made = ""; # pkgs made during build
642 foreach my $pbpkg (@pkgs) {
643 my $vertag = $pkg->{$pbpkg};
644 # get the version of the current package - maybe different
645 ($pbver,$pbtag) = split(/-/,$vertag);
646
647 my $src="$ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz";
648 pb_log(2,"Source file: $src\n");
649
650 pb_log(2,"Working directory: $ENV{'PBBUILDDIR'}\n");
651 if ($dtype eq "rpm") {
652 foreach my $d ('RPMS','SRPMS','SPECS','SOURCES','BUILD') {
653 if (! -d "$ENV{'PBBUILDDIR'}/$d") {
654 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";
655 }
656 }
657
658 # Remove in case a previous link/file was there
659 unlink "$ENV{'PBBUILDDIR'}/SOURCES/".basename($src);
660 symlink "$src","$ENV{'PBBUILDDIR'}/SOURCES/".basename($src) || die "Unable to symlink $src in $ENV{'PBBUILDDIR'}/SOURCES";
661 # We need to first extract the spec file
662 my @specfile;
663 @specfile = pb_extract_build_files($src,"$pbpkg-$pbver/pbconf/$ddir-$dver/","$ENV{'PBBUILDDIR'}/SPECS");
664
665 pb_log(2,"specfile: ".Dumper(\@specfile)."\n");
666 # set LANGUAGE to check for correct log messages
667 $ENV{'LANGUAGE'}="C";
668 foreach my $f (@specfile) {
669 if ($f =~ /\.spec$/) {
670 pb_system("rpmbuild --define \'packager $pbpackager\' --define \"_topdir $ENV{'PBBUILDDIR'}\" -ba $f","Building package with $f under $ENV{'PBBUILDDIR'}");
671 last;
672 }
673 }
674 $made="$made RPMS/*/$pbpkg-$pbver-$pbtag$pbsuf.*.rpm SRPMS/$pbpkg-$pbver-$pbtag$pbsuf.src.rpm";
675 if (-f "/usr/bin/rpmlint") {
676 pb_system("rpmlint $made","Checking validity of rpms with rpmlint");
677 }
678 } elsif ($dtype eq "deb") {
679 chdir "$ENV{'PBBUILDDIR'}" || die "Unable to chdir to $ENV{'PBBUILDDIR'}";
680 pb_system("tar xfz $src","Extracting sources");
681
682 chdir "$pbpkg-$pbver" || die "Unable to chdir to $pbpkg-$pbver";
683 pb_rm_rf("debian");
684 symlink "pbconf/$ddir-$dver","debian" || die "Unable to symlink to pbconf/$ddir-$dver";
685 chmod 0755,"debian/rules";
686 pb_system("dpkg-buildpackage -us -uc -rfakeroot","Building package");
687 $made="$made $pbpkg"."_*.deb $pbpkg"."_*.dsc $pbpkg"."_*.tar.gz";
688 if (-f "/usr/bin/lintian") {
689 pb_system("lintian $made","Checking validity of debs with lintian");
690 }
691 } elsif ($dtype eq "ebuild") {
692 my @ebuildfile;
693 # For gentoo we need to take pb as subsystem name
694 # We put every apps here under sys-apps. hope it's correct
695 # We use pb's home dir in order o have a single OVERLAY line
696 my $tmpd = "$ENV{'HOME'}/portage/pb/sys-apps/$pbpkg";
697 pb_mkdir_p($tmpd) if (! -d "$tmpd");
698 pb_mkdir_p("$ENV{'HOME'}/portage/distfiles") if (! -d "$ENV{'HOME'}/portage/distfiles");
699
700 # We need to first extract the ebuild file
701 @ebuildfile = pb_extract_build_files($src,"$pbpkg-$pbver/pbconf/$ddir-$dver/","$tmpd");
702
703 # Prepare the build env for gentoo
704 my $found = 0;
705 my $pbbd = $ENV{'HOME'};
706 $pbbd =~ s|/|\\/|g;
707 if (-r "/etc/make.conf") {
708 open(MAKE,"/etc/make.conf");
709 while (<MAKE>) {
710 $found = 1 if (/$pbbd\/portage/);
711 }
712 close(MAKE);
713 }
714 if ($found == 0) {
715 pb_system("sudo sh -c 'echo PORTDIR_OVERLAY=\"$ENV{'HOME'}/portage\" >> /etc/make.conf'");
716 }
717 #$found = 0;
718 #if (-r "/etc/portage/package.keywords") {
719 #open(KEYW,"/etc/portage/package.keywords");
720 #while (<KEYW>) {
721 #$found = 1 if (/portage\/pb/);
722 #}
723 #close(KEYW);
724 #}
725 #if ($found == 0) {
726 #pb_system("sudo sh -c \"echo portage/pb >> /etc/portage/package.keywords\"");
727 #}
728
729 # Build
730 foreach my $f (@ebuildfile) {
731 if ($f =~ /\.ebuild$/) {
732 move($f,"$tmpd/$pbpkg-$pbver.ebuild");
733 pb_system("cd $tmpd ; ebuild $pbpkg-$pbver.ebuild clean ; ebuild $pbpkg-$pbver.ebuild digest ; ebuild $pbpkg-$pbver.ebuild package");
734 # Now move it where pb expects it
735 pb_mkdir_p("$ENV{'PBBUILDDIR'}/portage/pb/sys-apps/$pbpkg");
736 move("$tmpd/$pbpkg-$pbver.ebuild","$ENV{'PBBUILDDIR'}/portage/pb/sys-apps/$pbpkg");
737 }
738 }
739
740 $made="$made portage/pb/sys-apps/$pbpkg/$pbpkg-$pbver.ebuild";
741 } elsif ($dtype eq "slackware") {
742 $made="$made build-$pbpkg/$pbpkg-$pbver-*-$pbtag.tgz";
743 pb_mkdir_p("$ENV{'PBBUILDDIR'}/install") if (! -d "$ENV{'PBBUILDDIR'}/install");
744 } else {
745 die "Unknown dtype format $dtype";
746 }
747 }
748 # Keep track of what is generated so that we can get them back from VMs
749 open(KEEP,"> $ENV{'PBBUILDDIR'}/pbgen-$pbprojver-$pbprojtag") || die "Unable to create $ENV{'PBBUILDDIR'}/pbgen-$pbprojver-$pbprojtag";
750 print KEEP "$made\n";
751 close(KEEP);
752}
753
754sub pb_build2ssh {
755 pb_send2target("Sources");
756}
757
758sub pb_pkg2ssh {
759 pb_send2target("Packages");
760}
761
762# By default deliver to the the public site hosting the
763# ftp structure (or whatever) or a VM/VE
764sub pb_send2target {
765
766 my $cmt = shift;
767 my $v = shift || undef;
768 my $vmexist = shift || 0; # 0 is FALSE
769 my $vmpid = shift || 0; # 0 is FALSE
770
771 my $host = "sshhost";
772 my $login = "sshlogin";
773 my $dir = "sshdir";
774 my $port = "sshport";
775 my $tmout = "sshtmout";
776 my $path = "sshpath";
777 my $conf = "sshconf";
778 my $rebuild = "sshrebuild";
779 if ($cmt eq "vm") {
780 $login = "vmlogin";
781 $dir = "pbdefdir";
782 $tmout = "vmtmout";
783 $rebuild = "vmrebuild";
784 # Specific VM
785 $host = "vmhost";
786 $port = "vmport";
787 } elsif ($cmt eq "ve") {
788 $login = "velogin";
789 $dir = "pbdefdir";
790 $tmout = "vetmout";
791 # Specific VE
792 $path = "vepath";
793 $conf = "veconf";
794 $rebuild = "verebuild";
795 }
796 my $cmd = "";
797
798 # Get list of packages to build
799 my $ptr = pb_get_pkg($defpkgdir,$extpkgdir);
800 @pkgs = @$ptr;
801
802 # Get the running distro to consider
803 my ($odir,$over,$oarch) = (undef, undef);
804 if (defined $v) {
805 ($odir,$over,$oarch) = split(/-/,$v);
806 }
807 my ($ddir, $dver, $dfam, $dtype, $pbsuf) = pb_distro_init($odir,$over);
808 pb_log(2,"DEBUG: distro tuple: ".join(',',($ddir, $dver, $dfam, $dtype, $pbsuf))."\n");
809
810 # Get content saved in cms2build
811 my ($pkg) = pb_conf_read("$ENV{'PBDESTDIR'}/$pbprojver-$pbprojtag.pb","pbpkg");
812 $pkg = { } if (not defined $pkg);
813
814 my $src = "";
815 chdir "$ENV{'PBBUILDDIR'}";
816 foreach my $pbpkg (@pkgs) {
817 my $vertag = $pkg->{$pbpkg};
818 # get the version of the current package - maybe different
819 ($pbver,$pbtag) = split(/-/,$vertag);
820
821 if (($cmt eq "Sources") || ($cmt eq "vm") || ($cmt eq "ve")) {
822 $src = "$src $ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz";
823 if ($cmd eq "") {
824 $cmd = "ln -sf $pbpkg-$pbver.tar.gz $pbpkg-latest.tar.gz";
825 } else {
826 $cmd = "$cmd ; ln -sf $pbpkg-$pbver.tar.gz $pbpkg-latest.tar.gz";
827 }
828 }
829 }
830 if (($cmt eq "vm") || ($cmt eq "ve")) {
831 $src="$src $ENV{'PBDESTDIR'}/pbscript $ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb $ENV{'PBDESTDIR'}/$pbprojver-$pbprojtag.pb $ENV{'PBETC'}";
832 } elsif ($cmt eq "Script") {
833 $src="$src $ENV{'PBDESTDIR'}/pbscript";
834 } elsif ($cmt eq "Packages") {
835 # Get package list from file made during build2pkg
836 open(KEEP,"$ENV{'PBBUILDDIR'}/pbgen-$pbprojver-$pbprojtag") || die "Unable to read $ENV{'PBBUILDDIR'}/pbgen-$pbprojver-$pbprojtag";
837 $src = <KEEP>;
838 chomp($src);
839 close(KEEP);
840 if ($dtype eq "rpm") {
841 # Also make a pbscript to generate yum/urpmi bases
842 # $src = "$src $ENV{'PBDESTDIR'}/pbscript"
843 } elsif ($dtype eq "deb") {
844 # Also make a pbscript to generate apt bases
845 # $src = "$src $ENV{'PBDESTDIR'}/pbscript"
846 }
847 }
848 # Remove potential leading spaces (cause problem with basename)
849 $src =~ s/^ *//;
850 my $basesrc = "";
851 foreach my $i (split(/ +/,$src)) {
852 $basesrc .= " ".basename($i);
853 }
854
855 pb_log(0,"Sources handled ($cmt): $src\n");
856 my ($sshhost,$sshlogin,$sshdir,$sshport,$vtmout,$vrebuild,$vepath,$veconf) = pb_conf_get($host,$login,$dir,$port,$tmout,$rebuild,$path,$conf);
857 pb_log(2,"ssh: ".Dumper(($sshhost,$sshlogin,$sshdir,$sshport,$vtmout,$vrebuild,$vepath,$veconf))."\n");
858 # Not mandatory
859 my ($testver) = pb_conf_get_if("testver");
860
861 my $mac;
862 # Useless for VE
863 if ($cmt ne "ve") {
864 $mac = "$sshlogin->{$ENV{'PBPROJ'}}\@$sshhost->{$ENV{'PBPROJ'}}";
865 # Overwrite account value if passed as parameter
866 $mac = "$pbaccount\@$sshhost->{$ENV{'PBPROJ'}}" if (defined $pbaccount);
867 }
868
869 my $tdir;
870 my $bdir;
871 if (($cmt eq "Sources") || ($cmt eq "Script")) {
872 $tdir = "$sshdir->{$ENV{'PBPROJ'}}/src";
873 } elsif (($cmt eq "vm") || ($cmt eq "ve")) {
874 $tdir = $sshdir->{$ENV{'PBPROJ'}}."/$ENV{'PBPROJ'}/delivery";
875 $bdir = $sshdir->{$ENV{'PBPROJ'}}."/$ENV{'PBPROJ'}/build";
876 # Remove a potential $ENV{'HOME'} as bdir should be relative to pb's home
877 $bdir =~ s|\$ENV.+\}/||;
878 } elsif ($cmt eq "Packages") {
879 $tdir = "$sshdir->{$ENV{'PBPROJ'}}/$ddir/$dver";
880 if ((defined $testver) && (defined $testver->{$ENV{'PBPROJ'}}) && ($testver->{$ENV{'PBPROJ'}} =~ /true/i)) {
881 # This is a test pkg => target dir is under test
882 $tdir .= "/test";
883 }
884 } else {
885 return;
886 }
887
888 # Useless for VE
889 my $nport;
890 if ($cmt ne "ve") {
891 $nport = $sshport->{$ENV{'PBPROJ'}};
892 $nport = "$pbport" if (defined $pbport);
893 }
894
895 # Remove a potential $ENV{'HOME'} as tdir should be relative to pb's home
896 $tdir =~ s|\$ENV.+\}/||;
897
898 my $tm = $vtmout->{$ENV{'PBPROJ'}};
899
900 # ssh communication if not VE
901 my ($shcmd,$cpcmd,$cptarget,$cp2target);
902 if ($cmt ne "ve") {
903 $shcmd = "ssh -q -p $nport $mac";
904 $cpcmd = "scp -p -P $nport";
905 $cptarget = "$mac:$tdir";
906 $cp2target = "$mac:$bdir";
907 } else {
908 my $tp = $vepath->{$ENV{'PBPROJ'}};
909 $shcmd = "sudo chroot $tp/$v /bin/su - $sshlogin->{$ENV{'PBPROJ'}} -c ";
910 $cpcmd = "cp -a ";
911 $cptarget = "$tp/$tdir";
912 $cp2target = "$tp/$bdir";
913 }
914
915 pb_system("$shcmd \"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 $cptarget");
916 pb_system("cd $ENV{'PBBUILDDIR'} ; $cpcmd $src $cptarget 2> /dev/null","$cmt delivery in $cptarget");
917 # For VE we need to change the owner manually - To be tested if needed
918 #if ($cmt eq "ve") {
919 #pb_system("cd $cptarget ; sudo chown -R $sshlogin->{$ENV{'PBPROJ'}} .","$cmt chown in $cptarget to $sshlogin->{$ENV{'PBPROJ'}}");
920 #}
921 pb_system("$shcmd \"echo \'cd $tdir ; if [ -f pbscript ]; then ./pbscript; fi\' | bash\"","Executing pbscript on $cptarget if needed");
922 if (($cmt eq "vm") || ($cmt eq "ve")) {
923 # Get back info on pkg produced, compute their name and get them from the VM
924 pb_system("$cpcmd $cp2target/pbgen-$pbprojver-$pbprojtag $ENV{'PBBUILDDIR'} 2> /dev/null","Get package names in $cp2target");
925 open(KEEP,"$ENV{'PBBUILDDIR'}/pbgen-$pbprojver-$pbprojtag") || die "Unable to read $ENV{'PBBUILDDIR'}/pbgen-$pbprojver-$pbprojtag";
926 my $src = <KEEP>;
927 chomp($src);
928 close(KEEP);
929 $src =~ s/^ *//;
930 pb_mkdir_p("$ENV{'PBBUILDDIR'}/$odir/$over");
931 # Change pgben to make the next send2target happy
932 my $made = "";
933 open(KEEP,"> $ENV{'PBBUILDDIR'}/pbgen-$pbprojver-$pbprojtag") || die "Unable to write $ENV{'PBBUILDDIR'}/pbgen-$pbprojver-$pbprojtag";
934 foreach my $p (split(/ +/,$src)) {
935 my $j = basename($p);
936 pb_system("$cpcmd $cp2target/\'$p\' $ENV{'PBBUILDDIR'}/$odir/$over 2> /dev/null","Package recovery of $j in $cp2target");
937 $made="$made $odir/$over/$j" if (($dtype ne "rpm") || ($j !~ /.src.rpm$/));
938 }
939 print KEEP "$made\n";
940 close(KEEP);
941 pb_system("$shcmd \"rm -rf $tdir $bdir\"","$cmt cleanup");
942 pb_send2target("Packages","$odir"."_"."$over");
943 if ((! $vmexist) && ($cmt eq "vm")) {
944 pb_system("$shcmd \"sudo /sbin/halt -p \"; sleep $tm ; echo \'if [ -d /proc/$vmpid ]; then kill -9 $vmpid; fi \' | bash ; sleep 10","VM $v halt (pid $vmpid)");
945 }
946 pb_rm_rf("$ENV{'PBBUILDDIR'}/$odir");
947 }
948}
949
950sub pb_script2v {
951 my $pbscript=shift;
952 my $vtype=shift;
953
954 # Prepare the script to be executed on the VM
955 # in $ENV{'PBDESTDIR'}/pbscript
956 if ((defined $pbscript ) && ($pbscript ne "$ENV{'PBDESTDIR'}/pbscript")) {
957 copy($pbscript,"$ENV{'PBDESTDIR'}/pbscript") || die "Unable to create $ENV{'PBDESTDIR'}/pbscript";
958 chmod 0755,"$ENV{'PBDESTDIR'}/pbscript";
959 }
960
961 my ($vm,$all) = pb_get_v($vtype);
962 my ($vmexist,$vmpid) = (undef,undef);
963
964 foreach my $v (@$vm) {
965 # Launch the VM/VE
966 if ($vtype eq "vm") {
967 ($vmexist,$vmpid) = pb_launchv($vtype,$v,0);
968
969 # Skip that VM if something went wrong
970 next if (($vmpid == 0) && ($vmexist ==0));
971 }
972
973 # Gather all required files to send them to the VM
974 # and launch the build through pbscript
975 pb_send2target("Script","$v",$vmexist,$vmpid);
976
977 }
978}
979
980sub pb_launchv {
981 my $vtype = shift;
982 my $v = shift;
983 my $create = shift || 0; # By default do not create a VM
984
985 die "No VM/VE defined, unable to launch" if (not defined $v);
986 # Keep only the first VM in case many were given
987 $v =~ s/,.*//;
988
989 # Which is our local arch ? (standardize on i386 for those platforms)
990 my $arch = `uname -m`;
991 chomp($arch);
992 $arch =~ s/i.86/i386/;
993
994 # Launch the VMs/VEs
995 if ($vtype eq "vm") {
996 die "-i iso parameter needed" if (((not defined $iso) || ($iso eq "")) && ($create != 0));
997
998 my ($ptr,$vmopt,$vmport,$vmpath,$vmtmout,$vmsize) = pb_conf_get("vmtype","vmopt","vmport","vmpath","vmtmout","vmsize");
999
1000 my $vmtype = $ptr->{$ENV{'PBPROJ'}};
1001 if (not defined $ENV{'PBVMOPT'}) {
1002 $ENV{'PBVMOPT'} = "";
1003 }
1004 if (defined $vmopt->{$ENV{'PBPROJ'}}) {
1005 $ENV{'PBVMOPT'} .= " $vmopt->{$ENV{'PBPROJ'}}" if ($ENV{'PBVMOPT'} !~ / $vmopt->{$ENV{'PBPROJ'}}/);
1006 }
1007 my $nport = $vmport->{$ENV{'PBPROJ'}};
1008 $nport = "$pbport" if (defined $pbport);
1009
1010 my $cmd;
1011 my $vmcmd; # has to be used for pb_check_ps
1012 my $vmm; # has to be used for pb_check_ps
1013 if ($vmtype eq "qemu") {
1014 my $qemucmd32;
1015 my $qemucmd64;
1016 if ($arch eq "x86_64") {
1017 $qemucmd32 = "/usr/bin/qemu-system-i386";
1018 $qemucmd64 = "/usr/bin/qemu";
1019 } else {
1020 $qemucmd32 = "/usr/bin/qemu";
1021 $qemucmd64 = "/usr/bin/qemu-system-x86_64";
1022 }
1023 if ($v =~ /x86_64/) {
1024 $vmcmd = "$qemucmd64 -no-kqemu";
1025 } else {
1026 $vmcmd = "$qemucmd32";
1027 }
1028 $vmm = "$vmpath->{$ENV{'PBPROJ'}}/$v.qemu";
1029 if ($create != 0) {
1030 $ENV{'PBVMOPT'} .= " -cdrom $iso -boot d";
1031 }
1032 $cmd = "$vmcmd $ENV{'PBVMOPT'} -redir tcp:$nport:10.0.2.15:22 $vmm"
1033 } elsif ($vmtype eq "xen") {
1034 } elsif ($vmtype eq "vmware") {
1035 } else {
1036 die "VM of type $vmtype not supported. Report to the dev team";
1037 }
1038 my ($tmpcmd,$void) = split(/ +/,$cmd);
1039 my $vmexist = pb_check_ps($tmpcmd,$vmm);
1040 my $vmpid = 0;
1041 if (! $vmexist) {
1042 if ($create != 0) {
1043 if (($vmtype eq "qemu") || ($vmtype eq "xen")) {
1044 pb_system("/usr/bin/qemu-img create -f qcow2 $vmm $vmsize->{$ENV{'PBPROJ'}}","Creating the QEMU VM");
1045 } elsif ($vmtype eq "vmware") {
1046 } else {
1047 }
1048 }
1049 if (! -f "$vmm") {
1050 pb_log(0,"Unable to find VM $vmm\n");
1051 } else {
1052 pb_system("$cmd &","Launching the VM $vmm");
1053 pb_system("sleep $vmtmout->{$ENV{'PBPROJ'}}","Waiting for VM $v to come up");
1054 $vmpid = pb_check_ps($tmpcmd,$vmm);
1055 }
1056 } else {
1057 pb_log(0,"Found an existing VM $vmm (pid $vmexist)\n");
1058 }
1059 return($vmexist,$vmpid);
1060 # VE here
1061 } else {
1062 # Get VE context
1063 my ($ptr,$vepath,$vetmout,$verebuild,$veconf) = pb_conf_get("vetype","vepath","vetmout","verebuild","veconf");
1064 my $vetype = $ptr->{$ENV{'PBPROJ'}};
1065
1066 # Get distro context
1067 my ($name,$ver,$darch) = split(/-/,$v);
1068 chomp($darch);
1069 my ($ddir, $dver, $dfam, $dtype, $pbsuf) = pb_distro_init($name,$ver);
1070
1071 if ($vetype eq "chroot") {
1072 # Architecture consistency
1073 if ($arch ne $darch) {
1074 die "Unable to launch a VE of architecture $darch on a $arch platform" if (not (($darch eq "x86_64") && ($arch =~ /i?86/)));
1075 }
1076
1077 if (($create != 0) || ($verebuild->{$ENV{'PBPROJ'}} eq "true") || ($force == 1)) {
1078 # We have to rebuild the chroot
1079 if ($dtype eq "rpm") {
1080 pb_system("sudo /usr/sbin/mock --init --resultdir=\"/tmp\" --configdir=\"$veconf->{$ENV{'PBPROJ'}}\" -r $v","Creating the mock VE");
1081 # Once setup we need to install some packages, the pb account, ...
1082 pb_system("sudo /usr/sbin/mock --install --configdir=\"$veconf->{$ENV{'PBPROJ'}}\" -r $v su","Configuring the mock VE");
1083 #pb_system("sudo /usr/sbin/mock --init --resultdir=\"/tmp\" --configdir=\"$veconf->{$ENV{'PBPROJ'}}\" --basedir=\"$vepath->{$ENV{'PBPROJ'}}\" -r $v","Creating the mock VE");
1084 } elsif ($dtype eq "deb") {
1085 pb_system("","Creating the pbuilder VE");
1086 } elsif ($dtype eq "ebuild") {
1087 die "Please teach the dev team how to build gentoo chroot";
1088 } else {
1089 die "Unknown distribution type $dtype. Report to dev team";
1090 }
1091 }
1092 # Nothing more to do for VE. No real launch
1093 } else {
1094 die "VE of type $vetype not supported. Report to the dev team";
1095 }
1096 }
1097}
1098
1099sub pb_build2v {
1100
1101my $vtype = shift;
1102
1103# Prepare the script to be executed on the VM/VE
1104# in $ENV{'PBDESTDIR'}/pbscript
1105my ($ntp) = pb_conf_get($vtype."ntp");
1106my $vntp = $ntp->{$ENV{'PBPROJ'}};
1107
1108open(SCRIPT,"> $ENV{'PBDESTDIR'}/pbscript") || die "Unable to create $ENV{'PBDESTDIR'}/pbscript";
1109print SCRIPT "#!/bin/bash\n";
1110print SCRIPT "echo ... Execution needed\n";
1111print SCRIPT "# This is in directory delivery\n";
1112print SCRIPT "# Setup the variables required for building\n";
1113print SCRIPT "export PBPROJ=$ENV{'PBPROJ'}\n";
1114print SCRIPT "# Preparation for pb\n";
1115print SCRIPT "mv .pbrc \$HOME\n";
1116print SCRIPT "cd ..\n";
1117# Force new date to be in the future compared to the date of the tar file by adding 1 minute
1118my @date=pb_get_date();
1119$date[1]++;
1120my $upddate = strftime("%m%d%H%M%Y", @date);
1121print SCRIPT "echo Setting up date on $vntp...\n";
1122# Or use ntpdate if available TBC
1123print SCRIPT "sudo date $upddate\n";
1124# This exports avoids pb_env_init to deal with PBCONF stuff
1125print SCRIPT "export PBCONF=/tmp\n";
1126print SCRIPT "export PBVER=$ENV{'PBVER'}\n";
1127print SCRIPT "export PBTAG=$ENV{'PBTAG'}\n";
1128print SCRIPT "export PBPACKAGER=\"$ENV{'PBPACKAGER'}\"\n";
1129print SCRIPT "# Build\n";
1130# Get list of packages to build
1131my $ptr = pb_get_pkg($defpkgdir,$extpkgdir);
1132@pkgs = @$ptr;
1133my $p = join(' ',@pkgs) if (@pkgs);
1134print SCRIPT "echo Building packages on $vtype...\n";
1135print SCRIPT "pb -p $ENV{'PBPROJ'} build2pkg $p\n";
1136close(SCRIPT);
1137chmod 0755,"$ENV{'PBDESTDIR'}/pbscript";
1138
1139my ($v,$all) = pb_get_v($vtype);
1140
1141# Send tar files when we do a global generation
1142pb_build2ssh() if ($all == 1);
1143
1144my ($vmexist,$vmpid) = (undef,undef);
1145
1146foreach my $v (@$v) {
1147 if ($vtype eq "vm") {
1148 # Launch the VM
1149 my ($vmexist,$vmpid) = pb_launchv($vtype,$v,0);
1150
1151 # Skip that VM if it something went wrong
1152 next if (($vmpid == 0) && ($vmexist == 0));
1153 }
1154 # Gather all required files to send them to the VM/VE
1155 # and launch the build thourgh pbscript
1156 pb_send2target($vtype,"$v",$vmexist,$vmpid);
1157}
1158}
1159
1160
1161sub pb_newver {
1162
1163 die "-V Version parameter needed" if ((not defined $newver) || ($newver eq ""));
1164
1165 my ($scheme,$uri)=pb_cms_init($pbinit);
1166
1167 if ($scheme !~ /^svn/) {
1168 die "Only SVN is supported at the moment";
1169 }
1170 my $res = pb_cms_isdiff($scheme);
1171 die "You need to have no differences before creating a new version" if ($res != 0);
1172 my $cmsurl = pb_cms_getinfo($scheme,$ENV{'PBROOTDIR'},"URL:");
1173 my $newurl = dirname($cmsurl)."/$newver";
1174 pb_cms_copy($scheme,$cmsurl,$newurl);
1175 pb_cms_checkout($scheme,$newurl,"$ENV{'PBROOTDIR'}/../$newver");
1176 my $oldver=basename($cmsurl);
1177 open(FILE,"$ENV{'PBROOTDIR'}/../$newver/pbconf/$ENV{'PBPROJ'}.pb") || die "Unable to open $ENV{'PBROOTDIR'}/../$newver/pbconf/$ENV{'PBPROJ'}.pb";
1178 open(OUT,"> $ENV{'PBROOTDIR'}/../$newver/pbconf/$ENV{'PBPROJ'}.pb.new") || die "Unable to write to $ENV{'PBROOTDIR'}/../$newver/pbconf/$ENV{'PBPROJ'}.pb.new";
1179 while(<FILE>) {
1180 s/projver\s+$ENV{'PBPROJ'}\s*=\s*$oldver/projver $ENV{'PBPROJ'} = $newver/;
1181 print OUT $_;
1182 }
1183 close(FILE);
1184 close(OUT);
1185 rename("$ENV{'PBROOTDIR'}/../$newver/pbconf/$ENV{'PBPROJ'}.pb.new","$ENV{'PBROOTDIR'}/../$newver/pbconf/$ENV{'PBPROJ'}.pb");
1186 pb_cms_checkin($scheme,"$ENV{'PBROOTDIR'}/../$newver");
1187}
1188
1189#
1190# Return the list of VMs/VEs we are working on
1191# $all is a flag to know if we return all of them
1192# or only some (if all we publish also tar files in addition to pkgs
1193#
1194sub pb_get_v {
1195
1196my $vtype = shift;
1197my @v;
1198my $all = 0;
1199my $vlist;
1200my $pbv = 'PBV';
1201
1202if ($vtype eq "vm") {
1203 $vlist = "vmlist";
1204} elsif ($vtype eq "ve") {
1205 $vlist = "velist";
1206}
1207# Get VM/VE list
1208if ((not defined $ENV{$pbv}) || ($ENV{$pbv} =~ /^all$/)) {
1209 my ($ptr) = pb_conf_get($vlist);
1210 $ENV{$pbv} = $ptr->{$ENV{'PBPROJ'}};
1211 $all = 1;
1212}
1213pb_log(2,"$vtype: $ENV{$pbv}\n");
1214@v = split(/,/,$ENV{$pbv});
1215return(\@v,$all);
1216}
1217
1218sub pb_setup_v {
1219# Function to create a potentialy missing pb account on the VM/VE, and adds it to sudo
1220# Needs to use root account to connect to the VM/VE
1221
1222# pb will take your local public SSH key to access
1223# the pb account in the VM later on
1224
1225my $vtype = shift;
1226
1227my $file = "$ENV{'HOME'}/.ssh/id_dsa.pub";
1228die "Unable to find your public ssh key as $file";
1229
1230open(SCRIPT,"> $ENV{'PBDESTDIR'}/pbscript") || die "Unable to create $ENV{'PBDESTDIR'}/pbscript";
1231print SCRIPT << 'EOF';
1232#!/usr/bin/perl -w
1233
1234$file="/etc/passwd";
1235open(PBFILE,$file) || die "Unable to open $file";
1236my $found = 0;
1237while (<PBFILE>) {
1238 $found = 1 if (/^pb:/);
1239}
1240close(PBFILE);
1241
1242if ( $found == 0 ) {
1243 if ( ! -d "/home" ) {
1244 mkdir "/home";
1245 }
1246 system "groupadd pb";
1247 system "useradd pb -g pb -m -d /home/pb";
1248}
1249
1250# For root
1251mkdir ".ssh",0700;
1252system 'cp /tmp/pbkey .ssh/authorized_keys';
1253chmod 0600,".ssh/authorized_keys";
1254
1255# For pb
1256chdir "/home/pb";
1257mkdir ".ssh",0700;
1258system 'cp /tmp/pbkey .ssh/authorized_keys';
1259chmod 0600,".ssh/authorized_keys";
1260system 'chown -R pb:pb .ssh';
1261
1262# No passwd for pb only keys
1263$file="/etc/shadow";
1264open(PBFILE,$file) || die "Unable to open $file";
1265open(PBOUT,"> $file.new") || die "Unable to open $file.new";
1266while (<PBFILE>) {
1267 s/^pb:\!\!:/pb:*:/;
1268 s/^pb:\!:/pb:*:/; #SLES 9 e.g.
1269 print PBOUT $_;
1270}
1271close(PBFILE);
1272close(PBOUT);
1273rename("$file.new",$file);
1274chmod 0640,$file;
1275
1276# pb has to be added to portage group on gentoo
1277unlink "/tmp/pbkey";
1278
1279my ($ddir, $dver, $dfam, $dtype, $pbsuf) = pb_distro_init();
1280print "distro tuple: ".join(',',($ddir, $dver, $dfam, $dtype, $pbsuf))."\n";
1281
1282# Get and install pb
1283if ( $ddir eq "fedora" ) {
1284 system "yum clean all";
1285 system "yum update -y";
1286 my $arch=`uname -m`;
1287 my $opt = "";
1288 chomp($arch);
1289 if ($arch eq "x86_64") {
1290 $opt="--exclude=*.i?86";
1291 }
1292
1293 system "yum -y $opt install rpm-build wget patch ntp sudo perl-DateManip perl-ExtUtils-MakeMaker";
1294} elsif (( $dfam eq "rh" ) || ($ddir eq "sles") || (($ddir eq "suse") && (($dver eq "10.1") || ($dver eq "10.0"))) || (($ddir eq "mandrake") && ($dver eq "10.1"))) {
1295 # Suppose pkg are installed already
1296 system "rpm -e lsb 2>&1 > /dev/null";
1297 system "rm -rf DateManip* ; wget http://search.cpan.org/CPAN/authors/id/S/SB/SBECK/Date-Manip-5.46.tar.gz ; tar xvfz Date-Manip-5.46.tar.gz ; cd Date-Manip* ; perl Makefile.PL ; make ; make install ; cd .. ";
1298} elsif ($ddir eq "suse") {
1299 # New OpenSuSE
1300 system "export TERM=linux ; liste=\"\" ; for i in make wget patch sudo perl-DateManip perl-File-HomeDir xntp; do rpm -q \$i 1> /dev/null 2> /dev/null ; if [ \$\? != 0 ]; then liste=\"\$liste \$i\"; fi; done; echo \"Liste: \$liste\" ; if [ \"\$liste\" != \"\" ]; then yast2 -i \$liste ; fi";
1301} elsif ( $dfam eq "md" ) {
1302 system "urpmi.update -a ; urpmi --auto rpm-build wget sudo patch ntp-client perl-DateManip";
1303} elsif ( $dfam eq "du" ) {
1304 if (( $dver eq "3.1" ) && ($ddir eq "debian")) {
1305 system "apt-get update; apt-get -y install wget patch ssh sudo debian-builder dh-make fakeroot ntpdate libdate-manip-perl";
1306 } else {
1307 system "apt-get update; apt-get -y install wget patch openssh-server dpkg-dev sudo debian-builder dh-make fakeroot ntpdate rses5-dev libdate-manip-perl";
1308 }
1309} elsif ( $dfam eq "gen" ) {
1310 system "emerge -u system ; emerge wget sudo ntp DateManip";
1311} else {
1312 print "No pkg to install\n";
1313}
1314
1315# Adapt sudoers
1316$file="/etc/sudoers";
1317open(PBFILE,$file) || die "Unable to open $file";
1318open(PBOUT,"> $file.new") || die "Unable to open $file.new";
1319while (<PBFILE>) {
1320 next if (/^pb /);
1321 s/Defaults[ \t]+requiretty//;
1322 print PBOUT $_;
1323}
1324close(PBFILE);
1325print PBOUT "pb ALL=(ALL) NOPASSWD:ALL\n";
1326close(PBOUT);
1327rename("$file.new",$file);
1328chmod 0440,$file;
1329
1330# Suse wants sudoers as 640
1331if (($ddir eq "sles") || (($ddir eq "suse")) && ($dver ne "10.3")) {
1332 chmod 0640,$file;
1333}
1334
1335# Sync date
1336system "/usr/sbin/ntpdate ntp.pool.org";
1337
1338system "rm -rf project-builder-* ; wget --passive-ftp ftp://ftp.mondorescue.org/src/project-builder-latest.tar.gz ; tar xvfz project-builder-latest.tar.gz ; cd project-builder-* ; perl Makefile.PL ; make ; make install ; cd ..";
1339EOF
1340close(SCRIPT);
1341}
1342
1343# Returns the pid of a running VM command using a specific VM file
1344sub pb_check_ps {
1345 my $vmcmd = shift;
1346 my $vmm = shift;
1347 my $vmexist = 0; # FALSE by default
1348
1349 open(PS, "ps auxhww|") || die "Unable to call ps";
1350 while (<PS>) {
1351 next if (! /$vmcmd/);
1352 next if (! /$vmm/);
1353 my ($void1, $void2);
1354 ($void1, $vmexist, $void2) = split(/ +/);
1355 last;
1356 }
1357 return($vmexist);
1358}
1359
1360
1361sub pb_extract_build_files {
1362
1363my $src=shift;
1364my $dir=shift;
1365my $ddir=shift;
1366my @files;
1367
1368if ($src =~ /tar\.gz$/) {
1369 pb_system("tar xfpz $src $dir","Extracting build files");
1370} elsif ($src =~ /tar\.bz2$/) {
1371 pb_system("tar xfpj $src $dir","Extracting build files");
1372} else {
1373 die "Unknown compression algorithm for $src";
1374}
1375opendir(DIR,"$dir") || die "Unable to open directory $dir";
1376foreach my $f (readdir(DIR)) {
1377 next if ($f =~ /^\./);
1378 move("$dir/$f","$ddir") || die "Unable to move $dir/$f to $ddir";
1379 pb_log(2,"mv $dir/$f $ddir\n");
1380 push @files,"$ddir/$f";
1381}
1382closedir(DIR);
1383# Not enough but still a first cleanup
1384pb_rm_rf("$dir");
1385return(@files);
1386}
1387
1388sub pb_list_bfiles {
1389
1390my $dir = shift;
1391my $pbpkg = shift;
1392my $bfiles = shift;
1393my $pkgfiles = shift;
1394my $supfiles = shift;
1395
1396opendir(BDIR,"$dir") || die "Unable to open dir $dir: $!";
1397foreach my $f (readdir(BDIR)) {
1398 next if ($f =~ /^\./);
1399 $bfiles->{$f} = "$dir/$f";
1400 $bfiles->{$f} =~ s~$ENV{'PBROOTDIR'}~~;
1401 if (defined $supfiles->{$pbpkg}) {
1402 $pkgfiles->{$f} = "$dir/$f" if ($f =~ /$supfiles->{$pbpkg}/);
1403 }
1404}
1405closedir(BDIR);
1406}
1407
1408sub pb_syntax {
1409
1410my $exit_status = shift || -1;
1411my $verbose_level = shift || 0;
1412
1413my $filehandle = \*STDERR;
1414
1415$filehandle = \*STDOUT if ($exit_status == 0);
1416
1417pod2usage( { -message => "pb (aka project-builder.org) Version $projectbuilderver-$projectbuilderrev\n",
1418 -exitval => $exit_status ,
1419 -verbose => $verbose_level,
1420 -output => $filehandle } );
1421}
Note: See TracBrowser for help on using the repository browser.