source: devel/pb/bin/pb @ 344

Last change on this file since 344 was 344, checked in by bruno, 11 years ago

Lots of fixes in order to make it work for netperf from scratch (newver, cms2build, build2pkg, pbcl)

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