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

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

announce function - begining of coding

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