source: devel/pb/bin/pb @ 332

Revision 332, 43.7 KB checked in by bruno, 5 years ago (diff)

Improved doc

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