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

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

First attempt to code a setupvm/ve function into pb

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