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

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

backport 0.8.13 feature into devel

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