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

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

Working announce action for pb

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