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

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

Version allowing build of pb and mondorescue. Target for 0.9.0

  • Property svn:executable set to *
File size: 43.9 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);
294getopts('a:fhi:l:m:P:p:qr:s:tvV:',\%opts);
295
296my ($projectbuilderver,$projectbuilderrev) = pb_version_init();
297
298GetOptions("help|?|h" => \$opts{'h'},
299 "man" => \$opts{'man'},
300 "verbose|v+" => \$opts{'v'},
301 "quiet|q" => \$opts{'q'},
302 "log-files|l=s" => \$opts{'l'},
303 "force|f" => \$opts{'f'},
304 "account|a=s" => \$opts{'a'},
305 "revision|r=s" => \$opts{'r'},
306 "script|s=s" => \$opts{'s'},
307 "machines|mock|m=s" => \$opts{'m'},
308 "port|P=i" => \$opts{'P'},
309 "project|p=s" => \$opts{'p'},
310 "iso|i=s" => \$opts{'i'},
311 "version|V=s" => \$opts{'V'},
312) || pb_syntax(-1,0);
313
314if (defined $opts{'h'}) {
315 pb_syntax(0,1);
316}
317if (defined $opts{'man'}) {
318 pb_syntax(0,2);
319}
320if (defined $opts{'v'}) {
321 $debug = $opts{'v'};
322 pb_log(0,"Debug value: $debug\n");
323}
324if (defined $opts{'f'}) {
325 $force=1;
326}
327if (defined $opts{'q'}) {
328 $debug=-1;
329}
330if (defined $opts{'l'}) {
331 open(LOG,"> $opts{'l'}") || die "Unable to log to $opts{'l'}: $!";
332 $LOG = *LOG;
333 $debug = 0 if ($debug == -1);
334 }
335pb_log_init($debug, $LOG);
336
337# Handle root of the project if defined
338if (defined $opts{'r'}) {
339 $ENV{'PBROOTDIR'} = $opts{'r'};
340}
341# Handle virtual machines if any
342if (defined $opts{'m'}) {
343 $ENV{'PBV'} = $opts{'m'};
344}
345if (defined $opts{'s'}) {
346 $pbscript = $opts{'s'};
347}
348if (defined $opts{'a'}) {
349 $pbaccount = $opts{'a'};
350}
351if (defined $opts{'P'}) {
352 $pbport = $opts{'P'};
353}
354if (defined $opts{'V'}) {
355 $newver = $opts{'V'};
356}
357if (defined $opts{'i'}) {
358 $iso = $opts{'i'};
359}
360
361# Get Action
362$action = shift @ARGV;
363die pb_syntax(-1,1) if (not defined $action);
364
365my ($filteredfiles, $supfiles, $defpkgdir, $extpkgdir);
366my $pbinit = undef;
367$pbinit = 1 if ($action =~ /^newproj$/);
368
369# Handles project name if any
370# And get global params
371if (defined $opts{'p'}) {
372 ($filteredfiles, $supfiles, $defpkgdir, $extpkgdir)
373 = pb_env_init($opts{'p'},$pbinit);
374} else {
375 ($filteredfiles, $supfiles, $defpkgdir, $extpkgdir)
376 = pb_env_init(undef,$pbinit);
377}
378
379pb_log(0,"Project: $ENV{'PBPROJ'}\n");
380pb_log(0,"Action: $action\n");
381
382# Keep those project values to store them at the end each time
383my $pbprojtag = $ENV{'PBTAG'};
384my $pbprojver = $ENV{'PBVER'};
385
386# Act depending on action
387if ($action =~ /^cms2build$/) {
388 pb_cms2build();
389} elsif ($action =~ /^build2pkg$/) {
390 pb_build2pkg();
391} elsif ($action =~ /^cms2pkg$/) {
392 pb_cms2build();
393 pb_build2pkg();
394} elsif ($action =~ /^build2ssh$/) {
395 pb_build2ssh();
396} elsif ($action =~ /^cms2ssh$/) {
397 pb_cms2build();
398 pb_build2ssh();
399} elsif ($action =~ /^pkg2ssh$/) {
400 pb_pkg2ssh();
401} elsif ($action =~ /^build2ve$/) {
402 pb_build2v("ve");
403} elsif ($action =~ /^build2vm$/) {
404 pb_build2v("vm");
405} elsif ($action =~ /^cms2ve$/) {
406 pb_cms2build();
407 pb_build2v("ve");
408} elsif ($action =~ /^cms2vm$/) {
409 pb_cms2build();
410 pb_build2v("vm");
411} elsif ($action =~ /^launchvm$/) {
412 pb_launchv("vm",$ENV{'PBV'},0);
413} elsif ($action =~ /^launchve$/) {
414 pb_launchv("ve",$ENV{'PBV'},0);
415} elsif ($action =~ /^script2vm$/) {
416 pb_script2v($pbscript,"vm");
417} elsif ($action =~ /^script2ve$/) {
418 pb_script2v($pbscript,"ve");
419} elsif ($action =~ /^newver$/) {
420 pb_newver();
421} elsif ($action =~ /^newve$/) {
422 pb_launchv("ve",$ENV{'PBV'},1);
423} elsif ($action =~ /^newvm$/) {
424 pb_launchv("vm",$ENV{'PBV'},1);
425} elsif ($action =~ /^newproj$/) {
426 # Nothing to do - already done in pb_env_init
427} elsif ($action =~ /^clean$/) {
428} else {
429 pb_log(0,"\'$action\' is not available\n");
430 pb_syntax(-2,1);
431}
432
433sub pb_cms2build {
434
435 my $ptr = pb_get_pkg($defpkgdir,$extpkgdir);
436 @pkgs = @$ptr;
437 my ($uri) = pb_conf_get("pburl");
438 my ($scheme, $account, $host, $port, $path) = pb_get_uri($uri->{$ENV{'PBPROJ'}});
439
440 # Some variable initialization depending on CMS type
441 my ($scheme,$uri)=pb_cms_init($pbinit);
442
443 my ($pkgv, $pkgt) = pb_conf_get_if("pkgver","pkgtag");
444
445 # declare packager for filtering
446 my ($tmp) = pb_conf_get("pbpackager");
447 my $pbpackager = $tmp->{$ENV{'PBPROJ'}};
448
449 foreach my $pbpkg (@pkgs) {
450 $ENV{'PBPKG'} = $pbpkg;
451 $ENV{'PBVER'} = $pbprojver;
452 $ENV{'PBTAG'} = $pbprojtag;
453 if ((defined $pkgv) && (defined $pkgv->{$pbpkg})) {
454 $pbver = $pkgv->{$pbpkg};
455 $ENV{'PBVER'} = $pbver;
456 } else {
457 $pbver = $ENV{'PBVER'};
458 }
459 if ((defined $pkgt) && (defined $pkgt->{$pbpkg})) {
460 $pbtag = $pkgt->{$pbpkg};
461 $ENV{'PBTAG'} = $pbtag;
462 } else {
463 $pbtag = $ENV{'PBTAG'};
464 }
465
466 $pbrev = $ENV{'PBREVISION'};
467 pb_log(0,"\n");
468 pb_log(0,"Management of $pbpkg $pbver-$pbtag (rev $pbrev)\n");
469 die "Unable to get env var PBDESTDIR" if (not defined $ENV{'PBDESTDIR'});
470 # Clean up dest if necessary. The export will recreate it
471 my $dest = "$ENV{'PBDESTDIR'}/$pbpkg-$pbver";
472 pb_rm_rf($dest) if (-d $dest);
473
474 # Export CMS tree for the concerned package to dest
475 # And generate some additional files
476 $OUTPUT_AUTOFLUSH=1;
477
478 # computes in which dir we have to work
479 my $dir = $defpkgdir->{$pbpkg};
480 $dir = $extpkgdir->{$pbpkg} if (not defined $dir);
481 pb_log(2,"def:".Dumper($defpkgdir)." ext: ".Dumper($extpkgdir)." \n");
482
483 # Exporting from CMS
484 pb_cms_export($uri,"$ENV{'PBDIR'}/$dir",$dest);
485
486 # Get project info on authors and log file
487 my $chglog = "$ENV{'PBROOTDIR'}/$pbpkg/pbcl";
488 $chglog = "$ENV{'PBROOTDIR'}/pbcl" if (! -f $chglog);
489 $chglog = undef if (! -f $chglog);
490
491 my $authors = "$ENV{'PBROOTDIR'}/$pbpkg/pbauthors";
492 $authors = "$ENV{'PBROOTDIR'}/pbauthors" if (! -f $authors);
493 $authors = "/dev/null" if (! -f $authors);
494
495 # Extract cms log history and store it
496 if ((defined $chglog) && (! -f "$dest/NEWS")) {
497 pb_log(2,"Generating NEWS file from $chglog\n");
498 copy($chglog,"$dest/NEWS") || die "Unable to create $dest/NEWS";
499 }
500 pb_cms_log($scheme,"$ENV{'PBDIR'}/$dir",$dest,$chglog,$authors);
501
502 my %build;
503
504 my @pt;
505 @pt = pb_conf_get_if("vmlist","velist");
506 my $tmpl = "";
507 if (defined $pt[0]->{$ENV{'PBPROJ'}}) {
508 $tmpl .= $pt[0]->{$ENV{'PBPROJ'}};
509 }
510 if (defined $pt[1]->{$ENV{'PBPROJ'}}) {
511 # the 2 lists needs to be grouped with a ',' separated them
512 if ($tmpl ne "") {
513 $tmpl .= ",";
514 }
515 $tmpl .= $pt[1]->{$ENV{'PBPROJ'}}
516 }
517 foreach my $d (split(/,/,$tmpl)) {
518 my ($name,$ver,$arch) = split(/-/,$d);
519 chomp($arch);
520 my ($ddir, $dver, $dfam, $dtype, $pbsuf) = pb_distro_init($name,$ver);
521 pb_log(2,"DEBUG: distro tuple: ".Dumper($ddir, $dver, $dfam, $dtype, $pbsuf)."\n");
522 pb_log(2,"DEBUG Filtering PBDATE => $pbdate, PBTAG => $pbtag, PBVER => $pbver\n");
523
524 # Filter build files from the less precise up to the most with overloading
525 # Filter all files found, keeping the name, and generating in dest
526
527 # Find all build files first relatively to PBROOTDIR
528 # Find also all specific files referenced in the .pb conf file
529 my %bfiles = ();
530 my %pkgfiles = ();
531 $build{"$ddir-$dver"} = "yes";
532
533 if (-d "$ENV{'PBROOTDIR'}/$pbpkg/$dtype") {
534 pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$dtype",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
535 } elsif (-d "$ENV{'PBROOTDIR'}/$pbpkg/$dfam") {
536 pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$dfam",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
537 } elsif (-d "$ENV{'PBROOTDIR'}/$pbpkg/$ddir") {
538 pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$ddir",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
539 } elsif (-d "$ENV{'PBROOTDIR'}/$pbpkg/$ddir-$dver") {
540 pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$ddir-$dver",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
541 } else {
542 $build{"$ddir-$dver"} = "no";
543 next;
544 }
545 pb_log(2,"DEBUG bfiles: ".Dumper(\%bfiles)."\n");
546
547 # Get all filters to apply
548 my $ptr = pb_get_filters($pbpkg, $dtype, $dfam, $ddir, $dver);
549
550 # Apply now all the filters on all the files concerned
551 # destination dir depends on the type of file
552 if (defined $ptr) {
553 foreach my $f (values %bfiles,values %pkgfiles) {
554 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);
555 }
556 }
557 }
558 my @found;
559 my @notfound;
560 foreach my $b (keys %build) {
561 push @found,$b if ($build{$b} =~ /yes/);
562 push @notfound,$b if ($build{$b} =~ /no/);
563 }
564 pb_log(0,"Build files generated for ".join(',',@found)."\n");
565 pb_log(0,"No Build files found for ".join(',',@notfound)."\n") if (@notfound);
566 # Get the generic filter (all.pbf) and
567 # apply those to the non-build files including those
568 # generated by pbinit if applicable
569
570 # Get only all.pbf filter
571 $ptr = pb_get_filters($pbpkg);
572
573 my $liste ="";
574 if (defined $filteredfiles->{$pbpkg}) {
575 foreach my $f (split(/,/,$filteredfiles->{$pbpkg})) {
576 pb_filter_file_inplace($ptr,"$dest/$f",$ENV{'PBPROJ'},$pbpkg,$pbver,$pbtag,$pbrev,$pbdate,$pbpackager);
577 $liste = "$f $liste";
578 }
579 }
580 pb_log(2,"Files ".$liste."have been filtered\n");
581
582 # Prepare the dest directory for archive
583 if (-x "$ENV{'PBROOTDIR'}/$pbpkg/pbinit") {
584 pb_filter_file("$ENV{'PBROOTDIR'}/$pbpkg/pbinit",$ptr,"$ENV{'PBTMP'}/pbinit",$ENV{'PBPROJ'},$pbpkg,$pbver,$pbtag,$pbrev,$pbdate,$pbpackager);
585 chmod 0755,"$ENV{'PBTMP'}/pbinit";
586 pb_system("cd $dest ; $ENV{'PBTMP'}/pbinit","Executing init script from $ENV{'PBROOTDIR'}/$pbpkg/pbinit");
587 }
588
589 # Archive dest dir
590 chdir "$ENV{'PBDESTDIR'}" || die "Unable to change dir to $ENV{'PBDESTDIR'}";
591 # Possibility to look at PBSRC to guess more the filename
592 pb_system("tar cfz $pbpkg-$pbver.tar.gz $pbpkg-$pbver","Creating $pbpkg tar files compressed");
593 pb_log(2,"Under $ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz\n");
594
595 # Keep track of what is generated by default
596 open(LAST,"> $ENV{'PBDESTDIR'}/pbrc") || die "Unable to create $ENV{'PBDESTDIR'}/pbrc";
597 #print LAST "pbroot $pbprojver-$pbprojtag = $ENV{'PBROOTDIR'}\n";
598 # Why not use pbproj ?
599 print LAST "pbroot $ENV{'PBPROJ'} = $ENV{'PBROOTDIR'}\n";
600 close(LAST);
601
602 # Keep track of per package version
603 my ($pkg) = pb_conf_read_if("$ENV{'PBDESTDIR'}/$pbprojver-$pbprojtag.pb","pbpkg");
604 $pkg = { } if (not defined $pkg);
605 if ((not defined $pkg->{$pbpkg}) || ($pkg->{$pbpkg} ne "$pbver-$pbtag")) {
606 $pkg->{$pbpkg} = "$pbver-$pbtag";
607 }
608
609 pb_log(2,"DEBUG pkg: ".Dumper($pkg)."\n");
610 open(PKG,"> $ENV{'PBDESTDIR'}/$pbprojver-$pbprojtag.pb") || die "Unable to create $ENV{'PBDESTDIR'}/$pbprojver-$pbprojtag.pb";
611 foreach my $p (keys %$pkg) {
612 print PKG "pbpkg $p = $pkg->{$p}\n";
613 }
614 close(PKG);
615
616 # Final cleanup
617 pb_rm_rf($dest) if (-d $dest);
618 }
619}
620
621sub pb_build2pkg {
622
623 # Get list of packages to build
624 my $ptr = pb_get_pkg($defpkgdir,$extpkgdir);
625 @pkgs = @$ptr;
626
627 # Get the running distro to build on
628 my ($ddir, $dver, $dfam, $dtype, $pbsuf) = pb_distro_init();
629 pb_log(2,"DEBUG: distro tuple: ".join(',',($ddir, $dver, $dfam, $dtype, $pbsuf))."\n");
630
631 # Get content saved in cms2build
632 my ($pkg) = pb_conf_read("$ENV{'PBDESTDIR'}/$pbprojver-$pbprojtag.pb","pbpkg");
633 $pkg = { } if (not defined $pkg);
634
635 # declare packager (via env var in VM/VE
636 my $pbpackager;
637 if (not defined $ENV{'PBPACKAGER'}) {
638 my ($tmp) = pb_conf_get("pbpackager");
639 $pbpackager = $tmp->{$ENV{'PBPROJ'}};
640 } else {
641 $pbpackager = $ENV{'PBPACKAGER'};
642 }
643
644 chdir "$ENV{'PBBUILDDIR'}";
645 my $made = ""; # pkgs made during build
646 foreach my $pbpkg (@pkgs) {
647 my $vertag = $pkg->{$pbpkg};
648 # get the version of the current package - maybe different
649 ($pbver,$pbtag) = split(/-/,$vertag);
650
651 my $src="$ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz";
652 pb_log(2,"Source file: $src\n");
653
654 pb_log(2,"Working directory: $ENV{'PBBUILDDIR'}\n");
655 if ($dtype eq "rpm") {
656 foreach my $d ('RPMS','SRPMS','SPECS','SOURCES','BUILD') {
657 if (! -d "$ENV{'PBBUILDDIR'}/$d") {
658 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";
659 }
660 }
661
662 # Remove in case a previous link/file was there
663 unlink "$ENV{'PBBUILDDIR'}/SOURCES/".basename($src);
664 symlink "$src","$ENV{'PBBUILDDIR'}/SOURCES/".basename($src) || die "Unable to symlink $src in $ENV{'PBBUILDDIR'}/SOURCES";
665 # We need to first extract the spec file
666 my @specfile;
667 @specfile = pb_extract_build_files($src,"$pbpkg-$pbver/pbconf/$ddir-$dver/","$ENV{'PBBUILDDIR'}/SPECS");
668
669 pb_log(2,"specfile: ".Dumper(\@specfile)."\n");
670 # set LANGUAGE to check for correct log messages
671 $ENV{'LANGUAGE'}="C";
672 foreach my $f (@specfile) {
673 if ($f =~ /\.spec$/) {
674 pb_system("rpmbuild --define \'packager $pbpackager\' --define \"_topdir $ENV{'PBBUILDDIR'}\" -ba $f","Building package with $f under $ENV{'PBBUILDDIR'}");
675 last;
676 }
677 }
678 $made="$made RPMS/*/$pbpkg-$pbver-$pbtag$pbsuf.*.rpm SRPMS/$pbpkg-$pbver-$pbtag$pbsuf.src.rpm";
679 if (-f "/usr/bin/rpmlint") {
680 pb_system("rpmlint $made","Checking validity of rpms with rpmlint");
681 }
682 } elsif ($dtype eq "deb") {
683 chdir "$ENV{'PBBUILDDIR'}" || die "Unable to chdir to $ENV{'PBBUILDDIR'}";
684 pb_system("tar xfz $src","Extracting sources");
685
686 chdir "$pbpkg-$pbver" || die "Unable to chdir to $pbpkg-$pbver";
687 pb_rm_rf("debian");
688 symlink "pbconf/$ddir-$dver","debian" || die "Unable to symlink to pbconf/$ddir-$dver";
689 chmod 0755,"debian/rules";
690 pb_system("dpkg-buildpackage -us -uc -rfakeroot","Building package");
691 $made="$made $pbpkg"."_*.deb $pbpkg"."_*.dsc $pbpkg"."_*.tar.gz";
692 if (-f "/usr/bin/lintian") {
693 pb_system("lintian $made","Checking validity of debs with lintian");
694 }
695 } elsif ($dtype eq "ebuild") {
696 my @ebuildfile;
697 # For gentoo we need to take pb as subsystem name
698 # We put every apps here under sys-apps. hope it's correct
699 # We use pb's home dir in order o have a single OVERLAY line
700 my $tmpd = "$ENV{'HOME'}/portage/pb/sys-apps/$pbpkg";
701 pb_mkdir_p($tmpd) if (! -d "$tmpd");
702 pb_mkdir_p("$ENV{'HOME'}/portage/distfiles") if (! -d "$ENV{'HOME'}/portage/distfiles");
703
704 # We need to first extract the ebuild file
705 @ebuildfile = pb_extract_build_files($src,"$pbpkg-$pbver/pbconf/$ddir-$dver/","$tmpd");
706
707 # Prepare the build env for gentoo
708 my $found = 0;
709 my $pbbd = $ENV{'HOME'};
710 $pbbd =~ s|/|\\/|g;
711 if (-r "/etc/make.conf") {
712 open(MAKE,"/etc/make.conf");
713 while (<MAKE>) {
714 $found = 1 if (/$pbbd\/portage/);
715 }
716 close(MAKE);
717 }
718 if ($found == 0) {
719 pb_system("sudo sh -c 'echo PORTDIR_OVERLAY=\"$ENV{'HOME'}/portage\" >> /etc/make.conf'");
720 }
721 #$found = 0;
722 #if (-r "/etc/portage/package.keywords") {
723 #open(KEYW,"/etc/portage/package.keywords");
724 #while (<KEYW>) {
725 #$found = 1 if (/portage\/pb/);
726 #}
727 #close(KEYW);
728 #}
729 #if ($found == 0) {
730 #pb_system("sudo sh -c \"echo portage/pb >> /etc/portage/package.keywords\"");
731 #}
732
733 # Build
734 foreach my $f (@ebuildfile) {
735 if ($f =~ /\.ebuild$/) {
736 move($f,"$tmpd/$pbpkg-$pbver.ebuild");
737 pb_system("cd $tmpd ; ebuild $pbpkg-$pbver.ebuild clean ; ebuild $pbpkg-$pbver.ebuild digest ; ebuild $pbpkg-$pbver.ebuild package");
738 # Now move it where pb expects it
739 pb_mkdir_p("$ENV{'PBBUILDDIR'}/portage/pb/sys-apps/$pbpkg");
740 move("$tmpd/$pbpkg-$pbver.ebuild","$ENV{'PBBUILDDIR'}/portage/pb/sys-apps/$pbpkg");
741 }
742 }
743
744 $made="$made portage/pb/sys-apps/$pbpkg/$pbpkg-$pbver.ebuild";
745 } elsif ($dtype eq "slackware") {
746 $made="$made build-$pbpkg/$pbpkg-$pbver-*-$pbtag.tgz";
747 pb_mkdir_p("$ENV{'PBBUILDDIR'}/install") if (! -d "$ENV{'PBBUILDDIR'}/install");
748 } else {
749 die "Unknown dtype format $dtype";
750 }
751 }
752 # Keep track of what is generated so that we can get them back from VMs
753 open(KEEP,"> $ENV{'PBBUILDDIR'}/pbgen-$pbprojver-$pbprojtag") || die "Unable to create $ENV{'PBBUILDDIR'}/pbgen-$pbprojver-$pbprojtag";
754 print KEEP "$made\n";
755 close(KEEP);
756}
757
758sub pb_build2ssh {
759 pb_send2target("Sources");
760}
761
762sub pb_pkg2ssh {
763 pb_send2target("Packages");
764}
765
766# By default deliver to the the public site hosting the
767# ftp structure (or whatever) or a VM/VE
768sub pb_send2target {
769
770 my $cmt = shift;
771 my $v = shift || undef;
772 my $vmexist = shift || 0; # 0 is FALSE
773 my $vmpid = shift || 0; # 0 is FALSE
774
775 my $host = "sshhost";
776 my $login = "sshlogin";
777 my $dir = "sshdir";
778 my $port = "sshport";
779 my $tmout = "sshtmout";
780 my $path = "sshpath";
781 my $conf = "sshconf";
782 my $rebuild = "sshrebuild";
783 if ($cmt eq "vm") {
784 $login = "vmlogin";
785 $dir = "pbdefdir";
786 $tmout = "vmtmout";
787 $rebuild = "vmrebuild";
788 # Specific VM
789 $host = "vmhost";
790 $port = "vmport";
791 } elsif ($cmt eq "ve") {
792 $login = "velogin";
793 $dir = "pbdefdir";
794 $tmout = "vetmout";
795 # Specific VE
796 $path = "vepath";
797 $conf = "veconf";
798 $rebuild = "verebuild";
799 }
800 my $cmd = "";
801
802 # Get list of packages to build
803 my $ptr = pb_get_pkg($defpkgdir,$extpkgdir);
804 @pkgs = @$ptr;
805
806 # Get the running distro to consider
807 my ($odir,$over,$oarch) = (undef, undef);
808 if (defined $v) {
809 ($odir,$over,$oarch) = split(/-/,$v);
810 }
811 my ($ddir, $dver, $dfam, $dtype, $pbsuf) = pb_distro_init($odir,$over);
812 pb_log(2,"DEBUG: distro tuple: ".join(',',($ddir, $dver, $dfam, $dtype, $pbsuf))."\n");
813
814 # Get content saved in cms2build
815 my ($pkg) = pb_conf_read("$ENV{'PBDESTDIR'}/$pbprojver-$pbprojtag.pb","pbpkg");
816 $pkg = { } if (not defined $pkg);
817
818 my $src = "";
819 chdir "$ENV{'PBBUILDDIR'}";
820 foreach my $pbpkg (@pkgs) {
821 my $vertag = $pkg->{$pbpkg};
822 # get the version of the current package - maybe different
823 ($pbver,$pbtag) = split(/-/,$vertag);
824
825 if (($cmt eq "Sources") || ($cmt eq "vm") || ($cmt eq "ve")) {
826 $src = "$src $ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz";
827 if ($cmd eq "") {
828 $cmd = "ln -sf $pbpkg-$pbver.tar.gz $pbpkg-latest.tar.gz";
829 } else {
830 $cmd = "$cmd ; ln -sf $pbpkg-$pbver.tar.gz $pbpkg-latest.tar.gz";
831 }
832 }
833 }
834 if (($cmt eq "vm") || ($cmt eq "ve")) {
835 $src="$src $ENV{'PBDESTDIR'}/pbscript $ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb $ENV{'PBDESTDIR'}/$pbprojver-$pbprojtag.pb $ENV{'PBETC'}";
836 } elsif ($cmt eq "Script") {
837 $src="$src $ENV{'PBDESTDIR'}/pbscript";
838 } elsif ($cmt eq "Packages") {
839 # Get package list from file made during build2pkg
840 open(KEEP,"$ENV{'PBBUILDDIR'}/pbgen-$pbprojver-$pbprojtag") || die "Unable to read $ENV{'PBBUILDDIR'}/pbgen-$pbprojver-$pbprojtag";
841 $src = <KEEP>;
842 chomp($src);
843 close(KEEP);
844 if ($dtype eq "rpm") {
845 # Also make a pbscript to generate yum/urpmi bases
846 # $src = "$src $ENV{'PBDESTDIR'}/pbscript"
847 } elsif ($dtype eq "deb") {
848 # Also make a pbscript to generate apt bases
849 # $src = "$src $ENV{'PBDESTDIR'}/pbscript"
850 }
851 }
852 # Remove potential leading spaces (cause problem with basename)
853 $src =~ s/^ *//;
854 my $basesrc = "";
855 foreach my $i (split(/ +/,$src)) {
856 $basesrc .= " ".basename($i);
857 }
858
859 pb_log(0,"Sources handled ($cmt): $src\n");
860 my ($sshhost,$sshlogin,$sshdir,$sshport,$vtmout,$vrebuild,$vepath,$veconf) = pb_conf_get($host,$login,$dir,$port,$tmout,$rebuild,$path,$conf);
861 pb_log(2,"ssh: ".Dumper(($sshhost,$sshlogin,$sshdir,$sshport,$vtmout,$vrebuild,$vepath,$veconf))."\n");
862 # Not mandatory
863 my ($testver) = pb_conf_get_if("testver");
864
865 my $mac;
866 # Useless for VE
867 if ($cmt ne "ve") {
868 $mac = "$sshlogin->{$ENV{'PBPROJ'}}\@$sshhost->{$ENV{'PBPROJ'}}";
869 # Overwrite account value if passed as parameter
870 $mac = "$pbaccount\@$sshhost->{$ENV{'PBPROJ'}}" if (defined $pbaccount);
871 }
872
873 my $tdir;
874 my $bdir;
875 if (($cmt eq "Sources") || ($cmt eq "Script")) {
876 $tdir = "$sshdir->{$ENV{'PBPROJ'}}/src";
877 } elsif (($cmt eq "vm") || ($cmt eq "ve")) {
878 $tdir = $sshdir->{$ENV{'PBPROJ'}}."/$ENV{'PBPROJ'}/delivery";
879 $bdir = $sshdir->{$ENV{'PBPROJ'}}."/$ENV{'PBPROJ'}/build";
880 # Remove a potential $ENV{'HOME'} as bdir should be relative to pb's home
881 $bdir =~ s|\$ENV.+\}/||;
882 } elsif ($cmt eq "Packages") {
883 $tdir = "$sshdir->{$ENV{'PBPROJ'}}/$ddir/$dver";
884 if ((defined $testver) && (defined $testver->{$ENV{'PBPROJ'}}) && ($testver->{$ENV{'PBPROJ'}} =~ /true/i)) {
885 # This is a test pkg => target dir is under test
886 $tdir .= "/test";
887 }
888 } else {
889 return;
890 }
891
892 # Useless for VE
893 my $nport;
894 if ($cmt ne "ve") {
895 $nport = $sshport->{$ENV{'PBPROJ'}};
896 $nport = "$pbport" if (defined $pbport);
897 }
898
899 # Remove a potential $ENV{'HOME'} as tdir should be relative to pb's home
900 $tdir =~ s|\$ENV.+\}/||;
901
902 my $tm = $vtmout->{$ENV{'PBPROJ'}};
903
904 # ssh communication if not VE
905 my ($shcmd,$cpcmd,$cptarget,$cp2target);
906 if ($cmt ne "ve") {
907 $shcmd = "ssh -q -p $nport $mac";
908 $cpcmd = "scp -p -P $nport";
909 $cptarget = "$mac:$tdir";
910 $cp2target = "$mac:$bdir";
911 } else {
912 my $tp = $vepath->{$ENV{'PBPROJ'}};
913 $shcmd = "sudo chroot $tp/$v /bin/su - $sshlogin->{$ENV{'PBPROJ'}} -c ";
914 $cpcmd = "cp -a ";
915 $cptarget = "$tp/$tdir";
916 $cp2target = "$tp/$bdir";
917 }
918
919 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");
920 pb_system("cd $ENV{'PBBUILDDIR'} ; $cpcmd $src $cptarget 2> /dev/null","$cmt delivery in $cptarget");
921 # For VE we need to change the owner manually - To be tested if needed
922 #if ($cmt eq "ve") {
923 #pb_system("cd $cptarget ; sudo chown -R $sshlogin->{$ENV{'PBPROJ'}} .","$cmt chown in $cptarget to $sshlogin->{$ENV{'PBPROJ'}}");
924 #}
925 pb_system("$shcmd \"echo \'cd $tdir ; if [ -f pbscript ]; then ./pbscript; fi\' | bash\"","Executing pbscript on $cptarget if needed");
926 if (($cmt eq "vm") || ($cmt eq "ve")) {
927 # Get back info on pkg produced, compute their name and get them from the VM
928 pb_system("$cpcmd $cp2target/pbgen-$pbprojver-$pbprojtag $ENV{'PBBUILDDIR'} 2> /dev/null","Get package names in $cp2target");
929 open(KEEP,"$ENV{'PBBUILDDIR'}/pbgen-$pbprojver-$pbprojtag") || die "Unable to read $ENV{'PBBUILDDIR'}/pbgen-$pbprojver-$pbprojtag";
930 my $src = <KEEP>;
931 chomp($src);
932 close(KEEP);
933 $src =~ s/^ *//;
934 pb_mkdir_p("$ENV{'PBBUILDDIR'}/$odir/$over");
935 # Change pgben to make the next send2target happy
936 my $made = "";
937 open(KEEP,"> $ENV{'PBBUILDDIR'}/pbgen-$pbprojver-$pbprojtag") || die "Unable to write $ENV{'PBBUILDDIR'}/pbgen-$pbprojver-$pbprojtag";
938 foreach my $p (split(/ +/,$src)) {
939 my $j = basename($p);
940 pb_system("$cpcmd $cp2target/\'$p\' $ENV{'PBBUILDDIR'}/$odir/$over 2> /dev/null","Package recovery of $j in $cp2target");
941 $made="$made $odir/$over/$j" if (($dtype ne "rpm") || ($j !~ /.src.rpm$/));
942 }
943 print KEEP "$made\n";
944 close(KEEP);
945 pb_system("$shcmd \"rm -rf $tdir $bdir\"","$cmt cleanup");
946 pb_send2target("Packages","$odir"."_"."$over");
947 if ((! $vmexist) && ($cmt eq "vm")) {
948 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)");
949 }
950 pb_rm_rf("$ENV{'PBBUILDDIR'}/$odir");
951 }
952}
953
954sub pb_script2v {
955 my $pbscript=shift;
956 my $vtype=shift;
957
958 # Prepare the script to be executed on the VM
959 # in $ENV{'PBDESTDIR'}/pbscript
960 if ((defined $pbscript ) && ($pbscript ne "$ENV{'PBDESTDIR'}/pbscript")) {
961 copy($pbscript,"$ENV{'PBDESTDIR'}/pbscript") || die "Unable to create $ENV{'PBDESTDIR'}/pbscript";
962 chmod 0755,"$ENV{'PBDESTDIR'}/pbscript";
963 }
964
965 my ($vm,$all) = pb_get_v($vtype);
966 my ($vmexist,$vmpid) = (undef,undef);
967
968 foreach my $v (@$vm) {
969 # Launch the VM/VE
970 if ($vtype eq "vm") {
971 ($vmexist,$vmpid) = pb_launchv($vtype,$v,0);
972
973 # Skip that VM if something went wrong
974 next if (($vmpid == 0) && ($vmexist ==0));
975 }
976
977 # Gather all required files to send them to the VM
978 # and launch the build through pbscript
979 pb_send2target("Script","$v",$vmexist,$vmpid);
980
981 }
982}
983
984sub pb_launchv {
985 my $vtype = shift;
986 my $v = shift;
987 my $create = shift || 0; # By default do not create a VM
988
989 die "No VM/VE defined, unable to launch" if (not defined $v);
990 # Keep only the first VM in case many were given
991 $v =~ s/,.*//;
992
993 # Which is our local arch ? (standardize on i386 for those platforms)
994 my $arch = `uname -m`;
995 chomp($arch);
996 $arch =~ s/i.86/i386/;
997
998 # Launch the VMs/VEs
999 if ($vtype eq "vm") {
1000 die "-i iso parameter needed" if (((not defined $iso) || ($iso eq "")) && ($create != 0));
1001
1002 my ($ptr,$vmopt,$vmport,$vmpath,$vmtmout,$vmsize) = pb_conf_get("vmtype","vmopt","vmport","vmpath","vmtmout","vmsize");
1003
1004 my $vmtype = $ptr->{$ENV{'PBPROJ'}};
1005 if (not defined $ENV{'PBVMOPT'}) {
1006 $ENV{'PBVMOPT'} = "";
1007 }
1008 if (defined $vmopt->{$ENV{'PBPROJ'}}) {
1009 $ENV{'PBVMOPT'} .= " $vmopt->{$ENV{'PBPROJ'}}" if ($ENV{'PBVMOPT'} !~ / $vmopt->{$ENV{'PBPROJ'}}/);
1010 }
1011 my $nport = $vmport->{$ENV{'PBPROJ'}};
1012 $nport = "$pbport" if (defined $pbport);
1013
1014 my $cmd;
1015 my $vmcmd; # has to be used for pb_check_ps
1016 my $vmm; # has to be used for pb_check_ps
1017 if ($vmtype eq "qemu") {
1018 my $qemucmd32;
1019 my $qemucmd64;
1020 if ($arch eq "x86_64") {
1021 $qemucmd32 = "/usr/bin/qemu-system-i386";
1022 $qemucmd64 = "/usr/bin/qemu";
1023 } else {
1024 $qemucmd32 = "/usr/bin/qemu";
1025 $qemucmd64 = "/usr/bin/qemu-system-x86_64";
1026 }
1027 if ($v =~ /x86_64/) {
1028 $vmcmd = "$qemucmd64 -no-kqemu";
1029 } else {
1030 $vmcmd = "$qemucmd32";
1031 }
1032 $vmm = "$vmpath->{$ENV{'PBPROJ'}}/$v.qemu";
1033 if ($create != 0) {
1034 $ENV{'PBVMOPT'} .= " -cdrom $iso -boot d";
1035 }
1036 $cmd = "$vmcmd $ENV{'PBVMOPT'} -redir tcp:$nport:10.0.2.15:22 $vmm"
1037 } elsif ($vmtype eq "xen") {
1038 } elsif ($vmtype eq "vmware") {
1039 } else {
1040 die "VM of type $vmtype not supported. Report to the dev team";
1041 }
1042 my ($tmpcmd,$void) = split(/ +/,$cmd);
1043 my $vmexist = pb_check_ps($tmpcmd,$vmm);
1044 my $vmpid = 0;
1045 if (! $vmexist) {
1046 if ($create != 0) {
1047 if (($vmtype eq "qemu") || ($vmtype eq "xen")) {
1048 pb_system("/usr/bin/qemu-img create -f qcow2 $vmm $vmsize->{$ENV{'PBPROJ'}}","Creating the QEMU VM");
1049 } elsif ($vmtype eq "vmware") {
1050 } else {
1051 }
1052 }
1053 if (! -f "$vmm") {
1054 pb_log(0,"Unable to find VM $vmm\n");
1055 } else {
1056 pb_system("$cmd &","Launching the VM $vmm");
1057 pb_system("sleep $vmtmout->{$ENV{'PBPROJ'}}","Waiting for VM $v to come up");
1058 $vmpid = pb_check_ps($tmpcmd,$vmm);
1059 }
1060 } else {
1061 pb_log(0,"Found an existing VM $vmm (pid $vmexist)\n");
1062 }
1063 return($vmexist,$vmpid);
1064 # VE here
1065 } else {
1066 # Get VE context
1067 my ($ptr,$vepath,$vetmout,$verebuild,$veconf) = pb_conf_get("vetype","vepath","vetmout","verebuild","veconf");
1068 my $vetype = $ptr->{$ENV{'PBPROJ'}};
1069
1070 # Get distro context
1071 my ($name,$ver,$darch) = split(/-/,$v);
1072 chomp($darch);
1073 my ($ddir, $dver, $dfam, $dtype, $pbsuf) = pb_distro_init($name,$ver);
1074
1075 if ($vetype eq "chroot") {
1076 # Architecture consistency
1077 if ($arch ne $darch) {
1078 die "Unable to launch a VE of architecture $darch on a $arch platform" if (not (($darch eq "x86_64") && ($arch =~ /i?86/)));
1079 }
1080
1081 if (($create != 0) || ($verebuild->{$ENV{'PBPROJ'}} eq "true") || ($force == 1)) {
1082 # We have to rebuild the chroot
1083 if ($dtype eq "rpm") {
1084 pb_system("sudo /usr/sbin/mock --init --resultdir=\"/tmp\" --configdir=\"$veconf->{$ENV{'PBPROJ'}}\" -r $v","Creating the mock VE");
1085 # Once setup we need to install some packages, the pb account, ...
1086 pb_system("sudo /usr/sbin/mock --install --configdir=\"$veconf->{$ENV{'PBPROJ'}}\" -r $v su","Configuring the mock VE");
1087 #pb_system("sudo /usr/sbin/mock --init --resultdir=\"/tmp\" --configdir=\"$veconf->{$ENV{'PBPROJ'}}\" --basedir=\"$vepath->{$ENV{'PBPROJ'}}\" -r $v","Creating the mock VE");
1088 } elsif ($dtype eq "deb") {
1089 pb_system("","Creating the pbuilder VE");
1090 } elsif ($dtype eq "ebuild") {
1091 die "Please teach the dev team how to build gentoo chroot";
1092 } else {
1093 die "Unknown distribution type $dtype. Report to dev team";
1094 }
1095 }
1096 # Nothing more to do for VE. No real launch
1097 } else {
1098 die "VE of type $vetype not supported. Report to the dev team";
1099 }
1100 }
1101}
1102
1103sub pb_build2v {
1104
1105my $vtype = shift;
1106
1107# Prepare the script to be executed on the VM/VE
1108# in $ENV{'PBDESTDIR'}/pbscript
1109my ($ntp) = pb_conf_get($vtype."ntp");
1110my $vntp = $ntp->{$ENV{'PBPROJ'}};
1111
1112open(SCRIPT,"> $ENV{'PBDESTDIR'}/pbscript") || die "Unable to create $ENV{'PBDESTDIR'}/pbscript";
1113print SCRIPT "#!/bin/bash\n";
1114print SCRIPT "echo ... Execution needed\n";
1115print SCRIPT "# This is in directory delivery\n";
1116print SCRIPT "# Setup the variables required for building\n";
1117print SCRIPT "export PBPROJ=$ENV{'PBPROJ'}\n";
1118print SCRIPT "# Preparation for pb\n";
1119print SCRIPT "mv .pbrc \$HOME\n";
1120print SCRIPT "cd ..\n";
1121# Force new date to be in the future compared to the date of the tar file by adding 1 minute
1122my @date=pb_get_date();
1123$date[1]++;
1124my $upddate = strftime("%m%d%H%M%Y", @date);
1125print SCRIPT "echo Setting up date on $vntp...\n";
1126# Or use ntpdate if available TBC
1127print SCRIPT "sudo date $upddate\n";
1128# This exports avoids pb_env_init to deal with PBCONF stuff
1129print SCRIPT "export PBCONF=/tmp\n";
1130print SCRIPT "export PBVER=$ENV{'PBVER'}\n";
1131print SCRIPT "export PBTAG=$ENV{'PBTAG'}\n";
1132print SCRIPT "export PBPACKAGER=\"$ENV{'PBPACKAGER'}\"\n";
1133print SCRIPT "# Build\n";
1134# Get list of packages to build
1135my $ptr = pb_get_pkg($defpkgdir,$extpkgdir);
1136@pkgs = @$ptr;
1137my $p = join(' ',@pkgs) if (@pkgs);
1138print SCRIPT "echo Building packages on $vtype...\n";
1139print SCRIPT "pb -p $ENV{'PBPROJ'} build2pkg $p\n";
1140close(SCRIPT);
1141chmod 0755,"$ENV{'PBDESTDIR'}/pbscript";
1142
1143my ($v,$all) = pb_get_v($vtype);
1144
1145# Send tar files when we do a global generation
1146pb_build2ssh() if ($all == 1);
1147
1148my ($vmexist,$vmpid) = (undef,undef);
1149
1150foreach my $v (@$v) {
1151 if ($vtype eq "vm") {
1152 # Launch the VM
1153 my ($vmexist,$vmpid) = pb_launchv($vtype,$v,0);
1154
1155 # Skip that VM if it something went wrong
1156 next if (($vmpid == 0) && ($vmexist == 0));
1157 }
1158 # Gather all required files to send them to the VM/VE
1159 # and launch the build thourgh pbscript
1160 pb_send2target($vtype,"$v",$vmexist,$vmpid);
1161}
1162}
1163
1164
1165sub pb_newver {
1166
1167 die "-V Version parameter needed" if ((not defined $newver) || ($newver eq ""));
1168
1169 my ($scheme,$uri)=pb_cms_init($pbinit);
1170
1171 if ($scheme !~ /^svn/) {
1172 die "Only SVN is supported at the moment";
1173 }
1174 my $res = pb_cms_isdiff($scheme);
1175 die "You need to have no differences before creating a new version" if ($res != 0);
1176 my $cmsurl = pb_cms_getinfo($scheme,$ENV{'PBROOTDIR'},"URL:");
1177 my $newurl = dirname($cmsurl)."/$newver";
1178 pb_cms_copy($scheme,$cmsurl,$newurl);
1179 pb_cms_checkout($scheme,$newurl,"$ENV{'PBROOTDIR'}/../$newver");
1180 my $oldver=basename($cmsurl);
1181 open(FILE,"$ENV{'PBROOTDIR'}/../$newver/pbconf/$ENV{'PBPROJ'}.pb") || die "Unable to open $ENV{'PBROOTDIR'}/../$newver/pbconf/$ENV{'PBPROJ'}.pb";
1182 open(OUT,"> $ENV{'PBROOTDIR'}/../$newver/pbconf/$ENV{'PBPROJ'}.pb.new") || die "Unable to write to $ENV{'PBROOTDIR'}/../$newver/pbconf/$ENV{'PBPROJ'}.pb.new";
1183 while(<FILE>) {
1184 s/projver\s+$ENV{'PBPROJ'}\s*=\s*$oldver/projver $ENV{'PBPROJ'} = $newver/;
1185 print OUT $_;
1186 }
1187 close(FILE);
1188 close(OUT);
1189 rename("$ENV{'PBROOTDIR'}/../$newver/pbconf/$ENV{'PBPROJ'}.pb.new","$ENV{'PBROOTDIR'}/../$newver/pbconf/$ENV{'PBPROJ'}.pb");
1190 pb_cms_checkin($scheme,"$ENV{'PBROOTDIR'}/../$newver");
1191}
1192
1193#
1194# Return the list of VMs/VEs we are working on
1195# $all is a flag to know if we return all of them
1196# or only some (if all we publish also tar files in addition to pkgs
1197#
1198sub pb_get_v {
1199
1200my $vtype = shift;
1201my @v;
1202my $all = 0;
1203my $vlist;
1204my $pbv = 'PBV';
1205
1206if ($vtype eq "vm") {
1207 $vlist = "vmlist";
1208} elsif ($vtype eq "ve") {
1209 $vlist = "velist";
1210}
1211# Get VM/VE list
1212if ((not defined $ENV{$pbv}) || ($ENV{$pbv} =~ /^all$/)) {
1213 my ($ptr) = pb_conf_get($vlist);
1214 $ENV{$pbv} = $ptr->{$ENV{'PBPROJ'}};
1215 $all = 1;
1216}
1217pb_log(2,"$vtype: $ENV{$pbv}\n");
1218@v = split(/,/,$ENV{$pbv});
1219return(\@v,$all);
1220}
1221
1222sub pb_setup_v {
1223# Function to create a potentialy missing pb account on the VM/VE, and adds it to sudo
1224# Needs to use root account to connect to the VM/VE
1225
1226# pb will take your local public SSH key to access
1227# the pb account in the VM later on
1228
1229my $vtype = shift;
1230
1231my $file = "$ENV{'HOME'}/.ssh/id_dsa.pub";
1232die "Unable to find your public ssh key as $file";
1233
1234open(SCRIPT,"> $ENV{'PBDESTDIR'}/pbscript") || die "Unable to create $ENV{'PBDESTDIR'}/pbscript";
1235print SCRIPT << 'EOF';
1236#!/usr/bin/perl -w
1237
1238$file="/etc/passwd";
1239open(PBFILE,$file) || die "Unable to open $file";
1240my $found = 0;
1241while (<PBFILE>) {
1242 $found = 1 if (/^pb:/);
1243}
1244close(PBFILE);
1245
1246if ( $found == 0 ) {
1247 if ( ! -d "/home" ) {
1248 mkdir "/home";
1249 }
1250 system "groupadd pb";
1251 system "useradd pb -g pb -m -d /home/pb";
1252}
1253
1254# For root
1255mkdir ".ssh",0700;
1256system 'cp /tmp/pbkey .ssh/authorized_keys';
1257chmod 0600,".ssh/authorized_keys";
1258
1259# For pb
1260chdir "/home/pb";
1261mkdir ".ssh",0700;
1262system 'cp /tmp/pbkey .ssh/authorized_keys';
1263chmod 0600,".ssh/authorized_keys";
1264system 'chown -R pb:pb .ssh';
1265
1266# No passwd for pb only keys
1267$file="/etc/shadow";
1268open(PBFILE,$file) || die "Unable to open $file";
1269open(PBOUT,"> $file.new") || die "Unable to open $file.new";
1270while (<PBFILE>) {
1271 s/^pb:\!\!:/pb:*:/;
1272 s/^pb:\!:/pb:*:/; #SLES 9 e.g.
1273 print PBOUT $_;
1274}
1275close(PBFILE);
1276close(PBOUT);
1277rename("$file.new",$file);
1278chmod 0640,$file;
1279
1280# pb has to be added to portage group on gentoo
1281unlink "/tmp/pbkey";
1282
1283my ($ddir, $dver, $dfam, $dtype, $pbsuf) = pb_distro_init();
1284print "distro tuple: ".join(',',($ddir, $dver, $dfam, $dtype, $pbsuf))."\n";
1285
1286# Get and install pb
1287if ( $ddir eq "fedora" ) {
1288 system "yum clean all";
1289 system "yum update -y";
1290 my $arch=`uname -m`;
1291 my $opt = "";
1292 chomp($arch);
1293 if ($arch eq "x86_64") {
1294 $opt="--exclude=*.i?86";
1295 }
1296
1297 system "yum -y $opt install rpm-build wget patch ntp sudo perl-DateManip perl-ExtUtils-MakeMaker";
1298} 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"))) {
1299 # Suppose pkg are installed already
1300 system "rpm -e lsb 2>&1 > /dev/null";
1301 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 .. ";
1302} elsif ($ddir eq "suse") {
1303 # New OpenSuSE
1304 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";
1305} elsif ( $dfam eq "md" ) {
1306 system "urpmi.update -a ; urpmi --auto rpm-build wget sudo patch ntp-client perl-DateManip";
1307} elsif ( $dfam eq "du" ) {
1308 if (( $dver eq "3.1" ) && ($ddir eq "debian")) {
1309 system "apt-get update; apt-get -y install wget patch ssh sudo debian-builder dh-make fakeroot ntpdate libdate-manip-perl";
1310 } else {
1311 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";
1312 }
1313} elsif ( $dfam eq "gen" ) {
1314 system "emerge -u system ; emerge wget sudo ntp DateManip";
1315} else {
1316 print "No pkg to install\n";
1317}
1318
1319# Adapt sudoers
1320$file="/etc/sudoers";
1321open(PBFILE,$file) || die "Unable to open $file";
1322open(PBOUT,"> $file.new") || die "Unable to open $file.new";
1323while (<PBFILE>) {
1324 next if (/^pb /);
1325 s/Defaults[ \t]+requiretty//;
1326 print PBOUT $_;
1327}
1328close(PBFILE);
1329print PBOUT "pb ALL=(ALL) NOPASSWD:ALL\n";
1330close(PBOUT);
1331rename("$file.new",$file);
1332chmod 0440,$file;
1333
1334# Suse wants sudoers as 640
1335if (($ddir eq "sles") || (($ddir eq "suse")) && ($dver ne "10.3")) {
1336 chmod 0640,$file;
1337}
1338
1339# Sync date
1340system "/usr/sbin/ntpdate ntp.pool.org";
1341
1342system "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 ..";
1343EOF
1344close(SCRIPT);
1345}
1346
1347# Returns the pid of a running VM command using a specific VM file
1348sub pb_check_ps {
1349 my $vmcmd = shift;
1350 my $vmm = shift;
1351 my $vmexist = 0; # FALSE by default
1352
1353 open(PS, "ps auxhww|") || die "Unable to call ps";
1354 while (<PS>) {
1355 next if (! /$vmcmd/);
1356 next if (! /$vmm/);
1357 my ($void1, $void2);
1358 ($void1, $vmexist, $void2) = split(/ +/);
1359 last;
1360 }
1361 return($vmexist);
1362}
1363
1364
1365sub pb_extract_build_files {
1366
1367my $src=shift;
1368my $dir=shift;
1369my $ddir=shift;
1370my @files;
1371
1372if ($src =~ /tar\.gz$/) {
1373 pb_system("tar xfpz $src $dir","Extracting build files");
1374} elsif ($src =~ /tar\.bz2$/) {
1375 pb_system("tar xfpj $src $dir","Extracting build files");
1376} else {
1377 die "Unknown compression algorithm for $src";
1378}
1379opendir(DIR,"$dir") || die "Unable to open directory $dir";
1380foreach my $f (readdir(DIR)) {
1381 next if ($f =~ /^\./);
1382 move("$dir/$f","$ddir") || die "Unable to move $dir/$f to $ddir";
1383 pb_log(2,"mv $dir/$f $ddir\n");
1384 push @files,"$ddir/$f";
1385}
1386closedir(DIR);
1387# Not enough but still a first cleanup
1388pb_rm_rf("$dir");
1389return(@files);
1390}
1391
1392sub pb_list_bfiles {
1393
1394my $dir = shift;
1395my $pbpkg = shift;
1396my $bfiles = shift;
1397my $pkgfiles = shift;
1398my $supfiles = shift;
1399
1400opendir(BDIR,"$dir") || die "Unable to open dir $dir: $!";
1401foreach my $f (readdir(BDIR)) {
1402 next if ($f =~ /^\./);
1403 $bfiles->{$f} = "$dir/$f";
1404 $bfiles->{$f} =~ s~$ENV{'PBROOTDIR'}~~;
1405 if (defined $supfiles->{$pbpkg}) {
1406 $pkgfiles->{$f} = "$dir/$f" if ($f =~ /$supfiles->{$pbpkg}/);
1407 }
1408}
1409closedir(BDIR);
1410}
1411
1412sub pb_syntax {
1413
1414my $exit_status = shift || -1;
1415my $verbose_level = shift || 0;
1416
1417my $filehandle = \*STDERR;
1418
1419$filehandle = \*STDOUT if ($exit_status == 0);
1420
1421pod2usage( { -message => "pb (aka project-builder.org) Version $projectbuilderver-$projectbuilderrev\n",
1422 -exitval => $exit_status ,
1423 -verbose => $verbose_level,
1424 -output => $filehandle } );
1425}
Note: See TracBrowser for help on using the repository browser.