source: devel/pb/bin/pb @ 460

Revision 460, 56.8 KB checked in by bruno, 5 years ago (diff)

Should fix #13 definitely

  • Property svn:executable set to *
Line 
1#!/usr/bin/perl -w
2#
3# Project Builder main application
4#
5# $Id$
6#
7# Copyright B. Cornec 2007
8# Provided under the GPL v2
9
10# Syntax: see at end
11
12use strict 'vars';
13use Getopt::Long qw(:config auto_abbrev no_ignore_case);
14use Data::Dumper;
15use English;
16use File::Basename;
17use File::Copy;
18use File::stat;
19use File::Temp qw(tempdir);
20use POSIX qw(strftime);
21use lib qw (lib);
22use ProjectBuilder::Version;
23use ProjectBuilder::Base;
24use ProjectBuilder::Conf;
25use ProjectBuilder::Distribution;
26use ProjectBuilder::CMS;
27use ProjectBuilder::Env;
28use ProjectBuilder::Filter;
29
30# Global variables
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<setupvm>
206
207Setup a virtual machine for pb usage
208
209=item B<setupve>
210
211Setup a virtual environment for pb usage
212
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
303my ($projectbuilderver,$projectbuilderrev) = pb_version_init();
304
305# Initialize the syntax string
306
307pb_syntax_init("pb (aka project-builder.org) Version $projectbuilderver-$projectbuilderrev\n");
308
309GetOptions("help|?|h" => \$opts{'h'}, 
310                "man" => \$opts{'man'},
311                "verbose|v+" => \$opts{'v'},
312                "quiet|q" => \$opts{'q'},
313                "log-files|l=s" => \$opts{'l'},
314                "force|f" => \$opts{'f'},
315                "account|a=s" => \$opts{'a'},
316                "revision|r=s" => \$opts{'r'},
317                "script|s=s" => \$opts{'s'},
318                "machines|mock|m=s" => \$opts{'m'},
319                "port|P=i" => \$opts{'P'},
320                "project|p=s" => \$opts{'p'},
321                "iso|i=s" => \$opts{'i'},
322                "version|V=s" => \$opts{'V'},
323) || pb_syntax(-1,0);
324
325if (defined $opts{'h'}) {
326        pb_syntax(0,1);
327}
328if (defined $opts{'man'}) {
329        pb_syntax(0,2);
330}
331if (defined $opts{'v'}) {
332        $debug = $opts{'v'};
333}
334if (defined $opts{'f'}) {
335        $force=1;
336}
337if (defined $opts{'q'}) {
338        $debug=-1;
339}
340if (defined $opts{'l'}) {
341        open(LOG,"> $opts{'l'}") || die "Unable to log to $opts{'l'}: $!";
342        $LOG = \*LOG;
343        $debug = 0  if ($debug == -1);
344        }
345pb_log_init($debug, $LOG);
346
347# Handle root of the project if defined
348if (defined $opts{'r'}) {
349        $ENV{'PBROOTDIR'} = $opts{'r'};
350}
351# Handle virtual machines if any
352if (defined $opts{'m'}) {
353        $ENV{'PBV'} = $opts{'m'};
354}
355if (defined $opts{'s'}) {
356        $pbscript = $opts{'s'};
357}
358if (defined $opts{'a'}) {
359        $pbaccount = $opts{'a'};
360        die "option -a requires a -s script option" if (not defined $pbscript);
361}
362if (defined $opts{'P'}) {
363        $pbport = $opts{'P'};
364}
365if (defined $opts{'V'}) {
366        $newver = $opts{'V'};
367}
368if (defined $opts{'i'}) {
369        $iso = $opts{'i'};
370}
371
372# Get Action
373$action = shift @ARGV;
374die pb_syntax(-1,1) if (not defined $action);
375
376my ($filteredfiles, $supfiles, $defpkgdir, $extpkgdir);
377my $pbinit = undef;
378$pbinit = 1 if ($action =~ /^newproj$/);
379
380# Handles project name if any
381# And get global params
382($filteredfiles, $supfiles, $defpkgdir, $extpkgdir) = pb_env_init($opts{'p'},$pbinit,$action);
383
384pb_log(0,"Project: $ENV{'PBPROJ'}\n");
385pb_log(0,"Action: $action\n");
386
387# Act depending on action
388if ($action =~ /^cms2build$/) {
389        pb_cms2build();
390} elsif ($action =~ /^build2pkg$/) {
391        pb_build2pkg();
392} elsif ($action =~ /^cms2pkg$/) {
393        pb_cms2build();
394        pb_build2pkg();
395} elsif ($action =~ /^build2ssh$/) {
396        pb_build2ssh();
397} elsif ($action =~ /^cms2ssh$/) {
398        pb_cms2build();
399        pb_build2ssh();
400} elsif ($action =~ /^pkg2ssh$/) {
401        pb_pkg2ssh();
402} elsif ($action =~ /^build2ve$/) {
403        pb_build2v("ve");
404} elsif ($action =~ /^build2vm$/) {
405        pb_build2v("vm");
406} elsif ($action =~ /^cms2ve$/) {
407        pb_cms2build();
408        pb_build2v("ve");
409} elsif ($action =~ /^cms2vm$/) {
410        pb_cms2build();
411        pb_build2v("vm");
412} elsif ($action =~ /^launchvm$/) {
413        pb_launchv("vm",$ENV{'PBV'},0);
414} elsif ($action =~ /^launchve$/) {
415        pb_launchv("ve",$ENV{'PBV'},0);
416} elsif ($action =~ /^script2vm$/) {
417        pb_script2v($pbscript,"vm");
418} elsif ($action =~ /^script2ve$/) {
419        pb_script2v($pbscript,"ve");
420} elsif ($action =~ /^newver$/) {
421        pb_newver();
422} elsif ($action =~ /^newve$/) {
423        pb_launchv("ve",$ENV{'PBV'},1);
424} elsif ($action =~ /^newvm$/) {
425        pb_launchv("vm",$ENV{'PBV'},1);
426} elsif ($action =~ /^setupve$/) {
427        pb_setup_v("ve");
428} elsif ($action =~ /^setupvm$/) {
429        pb_setup_v("vm");
430} elsif ($action =~ /^newproj$/) {
431        # Nothing to do - already done in pb_env_init
432} elsif ($action =~ /^clean$/) {
433} else {
434        pb_log(0,"\'$action\' is not available\n");
435        pb_syntax(-2,1);
436}
437
438sub pb_cms2build {
439
440        my $pkg = pb_cms_get_pkg($defpkgdir,$extpkgdir);
441        my @pkgs = @$pkg;
442        my %pkgs;
443
444        my ($scheme, $uri) = pb_cms_init($pbinit);
445
446        my ($pkgv, $pkgt) = pb_conf_get_if("pkgver","pkgtag");
447
448        # declare packager and repo for filtering
449        my ($tmp1, $tmp2) = pb_conf_get("pbpackager","pbrepo");
450        $ENV{'PBPACKAGER'} = $tmp1->{$ENV{'PBPROJ'}};
451        $ENV{'PBREPO'} = $tmp2->{$ENV{'PBPROJ'}};
452
453        foreach my $pbpkg (@pkgs) {
454                $ENV{'PBPKG'} = $pbpkg;
455                if ((defined $pkgv) && (defined $pkgv->{$pbpkg})) {
456                        $pbver = $pkgv->{$pbpkg};
457                } else {
458                        $pbver = $ENV{'PBPROJVER'};
459                }
460                if ((defined $pkgt) && (defined $pkgt->{$pbpkg})) {
461                        $pbtag = $pkgt->{$pbpkg};
462                } else {
463                        $pbtag = $ENV{'PBPROJTAG'};
464                }
465
466                $pbrev = $ENV{'PBREVISION'};
467                pb_log(0,"\n");
468                pb_log(0,"Management of $pbpkg $pbver-$pbtag (rev $pbrev)\n");
469                die "Unable to get env var PBDESTDIR" if (not defined $ENV{'PBDESTDIR'});
470                # Clean up dest if necessary. The export will recreate it
471                my $dest = "$ENV{'PBDESTDIR'}/$pbpkg-$pbver";
472                pb_rm_rf($dest) if (-d $dest);
473
474                # Export CMS tree for the concerned package to dest
475                # And generate some additional files
476                $OUTPUT_AUTOFLUSH=1;
477
478                # computes in which dir we have to work
479                my $dir = $defpkgdir->{$pbpkg};
480                $dir = $extpkgdir->{$pbpkg} if (not defined $dir);
481                pb_log(2,"def:".Dumper($defpkgdir)." ext: ".Dumper($extpkgdir)." \n");
482
483                # Exporting from CMS
484                pb_cms_export($uri,"$ENV{'PBDIR'}/$dir",$dest);
485
486                # Generated fake content for test versions to speed up stuff
487                my ($testver) = pb_conf_get_if("testver");
488                my $chglog;
489
490                # Get project info on authors and log file
491                $chglog = "$ENV{'PBROOTDIR'}/$pbpkg/pbcl";
492                $chglog = "$ENV{'PBROOTDIR'}/pbcl" if (! -f $chglog);
493                $chglog = undef if (! -f $chglog);
494
495                my $authors = "$ENV{'PBROOTDIR'}/$pbpkg/pbauthors";
496                $authors = "$ENV{'PBROOTDIR'}/pbauthors" if (! -f $authors);
497                $authors = "/dev/null" if (! -f $authors);
498
499                # Extract cms log history and store it
500                if ((defined $chglog) && (! -f "$dest/NEWS")) {
501                        pb_log(2,"Generating NEWS file from $chglog\n");
502                        copy($chglog,"$dest/NEWS") || die "Unable to create $dest/NEWS";
503                }
504                pb_cms_log($scheme,"$ENV{'PBDIR'}/$dir",$dest,$chglog,$authors,$testver);
505
506                my %build;
507                my @pt;
508                my $tmpl = "";
509
510                @pt = pb_conf_get_if("vmlist","velist");
511                if (defined $pt[0]->{$ENV{'PBPROJ'}}) {
512                        $tmpl .= $pt[0]->{$ENV{'PBPROJ'}};
513                }
514                if (defined $pt[1]->{$ENV{'PBPROJ'}}) {
515                        # the 2 lists needs to be grouped with a ',' separated them
516                        if ($tmpl ne "") {
517                                $tmpl .= ",";
518                        }
519                        $tmpl .= $pt[1]->{$ENV{'PBPROJ'}} 
520                }
521                foreach my $d (split(/,/,$tmpl)) {
522                        my ($name,$ver,$arch) = split(/-/,$d);
523                        chomp($arch);
524                        my ($ddir, $dver, $dfam, $dtype, $pbsuf) = pb_distro_init($name,$ver);
525                        pb_log(2,"DEBUG: distro tuple: ".Dumper($ddir, $dver, $dfam, $dtype, $pbsuf)."\n");
526                        pb_log(2,"DEBUG Filtering PBDATE => $pbdate, PBTAG => $pbtag, PBVER => $pbver\n");
527
528                        # Filter build files from the less precise up to the most with overloading
529                        # Filter all files found, keeping the name, and generating in dest
530
531                        # Find all build files first relatively to PBROOTDIR
532                        # Find also all specific files referenced in the .pb conf file
533                        my %bfiles = ();
534                        my %pkgfiles = ();
535                        $build{"$ddir-$dver"} = "yes";
536
537                        if (-d "$ENV{'PBROOTDIR'}/$pbpkg/$dtype") {
538                                pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$dtype",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
539                        } elsif (-d "$ENV{'PBROOTDIR'}/$pbpkg/$dfam") {
540                                pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$dfam",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
541                        } elsif (-d "$ENV{'PBROOTDIR'}/$pbpkg/$ddir") {
542                                pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$ddir",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
543                        } elsif (-d "$ENV{'PBROOTDIR'}/$pbpkg/$ddir-$dver") {
544                                pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$ddir-$dver",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
545                        } else {
546                                $build{"$ddir-$dver"} = "no";
547                                next;
548                        }
549                        pb_log(2,"DEBUG bfiles: ".Dumper(\%bfiles)."\n");
550
551                        # Get all filters to apply
552                        my $ptr = pb_get_filters($pbpkg, $dtype, $dfam, $ddir, $dver);
553
554                        # Apply now all the filters on all the files concerned
555                        # destination dir depends on the type of file
556                        if (defined $ptr) {
557                                foreach my $f (values %bfiles,values %pkgfiles) {
558                                        pb_filter_file_pb("$ENV{'PBROOTDIR'}/$f",$ptr,"$dest/pbconf/$ddir-$dver/".basename($f),$dtype,$pbsuf,$pbpkg,$pbver,$pbtag,$pbrev,$pbdate,$defpkgdir,$extpkgdir,$ENV{'PBPACKAGER'},$chglog,$ENV{'PBPROJ'},$ENV{'PBREPO'});
559                                }
560                        }
561                }
562                my @found;
563                my @notfound;
564                foreach my $b (keys %build) {
565                        push @found,$b if ($build{$b} =~ /yes/);
566                        push @notfound,$b if ($build{$b} =~ /no/);
567                }
568                pb_log(0,"Build files generated for ".join(',',sort(@found))."\n");
569                pb_log(0,"No Build files found for ".join(',',sort(@notfound))."\n") if (@notfound);
570                # Get the generic filter (all.pbf) and
571                # apply those to the non-build files including those
572                # generated by pbinit if applicable
573
574                # Get only all.pbf filter
575                my $ptr = pb_get_filters($pbpkg);
576
577                my $liste ="";
578                if (defined $filteredfiles->{$pbpkg}) {
579                        foreach my $f (split(/,/,$filteredfiles->{$pbpkg})) {
580                                pb_filter_file_inplace($ptr,"$dest/$f",$pbpkg,$pbver,$pbtag,$pbrev,$pbdate,$ENV{'PBPACKAGER'},$ENV{'PBPROJ'},$ENV{'PBREPO'});
581                                $liste = "$f $liste";
582                        }
583                }
584                pb_log(2,"Files ".$liste."have been filtered\n");
585
586                # Prepare the dest directory for archive
587                if (-x "$ENV{'PBROOTDIR'}/$pbpkg/pbinit") {
588                        pb_filter_file("$ENV{'PBROOTDIR'}/$pbpkg/pbinit",$ptr,"$ENV{'PBTMP'}/pbinit",$pbpkg,$pbver,$pbtag,$pbrev,$pbdate,$ENV{'PBPACKAGER'},$ENV{'PBPROJ'},$ENV{'PBREPO'});
589                        chmod 0755,"$ENV{'PBTMP'}/pbinit";
590                        pb_system("cd $dest ; $ENV{'PBTMP'}/pbinit","Executing init script from $ENV{'PBROOTDIR'}/$pbpkg/pbinit");
591                }
592
593                # Archive dest dir
594                chdir "$ENV{'PBDESTDIR'}" || die "Unable to change dir to $ENV{'PBDESTDIR'}";
595                # Possibility to look at PBSRC to guess more the filename
596                pb_system("tar cfz $pbpkg-$pbver.tar.gz $pbpkg-$pbver","Creating $pbpkg tar files compressed");
597                pb_log(0,"Under $ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz\n");
598
599                # Keep track of version-tag per pkg
600                $pkgs{$pbpkg} = "$pbver-$pbtag";
601
602                # Final cleanup
603                pb_rm_rf($dest) if (-d $dest);
604        }
605
606        # Keep track of per package version
607        pb_log(2,"DEBUG pkgs: ".Dumper(%pkgs)."\n");
608        open(PKG,"> $ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb") || die "Unable to create $ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb";
609        foreach my $pbpkg (@pkgs) {
610                print PKG "pbpkg $pbpkg = $pkgs{$pbpkg}\n";
611        }
612        close(PKG);
613
614        # Keep track of what is generated by default
615        # We need to store the dir and info on version-tag
616        # Base our content on the existing .pb file
617        copy("$ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb","$ENV{'PBDESTDIR'}/pbrc");
618        open(LAST,">> $ENV{'PBDESTDIR'}/pbrc") || die "Unable to create $ENV{'PBDESTDIR'}/pbrc";
619        print LAST "pbroot $ENV{'PBPROJ'} = $ENV{'PBROOTDIR'}\n";
620        print LAST "pbprojver $ENV{'PBPROJ'} = $ENV{'PBPROJVER'}\n";
621        print LAST "pbprojtag $ENV{'PBPROJ'} = $ENV{'PBPROJTAG'}\n";
622        print LAST "pbpackager $ENV{'PBPROJ'} = $ENV{'PBPACKAGER'}\n";
623        close(LAST);
624}
625
626sub pb_build2pkg {
627
628        # Get the running distro to build on
629        my ($ddir, $dver, $dfam, $dtype, $pbsuf) = pb_distro_init();
630        pb_log(2,"DEBUG: distro tuple: ".join(',',($ddir, $dver, $dfam, $dtype, $pbsuf))."\n");
631
632        # Get list of packages to build
633        # Get content saved in cms2build
634        my $ptr = pb_get_pkg();
635        @pkgs = @$ptr;
636
637        my ($pkg) = pb_conf_read("$ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb","pbpkg");
638        $pkg = { } if (not defined $pkg);
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                        # Older Redhat use _target_platform in %configure incorrectly
669                        my $specialdef = "";
670                        if (($ddir eq "redhat") || (($ddir eq "rhel") && ($dver eq "2.1"))) {
671                                $specialdef = "--define \'_target_platform \"\"\'";
672                        }
673                        foreach my $f (@specfile) {
674                                if ($f =~ /\.spec$/) {
675                                        pb_system("rpmbuild $specialdef --define \'packager $ENV{'PBPACKAGER'}\' --define \"_topdir $ENV{'PBBUILDDIR'}\" -ba $f","Building package with $f under $ENV{'PBBUILDDIR'}");
676                                        last;
677                                }
678                        }
679                        $made="$made RPMS/*/$pbpkg-$pbver-$pbtag$pbsuf.*.rpm SRPMS/$pbpkg-$pbver-$pbtag$pbsuf.src.rpm";
680                        if (-f "/usr/bin/rpmlint") {
681                                pb_system("rpmlint $made","Checking validity of rpms with rpmlint");
682                        }
683                } elsif ($dtype eq "deb") {
684                        chdir "$ENV{'PBBUILDDIR'}" || die "Unable to chdir to $ENV{'PBBUILDDIR'}";
685                        pb_system("tar xfz $src","Extracting sources");
686
687                        chdir "$pbpkg-$pbver" || die "Unable to chdir to $pbpkg-$pbver";
688                        pb_rm_rf("debian");
689                        symlink "pbconf/$ddir-$dver","debian" || die "Unable to symlink to pbconf/$ddir-$dver";
690                        chmod 0755,"debian/rules";
691                        if ($dver !~ /[0-9]/) {
692                                # dpkg-deb doesn't accept non digit versions. removing checks
693                                # dpkg-source checks upper case when generating perl modules
694                        }
695                        pb_system("dpkg-buildpackage -us -uc -rfakeroot","Building package");
696                        $made="$made $pbpkg"."_*.deb $pbpkg"."_*.dsc $pbpkg"."_*.tar.gz";
697                        if (-f "/usr/bin/lintian") {
698                                pb_system("lintian $made","Checking validity of debs with lintian");
699                        }
700                } elsif ($dtype eq "ebuild") {
701                        my @ebuildfile;
702                        # For gentoo we need to take pb as subsystem name
703                        # We put every apps here under sys-apps. hope it's correct
704                        # We use pb's home dir in order to have a single OVERLAY line
705                        my $tmpd = "$ENV{'HOME'}/portage/pb/sys-apps/$pbpkg";
706                        pb_mkdir_p($tmpd) if (! -d "$tmpd");
707                        pb_mkdir_p("$ENV{'HOME'}/portage/distfiles") if (! -d "$ENV{'HOME'}/portage/distfiles");
708
709                        # We need to first extract the ebuild file
710                        @ebuildfile = pb_extract_build_files($src,"$pbpkg-$pbver/pbconf/$ddir-$dver/","$tmpd");
711
712                        # Prepare the build env for gentoo
713                        my $found = 0;
714                        my $pbbd = $ENV{'HOME'};
715                        $pbbd =~ s|/|\\/|g;
716                        if (-r "/etc/make.conf") {
717                                open(MAKE,"/etc/make.conf");
718                                while (<MAKE>) {
719                                        $found = 1 if (/$pbbd\/portage/);
720                                }
721                                close(MAKE);
722                        }
723                        if ($found == 0) {
724                                pb_system("sudo sh -c 'echo PORTDIR_OVERLAY=\"$ENV{'HOME'}/portage\" >> /etc/make.conf'");
725                        }
726                        #$found = 0;
727                        #if (-r "/etc/portage/package.keywords") {
728                        #open(KEYW,"/etc/portage/package.keywords");
729                        #while (<KEYW>) {
730                        #$found = 1 if (/portage\/pb/);
731                        #}
732                        #close(KEYW);
733                        #}
734                        #if ($found == 0) {
735                        #pb_system("sudo sh -c \"echo portage/pb >> /etc/portage/package.keywords\"");
736                        #}
737
738                        # Build
739                        foreach my $f (@ebuildfile) {
740                                if ($f =~ /\.ebuild$/) {
741                                        move($f,"$tmpd/$pbpkg-$pbver.ebuild");
742                                        pb_system("cd $tmpd ; ebuild $pbpkg-$pbver.ebuild clean ; ebuild $pbpkg-$pbver.ebuild digest ; ebuild $pbpkg-$pbver.ebuild package");
743                                        # Now move it where pb expects it
744                                        pb_mkdir_p("$ENV{'PBBUILDDIR'}/portage/pb/sys-apps/$pbpkg");
745                                        move("$tmpd/$pbpkg-$pbver.ebuild","$ENV{'PBBUILDDIR'}/portage/pb/sys-apps/$pbpkg");
746                                }
747                        }
748
749                        $made="$made portage/pb/sys-apps/$pbpkg/$pbpkg-$pbver.ebuild";
750                } elsif ($dtype eq "tgz") {
751                        # Slackware family
752                        $made="$made $pbpkg/$pbpkg-$pbver-*-$pbtag.tgz";
753
754                        chdir "$ENV{'PBBUILDDIR'}" || die "Unable to chdir to $ENV{'PBBUILDDIR'}";
755                        pb_system("tar xfz $src","Extracting sources");
756                        chdir "$pbpkg-$pbver" || die "Unable to chdir to $pbpkg-$pbver";
757                        symlink "pbconf/$ddir-$dver","install" || die "Unable to symlink to pbconf/$ddir-$dver";
758                        if (-x "install/pbslack") {
759                                pb_system("./install/pbslack","Building package");
760                                pb_system("sudo /sbin/makepkg -p -l y -c y $pbpkg","Packaging $pbpkg");
761                        }
762                } else {
763                        die "Unknown dtype format $dtype";
764                }
765        }
766        # Keep track of what is generated so that we can get them back from VMs
767        open(KEEP,"> $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}") || die "Unable to create $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}";
768        print KEEP "$made\n";
769        close(KEEP);
770}
771
772sub pb_build2ssh {
773        pb_send2target("Sources");
774}
775
776sub pb_pkg2ssh {
777        pb_send2target("Packages");
778}
779
780# By default deliver to the the public site hosting the
781# ftp structure (or whatever) or a VM/VE
782sub pb_send2target {
783
784        my $cmt = shift;
785        my $v = shift || undef;
786        my $vmexist = shift || 0;                       # 0 is FALSE
787        my $vmpid = shift || 0;                         # 0 is FALSE
788
789        pb_log(2,"DEBUG: pb_send2target($cmt,".Dumper($v).",$vmexist,$vmpid)\n");
790        my $host = "sshhost";
791        my $login = "sshlogin";
792        my $dir = "sshdir";
793        my $port = "sshport";
794        my $conf = "sshconf";
795        my $rebuild = "sshrebuild";
796        my $tmout = "vmtmout";
797        my $path = "vmpath";
798        if (($cmt eq "vm") || ($cmt eq "Script")) {
799                $login = "vmlogin";
800                $dir = "pbdefdir";
801                $tmout = "vmtmout";
802                $rebuild = "vmrebuild";
803                # Specific VM
804                $host = "vmhost";
805                $port = "vmport";
806        } elsif ($cmt eq "ve") {
807                $login = "velogin";
808                $dir = "pbdefdir";
809                $tmout = "vetmout";
810                # Specific VE
811                $path = "vepath";
812                $conf = "veconf";
813                $rebuild = "verebuild";
814        }
815        my $cmd = "";
816
817        my $ptr = pb_get_pkg();
818        @pkgs = @$ptr;
819
820        # Get the running distro to consider
821        my ($odir,$over,$oarch) = (undef, undef, undef);
822        if (defined $v) {
823                ($odir,$over,$oarch) = split(/-/,$v);
824        }
825        my ($ddir, $dver, $dfam, $dtype, $pbsuf) = pb_distro_init($odir,$over);
826        pb_log(2,"DEBUG: distro tuple: ".join(',',($ddir, $dver, $dfam, $dtype, $pbsuf))."\n");
827
828        # Get list of packages to build
829        # Get content saved in cms2build
830        my ($pkg) = pb_conf_read("$ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb","pbpkg");
831        $pkg = { } if (not defined $pkg);
832
833        my $src = "";
834        chdir "$ENV{'PBBUILDDIR'}";
835        foreach my $pbpkg (@pkgs) {
836                my $vertag = $pkg->{$pbpkg};
837                # get the version of the current package - maybe different
838                ($pbver,$pbtag) = split(/-/,$vertag);
839
840                if (($cmt eq "Sources") || ($cmt eq "vm") || ($cmt eq "ve")) {
841                        $src = "$src $ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz";
842                        if ($cmd eq "") {
843                                $cmd = "ln -sf $pbpkg-$pbver.tar.gz $pbpkg-latest.tar.gz";
844                        } else {
845                                $cmd = "$cmd ; ln -sf $pbpkg-$pbver.tar.gz $pbpkg-latest.tar.gz";
846                        }
847                }
848        }
849        # Adds conf file for availability of conf elements
850        pb_conf_add("$ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb");
851
852        if (($cmt eq "vm") || ($cmt eq "ve")) {
853                $src="$src $ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb $ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb $ENV{'PBETC'} $ENV{'PBDESTDIR'}/pbrc $ENV{'PBDESTDIR'}/pbscript";
854        } elsif ($cmt eq "Script") {
855                $src="$src $ENV{'PBDESTDIR'}/pbscript";
856        } elsif ($cmt eq "Packages") {
857                # Get package list from file made during build2pkg
858                open(KEEP,"$ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}") || die "Unable to read $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}";
859                $src = <KEEP>;
860                chomp($src);
861                close(KEEP);
862                $src="$src $ENV{'PBBUILDDIR'}/pbscript" if ($cmt ne "Sources");
863        }
864        # Remove potential leading spaces (cause problem with basename)
865        $src =~ s/^ *//;
866        my $basesrc = "";
867        foreach my $i (split(/ +/,$src)) {
868                $basesrc .= " ".basename($i);
869        }
870
871        pb_log(0,"Sources handled ($cmt): $src\n");
872        pb_log(2,"values: ".Dumper(($host,$login,$dir,$port,$tmout,$rebuild,$path,$conf))."\n");
873        my ($sshhost,$sshlogin,$sshdir,$sshport,$vtmout,$vepath) = pb_conf_get($host,$login,$dir,$port,$tmout,$path);
874        my ($vrebuild,$veconf) = pb_conf_get_if($rebuild,$conf);
875        pb_log(2,"ssh: ".Dumper(($sshhost,$sshlogin,$sshdir,$sshport,$vtmout,$vrebuild,$vepath,$veconf))."\n");
876        # Not mandatory
877        my ($testver) = pb_conf_get_if("testver");
878
879        my $mac;
880        # Useless for VE
881        if ($cmt ne "ve") {
882                $mac = "$sshlogin->{$ENV{'PBPROJ'}}\@$sshhost->{$ENV{'PBPROJ'}}";
883                # Overwrite account value if passed as parameter
884                $mac = "$pbaccount\@$sshhost->{$ENV{'PBPROJ'}}" if (defined $pbaccount);
885                pb_log(2, "DEBUG: pbaccount: $pbaccount => mac: $mac\n") if (defined $pbaccount);
886        }
887
888        my $tdir;
889        my $bdir;
890        if (($cmt eq "Sources") || ($cmt eq "Script")) {
891                $tdir = "$sshdir->{$ENV{'PBPROJ'}}/src";
892                if ((defined $testver) && (defined $testver->{$ENV{'PBPROJ'}}) && ($testver->{$ENV{'PBPROJ'}} =~ /true/i)) {
893                        # This is a test pkg => target dir is under test
894                        $tdir = "$sshdir->{$ENV{'PBPROJ'}}/test/src";
895                }
896        } elsif (($cmt eq "vm") || ($cmt eq "ve")) {
897                $tdir = $sshdir->{$ENV{'PBPROJ'}}."/$ENV{'PBPROJ'}/delivery";
898                $bdir = $sshdir->{$ENV{'PBPROJ'}}."/$ENV{'PBPROJ'}/build";
899                # Remove a potential $ENV{'HOME'} as bdir should be relative to pb's home
900                $bdir =~ s|\$ENV.+\}/||;
901        } elsif ($cmt eq "Packages") {
902                $tdir = "$sshdir->{$ENV{'PBPROJ'}}/$ddir/$dver";
903
904                if ((defined $testver) && (defined $testver->{$ENV{'PBPROJ'}}) && ($testver->{$ENV{'PBPROJ'}} =~ /true/i)) {
905                        # This is a test pkg => target dir is under test
906                        $tdir = "$sshdir->{$ENV{'PBPROJ'}}/test/$ddir/$dver";
907                }
908
909                my $repodir = $tdir;
910                $repodir =~ s|^$sshdir->{$ENV{'PBPROJ'}}/||;
911
912                my ($pbrepo) = pb_conf_get("pbrepo");
913
914                # Repository management
915                open(PBS,"> $ENV{'PBBUILDDIR'}/pbscript") || die "Unable to create $ENV{'PBBUILDDIR'}/pbscript";
916                if ($dtype eq "rpm") {
917                        # Also make a pbscript to generate yum/urpmi bases
918                        print PBS << "EOF";
919#!/bin/bash
920# Prepare a script to ease yum setup
921cat > $ENV{'PBPROJ'}.repo << EOT
922[$ENV{'PBPROJ'}]
923name=$ddir $dver - $ENV{'PBPROJ'} Vanilla Packages
924baseurl=$pbrepo->{$ENV{'PBPROJ'}}/$repodir
925enabled=1
926gpgcheck=0
927EOT
928chmod 644 $ENV{'PBPROJ'}.repo
929
930# Clean up old repo content
931rm -rf headers/ repodata/
932# Create yum repo
933yum-arch .
934# Create repodata
935createrepo .
936EOF
937                        if ($dfam eq "md") {
938                                # For Mandriva add urpmi management
939                                print PBS << "EOF";
940# Prepare a script to ease urpmi setup
941cat > $ENV{'PBPROJ'}.addmedia << EOT
942urpmi.addmedia $ENV{'PBPROJ'} $pbrepo->{$ENV{'PBPROJ'}}/$repodir with hdlist.cz
943EOT
944chmod 755 $ENV{'PBPROJ'}.addmedia
945
946# Clean up old repo content
947rm -f hdlist.cz synthesis.hdlist.cz
948# Create urpmi repo
949genhdlist .
950EOF
951                        }
952                } elsif ($dtype eq "deb") {
953                        # Also make a pbscript to generate apt bases
954                        # Cf: http://www.debian.org/doc/manuals/repository-howto/repository-howto.fr.html
955                        my $rpd = basename($pbrepo->{$ENV{'PBPROJ'}}/$repodir);
956                        print PBS << "EOF";
957# Prepare a script to ease apt i setup
958cat > $ENV{'PBPROJ'}.apt << EOT
959deb $rpd $dver/
960deb-src $rpd $dver/
961EOT
962chmod 644 $ENV{'PBPROJ'}.apt
963
964# Prepare a script to create apt info file
965(cd .. ; dpkg-scanpackages $dver /dev/null | gzip -c9 > $dver/Packages.gz
966(cd .. ; dpkg-scansources $dver /dev/null | gzip -c9 > $dver/Sources.gz
967EOF
968                }
969                close(PBS);
970                chmod 0755,"$ENV{'PBBUILDDIR'}/pbscript";
971
972        } else {
973                return;
974        }
975
976        # Useless for VE
977        my $nport;
978        if ($cmt ne "ve") {
979                $nport = $sshport->{$ENV{'PBPROJ'}};
980                $nport = "$pbport" if (defined $pbport);
981        }
982
983        # Remove a potential $ENV{'HOME'} as tdir should be relative to pb's home
984        $tdir =~ s|\$ENV.+\}/||;
985
986        my $tm = $vtmout->{$ENV{'PBPROJ'}};
987
988        # ssh communication if not VE
989        # should use a hash instead...
990        my ($shcmd,$cpcmd,$cptarget,$cp2target);
991        if ($cmt ne "ve") {
992                my $keyfile = pb_ssh_get(0);
993                $shcmd = "ssh -i $keyfile -q -o UserKnownHostsFile=/dev/null -p $nport $mac";
994                $cpcmd = "scp -i $keyfile -p -o UserKnownHostsFile=/dev/null -P $nport";
995                $cptarget = "$mac:$tdir";
996                if ($cmt eq "vm") {
997                        $cp2target = "$mac:$bdir";
998                }
999        } else {
1000                my $tp = $vepath->{$ENV{'PBPROJ'}};
1001                $shcmd = "sudo chroot $tp/$v /bin/su - $sshlogin->{$ENV{'PBPROJ'}} -c ";
1002                $cpcmd = "cp -a ";
1003                $cptarget = "$tp/$tdir";
1004                $cp2target = "$tp/$bdir";
1005        }
1006
1007        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");
1008        pb_system("cd $ENV{'PBBUILDDIR'} ; $cpcmd $src $cptarget 2> /dev/null","$cmt delivery in $cptarget");
1009
1010        # For VE we need to change the owner manually - To be tested if needed
1011        #if ($cmt eq "ve") {
1012        #pb_system("cd $cptarget ; sudo chown -R $sshlogin->{$ENV{'PBPROJ'}} .","$cmt chown in $cptarget to $sshlogin->{$ENV{'PBPROJ'}}");
1013        #}
1014        pb_system("$shcmd \"echo \'cd $tdir ; if [ -f pbscript ]; then ./pbscript; fi ; rm -f ./pbscript\' | bash\"","Executing pbscript on $cptarget if needed");
1015        if (($cmt eq "vm") || ($cmt eq "ve")) {
1016                # Get back info on pkg produced, compute their name and get them from the VM
1017                pb_system("$cpcmd $cp2target/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'} $ENV{'PBBUILDDIR'} 2> /dev/null","Get package names in $cp2target");
1018                open(KEEP,"$ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}") || die "Unable to read $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}";
1019                my $src = <KEEP>;
1020                chomp($src);
1021                close(KEEP);
1022                $src =~ s/^ *//;
1023                pb_mkdir_p("$ENV{'PBBUILDDIR'}/$odir/$over");
1024                # Change pgben to make the next send2target happy
1025                my $made = "";
1026                open(KEEP,"> $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}") || die "Unable to write $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}";
1027                foreach my $p (split(/ +/,$src)) {
1028                        my $j = basename($p);
1029                        pb_system("$cpcmd $cp2target/\'$p\' $ENV{'PBBUILDDIR'}/$odir/$over 2> /dev/null","Package recovery of $j in $cp2target");
1030                        $made="$made $odir/$over/$j" if (($dtype ne "rpm") || ($j !~ /.src.rpm$/));
1031                }
1032                print KEEP "$made\n";
1033                close(KEEP);
1034                pb_system("$shcmd \"rm -rf $tdir $bdir\"","$cmt cleanup");
1035
1036                # We want to send them to the ssh account so overwrite what has been done before
1037                undef $pbaccount;
1038                pb_log(2,"Before sending pkgs, vmexist: $vmexist, vmpid: $vmpid\n");
1039                pb_send2target("Packages",$odir."-".$over."-".$oarch,$vmexist,$vmpid);
1040                pb_rm_rf("$ENV{'PBBUILDDIR'}/$odir");
1041        }
1042        pb_log(2,"Before halt, vmexist: $vmexist, vmpid: $vmpid\n");
1043        if ((! $vmexist) && (($cmt eq "vm") || ($cmt eq "Script"))) {
1044                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)");
1045        }
1046}
1047
1048sub pb_script2v {
1049        my $pbscript=shift;
1050        my $vtype=shift;
1051        my $force=shift || 0;   # Force stop of VM. Default not
1052        my $vm1=shift || undef; # Only that VM to treat
1053        my $vm;
1054        my $all;
1055
1056        pb_log(2,"DEBUG: pb_script2v($pbscript,$vtype,$force,$vm1)\n");
1057        # Prepare the script to be executed on the VM
1058        # in $ENV{'PBDESTDIR'}/pbscript
1059        if ((defined $pbscript ) && ($pbscript ne "$ENV{'PBDESTDIR'}/pbscript")) {
1060                copy($pbscript,"$ENV{'PBDESTDIR'}/pbscript") || die "Unable to create $ENV{'PBDESTDIR'}/pbscript";
1061                chmod 0755,"$ENV{'PBDESTDIR'}/pbscript";
1062        }
1063
1064        if (not defined $vm1) {
1065                ($vm,$all) = pb_get_v($vtype);
1066        } else {
1067                @$vm = ($vm1);
1068        }
1069        my ($vmexist,$vmpid) = (undef,undef);
1070
1071        foreach my $v (@$vm) {
1072                # Launch the VM/VE
1073                if ($vtype eq "vm") {
1074                        ($vmexist,$vmpid) = pb_launchv($vtype,$v,0);
1075                        pb_log(2,"DEBUG: After pb_launchv, vmexist: $vmexist, vmpid: $vmpid\n");
1076
1077                        # Skip that VM if something went wrong
1078                        next if (($vmpid == 0) && ($vmexist == 0));
1079
1080                        # If force stopping the VM then reset vmexist
1081                        if ($force == 1) {
1082                                $vmpid = $vmexist;
1083                                $vmexist = 0;
1084                        }
1085                }
1086
1087                # Gather all required files to send them to the VM
1088                # and launch the build through pbscript
1089                pb_log(2,"DEBUG: Before send2target, vmexist: $vmexist, vmpid: $vmpid\n");
1090                pb_send2target("Script","$v",$vmexist,$vmpid);
1091
1092        }
1093}
1094
1095sub pb_launchv {
1096        my $vtype = shift;
1097        my $v = shift;
1098        my $create = shift || 0;                # By default do not create a VM
1099
1100        pb_log(2,"DEBUG: pb_launchv($vtype,$v,$create)\n");
1101        die "No VM/VE defined, unable to launch" if (not defined $v);
1102        # Keep only the first VM in case many were given
1103        $v =~ s/,.*//;
1104
1105        # Which is our local arch ? (standardize on i386 for those platforms)
1106        my $arch = `uname -m`;
1107        chomp($arch);
1108        $arch =~ s/i.86/i386/;
1109
1110        # Launch the VMs/VEs
1111        if ($vtype eq "vm") {
1112                die "-i iso parameter needed" if (((not defined $iso) || ($iso eq "")) && ($create != 0));
1113
1114                my ($ptr,$vmopt,$vmpath,$vmport,$vmtmout,$vmsize) = pb_conf_get("vmtype","vmopt","vmpath","vmport","vmtmout","vmsize");
1115
1116                my $vmtype = $ptr->{$ENV{'PBPROJ'}};
1117                if (not defined $ENV{'PBVMOPT'}) {
1118                        $ENV{'PBVMOPT'} = "";
1119                }
1120                if (defined $vmopt->{$ENV{'PBPROJ'}}) {
1121                        $ENV{'PBVMOPT'} .= " $vmopt->{$ENV{'PBPROJ'}}" if ($ENV{'PBVMOPT'} !~ / $vmopt->{$ENV{'PBPROJ'}}/);
1122                }
1123                my $nport = $vmport->{$ENV{'PBPROJ'}};
1124                $nport = "$pbport" if (defined $pbport);
1125       
1126                my $cmd;
1127                my $vmcmd;              # has to be used for pb_check_ps
1128                my $vmm;                # has to be used for pb_check_ps
1129                if ($vmtype eq "qemu") {
1130                        my $qemucmd32;
1131                        my $qemucmd64;
1132                        if ($arch eq "x86_64") {
1133                                $qemucmd32 = "/usr/bin/qemu-system-i386";
1134                                $qemucmd64 = "/usr/bin/qemu";
1135                        } else {
1136                                $qemucmd32 = "/usr/bin/qemu";
1137                                $qemucmd64 = "/usr/bin/qemu-system-x86_64";
1138                        }
1139                if ($v =~ /x86_64/) {
1140                                $vmcmd = "$qemucmd64 -no-kqemu";
1141                        } else {
1142                                $vmcmd = "$qemucmd32";
1143                        }
1144                        $vmm = "$vmpath->{$ENV{'PBPROJ'}}/$v.qemu";
1145                        if ($create != 0) {
1146                                $ENV{'PBVMOPT'} .= " -cdrom $iso -boot d";
1147                        }
1148                        $cmd = "$vmcmd $ENV{'PBVMOPT'} -redir tcp:$nport:10.0.2.15:22 $vmm"
1149                } elsif ($vmtype eq "xen") {
1150                } elsif ($vmtype eq "vmware") {
1151                } else {
1152                        die "VM of type $vmtype not supported. Report to the dev team";
1153                }
1154                my ($tmpcmd,$void) = split(/ +/,$cmd);
1155                my $vmexist = pb_check_ps($tmpcmd,$vmm);
1156                my $vmpid = 0;
1157                if (! $vmexist) {
1158                        if ($create != 0) {
1159                                if (($vmtype eq "qemu") || ($vmtype eq "xen")) {
1160                                        pb_system("/usr/bin/qemu-img create -f qcow2 $vmm $vmsize->{$ENV{'PBPROJ'}}","Creating the QEMU VM");
1161                                } elsif ($vmtype eq "vmware") {
1162                                } else {
1163                                }
1164                        }
1165                        if (! -f "$vmm") {
1166                                pb_log(0,"Unable to find VM $vmm\n");
1167                        } else {
1168                                pb_system("$cmd &","Launching the VM $vmm");
1169                                pb_system("sleep $vmtmout->{$ENV{'PBPROJ'}}","Waiting for VM $v to come up");
1170                                $vmpid = pb_check_ps($tmpcmd,$vmm);
1171                                pb_log(0,"VM $vmm launched (pid $vmpid)\n");
1172                        }
1173                } else {
1174                        pb_log(0,"Found an existing VM $vmm (pid $vmexist)\n");
1175                }
1176                pb_log(2,"DEBUG: pb_launchv returns ($vmexist,$vmpid)\n");
1177                return($vmexist,$vmpid);
1178        # VE here
1179        } else {
1180                # Get VE context
1181                my ($ptr,$vetmout,$vepath,$verebuild,$veconf) = pb_conf_get("vetype","vetmout","vepath","verebuild","veconf");
1182                my $vetype = $ptr->{$ENV{'PBPROJ'}};
1183
1184                # Get distro context
1185                my ($name,$ver,$darch) = split(/-/,$v);
1186                chomp($darch);
1187                my ($ddir, $dver, $dfam, $dtype, $pbsuf) = pb_distro_init($name,$ver);
1188
1189                if ($vetype eq "chroot") {
1190                        # Architecture consistency
1191                        if ($arch ne $darch) {
1192                                die "Unable to launch a VE of architecture $darch on a $arch platform" if (not (($darch eq "x86_64") && ($arch =~ /i?86/)));
1193                        }
1194
1195                        if (($create != 0) || ($verebuild->{$ENV{'PBPROJ'}} eq "true") || ($force == 1)) {
1196                                # We have to rebuild the chroot
1197                                if ($dtype eq "rpm") {
1198                                        pb_system("sudo /usr/sbin/mock --init --resultdir=\"/tmp\" --configdir=\"$veconf->{$ENV{'PBPROJ'}}\" -r $v","Creating the mock VE");
1199                                        # Once setup we need to install some packages, the pb account, ...
1200                                        pb_system("sudo /usr/sbin/mock --install --configdir=\"$veconf->{$ENV{'PBPROJ'}}\" -r $v su","Configuring the mock VE");
1201                                        #pb_system("sudo /usr/sbin/mock --init --resultdir=\"/tmp\" --configdir=\"$veconf->{$ENV{'PBPROJ'}}\" --basedir=\"$vepath->{$ENV{'PBPROJ'}}\" -r $v","Creating the mock VE");
1202                                } elsif ($dtype eq "deb") {
1203                                        pb_system("","Creating the pbuilder VE");
1204                                } elsif ($dtype eq "ebuild") {
1205                                        die "Please teach the dev team how to build gentoo chroot";
1206                                } else {
1207                                        die "Unknown distribution type $dtype. Report to dev team";
1208                                }
1209                        }
1210                        # Nothing more to do for VE. No real launch
1211                } else {
1212                        die "VE of type $vetype not supported. Report to the dev team";
1213                }
1214        }
1215}
1216
1217sub pb_build2v {
1218
1219my $vtype = shift;
1220
1221# Prepare the script to be executed on the VM/VE
1222# in $ENV{'PBDESTDIR'}/pbscript
1223#my ($ntp) = pb_conf_get($vtype."ntp");
1224#my $vntp = $ntp->{$ENV{'PBPROJ'}};
1225
1226open(SCRIPT,"> $ENV{'PBDESTDIR'}/pbscript") || die "Unable to create $ENV{'PBDESTDIR'}/pbscript";
1227print SCRIPT "#!/bin/bash\n";
1228print SCRIPT "echo ... Execution needed\n";
1229print SCRIPT "# This is in directory delivery\n";
1230print SCRIPT "# Setup the variables required for building\n";
1231print SCRIPT "export PBPROJ=$ENV{'PBPROJ'}\n";
1232print SCRIPT "# Preparation for pb\n";
1233print SCRIPT "mv .pbrc \$HOME\n";
1234print SCRIPT "cd ..\n";
1235# Force new date to be in the future compared to the date of the tar file by adding 1 minute
1236my @date=pb_get_date();
1237$date[1]++;
1238my $upddate = strftime("%m%d%H%M%Y", @date);
1239#print SCRIPT "echo Setting up date on $vntp...\n";
1240# Or use ntpdate if available TBC
1241print SCRIPT "sudo date $upddate\n";
1242# Get list of packages to build and get some ENV vars as well
1243my $ptr = pb_get_pkg();
1244@pkgs = @$ptr;
1245my $p = join(' ',@pkgs) if (@pkgs);
1246print SCRIPT "export PBPROJVER=$ENV{'PBPROJVER'}\n";
1247print SCRIPT "export PBPROJTAG=$ENV{'PBPROJTAG'}\n";
1248print SCRIPT "export PBPACKAGER=\"$ENV{'PBPACKAGER'}\"\n";
1249print SCRIPT "# Build\n";
1250print SCRIPT "echo Building packages on $vtype...\n";
1251print SCRIPT "pb -p $ENV{'PBPROJ'} build2pkg $p\n";
1252close(SCRIPT);
1253chmod 0755,"$ENV{'PBDESTDIR'}/pbscript";
1254
1255my ($v,$all) = pb_get_v($vtype);
1256
1257# Send tar files when we do a global generation
1258pb_build2ssh() if ($all == 1);
1259
1260my ($vmexist,$vmpid) = (undef,undef);
1261
1262foreach my $v (@$v) {
1263        if ($vtype eq "vm") {
1264                # Launch the VM
1265                ($vmexist,$vmpid) = pb_launchv($vtype,$v,0);
1266
1267                # Skip that VM if it something went wrong
1268                next if (($vmpid == 0) && ($vmexist == 0));
1269        }
1270        # Gather all required files to send them to the VM/VE
1271        # and launch the build through pbscript
1272        pb_log(2,"Calling send2target $vtype,$v,$vmexist,$vmpid\n");
1273        pb_send2target($vtype,"$v",$vmexist,$vmpid);
1274}
1275}
1276
1277
1278sub pb_newver {
1279
1280        die "-V Version parameter needed" if ((not defined $newver) || ($newver eq ""));
1281
1282        # Need this call for PBDIR
1283        my ($scheme2,$uri) = pb_cms_init($pbinit);
1284
1285        my ($pbconf) = pb_conf_get("pbconfurl");
1286        $uri = $pbconf->{$ENV{'PBPROJ'}};
1287        my ($scheme, $account, $host, $port, $path) = pb_get_uri($uri);
1288
1289        # Checking CMS repositories status
1290        my ($pburl) = pb_conf_get("pburl");
1291        ($scheme2, $account, $host, $port, $path) = pb_get_uri($pburl->{$ENV{'PBPROJ'}});
1292
1293        if ($scheme !~ /^svn/) {
1294                die "Only SVN is supported at the moment";
1295        }
1296        my $res = pb_cms_isdiff($scheme,$ENV{'PBROOTDIR'});
1297        die "ERROR: No differences accepted in CMS for $ENV{'PBROOTDIR'} before creating a new version" if ($res != 0);
1298
1299        $res = pb_cms_isdiff($scheme2,$ENV{'PBDIR'});
1300        die "ERROR: No differences accepted in CMS for $ENV{'PBDIR'} before creating a new version" if ($res != 0);
1301
1302        # Tree identical between PBCONFDIR and PBROOTDIR. The delta is what
1303        # we want to get for the root of the new URL
1304
1305        my $tmp = $ENV{'PBROOTDIR'};
1306        $tmp =~ s|^$ENV{'PBCONFDIR'}||;
1307
1308        my $newurl = "$uri/".dirname($tmp)."/$newver";
1309        # Should probably use projver in the old file
1310        my $oldver= basename($tmp);
1311
1312        # Checking pbcl files
1313        foreach my $f (<$ENV{'PBROOTDIR'}/*/pbcl>) {
1314                open(PBCL,$f) || die "Unable to open $f";
1315                my $foundnew = 0;
1316                while (<PBCL>) {
1317                        $foundnew = 1 if (/^$newver \(/);
1318                }
1319                close(PBCL);
1320                die "ERROR: version $newver not found in $f" if ($foundnew == 0);
1321        }
1322
1323        # Duplicate and extract project-builder part
1324        pb_log(2,"Copying $uri/$tmp to $newurl\n");
1325        pb_cms_copy($scheme,"$uri/$tmp",$newurl);
1326        pb_log(2,"Checkout $newurl to $ENV{'PBROOTDIR'}/../$newver\n");
1327        pb_cms_up($scheme,"$ENV{'PBCONFDIR'}/..");
1328
1329        # Duplicate and extract project
1330        my $newurl2 = "$pburl->{$ENV{'PBPROJ'}}/".dirname($tmp)."/$newver";
1331
1332        pb_log(2,"Copying $pburl->{$ENV{'PBPROJ'}}/$tmp to $newurl2\n");
1333        pb_cms_copy($scheme,"$pburl->{$ENV{'PBPROJ'}}/$tmp",$newurl2);
1334        pb_log(2,"Checkout $newurl2 to $ENV{'PBDIR'}/../$newver\n");
1335        pb_cms_up($scheme,"$ENV{'PBDIR'}/..");
1336
1337        # Update the .pb file
1338        open(FILE,"$ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb") || die "Unable to open $ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb";
1339        open(OUT,"> $ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb.new") || die "Unable to write to $ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb.new";
1340        while(<FILE>) {
1341                s/^projver\s+$ENV{'PBPROJ'}\s*=\s*$oldver/projver $ENV{'PBPROJ'} = $newver/;
1342                pb_log(0,"Changing projver from $oldver to $newver in $ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb\n") if (/^projver\s+$ENV{'PBPROJ'}\s*=\s*$oldver/);
1343                s/^testver/#testver/;
1344                pb_log(0,"Commenting testver in $ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb\n") if (/^testver/);
1345                print OUT $_;
1346        }
1347        close(FILE);
1348        close(OUT);
1349        rename("$ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb.new","$ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb");
1350
1351        pb_log(2,"Checkin $ENV{'PBROOTDIR'}/../$newver\n");
1352        pb_cms_checkin($scheme,"$ENV{'PBROOTDIR'}/../$newver",undef);
1353}
1354
1355#
1356# Return the list of VMs/VEs we are working on
1357# $all is a flag to know if we return all of them
1358# or only some (if all we publish also tar files in addition to pkgs
1359#
1360sub pb_get_v {
1361
1362my $vtype = shift;
1363my @v;
1364my $all = 0;
1365my $vlist;
1366my $pbv = 'PBV';
1367
1368if ($vtype eq "vm") {
1369        $vlist = "vmlist";
1370} elsif ($vtype eq "ve") {
1371        $vlist = "velist";
1372}
1373# Get VM/VE list
1374if ((not defined $ENV{$pbv}) || ($ENV{$pbv} =~ /^all$/)) {
1375        my ($ptr) = pb_conf_get($vlist);
1376        $ENV{$pbv} = $ptr->{$ENV{'PBPROJ'}};
1377        $all = 1;
1378}
1379pb_log(2,"$vtype: $ENV{$pbv}\n");
1380@v = split(/,/,$ENV{$pbv});
1381return(\@v,$all);
1382}
1383
1384# Function to create a potentialy missing pb account on the VM/VE, and adds it to sudo
1385# Needs to use root account to connect to the VM/VE
1386# pb will take your local public SSH key to access
1387# the pb account in the VM later on if needed
1388sub pb_setup_v {
1389
1390my $vtype = shift;
1391
1392my ($vm,$all) = pb_get_v($vtype);
1393
1394# Script generated
1395my $pbscript = "$ENV{'PBDESTDIR'}/setupv";
1396
1397foreach my $v (@$vm) {
1398        # Name of the account to deal with for VM/VE
1399        # Do not use the one passed potentially with -a
1400        my ($pbac) = pb_conf_get($vtype."login");
1401        my ($key,$zero0,$zero1,$zero2);
1402        my ($vmexist,$vmpid);
1403
1404        if ($vtype eq "vm") {
1405                # Prepare the key to be used and transfered remotely
1406                my $keyfile = pb_ssh_get(1);
1407               
1408                my ($vmhost,$vmport) = pb_conf_get("vmhost","vmport");
1409                my $nport = $vmport->{$ENV{'PBPROJ'}};
1410                $nport = "$pbport" if (defined $pbport);
1411       
1412                # Launch the VM
1413                ($vmexist,$vmpid) = pb_launchv($vtype,$v,0);
1414
1415                # Skip that VM if something went wrong
1416                next if (($vmpid == 0) && ($vmexist == 0));
1417       
1418                # Store the pub key part in a variable
1419                open(FILE,"$keyfile.pub") || die "Unable to open $keyfile.pub";
1420                ($zero0,$zero1,$zero2) = split(/ /,<FILE>);
1421                close(FILE);
1422
1423                $key = "\Q$zero1";
1424
1425                pb_system("cat $keyfile.pub | ssh -q -o UserKnownHostsFile=/dev/null -p $nport -i $keyfile root\@$vmhost->{$ENV{'PBPROJ'}} \"mkdir -p .ssh ; chmod 700 .ssh ; cat >> .ssh/authorized_keys ; chmod 600 .ssh/authorized_keys\"","Copying local keys to $vtype. This will require the root password");
1426                # once this is done, we can do what we want on the VM remotely
1427        }
1428       
1429        # Prepare the script to be executed on the VM/VE
1430        # in $ENV{'PBDESTDIR'}/setupv
1431       
1432        open(SCRIPT,"> $pbscript") || die "Unable to create $pbscript";
1433        print SCRIPT << 'EOF';
1434#!/usr/bin/perl -w
1435
1436use strict;
1437use File::Copy;
1438
1439our $debug;
1440our $LOG;
1441our $synmsg = "pbscript";
1442pb_log_init($debug, $LOG);
1443pb_temp_init();
1444
1445EOF
1446        if ($vtype eq "vm") {
1447                print SCRIPT << 'EOF';
1448# Removes duplicate in .ssh/authorized_keys of our key if needed
1449#
1450my $file1="$ENV{'HOME'}/.ssh/authorized_keys";
1451open(PBFILE,$file1) || die "Unable to open $file1";
1452open(PBOUT,"> $file1.new") || die "Unable to open $file1.new";
1453my $count = 0;
1454while (<PBFILE>) {
1455EOF
1456                print SCRIPT << "EOF";
1457        if (/ $key /) {
1458                \$count++;
1459        }
1460print PBOUT \$_ if ((\$count <= 1) || (\$_ !~ / $key /));
1461}
1462close(PBFILE);
1463close(PBOUT);
1464rename("\$file1.new",\$file1);
1465chmod 0600,\$file1;
1466EOF
1467        }
1468        print SCRIPT << 'EOF';
1469
1470# Adds $pbac->{$ENV{'PBPROJ'}} as an account if needed
1471#
1472my $file="/etc/passwd";
1473open(PBFILE,$file) || die "Unable to open $file";
1474my $found = 0;
1475while (<PBFILE>) {
1476EOF
1477        print SCRIPT << "EOF";
1478        \$found = 1 if (/^$pbac->{$ENV{'PBPROJ'}}:/);
1479EOF
1480        print SCRIPT << 'EOF';
1481}
1482close(PBFILE);
1483
1484if ( $found == 0 ) {
1485        if ( ! -d "/home" ) {
1486                pb_mkdir("/home");
1487        }
1488EOF
1489        print SCRIPT << "EOF";
1490pb_system("groupadd $pbac->{$ENV{'PBPROJ'}}","Adding group $pbac->{$ENV{'PBPROJ'}}");
1491pb_system("useradd $pbac->{$ENV{'PBPROJ'}} -g $pbac->{$ENV{'PBPROJ'}} -m -d /home/$pbac->{$ENV{'PBPROJ'}}","Adding user $pbac->{$ENV{'PBPROJ'}} (group $pbac->{$ENV{'PBPROJ'}} - home /home/$pbac->{$ENV{'PBPROJ'}}");
1492}
1493
1494# allow ssh entry to build
1495#
1496mkdir "/home/$pbac->{$ENV{'PBPROJ'}}/.ssh",0700;
1497# Allow those accessing root to access the build account
1498copy("\$ENV{'HOME'}/.ssh/authorized_keys","/home/$pbac->{$ENV{'PBPROJ'}}/.ssh/authorized_keys");
1499chmod 0600,".ssh/authorized_keys";
1500pb_system("chown -R $pbac->{$ENV{'PBPROJ'}}:$pbac->{$ENV{'PBPROJ'}} /home/$pbac->{$ENV{'PBPROJ'}}/.ssh","Finish setting up the SSH env for $pbac->{$ENV{'PBPROJ'}}");
1501
1502EOF
1503        print SCRIPT << 'EOF';
1504# No passwd for build account only keys
1505$file="/etc/shadow";
1506open(PBFILE,$file) || die "Unable to open $file";
1507open(PBOUT,"> $file.new") || die "Unable to open $file.new";
1508while (<PBFILE>) {
1509EOF
1510        print SCRIPT << "EOF";
1511        s/^$pbac->{$ENV{'PBPROJ'}}:\!\!:/$pbac->{$ENV{'PBPROJ'}}:*:/;
1512        s/^$pbac->{$ENV{'PBPROJ'}}:\!:/$pbac->{$ENV{'PBPROJ'}}:*:/;     #SLES 9 e.g.
1513EOF
1514        print SCRIPT << 'EOF';
1515        print PBOUT $_;
1516}
1517close(PBFILE);
1518close(PBOUT);
1519rename("$file.new",$file);
1520chmod 0640,$file;
1521
1522# Keep the VM in text mode
1523$file="/etc/inittab";
1524if (-f $file) {
1525        open(PBFILE,$file) || die "Unable to open $file";
1526        open(PBOUT,"> $file.new") || die "Unable to open $file.new";
1527        while (<PBFILE>) {
1528                s/^(..):5:initdefault:$/$1:3:initdefault:/;
1529                print PBOUT $_;
1530        }
1531        close(PBFILE);
1532        close(PBOUT);
1533        rename("$file.new",$file);
1534        chmod 0640,$file;
1535}
1536
1537# pb has to be added to portage group on gentoo
1538
1539# Adapt sudoers
1540$file="/etc/sudoers";
1541open(PBFILE,$file) || die "Unable to open $file";
1542open(PBOUT,"> $file.new") || die "Unable to open $file.new";
1543while (<PBFILE>) {
1544EOF
1545        print SCRIPT << "EOF";
1546        next if (/^$pbac->{$ENV{'PBPROJ'}}   /);
1547EOF
1548        print SCRIPT << 'EOF';
1549        s/Defaults[ \t]+requiretty//;
1550        print PBOUT $_;
1551}
1552close(PBFILE);
1553EOF
1554        print SCRIPT << "EOF";
1555# This is needed in order to be able to halt the machine from the $pbac->{$ENV{'PBPROJ'}} account at least
1556print PBOUT "$pbac->{$ENV{'PBPROJ'}}   ALL=(ALL) NOPASSWD:ALL\n";
1557EOF
1558        print SCRIPT << 'EOF';
1559close(PBOUT);
1560rename("$file.new",$file);
1561chmod 0440,$file;
1562
1563EOF
1564               
1565        my $SCRIPT = \*SCRIPT;
1566       
1567        pb_install_deps($SCRIPT);
1568       
1569        print SCRIPT << 'EOF';
1570# Suse wants sudoers as 640
1571if (($ddir eq "sles") || (($ddir eq "suse")) && ($dver ne "10.3")) {
1572        chmod 0640,$file;
1573}
1574
1575# Sync date
1576#system "/usr/sbin/ntpdate ntp.pool.org";
1577
1578pb_system("rm -rf perl-ProjectBuilder-* ; wget --passive-ftp ftp://ftp.mondorescue.org/src/perl-ProjectBuilder-latest.tar.gz ; tar xvfz perl-ProjectBuilder-latest.tar.gz ; cd perl-ProjectBuilder-* ; perl Makefile.PL ; make ; make install ; cd .. ; rm -rf perl-ProjectBuilder-* ; 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 .. ; rm -rf project-builder-* ;","Building Project-Builder");
1579system "pb 2>&1 | head -5";
1580EOF
1581        # Adds pb_distro_init from ProjectBuilder::Distribution
1582        foreach my $d (@INC) {
1583                my @f = ("$d/ProjectBuilder/Base.pm","$d/ProjectBuilder/Distribution.pm");
1584                foreach my $f (@f) {
1585                        if (-f "$f") {
1586                                open(PBD,"$f") || die "Unable to open $f";
1587                                while (<PBD>) {
1588                                                next if (/^package/);
1589                                                next if (/^use Exporter/);
1590                                                next if (/^use ProjectBuilder::/);
1591                                                next if (/^our /);
1592                                        print SCRIPT $_;
1593                                }
1594                                close(PBD);
1595                        }
1596                }
1597        }
1598        close(SCRIPT);
1599        chmod 0755,"$pbscript";
1600
1601        # That build script needs to be run as root and force stop of VM at end
1602        $pbaccount = "root";
1603
1604        # Force shutdown of VM exept if it was already launched
1605        my $force = 0;
1606        if ((! $vmexist) && ($vtype eq "vm")) {
1607                $force = 1;
1608        }
1609       
1610        pb_script2v($pbscript,$vtype,$force,$v);
1611}
1612return;
1613}
1614
1615sub pb_install_deps {
1616
1617my $SCRIPT = shift;
1618
1619print {$SCRIPT} << 'EOF';
1620# We need to have that pb_distro_init function
1621# Get it from Project-Builder::Distribution
1622my ($ddir, $dver, $dfam, $dtype, $pbsuf) = pb_distro_init(); 
1623print "distro tuple: ".join(',',($ddir, $dver, $dfam, $dtype, $pbsuf))."\n";
1624
1625# Get and install pb
1626my $insdm = "rm -rf Date-Manip* ; wget http://search.cpan.org/CPAN/authors/id/S/SB/SBECK/Date-Manip-5.54.tar.gz ; tar xvfz Date-Manip-5.54.tar.gz ; cd Date-Manip* ; perl Makefile.PL ; make ; make install ; cd .. ; rm -rf Date-Manip*";
1627my $insmb = "rm -rf Module-Build* ; wget http://search.cpan.org/CPAN/authors/id/K/KW/KWILLIAMS/Module-Build-0.2808.tar.gz ; tar xvfz Module-Build-0.2808.tar.gz ; cd Module-Build* ; perl Makefile.PL ; make ; make install ; cd .. ; rm -rf Module-Build*";
1628my $insfm =     "rm -rf File-MimeInfo* ; wget http://search.cpan.org/CPAN/authors/id/P/PA/PARDUS/File-MimeInfo/File-MimeInfo-0.15.tar.gz ; tar xvfz File-MimeInfo-0.15.tar.gz ; cd File-MimeInfo* ; perl Makefile.PL ; make ; make install ; cd .. ; rm -rf File-MimeInfo*";
1629my $insfb = "rm -rf File-Basedir* ; wget http://search.cpan.org/CPAN/authors/id/P/PA/PARDUS/File-BaseDir-0.03.tar.gz ; tar xvfz File-BaseDir-0.03.tar.gz ; cd File-BaseDir* ; perl Makefile.PL ; make ; make install ; cd .. ; rm -rf File-BaseDir*";
1630my $cmtdm = "Installing Date-Manip perl module";
1631my $cmtmb = "Installing Module-Build perl module";
1632my $cmtfm = "Installing File-MimeInfo perl module";
1633my $cmtfb = "Installing File-Basedir perl module";
1634my $cmtall = "Installing required modules";
1635
1636if ( $ddir eq "fedora" ) {
1637        pb_system("yum clean all","Cleaning yum env");
1638        #system "yum update -y";
1639        my $arch=`uname -m`;
1640        my $opt = "";
1641        chomp($arch);
1642        if ($arch eq "x86_64") {
1643                $opt="--exclude=*.i?86";
1644        }
1645
1646        pb_system("yum -y $opt install rpm-build wget patch ntp sudo perl-DateManip perl-File-MimeInfo perl-ExtUtils-MakeMaker",$cmtall);
1647        if ($dver eq 4) {
1648                pb_system("$insmb","$cmtmb");
1649                pb_system("$insfm","$cmtfm");
1650                pb_system("$insfb","$cmtfb");
1651        }
1652} elsif (( $dfam eq "rh" ) || ($ddir eq "sles") || (($ddir eq "suse") && (($dver eq "10.1") || ($dver eq "10.0"))) || ($ddir eq "slackware")) {
1653        # Suppose pkg are installed already as no online mirror available
1654        pb_system("rpm -e lsb 2>&1 > /dev/null","Removing lsb package");
1655        pb_system("$insdm","$cmtdm");
1656        pb_system("$insmb","$cmtmb");
1657        pb_system("$insfm","$cmtfm");
1658        pb_system("$insfb","$cmtfb");
1659} elsif ($ddir eq "suse") { 
1660        # New OpenSuSE
1661        pb_system("$insmb","$cmtmb");
1662        pb_system("$insfm","$cmtfm");
1663        pb_system("$insfb","$cmtfb");
1664        pb_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","$cmtall");
1665} elsif ( $dfam eq "md" ) {
1666                pb_system("urpmi.update -a ; urpmi --auto rpm-build wget sudo patch ntp-client perl-File-MimeInfo","$cmtall");
1667                if (($ddir eq "mandrake") && ($dver eq "10.1")) {
1668                        pb_system("$insdm","$cmtdm");
1669                } else {
1670                        pb_system("urpmi --auto perl-DateManip","$cmtdm");
1671                }
1672} elsif ( $dfam eq "du" ) {
1673        if (( $dver eq "3.1" ) && ($ddir eq "debian")) {
1674                #system "apt-get update";
1675                pb_system("$insfb","$cmtfb");
1676                pb_system("$insfm","$cmtfm");
1677                pb_system("apt-get -y install wget patch ssh sudo debian-builder dh-make fakeroot ntpdate libmodule-build-perl libdate-manip-perl","$cmtall");
1678        } else  {
1679                pb_system("apt-get update; apt-get -y install wget patch openssh-server dpkg-dev sudo debian-builder dh-make fakeroot ntpdate libfile-mimeinfo-perl libmodule-build-perl libdate-manip-perl","$cmtall");
1680        }
1681} elsif ( $dfam eq "gen" ) {
1682                #system "emerge -u system";
1683                pb_system("emerge wget sudo ntp DateManip File-MimeInfo","$cmtall");
1684} else {
1685        print "No pkg to install\n";
1686}
1687EOF
1688}
1689
1690# Return the SSH key file to use
1691# Potentially create it if needed
1692
1693sub pb_ssh_get {
1694
1695my $create = shift || 0;        # Do not create keys by default
1696
1697# Check the SSH environment
1698my $keyfile = undef;
1699
1700# We have specific keys by default
1701$keyfile = "$ENV{'HOME'}/.ssh/pb_dsa";
1702if (!(-e $keyfile) && ($create eq 1)) {
1703        pb_system("ssh-keygen -q -b 1024 -N '' -f $keyfile -t dsa","Generating SSH keys for pb");
1704}
1705
1706$keyfile = "$ENV{'HOME'}/.ssh/id_rsa" if (-s "$ENV{'HOME'}/.ssh/id_rsa");
1707$keyfile = "$ENV{'HOME'}/.ssh/id_dsa" if (-s "$ENV{'HOME'}/.ssh/id_dsa");
1708$keyfile = "$ENV{'HOME'}/.ssh/pb_dsa" if (-s "$ENV{'HOME'}/.ssh/pb_dsa");
1709die "Unable to find your public ssh key under $keyfile" if (not defined $keyfile);
1710return($keyfile);
1711}
1712
1713
1714# Returns the pid of a running VM command using a specific VM file
1715sub pb_check_ps {
1716        my $vmcmd = shift;
1717        my $vmm = shift;
1718        my $vmexist = 0;                # FALSE by default
1719
1720        open(PS, "ps auxhww|") || die "Unable to call ps";
1721        while (<PS>) {
1722                next if (! /$vmcmd/);
1723                next if (! /$vmm/);
1724                my ($void1, $void2);
1725                ($void1, $vmexist, $void2) = split(/ +/);
1726                last;
1727        }
1728        return($vmexist);
1729}
1730
1731
1732sub pb_extract_build_files {
1733
1734my $src=shift;
1735my $dir=shift;
1736my $ddir=shift;
1737my @files;
1738
1739if ($src =~ /tar\.gz$/) {
1740        pb_system("tar xfpz $src $dir","Extracting build files");
1741} elsif ($src =~ /tar\.bz2$/) {
1742        pb_system("tar xfpj $src $dir","Extracting build files");
1743} else {
1744        die "Unknown compression algorithm for $src";
1745}
1746opendir(DIR,"$dir") || die "Unable to open directory $dir";
1747foreach my $f (readdir(DIR)) {
1748        next if ($f =~ /^\./);
1749        move("$dir/$f","$ddir") || die "Unable to move $dir/$f to $ddir";
1750        pb_log(2,"mv $dir/$f $ddir\n");
1751        push @files,"$ddir/$f";
1752}
1753closedir(DIR);
1754# Not enough but still a first cleanup
1755pb_rm_rf("$dir");
1756return(@files);
1757}
1758
1759sub pb_list_bfiles {
1760
1761my $dir = shift;
1762my $pbpkg = shift;
1763my $bfiles = shift;
1764my $pkgfiles = shift;
1765my $supfiles = shift;
1766
1767opendir(BDIR,"$dir") || die "Unable to open dir $dir: $!";
1768foreach my $f (readdir(BDIR)) {
1769        next if ($f =~ /^\./);
1770        $bfiles->{$f} = "$dir/$f";
1771        $bfiles->{$f} =~ s~$ENV{'PBROOTDIR'}~~;
1772        if (defined $supfiles->{$pbpkg}) {
1773                $pkgfiles->{$f} = "$dir/$f" if ($f =~ /$supfiles->{$pbpkg}/);
1774        }
1775}
1776closedir(BDIR);
1777}
1778
1779
1780#
1781# Return the list of packages we are working on in a non CMS action
1782#
1783sub pb_get_pkg {
1784
1785my @pkgs = ();
1786
1787my ($var) = pb_conf_read("$ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb","pbpkg");
1788@pkgs = keys %$var;
1789
1790pb_log(0,"Packages: ".join(',',@pkgs)."\n");
1791return(\@pkgs);
1792}
1793
17941;
Note: See TracBrowser for help on using the repository browser.