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

Last change on this file since 1111 was 1111, checked in by Bruno Cornec, 13 years ago
  • Rename previous option osupd into the more correct osins, and add a real osupd param to support distribution update commands
  • Adds 2 new commands to update distributions in VM|VE with updatevm|ve (Fix #70)
  • Property svn:executable set to *
File size: 102.4 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';
13
14# The modules mentioned here are required by pb when used both
15# locally or inside a VE/VM
16# Additional required modules only used locally are called with a require
17# in their respective section
18use Getopt::Long qw(:config auto_abbrev no_ignore_case);
19use Data::Dumper;
20use English;
21use File::Basename;
22use File::Copy;
23use File::stat;
24use File::Temp qw(tempdir);
25use File::Find;
26use Time::localtime qw(localtime);
27use POSIX qw(strftime);
28use lib qw (lib);
29use ProjectBuilder::Version;
30use ProjectBuilder::Base;
31use ProjectBuilder::Display;
32use ProjectBuilder::Conf;
33use ProjectBuilder::Distribution;
34use ProjectBuilder::CMS;
35use ProjectBuilder::Env;
36use ProjectBuilder::Filter;
37use ProjectBuilder::Changelog;
38
39# Global variables
40my %opts; # CLI Options
41my $action; # action to realize
42my $test = "FALSE"; # Not used
43my $pbforce = 0; # Force VE/VM rebuild
44my $pbsnap = 0; # Do not use snapshot mode for VM/VE by default
45my $option = ""; # Not used
46my @pkgs; # list of packages
47my $pbtag; # Global Tag variable
48my $pbver; # Global Version variable
49my $pbscript; # Name of the script
50my %pbver; # per package
51my %pbtag; # per package
52my $pbrev; # Global REVISION variable
53my $pbaccount; # Login to use to connect to the VM
54my $pbport; # Port to use to connect to the VM
55my $newver; # New version to create
56my $iso = undef; # ISO image for the VM to create
57
58my @date = pb_get_date();
59my $pbdate = strftime("%Y-%m-%d", @date);
60
61=pod
62
63=head1 NAME
64
65pb, aka project-builder.org - builds packages for your projects
66
67=head1 DESCRIPTION
68
69pb helps you build various packages directly from your project sources.
70Those sources could be handled by a CMS (Configuration Management System)
71such as Subversion, CVS, Git, Mercurial... or being a simple reference to a compressed tar file.
72It's based on a set of configuration files, a set of provided macros to help
73you keeping build files as generic as possible. For example, a single .spec
74file should be required to generate for all rpm based distributions, even
75if you could also have multiple .spec files if required.
76
77=head1 SYNOPSIS
78
79pb [-vhSq][-r pbroot][-p project][[-s script -a account -P port][-m mach-1[,...]]][-i iso] <action> [<pkg1> ...]
80
81pb [--verbose][--help][--man][--quiet][--snapshot][--revision pbroot][--project project][[--script script --account account --port port][--machine mach-1[,...]]][--iso iso] <action> [<pkg1> ...]
82
83=head1 OPTIONS
84
85=over 4
86
87=item B<-v|--verbose>
88
89Print a brief help message and exits.
90
91=item B<-q|--quiet>
92
93Do not print any output.
94
95=item B<-h|--help>
96
97Print a brief help message and exits.
98
99=item B<-S|--snapshot>
100
101Use the snapshot mode of VMs or VEs
102
103=item B<--man>
104
105Prints the manual page and exits.
106
107=item B<-m|--machine machine1[,machine2,...]>
108
109Name of the Virtual Machines (VM) or Virtual Environments (VE) you want to build on (coma separated).
110All if none precised (or use the env variable PBV).
111
112=item B<-s|--script script>
113
114Name of the script you want to execute on the related VMs or VEs.
115
116=item B<-i|--iso iso_image>
117
118Name of the ISO image of the distribution you want to install on the related VMs.
119
120=item B<-a|--account account>
121
122Name of the account to use to connect on the related VMs.
123
124=item B<-P|--port port_number>
125
126Port number to use to connect on the related VMs.\n";
127
128=item B<-p|--project project_name>
129
130Name of the project you're working on (or use the env variable PBPROJ)
131
132=item B<-r|--revision revision>
133
134Path Name of the project revision under the CMS (or use the env variable PBROOT)
135
136=item B<-V|--version new_version>
137
138New version of the project to create based on the current one.
139
140=back
141
142=head1 ARGUMENTS
143
144<action> can be:
145
146=over 4
147
148=item B<sbx2build>
149
150Create tar files for the project under your CMS.
151Current state of the exported content is taken.
152CMS supported are SVN, SVK, CVS, Git and Mercurial
153parameters are packages to build
154if not using default list
155
156=item B<cms2build>
157
158Create tar files for the project under your CMS.
159Current state of the CMS is taken.
160CMS supported are SVN, SVK, CVS, Git and Mercurial
161parameters are packages to build
162if not using default list
163
164=item B<build2pkg>
165
166Create packages for your running distribution
167
168=item B<cms2pkg>
169
170cms2build + build2pkg
171
172=item B<sbx2pkg>
173
174sbx2build + build2pkg
175
176=item B<build2ssh>
177
178Send the tar files to a SSH host
179
180=item B<sbx2ssh>
181
182sbx2build + build2ssh
183
184=item B<cms2ssh>
185
186cms2build + build2ssh
187
188=item B<pkg2ssh>
189
190Send the packages built to a SSH host
191
192=item B<build2vm>
193
194Create packages in VMs, launching them if needed
195and send those packages to a SSH host once built
196VM type supported are QEMU
197
198=item B<build2ve>
199
200Create packages in VEs, creating it if needed
201and send those packages to a SSH host once built
202
203=item B<sbx2vm>
204
205sbx2build + build2vm
206
207=item B<sbx2ve>
208
209sbx2build + build2ve
210
211=item B<cms2vm>
212
213cms2build + build2vm
214
215=item B<cms2ve>
216
217cms2build + build2ve
218
219=item B<launchvm>
220
221Launch one virtual machine
222
223=item B<launchve>
224
225Launch one virtual environment
226
227=item B<script2vm>
228
229Launch one virtual machine if needed
230and executes a script on it
231
232=item B<script2ve>
233
234Execute a script in a virtual environment
235
236=item B<newvm>
237
238Create a new virtual machine
239
240=item B<newve>
241
242Create a new virtual environment
243
244=item B<setupvm>
245
246Setup a virtual machine for pb usage
247
248=item B<setupve>
249
250Setup a virtual environment for pb usage
251
252=item B<snapvm>
253
254Snapshot a virtual machine for pb usage
255
256=item B<snapve>
257
258Snapshot a virtual environment for pb usage
259
260=item B<updatevm>
261
262Update the distribution in the virtual machine
263
264=item B<updateve>
265
266Update the distribution in the virtual environment
267
268=item B<test2pkg>
269
270Test a package locally
271
272=item B<test2vm>
273
274Test a package in a virtual machine
275
276=item B<test2ve>
277
278Test a package in a virtual environment
279
280=item B<newver>
281
282Create a new version of the project derived
283from the current one
284
285=item B<newproj>
286
287Create a new project and a template set of
288configuration files under pbconf
289
290=item B<announce>
291
292Announce the availability of the project through various means
293
294=item B<web2ssh>
295
296Deliver the Web site content to the target server using ssh.
297
298=item B<clean>
299
300Purge the build and delivery directories related to the current project
301
302=back
303
304<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).
305
306=head1 WEB SITES
307
308The 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/>.
309
310=head1 USER MAILING LIST
311
312None exists for the moment.
313
314=head1 CONFIGURATION FILES
315
316Each pb user may have a configuration in F<$HOME/.pbrc>. The values in this file may overwrite any other configuration file value.
317
318Here is an example of such a configuration file:
319
320 #
321 # Define for each project the URL of its pbconf repository
322 # No default option allowed here as they need to be all different
323 #
324 # URL of the pbconf content
325 # This is the format of a classical URL with the extension of additional schema such as
326 # svn+ssh, cvs+ssh, ...
327 #
328 pbconfurl linuxcoe = cvs+ssh://:ext:bcornec@linuxcoe.cvs.sourceforge.net:/cvsroot/linuxcoe/pbconf
329
330 # This is normaly defined in the project's configuration file
331 # Url of the project
332 #
333 pburl linuxcoe = cvs+ssh://:ext:bcornec@linuxcoe.cvs.sourceforge.net:/cvsroot/linuxcoe
334
335 # All these URLs needs to be defined here as the are the entry point
336 # for how to build packages for the project
337 #
338 pbconfurl pb = svn+ssh://svn.project-builder.org/mondo/svn/pb/pbconf
339 pbconfurl mondorescue = svn+ssh://svn.project-builder.org/mondo/svn/project-builder/mondorescue/pbconf
340 pbconfurl collectl = svn+ssh://bruno@svn.mondorescue.org/mondo/svn/project-builder/collectl/pbconf
341 pbconfurl netperf = svn+ssh://svn.mondorescue.org/mondo/svn/project-builder/netperf/pbconf
342
343 # Under that dir will take place everything related to pb
344 # If you want to use VMs/chroot/..., then use $ENV{'HOME'} to make it portable
345 # to your VMs/chroot/...
346 # if not defined then /var/cache
347 pbdefdir default = $ENV{'HOME'}/project-builder
348 pbdefdir pb = $ENV{'HOME'}
349 pbdefdir linuxcoe = $ENV{'HOME'}/LinuxCOE/cvs
350 pbdefdir mondorescue = $ENV{'HOME'}/mondo/svn
351
352 # pbconfdir points to the directory where the CMS content of the pbconfurl is checked out
353 # If not defined, pbconfdir is under pbdefdir/pbproj/pbconf
354 pbconfdir linuxcoe = $ENV{'HOME'}/LinuxCOE/cvs/pbconf
355 pbconfdir mondorescue = $ENV{'HOME'}/mondo/svn/pbconf
356
357 # pbdir points to the directory where the CMS content of the pburl is checked out
358 # If not defined, pbdir is under pbdefdir/pbproj
359 # Only defined if we have access to the dev of the project
360 pbdir linuxcoe = $ENV{'HOME'}/LinuxCOE/cvs
361 pbdir mondorescue = $ENV{'HOME'}/mondo/svn
362
363 # -daemonize doesn't work with qemu 0.8.2
364 vmopt default = -m 384
365
366=head1 AUTHORS
367
368The Project-Builder.org team L<http://trac.project-builder.org/> lead by Bruno Cornec L<mailto:bruno@project-builder.org>.
369
370=head1 COPYRIGHT
371
372Project-Builder.org is distributed under the GPL v2.0 license
373described in the file C<COPYING> included with the distribution.
374
375=cut
376
377# ---------------------------------------------------------------------------
378
379my ($projectbuilderver,$projectbuilderrev) = pb_version_init();
380my $appname = "pb";
381
382# Initialize the syntax string
383
384pb_syntax_init("$appname (aka project-builder.org) Version $projectbuilderver-$projectbuilderrev\n");
385
386GetOptions("help|?|h" => \$opts{'h'},
387 "man" => \$opts{'man'},
388 "verbose|v+" => \$opts{'v'},
389 "snapshot|S" => \$opts{'S'},
390 "quiet|q" => \$opts{'q'},
391 "log-files|l=s" => \$opts{'l'},
392 "force|f" => \$opts{'f'},
393 "account|a=s" => \$opts{'a'},
394 "revision|r=s" => \$opts{'r'},
395 "script|s=s" => \$opts{'s'},
396 "machines|mock|m=s" => \$opts{'m'},
397 "port|P=i" => \$opts{'P'},
398 "project|p=s" => \$opts{'p'},
399 "iso|i=s" => \$opts{'i'},
400 "version|V=s" => \$opts{'V'},
401) || pb_syntax(-1,0);
402
403if (defined $opts{'h'}) {
404 pb_syntax(0,1);
405}
406if (defined $opts{'man'}) {
407 pb_syntax(0,2);
408}
409if (defined $opts{'v'}) {
410 $pbdebug = $opts{'v'};
411}
412if (defined $opts{'f'}) {
413 $pbforce=1;
414}
415if (defined $opts{'q'}) {
416 $pbdebug=-1;
417}
418if (defined $opts{'S'}) {
419 $pbsnap=1;
420}
421if (defined $opts{'l'}) {
422 open(pbLOG,"> $opts{'l'}") || die "Unable to log to $opts{'l'}: $!";
423 $pbLOG = \*pbLOG;
424 $pbdebug = 0 if ($pbdebug == -1);
425 }
426pb_log_init($pbdebug, $pbLOG);
427pb_display_init("text","");
428
429# Handle root of the project if defined
430if (defined $opts{'r'}) {
431 $ENV{'PBROOTDIR'} = $opts{'r'};
432}
433# Handle virtual machines if any
434if (defined $opts{'m'}) {
435 $ENV{'PBV'} = $opts{'m'};
436}
437if (defined $opts{'s'}) {
438 $pbscript = $opts{'s'};
439}
440if (defined $opts{'a'}) {
441 $pbaccount = $opts{'a'};
442 die "option -a requires a -s script option" if (not defined $pbscript);
443}
444if (defined $opts{'P'}) {
445 $pbport = $opts{'P'};
446}
447if (defined $opts{'V'}) {
448 $newver = $opts{'V'};
449}
450if (defined $opts{'i'}) {
451 $iso = $opts{'i'};
452}
453
454# Get Action
455$action = shift @ARGV;
456die pb_syntax(-1,1) if (not defined $action);
457
458my ($filteredfiles, $supfiles, $defpkgdir, $extpkgdir);
459my $pbinit = undef;
460$pbinit = 1 if ($action =~ /^newproj$/);
461
462# Handles project name if any
463# And get global params
464($filteredfiles, $supfiles, $defpkgdir, $extpkgdir) = pb_env_init($opts{'p'},$pbinit,$action);
465
466#
467# Check for command requirements
468#
469my ($req,$opt) = pb_conf_get_if("oscmd","oscmdopt");
470my ($req2,$opt2) = (undef,undef);
471$req2 = $req->{$appname} if (defined $req);
472$opt2 = $opt->{$appname} if (defined $opt);
473pb_check_requirements($req2,$opt2);
474
475pb_log(0,"Project: $ENV{'PBPROJ'}\n");
476pb_log(0,"Action: $action\n");
477
478# Act depending on action
479if ($action =~ /^cms2build$/) {
480 pb_cms2build("CMS");
481} elsif ($action =~ /^sbx2build$/) {
482 pb_cms2build("SandBox");
483} elsif ($action =~ /^build2pkg$/) {
484 pb_build2pkg();
485} elsif ($action =~ /^cms2pkg$/) {
486 pb_cms2build("CMS");
487 pb_build2pkg();
488} elsif ($action =~ /^sbx2pkg$/) {
489 pb_cms2build("SandBox");
490 pb_build2pkg();
491} elsif ($action =~ /^build2ssh$/) {
492 pb_build2ssh();
493} elsif ($action =~ /^cms2ssh$/) {
494 pb_cms2build("CMS");
495 pb_build2ssh();
496} elsif ($action =~ /^sbx2ssh$/) {
497 pb_cms2build("SandBox");
498 pb_build2ssh();
499} elsif ($action =~ /^pkg2ssh$/) {
500 pb_pkg2ssh();
501} elsif ($action =~ /^build2ve$/) {
502 pb_build2v("ve","build");
503} elsif ($action =~ /^build2vm$/) {
504 pb_build2v("vm","build");
505} elsif ($action =~ /^cms2ve$/) {
506 pb_cms2build("CMS");
507 pb_build2v("ve","build");
508} elsif ($action =~ /^sbx2ve$/) {
509 pb_cms2build("SandBox");
510 pb_build2v("ve","build");
511} elsif ($action =~ /^cms2vm$/) {
512 pb_cms2build("CMS");
513 pb_build2v("vm","build");
514} elsif ($action =~ /^sbx2vm$/) {
515 pb_cms2build("SandBox");
516 pb_build2v("vm","build");
517} elsif ($action =~ /^launchvm$/) {
518 pb_launchv("vm",$ENV{'PBV'},0);
519} elsif ($action =~ /^launchve$/) {
520 pb_launchv("ve",$ENV{'PBV'},0);
521} elsif ($action =~ /^script2vm$/) {
522 pb_script2v($pbscript,"vm");
523} elsif ($action =~ /^script2ve$/) {
524 pb_script2v($pbscript,"ve");
525} elsif ($action =~ /^newver$/) {
526 pb_newver();
527} elsif ($action =~ /^newve$/) {
528 pb_launchv("ve",$ENV{'PBV'},1);
529} elsif ($action =~ /^newvm$/) {
530 pb_launchv("vm",$ENV{'PBV'},1);
531 pb_log(0, "Please ensure that sshd is running in your VM by default\n");
532 pb_log(0, "and that it allows remote root login (PermitRootLogin yes in /etc/ssh/sshd_config)\n");
533 pb_log(0, "Also ensure that network is up, firewalling correctly configured\n");
534 pb_log(0, "and perl, sudo, ntpdate and scp/ssh installed\n");
535 pb_log(0, "You should then be able to login with ssh -p VMPORT root\@localhost (if VM started with pb)\n");
536} elsif ($action =~ /^setupve$/) {
537 pb_setup2v("ve");
538} elsif ($action =~ /^setupvm$/) {
539 pb_setup2v("vm");
540} elsif ($action =~ /^updateve$/) {
541 pb_update2v("ve");
542} elsif ($action =~ /^updatevm$/) {
543 pb_update2v("vm");
544} elsif ($action =~ /^snapve$/) {
545 pb_snap2v("ve");
546} elsif ($action =~ /^snapvm$/) {
547 pb_snap2v("vm");
548} elsif ($action =~ /^test2pkg$/) {
549 pb_test2pkg();
550} elsif ($action =~ /^test2ve$/) {
551 pb_build2v("ve","test");
552} elsif ($action =~ /^test2vm$/) {
553 pb_build2v("vm","test");
554} elsif ($action =~ /^newproj$/) {
555 # Nothing to do - already done in pb_env_init
556} elsif ($action =~ /^clean$/) {
557 pb_clean();
558} elsif ($action =~ /^announce$/) {
559 # For announce only. Require avoids the systematic load of these modules
560 require DBI;
561 require DBD::SQLite;
562 require Mail::SendMail;
563
564 pb_announce();
565} elsif ($action =~ /^web2ssh$/) {
566 require DBI;
567 require DBD::SQLite;
568
569 pb_cms2build("Web");
570 pb_send2target("Web");
571} else {
572 pb_log(0,"\'$action\' is not available\n");
573 pb_syntax(-2,1);
574}
575
576sub pb_cms2build {
577
578 my $param = shift || undef;
579
580 my $pkg;
581 my @pkgs;
582 my $webdir;
583
584 my %pkgs;
585 my %pb; # Structure to store conf info
586
587 die "pb_cms2build requires a parameter: Web, SandBox or CMS" if (not defined $param);
588
589 # If Website, then pkg is only the website
590 if ($param eq "Web") {
591 ($webdir) = pb_conf_get("webdir");
592 pb_log(2,"webdir: ".Dumper($webdir)."\n");
593 $pkgs[0] = $webdir->{$ENV{'PBPROJ'}};
594 $extpkgdir = $webdir;
595 pb_log(0,"Package: $pkgs[0]\n");
596 } else {
597 $pkg = pb_cms_get_pkg($defpkgdir,$extpkgdir);
598 @pkgs = @$pkg;
599 }
600
601 my ($scheme, $uri) = pb_cms_init($pbinit,$param);
602
603 # We need 2 lines here
604 my ($pkgv, $pkgt, $testver) = pb_conf_get_if("pkgver","pkgtag","testver");
605 my @pt = pb_conf_get_if("vmlist","velist");
606
607 # declare packager and repo for filtering
608 # TODO: Is pbrepo needed so early in the process ?
609 my ($tmp1, $tmp2) = pb_conf_get("pbpackager","pbrepo");
610 $ENV{'PBPACKAGER'} = $tmp1->{$ENV{'PBPROJ'}};
611 $ENV{'PBREPO'} = $tmp2->{$ENV{'PBPROJ'}};
612
613 foreach my $pbpkg (@pkgs) {
614 $ENV{'PBPKG'} = $pbpkg;
615
616 if ((defined $pkgv) && (defined $pkgv->{$pbpkg})) {
617 $pbver = $pkgv->{$pbpkg};
618 } else {
619 $pbver = $ENV{'PBPROJVER'};
620 }
621 # If it's a test version, then tag == 0.date
622 if ((defined $testver) && (defined $testver->{$ENV{'PBPROJ'}}) && ($testver->{$ENV{'PBPROJ'}} =~ /true/i)) {
623 $pbtag = "0.".strftime("%Y%m%d%H%M%S", @date);
624 $ENV{'PBPROJTAG'} = $pbtag;
625 } elsif ((defined $pkgt) && (defined $pkgt->{$pbpkg})) {
626 $pbtag = $pkgt->{$pbpkg};
627 } else {
628 $pbtag = $ENV{'PBPROJTAG'};
629 }
630
631 $pbrev = $ENV{'PBREVISION'};
632 pb_log(0,"\n");
633 pb_log(0,"Management of $pbpkg $pbver-$pbtag (rev $pbrev)\n");
634 die "Unable to get env var PBDESTDIR" if (not defined $ENV{'PBDESTDIR'});
635
636 # Clean up dest if necessary. The export will recreate it
637 my $dest = "$ENV{'PBDESTDIR'}/$pbpkg-$pbver";
638 pb_rm_rf($dest) if (-d $dest);
639
640 # Export CMS tree for the concerned package to dest
641 # And generate some additional files
642 $OUTPUT_AUTOFLUSH=1;
643
644 # computes in which dir we have to work
645 my $dir = $defpkgdir->{$pbpkg};
646 $dir = $extpkgdir->{$pbpkg} if (not defined $dir);
647 $dir = $webdir->{$ENV{'PBPROJ'}} if ($param eq "Web");
648 pb_log(2,"def:".Dumper($defpkgdir)." ext: ".Dumper($extpkgdir)." \n");
649
650 # Exporting content from CMS
651 my $sourcedir = undef;
652 my $sourceuri = $uri;
653 if ($param eq "SandBox") {
654 # Point to the local instance
655 $sourcedir = "$ENV{'PBDIR'}/$dir";
656 } else {
657 # Get it from a subdir of the URI with same version as localy but different root
658 $sourceuri = "$ENV{'PBDIR'}/$dir";
659 $sourceuri =~ s|^$ENV{'PBPROJDIR'}/|$uri|;
660 }
661 my $preserve = pb_cms_export($sourceuri,$sourcedir,$dest);
662
663 # Generated fake content for test versions to speed up stuff
664 my $chglog;
665
666 # Get project info on authors and log file
667 $chglog = "$ENV{'PBROOTDIR'}/$pbpkg/pbcl";
668 $chglog = "$ENV{'PBROOTDIR'}/pbcl" if (! -f $chglog);
669 $chglog = undef if (! -f $chglog);
670
671 my $authors = "$ENV{'PBROOTDIR'}/$pbpkg/pbauthors";
672 $authors = "$ENV{'PBROOTDIR'}/pbauthors" if (! -f $authors);
673 $authors = "/dev/null" if (! -f $authors);
674
675 # Extract cms log history and store it
676 if ((defined $chglog) && (! -f "$dest/NEWS")) {
677 pb_log(2,"Generating NEWS file from $chglog\n");
678 copy($chglog,"$dest/NEWS") || die "Unable to create $dest/NEWS";
679 }
680 pb_cms_log($scheme,"$ENV{'PBDIR'}/$dir",$dest,$chglog,$authors,$testver);
681
682 my %build;
683 # We want to at least build for the underlying distro
684 my ($ddir, $dver, $dfam, $dtype, $dos, $pbsuf, $pbupd, $pbins, $arch) = pb_distro_init();
685 my $tmpl = "$ddir-$dver-$arch,";
686 my %patches;
687
688 # Get list of distributions for which we need to generate build files
689 if (defined $pt[0]->{$ENV{'PBPROJ'}}) {
690 $tmpl .= $pt[0]->{$ENV{'PBPROJ'}};
691 }
692 if (defined $pt[1]->{$ENV{'PBPROJ'}}) {
693 # The 2 lists needs to be grouped with a ',' separating them
694 if ($tmpl ne "") {
695 $tmpl .= ",";
696 }
697 $tmpl .= $pt[1]->{$ENV{'PBPROJ'}}
698 }
699
700 # Setup %pb structure to allow filtering later on, on files using that structure
701 $pb{'tag'} = $pbtag;
702 $pb{'rev'} = $pbrev;
703 $pb{'ver'} = $pbver;
704 $pb{'pkg'} = $pbpkg;
705 $pb{'date'} = $pbdate;
706 $pb{'defpkgdir'} = $defpkgdir;
707 $pb{'extpkgdir'} = $extpkgdir;
708 $pb{'chglog'} = $chglog;
709 $pb{'packager'} = $ENV{'PBPACKAGER'};
710 $pb{'proj'} = $ENV{'PBPROJ'};
711 $pb{'repo'} = $ENV{'PBREPO'};
712 $pb{'patches'} = \%patches;
713 pb_log(2,"DEBUG: pb: ".Dumper(%pb)."\n");
714
715 # Do not do that for website
716 if ($param ne "Web") {
717 pb_log(0,"Build files are being generated for ...\n");
718 my %virt;
719 # De-duplicate similar VM and VE
720 foreach my $d (split(/,/,$tmpl)) {
721 # skip ill-formatted vms (name-ver-arch)
722 next if ($d !~ /-/);
723 $virt{$d} = $d;
724 }
725
726 foreach my $d (keys %virt) {
727 my ($name,$ver,$arch) = split(/-/,$d);
728 pb_log(0,"Bad format for $d") if ((not defined $name) || (not defined $ver) || (not defined $arch)) ;
729 chomp($arch);
730 my ($ddir, $dver, $dfam);
731 ($ddir, $dver, $dfam, $pb{'dtype'}, $pb{'os'}, $pb{'suf'}, $pb{'upd'}, $pb{'arch'}) = pb_distro_init($name,$ver,$arch);
732 pb_log(2,"DEBUG: distro tuple: ".Dumper($ddir, $dver, $dfam, $pb{'dtype'}, $pb{'suf'})."\n");
733 pb_log(2,"DEBUG Filtering PBDATE => $pbdate, PBTAG => $pbtag, PBVER => $pbver\n");
734
735 # We need to compute the real name of the package
736 my $pbrealpkg = pb_cms_get_real_pkg($pbpkg,$pb{'dtype'});
737 $pb{'realpkg'} = $pbrealpkg;
738 pb_log(1,"Virtual package $pbpkg has a real package name of $pbrealpkg on $ddir-$dver\n") if ($pbrealpkg ne $pbpkg);
739
740 # Filter build files from the less precise up to the most with overloading
741 # Filter all files found, keeping the name, and generating in dest
742
743 # Find all build files first relatively to PBROOTDIR
744 # Find also all specific files referenced in the .pb conf file
745 my %bfiles = ();
746 my %pkgfiles = ();
747 $build{"$ddir-$dver-$arch"} = "yes";
748
749 if (-d "$ENV{'PBROOTDIR'}/$pbpkg/$pb{'dtype'}") {
750 pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$pb{'dtype'}",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
751 } elsif (-d "$ENV{'PBROOTDIR'}/$pbpkg/$dfam") {
752 pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$dfam",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
753 } elsif (-d "$ENV{'PBROOTDIR'}/$pbpkg/$ddir") {
754 pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$ddir",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
755 } elsif (-d "$ENV{'PBROOTDIR'}/$pbpkg/$ddir-$dver") {
756 pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$ddir-$dver",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
757 } elsif (-d "$ENV{'PBROOTDIR'}/$pbpkg/$ddir-$dver-$arch") {
758 pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$ddir-$dver-$arch",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
759 } else {
760 $build{"$ddir-$dver-$arch"} = "no";
761 next;
762 }
763 pb_log(2,"DEBUG bfiles: ".Dumper(\%bfiles)."\n");
764
765 # Get all filters to apply
766 my $ptr = pb_get_filters($pbpkg, $pb{'dtype'}, $dfam, $ddir, $dver);
767
768 # Prepare local patches for this distro - They are always applied first - May be a problem one day
769 foreach my $p (sort(<$ENV{'PBROOTDIR'}/$pbpkg/pbpatch/*>)) {
770 $patches{"$ddir-$dver-$arch"} .= "," if ((defined $patches{"$ddir-$dver-$arch"}) and ($p =~ /\.all$/));
771 $patches{"$ddir-$dver-$arch"} .= "file://$p" if ($p =~ /\.all$/);
772 $patches{"$ddir-$dver-$arch"} .= "," if ((defined $patches{"$ddir-$dver-$arch"}) and ($p =~ /\.$pb{'dtype'}$/));
773 $patches{"$ddir-$dver-$arch"} .= "file://$p" if ($p =~ /\.$pb{'dtype'}$/);
774 $patches{"$ddir-$dver-$arch"} .= "," if ((defined $patches{"$ddir-$dver-$arch"}) and ($p =~ /\.$dfam$/));
775 $patches{"$ddir-$dver-$arch"} .= "file://$p" if ($p =~ /\.$dfam$/);
776 $patches{"$ddir-$dver-$arch"} .= "," if ((defined $patches{"$ddir-$dver-$arch"}) and ($p =~ /\.$ddir$/));
777 $patches{"$ddir-$dver-$arch"} .= "file://$p" if ($p =~ /\.$ddir$/);
778 $patches{"$ddir-$dver-$arch"} .= "," if ((defined $patches{"$ddir-$dver-$arch"}) and ($p =~ /\.$ddir-$dver$/));
779 $patches{"$ddir-$dver-$arch"} .= "file://$p" if ($p =~ /\.$ddir-$dver$/);
780 $patches{"$ddir-$dver-$arch"} .= "," if ((defined $patches{"$ddir-$dver-$arch"}) and ($p =~ /\.$ddir-$dver-$arch$/));
781 $patches{"$ddir-$dver-$arch"} .= "file://$p" if ($p =~ /\.$ddir-$dver-$arch$/);
782 }
783
784 # Prepare also remote patches to be included - Applied after the local ones
785 foreach my $p ("all","$pb{'dtype'}","$dfam","$ddir","$ddir-$dver","$ddir-$dver-$arch") {
786 my $f = "$ENV{'PBROOTDIR'}/$pbpkg/pbextpatch.$p";
787 next if (not -f $f);
788 if (not open(PATCH,$f)) {
789 pb_display("Unable to open existing external patch file content $f\n");
790 next;
791 }
792 while (<PATCH>) {
793 chomp();
794 $patches{"$ddir-$dver-$arch"} .= "," if (defined $patches{"$ddir-$dver-$arch"});
795 $patches{"$ddir-$dver-$arch"} .= "$_";
796 }
797 close(PATCH);
798 }
799 pb_log(2,"DEBUG: pb->patches: ".Dumper($pb{'patches'})."\n");
800
801 # Apply now all the filters on all the files concerned
802 # destination dir depends on the type of file
803 if (defined $ptr) {
804 # For patch support
805 $pb{'tuple'} = "$ddir-$dver-$arch";
806 foreach my $f (values %bfiles,values %pkgfiles) {
807 pb_filter_file("$ENV{'PBROOTDIR'}/$f",$ptr,"$dest/pbconf/$ddir-$dver-$arch/".basename($f),\%pb);
808 }
809 }
810 }
811 my @found;
812 my @notfound;
813 foreach my $b (keys %build) {
814 push @found,$b if ($build{$b} =~ /yes/);
815 push @notfound,$b if ($build{$b} =~ /no/);
816 }
817 pb_log(0," ... ".join(',',sort(@found))."\n");
818 pb_log(0,"No Build files found for ".join(',',sort(@notfound))."\n") if (@notfound);
819 pb_log(2,"DEBUG: patches: ".Dumper(%patches)."\n");
820 }
821
822 # Get the generic filter (all.pbf) and
823 # apply those to the non-build files including those
824 # generated by pbinit if applicable
825
826 # Get only all.pbf filter
827 my $ptr = pb_get_filters($pbpkg);
828
829 my $liste ="";
830 if (defined $filteredfiles->{$pbpkg}) {
831 foreach my $f (split(/,/,$filteredfiles->{$pbpkg})) {
832 pb_filter_file_inplace($ptr,"$dest/$f",\%pb);
833 $liste = "$f $liste";
834 }
835 }
836 pb_log(2,"Files ".$liste."have been filtered\n");
837
838 # Do not do that for website
839 if ($param ne "Web") {
840 my %tmp;
841 my $warnflag = 0;
842 # Filter potential patches (local + remote)
843 pb_log(0,"Delivering and compressing patches ");
844 foreach my $v (keys %patches) {
845 pb_mkdir_p("$dest/pbconf/$v/pbpatch");
846 foreach my $pf (split(/,/,$patches{$v})) {
847 my $pp = basename($pf);
848 if ($param eq "SandBox") {
849 $warnflag = 1;
850 }
851 pb_cms_export($pf,undef,"$dest/pbconf/$v/pbpatch");
852 pb_filter_file_inplace($ptr,"$dest/pbconf/$v/pbpatch/$pp",\%pb);
853 pb_system("gzip -9f $dest/pbconf/$v/pbpatch/$pp","","quiet");
854 $tmp{$pf} = "";
855 }
856 }
857 foreach my $v (keys %tmp) {
858 pb_log(0,"$v ");
859 }
860 pb_log(0,"\n");
861 pb_log(0,"WARNING: Patches are always taken from repository not local export\n") if ($warnflag == 1);
862 } else {
863 # Instead call News generation
864 pb_web_news2html($dest);
865 # And create an empty pbconf
866 pb_mkdir_p("$dest/pbconf");
867 # And prepare the pbscript to execute remotely
868 open(SCRIPT,"> $ENV{'PBDESTDIR'}/pbscript") || die "Unable to create $ENV{'PBDESTDIR'}/pbscript";
869 print SCRIPT "#!/bin/bash\n";
870 print SCRIPT "#set -x\n";
871 print SCRIPT "echo ... Extracting Website content\n";
872 print SCRIPT "find . -type f | grep -Ev '^./$pbpkg-$pbver.tar.gz|^./pbscript' | xargs rm -f non-existent\n";
873 print SCRIPT "find * -type d -depth | xargs rmdir 2> /dev/null \n";
874 print SCRIPT "tar xfz $pbpkg-$pbver.tar.gz\n";
875 print SCRIPT "mv $pbpkg-$pbver/* .\n";
876 print SCRIPT "rm -f $pbpkg-$pbver.tar.gz\n";
877 print SCRIPT "rmdir $pbpkg-$pbver\n";
878 close(SCRIPT);
879 }
880
881 # Prepare the dest directory for archive
882 if (-x "$ENV{'PBROOTDIR'}/$pbpkg/pbinit") {
883 pb_filter_file("$ENV{'PBROOTDIR'}/$pbpkg/pbinit",$ptr,"$ENV{'PBTMP'}/pbinit",\%pb);
884 chmod 0755,"$ENV{'PBTMP'}/pbinit";
885 pb_system("cd $dest ; $ENV{'PBTMP'}/pbinit","Executing init script from $ENV{'PBROOTDIR'}/$pbpkg/pbinit","verbose");
886 }
887
888 # Do we have additional script to run to prepare the environement for the project ?
889 # Then include it in the pbconf delivery
890 foreach my $pbvf (<$ENV{'PBROOTDIR'}/pbv*.pre>,<$ENV{'PBROOTDIR'}/pbv*.post>, <$ENV{'PBROOTDIR'}/pbtest*>) {
891 if (-x "$pbvf") {
892 my $target = "$ENV{'PBDESTDIR'}/".basename($pbvf);
893 pb_filter_file("$pbvf",$ptr,$target,\%pb);
894 chmod 0755,"$target";
895 }
896 }
897
898 # Archive dest dir
899 chdir "$ENV{'PBDESTDIR'}" || die "Unable to change dir to $ENV{'PBDESTDIR'}";
900 if (defined $preserve) {
901 # In that case we want to preserve the original tar file for checksum purposes
902 # The one created is btw equivalent in that case to this one
903 # Maybe check basename of both to be sure they are the same ?
904 pb_log(0,"Preserving original tar file ");
905 move("$preserve","$pbpkg-$pbver.tar.gz");
906 } else {
907 # Possibility to look at PBSRC to guess more the filename
908 pb_system("tar cfz $pbpkg-$pbver.tar.gz --exclude=$pbpkg-$pbver/pbconf $pbpkg-$pbver","Creating $pbpkg tar files compressed");
909 }
910 pb_log(0,"Under $ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz\n");
911 pb_system("tar cfz $pbpkg-$pbver.pbconf.tar.gz $pbpkg-$pbver/pbconf","Creating pbconf tar files compressed");
912 pb_log(0,"Under $ENV{'PBDESTDIR'}/$pbpkg-$pbver.pbconf.tar.gz\n");
913
914 # Keep track of version-tag per pkg
915 $pkgs{$pbpkg} = "$pbver-$pbtag";
916
917 # Final cleanup
918 pb_rm_rf($dest) if (-d $dest);
919 }
920
921 # Keep track of per package version
922 pb_log(2,"DEBUG pkgs: ".Dumper(%pkgs)."\n");
923 open(PKG,"> $ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb") || die "Unable to create $ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb";
924 foreach my $pbpkg (keys %pkgs) {
925 print PKG "pbpkg $pbpkg = $pkgs{$pbpkg}\n";
926 }
927 close(PKG);
928
929 # Keep track of what is generated by default
930 # We need to store the dir and info on version-tag
931 # Base our content on the existing .pb file
932 copy("$ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb","$ENV{'PBDESTDIR'}/pbrc");
933 open(LAST,">> $ENV{'PBDESTDIR'}/pbrc") || die "Unable to create $ENV{'PBDESTDIR'}/pbrc";
934 print LAST "pbroot $ENV{'PBPROJ'} = $ENV{'PBROOTDIR'}\n";
935 print LAST "projver $ENV{'PBPROJ'} = $ENV{'PBPROJVER'}\n";
936 print LAST "projtag $ENV{'PBPROJ'} = $ENV{'PBPROJTAG'}\n";
937 print LAST "pbpackager $ENV{'PBPROJ'} = $ENV{'PBPACKAGER'}\n";
938 close(LAST);
939}
940
941sub pb_test2pkg {
942 # Get the running distro to test on
943 my ($ddir, $dver, $dfam, $dtype, $dos, $pbsuf, $pbupd, $pbins, $arch) = pb_distro_init();
944 pb_log(2,"DEBUG: distro tuple: ".join(',',($ddir, $dver, $dfam, $dtype, $pbsuf, $pbupd, $pbins, $arch))."\n");
945
946 # Get list of packages to test
947 # Get content saved in cms2build
948 my $ptr = pb_get_pkg();
949 @pkgs = @$ptr;
950
951 # Additional potential repo
952 pb_distro_setuprepo($ddir,$dver,$arch,$dtype);
953 foreach my $pbpkg (@pkgs) {
954 # We need to install the package to test, and deps brought with it
955 pb_distro_installdeps(undef,$dtype,$pbins,$pbpkg);
956 pb_system("$ENV{'PBDESTDIR'}/pbtest","Launching test for $pbpkg","verbose");
957 }
958}
959
960sub pb_build2pkg {
961
962 # Get the running distro to build on
963 my ($ddir, $dver, $dfam, $dtype, $dos, $pbsuf, $pbupd, $pbins, $arch) = pb_distro_init();
964 pb_log(2,"DEBUG: distro tuple: ".join(',',($ddir, $dver, $dfam, $dtype, $pbsuf, $pbupd, $pbins, $arch))."\n");
965
966 # Get list of packages to build
967 my $ptr = pb_get_pkg();
968 @pkgs = @$ptr;
969
970 # Get content saved in cms2build
971 my ($pkg) = pb_conf_read("$ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb","pbpkg");
972 $pkg = { } if (not defined $pkg);
973
974 chdir "$ENV{'PBBUILDDIR'}";
975 my $made = ""; # pkgs made during build
976 foreach my $pbpkg (@pkgs) {
977 my $vertag = $pkg->{$pbpkg};
978 # get the version of the current package - maybe different
979 ($pbver,$pbtag) = split(/-/,$vertag);
980
981 my $src="$ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz";
982 my $src2="$ENV{'PBDESTDIR'}/$pbpkg-$pbver.pbconf.tar.gz";
983 pb_log(2,"Source file: $src\n");
984 pb_log(2,"Pbconf file: $src2\n");
985
986 pb_log(2,"Working directory: $ENV{'PBBUILDDIR'}\n");
987 if ($dtype eq "rpm") {
988 foreach my $d ('RPMS','SRPMS','SPECS','SOURCES','BUILD') {
989 if (! -d "$ENV{'PBBUILDDIR'}/$d") {
990 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";
991 }
992 }
993
994 # Remove in case a previous link/file was there
995 unlink "$ENV{'PBBUILDDIR'}/SOURCES/".basename($src);
996 symlink "$src","$ENV{'PBBUILDDIR'}/SOURCES/".basename($src) || die "Unable to symlink $src in $ENV{'PBBUILDDIR'}/SOURCES";
997 # We need to first extract the spec file
998 my @specfile = pb_extract_build_files($src2,"$pbpkg-$pbver/pbconf/$ddir-$dver-$arch/","$ENV{'PBBUILDDIR'}/SPECS","spec");
999
1000 # We need to handle potential patches to upstream sources
1001 pb_extract_build_files($src2,"$pbpkg-$pbver/pbconf/$ddir-$dver-$arch/pbpatch/","$ENV{'PBBUILDDIR'}/SOURCES","patch");
1002
1003 pb_log(2,"specfile: ".Dumper(\@specfile)."\n");
1004 # set LANGUAGE to check for correct log messages
1005 $ENV{'LANGUAGE'}="C";
1006 # Older Redhat use _target_platform in %configure incorrectly
1007 my $specialdef = "";
1008 if (($ddir eq "redhat") || (($ddir eq "rhel") && ($dver eq "2.1"))) {
1009 $specialdef = "--define \'_target_platform \"\"\'";
1010 }
1011
1012 # If needed we may add repository to the build env
1013 pb_distro_setuprepo($ddir,$dver,$arch,$dtype);
1014 foreach my $f (@specfile) {
1015 if ($f =~ /\.spec$/) {
1016 pb_distro_installdeps($f,$dtype,$pbins);
1017 pb_system("rpmbuild $specialdef --define \"packager $ENV{'PBPACKAGER'}\" --define \"_topdir $ENV{'PBBUILDDIR'}\" -ba $f","Building package with $f under $ENV{'PBBUILDDIR'}","verbose");
1018 last;
1019 }
1020 }
1021 # Get the name of the generated packages
1022 open(LOG,"$ENV{'PBTMP'}/system.log") || die "Unable to open $ENV{'PBTMP'}/system.log";
1023 while (<LOG>) {
1024 chomp($_);
1025 next if ($_ !~ /^Wrote:/);
1026 s|.*/([S]*RPMS.*)|$1|;
1027 $made .=" $_";
1028 }
1029 close(LOG);
1030
1031 } elsif ($dtype eq "deb") {
1032 chdir "$ENV{'PBBUILDDIR'}" || die "Unable to chdir to $ENV{'PBBUILDDIR'}";
1033 pb_system("tar xfz $src","Extracting sources");
1034 pb_system("tar xfz $src2","Extracting pbconf");
1035
1036 chdir "$pbpkg-$pbver" || die "Unable to chdir to $pbpkg-$pbver";
1037 pb_rm_rf("debian");
1038 symlink "pbconf/$ddir-$dver-$arch","debian" || die "Unable to symlink to pbconf/$ddir-$dver-$arch";
1039 chmod 0755,"debian/rules";
1040
1041 pb_distro_setuprepo($ddir,$dver,$arch,$dtype);
1042 pb_distro_installdeps("debian/control",$dtype,$pbins);
1043 pb_system("dpkg-buildpackage -us -uc -rfakeroot","Building package","verbose");
1044 # Get the name of the generated packages
1045 open(LOG,"$ENV{'PBTMP'}/system.log") || die "Unable to open $ENV{'PBTMP'}/system.log";
1046 while (<LOG>) {
1047 chomp();
1048 my $tmp = $_;
1049 next if ($tmp !~ /^dpkg-deb.*:/);
1050 $tmp =~ s|.*../(.*)_(.*).deb.*|$1|;
1051 $made="$made $tmp.dsc $tmp.tar.gz $tmp"."_*.deb $tmp"."_*.changes";
1052 }
1053 close(LOG);
1054 } elsif ($dtype eq "ebuild") {
1055 my @ebuildfile;
1056 # For gentoo we need to take pb as subsystem name
1057 # We put every apps here under sys-apps. hope it's correct
1058 # We use pb's home dir in order to have a single OVERLAY line
1059 my $tmpd = "$ENV{'HOME'}/portage/pb/sys-apps/$pbpkg";
1060 pb_mkdir_p($tmpd) if (! -d "$tmpd");
1061 pb_mkdir_p("$ENV{'HOME'}/portage/distfiles") if (! -d "$ENV{'HOME'}/portage/distfiles");
1062
1063 # We need to first extract the ebuild file
1064 @ebuildfile = pb_extract_build_files($src2,"$pbpkg-$pbver/pbconf/$ddir-$dver-$arch/","$tmpd","ebuild");
1065
1066 # Prepare the build env for gentoo
1067 my $found = 0;
1068 my $pbbd = $ENV{'HOME'};
1069 $pbbd =~ s|/|\\/|g;
1070 if (-r "/etc/make.conf") {
1071 open(MAKE,"/etc/make.conf");
1072 while (<MAKE>) {
1073 $found = 1 if (/$pbbd\/portage/);
1074 }
1075 close(MAKE);
1076 }
1077 if ($found == 0) {
1078 pb_system("sudo sh -c 'echo PORTDIR_OVERLAY=\"$ENV{'HOME'}/portage\" >> /etc/make.conf'");
1079 }
1080 #$found = 0;
1081 #if (-r "/etc/portage/package.keywords") {
1082 #open(KEYW,"/etc/portage/package.keywords");
1083 #while (<KEYW>) {
1084 #$found = 1 if (/portage\/pb/);
1085 #}
1086 #close(KEYW);
1087 #}
1088 #if ($found == 0) {
1089 #pb_system("sudo sh -c \"echo portage/pb >> /etc/portage/package.keywords\"");
1090 #}
1091
1092 # Build
1093 foreach my $f (@ebuildfile) {
1094 if ($f =~ /\.ebuild$/) {
1095 pb_distro_installdeps($f,$dtype,$pbins);
1096 move($f,"$tmpd/$pbpkg-$pbver.ebuild");
1097 pb_system("cd $tmpd ; ebuild $pbpkg-$pbver.ebuild clean ; ebuild $pbpkg-$pbver.ebuild digest ; ebuild $pbpkg-$pbver.ebuild package","verbose");
1098 # Now move it where pb expects it
1099 pb_mkdir_p("$ENV{'PBBUILDDIR'}/portage/pb/sys-apps/$pbpkg");
1100 move("$tmpd/$pbpkg-$pbver.ebuild","$ENV{'PBBUILDDIR'}/portage/pb/sys-apps/$pbpkg/$pbpkg-$pbver-r$pbtag.ebuild");
1101 }
1102 }
1103
1104 $made="$made portage/pb/sys-apps/$pbpkg/$pbpkg-$pbver-r$pbtag.ebuild";
1105 } elsif ($dtype eq "tgz") {
1106 # Slackware family
1107 $made="$made $pbpkg/$pbpkg-$pbver-*-$pbtag.tgz";
1108
1109 chdir "$ENV{'PBBUILDDIR'}" || die "Unable to chdir to $ENV{'PBBUILDDIR'}";
1110 pb_system("tar xfz $src","Extracting sources");
1111 pb_system("tar xfz $src2","Extracting pbconf");
1112 chdir "$pbpkg-$pbver" || die "Unable to chdir to $pbpkg-$pbver";
1113 symlink "pbconf/$ddir-$dver-$arch","install" || die "Unable to symlink to pbconf/$ddir-$dver-$arch";
1114 if (-x "install/pbslack") {
1115 pb_distro_installdeps("./install/pbslack",$dtype,$pbins);
1116 pb_system("./install/pbslack","Building software");
1117 pb_system("sudo /sbin/makepkg -p -l y -c y $pbpkg","Packaging $pbpkg","verbose");
1118 }
1119 } elsif ($dtype eq "pkg") {
1120 # Solaris
1121 $made="$made $pbpkg-$pbver-$pbtag.pkg.gz";
1122 my $pkgdestdir="$ENV{'PBBUILDDIR'}/install";
1123
1124 chdir "$ENV{'PBBUILDDIR'}" || die "Unable to chdir to $ENV{'PBBUILDDIR'}";
1125 # Will host resulting packages
1126 pb_mkdir_p("$dtype");
1127 pb_mkdir_p("$pkgdestdir/delivery");
1128 pb_system("tar xfz $src","Extracting sources under $ENV{'PBBUILDDIR'}");
1129 pb_system("tar xfz $src2","Extracting pbconf under $ENV{'PBBUILDDIR'}");
1130 chdir "$pbpkg-$pbver" || die "Unable to chdir to $pbpkg-$pbver";
1131 if (-f "pbconf/$ddir-$dver-$arch/pbbuild") {
1132 chmod 0755,"pbconf/$ddir-$dver-$arch/pbbuild";
1133 # pkginfo file is mandatory
1134 die "Unable to find pkginfo file in pbconf/$ddir-$dver-$arch" if (! -f "pbconf/$ddir-$dver-$arch/pkginfo");
1135 # Build
1136 pb_system("pbconf/$ddir-$dver-$arch/pbbuild $pkgdestdir/delivery","Building software and installing under $pkgdestdir/delivery");
1137 # Copy complementary files
1138 if (-f "pbconf/$ddir-$dver-$arch/prototype") {
1139 copy("pbconf/$ddir-$dver-$arch/prototype", $pkgdestdir)
1140 } else {
1141 # No prototype provided, calculating it
1142 open(PROTO,"> $pkgdestdir/prototype") || die "Unable to create prototype file";
1143 print PROTO "i pkginfo\n";
1144 print PROTO "i depend\n" if (-f "pbconf/$ddir-$dver-$arch/depend");
1145 $ENV{'PBSOLDESTDIR'} = "$pkgdestdir/delivery";
1146 find(\&create_solaris_prototype, "$pkgdestdir/delivery");
1147 }
1148 copy("pbconf/$ddir-$dver-$arch/depend", $pkgdestdir) if (-f "pbconf/$ddir-$dver-$arch/depend");
1149 copy("pbconf/$ddir-$dver-$arch/pkginfo", $pkgdestdir);
1150 pb_system("cd $pkgdestdir/delivery ; pkgmk -o -f ../prototype -r $pkgdestdir/delivery -d $ENV{'PBBUILDDIR'}/$dtype","Packaging $pbpkg","verbose");
1151 pb_system("cd $ENV{'PBBUILDDIR'}/$dtype ; echo \"\" | pkgtrans -o -n -s $ENV{'PBBUILDDIR'}/$dtype $ENV{'PBBUILDDIR'}/$pbpkg-$pbver-$pbtag.pkg all","Transforming $pbpkg","verbose");
1152 pb_system("cd $ENV{'PBBUILDDIR'} ; gzip -9f $pbpkg-$pbver-$pbtag.pkg","Compressing $pbpkg-$pbver-$pbtag.pkg","verbose");
1153 } else {
1154 pb_log(0,"No pbconf/$ddir-$dver-$arch/pbbuild file found for $pbpkg-$pbver in \n");
1155 }
1156 chdir ".." || die "Unable to chdir to parent dir";
1157 pb_system("rm -rf $pbpkg-$pbver $ENV{'PBBUILDDIR'}/$dtype $pkgdestdir", "Cleanup");
1158 } else {
1159 die "Unknown dtype format $dtype";
1160 }
1161 }
1162 # Find the appropriate check cmd/opts
1163 my ($oschkcmd,$oschkopt) = pb_conf_get_if("oschkcmd","oschkopt");
1164 my $chkcmd .= pb_distro_get_param($ddir,$dver,$arch,$oschkcmd,$dtype,$dfam,$dos);
1165 my $chkopt .= pb_distro_get_param($ddir,$dver,$arch,$oschkopt,$dtype,$dfam,$dos);
1166
1167 # Packages check if needed
1168 if ($dtype eq "rpm") {
1169 if (-x $chkcmd) {
1170 pb_system("$chkcmd $chkopt $made","Checking validity of rpms with $chkcmd","verbose");
1171 }
1172 my $rpms ="";
1173 my $srpms ="";
1174 foreach my $f (split(/ /,$made)) {
1175 $rpms .= "$ENV{'PBBUILDDIR'}/$f " if ($f =~ /^RPMS\//);
1176 $srpms .= "$ENV{'PBBUILDDIR'}/$f " if ($f =~ /^SRPMS\//);
1177 }
1178 pb_log(0,"SRPM packages generated: $srpms\n");
1179 pb_log(0,"RPM packages generated: $rpms\n");
1180 } elsif ($dtype eq "deb") {
1181 my $made2 = "";
1182 foreach my $f (split(/ /,$made)) {
1183 $made2 .= "../$f " if ($f =~ /\.changes$/);
1184 }
1185 if (-x $chkcmd) {
1186 pb_system("$chkcmd $chkopt $made2","Checking validity of debs with $chkcmd","verbose");
1187 } else {
1188 pb_log(0,"deb packages generated: $made2\n");
1189 }
1190 } else {
1191 pb_log(0,"No check done for $dtype yet\n");
1192 pb_log(0,"Packages generated: $made\n");
1193 }
1194
1195 # Keep track of what is generated so that we can get them back from VMs
1196 open(KEEP,"> $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}") || die "Unable to create $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}";
1197 print KEEP "$made\n";
1198 close(KEEP);
1199}
1200
1201sub create_solaris_prototype {
1202
1203 my $uidgid = "bin bin";
1204 my $pkgdestdir = $ENV{'PBSOLDESTDIR'};
1205
1206 return if ($_ =~ /^$pkgdestdir$/);
1207 if (-d $_) {
1208 my $n = $File::Find::name;
1209 $n =~ s~$pkgdestdir/~~;
1210 print PROTO "d none $n 0755 $uidgid\n";
1211 } elsif (-x $_) {
1212 my $n = $File::Find::name;
1213 $n =~ s~$pkgdestdir/~~;
1214 print PROTO "f none $n 0755 $uidgid\n";
1215 } elsif (-f $_) {
1216 my $n = $File::Find::name;
1217 $n =~ s~$pkgdestdir/~~;
1218 print PROTO "f none $n 0644 $uidgid\n";
1219 }
1220}
1221
1222sub pb_build2ssh {
1223 pb_send2target("Sources");
1224}
1225
1226sub pb_pkg2ssh {
1227 pb_send2target("Packages");
1228}
1229
1230# By default deliver to the the public site hosting the
1231# ftp structure (or whatever) or a VM/VE
1232sub pb_send2target {
1233
1234 my $cmt = shift;
1235 my $v = shift || undef;
1236 my $vmexist = shift || 0; # 0 is FALSE
1237 my $vmpid = shift || 0; # 0 is FALSE
1238 my $snapme = shift || 0; # 0 is FALSE
1239
1240 pb_log(2,"DEBUG: pb_send2target($cmt,".Dumper($v).",$vmexist,$vmpid)\n");
1241 my $host = "sshhost";
1242 my $login = "sshlogin";
1243 my $dir = "sshdir";
1244 my $port = "sshport";
1245 my $conf = "sshconf";
1246 my $tmout = undef;
1247 my $path = undef;
1248 if ($cmt =~ /^VM/) {
1249 $login = "vmlogin";
1250 $dir = "pbdefdir";
1251 # Specific VM
1252 $tmout = "vmtmout";
1253 $path = "vmpath";
1254 $host = "vmhost";
1255 $port = "vmport";
1256 } elsif ($cmt =~ /^VE/) {
1257 $login = "velogin";
1258 $dir = "pbdefdir";
1259 # Specific VE
1260 $path = "vepath";
1261 $conf = "rbsconf";
1262 } elsif ($cmt eq "Web") {
1263 $host = "websshhost";
1264 $login = "websshlogin";
1265 $dir = "websshdir";
1266 $port = "websshport";
1267 }
1268 my $cmd = "";
1269 my $src = "";
1270 my ($odir,$over,$oarch) = (undef, undef, undef);
1271 my ($ddir, $dver, $dfam, $dtype, $dos, $pbsuf, $pbupd, $pbins, $darch);
1272
1273 if ($cmt ne "Announce") {
1274 # Get list of packages to build
1275 my $ptr = pb_get_pkg();
1276 @pkgs = @$ptr;
1277
1278 # Get the running distro to consider
1279 if (defined $v) {
1280 ($odir,$over,$oarch) = split(/-/,$v);
1281 }
1282 ($ddir, $dver, $dfam, $dtype, $dos, $pbsuf, $pbupd, $pbins, $darch) = pb_distro_init($odir,$over,$oarch);
1283 pb_log(2,"DEBUG: distro tuple: ".join(',',($ddir, $dver, $dfam, $dtype, $pbsuf, $pbupd, $pbins, $darch))."\n");
1284
1285 # Get list of packages to build
1286 # Get content saved in cms2build
1287 my ($pkg) = pb_conf_read("$ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb","pbpkg");
1288 $pkg = { } if (not defined $pkg);
1289
1290 chdir "$ENV{'PBBUILDDIR'}";
1291 foreach my $pbpkg (@pkgs) {
1292 my $vertag = $pkg->{$pbpkg};
1293 # get the version of the current package - maybe different
1294 ($pbver,$pbtag) = split(/-/,$vertag);
1295
1296 if (($cmt eq "Sources") || ($cmt =~ /V[EM]build/)) {
1297 $src = "$src $ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz $ENV{'PBDESTDIR'}/$pbpkg-$pbver.pbconf.tar.gz";
1298 if ($cmd eq "") {
1299 $cmd = "ln -sf $pbpkg-$pbver.tar.gz $pbpkg-latest.tar.gz";
1300 } else {
1301 $cmd = "$cmd ; ln -sf $pbpkg-$pbver.tar.gz $pbpkg-latest.tar.gz";
1302 }
1303 } elsif ($cmt eq "Web") {
1304 $src = "$src $ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz"
1305 }
1306 }
1307 # Adds conf file for availability of conf elements
1308 pb_conf_add("$ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb");
1309 }
1310
1311 if ($cmt =~ /V[EM]build/) {
1312 $src="$src $ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb $ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb $ENV{'PBETC'} $ENV{'PBDESTDIR'}/pbrc $ENV{'PBDESTDIR'}/pbscript";
1313 } elsif (($cmt =~ /V[EM]Script/) || ($cmt eq "Web")) {
1314 $src="$src $ENV{'PBDESTDIR'}/pbscript";
1315 } elsif ($cmt =~ /V[EM]test/) {
1316 $src="$src $ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb $ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb $ENV{'PBETC'} $ENV{'PBDESTDIR'}/pbrc $ENV{'PBDESTDIR'}/pbscript $ENV{'PBDESTDIR'}/pbtest";
1317 } elsif ($cmt eq "Announce") {
1318 $src="$src $ENV{'PBTMP'}/pbscript";
1319 } elsif ($cmt eq "Packages") {
1320 # Get package list from file made during build2pkg
1321 open(KEEP,"$ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}") || die "Unable to read $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}";
1322 $src = <KEEP>;
1323 chomp($src);
1324 close(KEEP);
1325 $src="$src $ENV{'PBBUILDDIR'}/pbscript";
1326 }
1327 # Remove potential leading spaces (cause problem with basename)
1328 $src =~ s/^ *//;
1329 my $basesrc = "";
1330 foreach my $i (split(/ +/,$src)) {
1331 $basesrc .= " ".basename($i);
1332 }
1333
1334 pb_log(0,"Sources handled ($cmt): $src\n");
1335 pb_log(2,"values: ".Dumper(($host,$login,$dir,$port,$tmout,$path,$conf))."\n");
1336 my ($sshhost,$sshlogin,$sshdir,$sshport) = pb_conf_get($host,$login,$dir,$port);
1337 # Not mandatory...
1338 my ($rbsconf,$testver,$delivery) = pb_conf_get_if($conf,"testver","delivery");
1339 $delivery->{$ENV{'PBPROJ'}} = "" if (not defined $delivery->{$ENV{'PBPROJ'}});
1340 my ($vtmout,$vepath);
1341 # ...Except those in virtual context
1342 if ($cmt =~ /^VE/) {
1343 ($vepath) = pb_conf_get($path);
1344 }
1345 if ($cmt =~ /^VM/) {
1346 ($vtmout) = pb_conf_get($tmout);
1347 }
1348 pb_log(2,"ssh: ".Dumper(($sshhost,$sshlogin,$sshdir,$sshport,$vtmout,$vepath,$rbsconf))."\n");
1349
1350 my $mac;
1351 if ($cmt !~ /^VE/) {
1352 $mac = "$sshlogin->{$ENV{'PBPROJ'}}\@$sshhost->{$ENV{'PBPROJ'}}";
1353 # Overwrite account value if passed as parameter
1354 $mac = "$pbaccount\@$sshhost->{$ENV{'PBPROJ'}}" if (defined $pbaccount);
1355 pb_log(2, "DEBUG: pbaccount: $pbaccount => mac: $mac\n") if (defined $pbaccount);
1356 } else {
1357 # VE
1358 # Overwrite account value if passed as parameter (typically for setup2ve)
1359 $mac = $sshlogin->{$ENV{'PBPROJ'}};
1360 $mac = $pbaccount if (defined $pbaccount);
1361 }
1362
1363 my $tdir;
1364 my $bdir;
1365 if (($cmt eq "Sources") || ($cmt =~ /V[EM]Script/)) {
1366 $tdir = "$sshdir->{$ENV{'PBPROJ'}}/$delivery->{$ENV{'PBPROJ'}}/src";
1367 } elsif (($cmt =~ /V[EM]build/) || ($cmt =~ /V[EM]test/)) {
1368 $tdir = $sshdir->{$ENV{'PBPROJ'}}."/$ENV{'PBPROJ'}/delivery";
1369 $bdir = $sshdir->{$ENV{'PBPROJ'}}."/$ENV{'PBPROJ'}/build";
1370 # Remove a potential $ENV{'HOME'} as bdir should be relative to pb's home
1371 $bdir =~ s|\$ENV.+\}/||;
1372 } elsif ($cmt eq "Announce") {
1373 $tdir = "$sshdir->{$ENV{'PBPROJ'}}/$delivery->{$ENV{'PBPROJ'}}";
1374 } elsif ($cmt eq "Web") {
1375 $tdir = "$sshdir->{$ENV{'PBPROJ'}}/$delivery->{$ENV{'PBPROJ'}}";
1376 } elsif ($cmt eq "Packages") {
1377 $tdir = "$sshdir->{$ENV{'PBPROJ'}}/$delivery->{$ENV{'PBPROJ'}}/$ddir/$dver/$darch";
1378
1379 my $repodir = $tdir;
1380 $repodir =~ s|^$sshdir->{$ENV{'PBPROJ'}}/||;
1381
1382 my ($pbrepo) = pb_conf_get("pbrepo");
1383
1384 # Repository management
1385 open(PBS,"> $ENV{'PBBUILDDIR'}/pbscript") || die "Unable to create $ENV{'PBBUILDDIR'}/pbscript";
1386 if ($dtype eq "rpm") {
1387 # Also make a pbscript to generate yum/urpmi bases
1388 print PBS << "EOF";
1389#!/bin/bash
1390# Prepare a script to ease yum setup
1391cat > $ENV{'PBPROJ'}.repo << EOT
1392[$ENV{'PBPROJ'}]
1393name=$ddir $dver $darch - $ENV{'PBPROJ'} Vanilla Packages
1394baseurl=$pbrepo->{$ENV{'PBPROJ'}}/$repodir
1395enabled=1
1396gpgcheck=0
1397EOT
1398chmod 644 $ENV{'PBPROJ'}.repo
1399
1400# Clean up old repo content
1401rm -rf headers/ repodata/
1402# Create yum repo
1403if [ -x /usr/bin/yum-arch ]; then
1404 yum-arch .
1405fi
1406# Create repodata
1407createrepo .
1408EOF
1409 if ($dfam eq "md") {
1410 # For Mandriva add urpmi management
1411 print PBS << "EOF";
1412# Prepare a script to ease urpmi setup
1413cat > $ENV{'PBPROJ'}.addmedia << EOT
1414urpmi.addmedia $ENV{'PBPROJ'} $pbrepo->{$ENV{'PBPROJ'}}/$repodir with media_info/hdlist.cz
1415EOT
1416chmod 755 $ENV{'PBPROJ'}.addmedia
1417
1418# Clean up old repo content
1419rm -f hdlist.cz synthesis.hdlist.cz
1420# Create urpmi repo
1421genhdlist2 --clean .
1422if [ \$\? -ne 0 ]; then
1423 genhdlist .
1424fi
1425EOF
1426 }
1427 if ($ddir eq "fedora") {
1428 # Extract the spec file to please Fedora maintainers :-(
1429 print PBS << "EOF";
1430for p in $basesrc; do
1431 echo \$p | grep -q 'src.rpm'
1432 if [ \$\? -eq 0 ]; then
1433 rpm2cpio \$p | cpio -ivdum --quiet '*.spec'
1434 fi
1435done
1436EOF
1437 }
1438 if ($dfam eq "novell") {
1439 # Add ymp scripts for one-click install on SuSE
1440 print PBS << "EOF";
1441# Prepare a script to ease SuSE one-click install
1442# Cf: http://de.opensuse.org/1-Klick-Installation/ISV
1443#
1444cat > $ENV{'PBPROJ'}.ymp << EOT
1445<?xml version="1.0" encoding="utf-8"?>
1446<!-- vim: set sw=2 ts=2 ai et: -->
1447<metapackage xmlns:os="http://opensuse.org/Standards/One_Click_Install" xmlns="http://opensuse.org/Standards/One_Click_Install">
1448 <group><!-- The group of software, typically one for project-builder.org -->
1449 <name>$ENV{'PBPROJ'} Bundle</name> <!-- Name of the software group -->
1450 <summary>Software bundle for the $ENV{'PBPROJ'} project</summary> <!--This message is shown to the user and should describe the whole bundle -->
1451 <description>This is the summary of the $ENV{'PBPROJ'} Project
1452
1453 Details are available on a per package basis below
1454
1455 </description><!--This is also shown to the user -->
1456 <remainSubscribed>false</remainSubscribed> <!-- Don't know what it mean -->
1457 <repositories><!-- List of needed repositories -->
1458 <repository>
1459 <name>$ENV{'PBPROJ'} Repository</name> <!-- Name of the repository -->
1460 <summary>This repository contains the $ENV{'PBPROJ'} project packages.</summary> <!-- Summary of the repository -->
1461 <description>This repository contains the $ENV{'PBPROJ'} project packages.</description><!-- This description is shown to the user -->
1462 <url>$pbrepo->{$ENV{'PBPROJ'}}/$repodir</url><!--URL of repository, which is added -->
1463 </repository>
1464 </repositories>
1465 <software><!-- A List of packages, which should be added through the one-click-installation -->
1466EOT
1467for p in $basesrc; do
1468 sum=`rpm -q --qf '%{SUMMARY}' \$p`
1469 name=`rpm -q --qf '%{NAME}' \$p`
1470 desc=`rpm -q --qf '%{description}' \$p`
1471 cat >> $ENV{'PBPROJ'}.ymp << EOT
1472 <item>
1473 <name>\$name</name><!-- Name of the package, is shown to the user and used to identify the package at the repository -->
1474 <summary>\$sum</summary> <!-- Summary of the package -->
1475 <description>\$desc</description> <!-- Description, is shown to the user -->
1476 </item>
1477EOT
1478done
1479cat >> $ENV{'PBPROJ'}.ymp << EOT
1480 </software>
1481 </group>
1482</metapackage>
1483EOT
1484chmod 644 $ENV{'PBPROJ'}.ymp
1485EOF
1486 }
1487 } elsif ($dtype eq "deb") {
1488 # Also make a pbscript to generate apt bases
1489 # Cf: http://www.debian.org/doc/manuals/repository-howto/repository-howto.fr.html
1490 my $rpd = dirname("$pbrepo->{$ENV{'PBPROJ'}}/$repodir");
1491 print PBS << "EOF";
1492#!/bin/bash
1493# Prepare a script to ease apt setup
1494cat > $ENV{'PBPROJ'}.sources.list << EOT
1495deb $rpd $dver contrib
1496deb-src $rpd $dver contrib
1497EOT
1498chmod 644 $ENV{'PBPROJ'}.sources.list
1499
1500# Prepare a script to create apt info file
1501(cd .. ; for a in i386 amd64 ia64; do mkdir -p dists/$dver/contrib/binary-\$a; dpkg-scanpackages -a\$a $dver/$darch /dev/null | gzip -c9 > dists/$dver/contrib/binary-\$a/Packages.gz; done; mkdir -p dists/$dver/contrib/source; dpkg-scansources $dver/$darch /dev/null | gzip -c9 > dists/$dver/contrib/source/Sources.gz)
1502#(cd .. ; rm -f dists/$dver/Release ; apt-ftparchive release dists/$dver > dists/$dver/Release; gpg --sign -ba -o dists/$dver/Release.gpg dists/$dver/Release)
1503EOF
1504 } elsif ($dtype eq "ebuild") {
1505 # make a pbscript to generate links to latest version
1506 print PBS << "EOF";
1507#!/bin/bash
1508# Prepare a script to create correct links
1509for p in $src; do
1510 echo \$p | grep -q '.ebuild'
1511 if [ \$\? -eq 0 ]; then
1512 j=`basename \$p`
1513 pp=`echo \$j | cut -d'-' -f1`
1514 ln -sf \$j \$pp.ebuild
1515 fi
1516done
1517EOF
1518 }
1519 close(PBS);
1520 chmod 0755,"$ENV{'PBBUILDDIR'}/pbscript";
1521 } else {
1522 return;
1523 }
1524
1525 # Useless for VE
1526 my $nport;
1527 if ($cmt !~ /^VE/) {
1528 $nport = $sshport->{$ENV{'PBPROJ'}};
1529 $nport = "$pbport" if (defined $pbport);
1530 }
1531
1532 # Remove a potential $ENV{'HOME'} as tdir should be relative to pb's home
1533 $tdir =~ s|\$ENV.+\}/||;
1534
1535 my $tm = undef;
1536 if ($cmt =~ /^VM/) {
1537 $tm = $vtmout->{$ENV{'PBPROJ'}};
1538 }
1539
1540 # ssh communication if not VE
1541 # should use a hash instead...
1542 my ($shcmd,$cpcmd,$cptarget,$cp2target);
1543 if ($cmt !~ /^VE/) {
1544 my $keyfile = pb_ssh_get(0);
1545 $shcmd = "ssh -i $keyfile -q -o UserKnownHostsFile=/dev/null -p $nport $mac";
1546 $cpcmd = "scp -i $keyfile -p -o UserKnownHostsFile=/dev/null -P $nport";
1547 $cptarget = "$mac:$tdir";
1548 if ($cmt =~ /^VMbuild/) {
1549 $cp2target = "$mac:$bdir";
1550 }
1551 } else {
1552 my $tp = $vepath->{$ENV{'PBPROJ'}};
1553 ($odir,$over,$oarch) = split(/-/,$v);
1554 my $tpdir = "$tp/$odir/$over/$oarch";
1555 my ($ptr) = pb_conf_get("vetype");
1556 my $vetype = $ptr->{$ENV{'PBPROJ'}};
1557 if ($vetype eq "chroot") {
1558 $shcmd = "sudo chroot $tpdir /bin/su - $mac -c ";
1559 } elsif ($vetype eq "schroot") {
1560 $shcmd = "schroot $tp -u $mac -- ";
1561 }
1562 $cpcmd = "sudo cp -r ";
1563 # We need to get the home dir of the target account to deliver in the right place
1564 open(PASS,"$tpdir/etc/passwd") || die "Unable to open $tpdir/etc/passwd";
1565 my $homedir = "";
1566 while (<PASS>) {
1567 my ($c1,$c2,$c3,$c4,$c5,$c6,$c7) = split(/:/);
1568 $homedir = $c6 if ($c1 =~ /^$mac$/);
1569 pb_log(3,"Homedir: $homedir - account: $c6\n");
1570 }
1571 close(PASS);
1572 $cptarget = "$tpdir/$homedir/$tdir";
1573 if ($cmt eq "VEbuild") {
1574 $cp2target = "$tpdir/$homedir/$bdir";
1575 }
1576 pb_log(2,"On VE using $cptarget as target dir to copy to\n");
1577 }
1578
1579 my $logres = "";
1580 # Do not touch when just announcing
1581 if ($cmt ne "Announce") {
1582 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");
1583 } else {
1584 $logres = "> ";
1585 }
1586 pb_system("cd $ENV{'PBBUILDDIR'} ; $cpcmd $src $cptarget 2> /dev/null","$cmt delivery in $cptarget");
1587
1588 # For VE we need to change the owner manually
1589 if ($cmt =~ /^VE/) {
1590 pb_system("$shcmd \"sudo chown -R $mac $tdir\"","Adapt owner in $tdir to $mac");
1591 }
1592
1593 pb_system("$shcmd \"echo \'cd $tdir ; if [ -x pbscript ]; then ./pbscript; fi ; rm -f ./pbscript\' | bash\"","Executing pbscript on $cptarget if needed","verbose");
1594 if ($cmt =~ /^V[EM]build/) {
1595 # Get back info on pkg produced, compute their name and get them from the VM
1596 pb_system("$cpcmd $cp2target/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'} $ENV{'PBBUILDDIR'} 2> /dev/null","Get package names in $cp2target");
1597 # For VE we need to change the owner manually
1598 if ($cmt eq "VEbuild") {
1599 pb_system("sudo chown $UID $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}","Adapt owner in $tdir to $UID");
1600 }
1601 # return here to avoid breaking the load on VMs/VEs in case of a bad one
1602 if (not -f "$ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}") {
1603 pb_log(0,"Problem with VM $v on $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}");
1604 return;
1605 }
1606 open(KEEP,"$ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}") || die "Unable to read $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}";
1607 my $src = <KEEP>;
1608 chomp($src);
1609 close(KEEP);
1610 $src =~ s/^ *//;
1611 pb_mkdir_p("$ENV{'PBBUILDDIR'}/$odir/$over");
1612 # Change pgben to make the next send2target happy
1613 my $made = "";
1614 open(KEEP,"> $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}") || die "Unable to write $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}";
1615 foreach my $p (split(/ +/,$src)) {
1616 my $j = basename($p);
1617 # For VM we don't want shell expansion to hapen locally but remotely
1618 my $delim = '\'';
1619 if ($cmt =~ /^VEbuild/) {
1620 # For VE we need to support shell expansion locally
1621 $delim = "";
1622 }
1623 pb_system("$cpcmd $cp2target/$delim$p$delim $ENV{'PBBUILDDIR'}/$odir/$over 2> /dev/null","Recovery of package $j in $ENV{'PBBUILDDIR'}/$odir/$over");
1624 $made="$made $odir/$over/$j"; # if (($dtype ne "rpm") || ($j !~ /.src.rpm$/));
1625 }
1626 print KEEP "$made\n";
1627 close(KEEP);
1628 pb_system("$shcmd \"rm -rf $tdir $bdir\"","$cmt cleanup");
1629
1630 # Sign packages locally
1631 if ($dtype eq "rpm") {
1632 #pb_system("rpm --addsign --define \"_signature gpg\" --define \"_gpg_name $ENV{'PBPACKAGER'}\" --define \"__gpg_sign_cmd /usr/bin/gpg --batch --no-verbose --no-armor --no-tty --no-secmem-warning -sbo %{__signature_filename} %{__plaintext_filename} --use-agent\" $made","Signing RPM packages packages");
1633 } elsif ($dtype eq "deb") {
1634 #pb_system("debsign $made","Signing DEB packages");
1635 } else {
1636 pb_log(0,"I don't know yet how to sign packages for type $dtype.\nPlease give feedback to dev team\n");
1637 }
1638
1639 # We want to send them to the ssh account so overwrite what has been done before
1640 undef $pbaccount;
1641 pb_log(2,"Before sending pkgs, vmexist: $vmexist, vmpid: $vmpid\n");
1642 pb_send2target("Packages",$odir."-".$over."-".$oarch,$vmexist,$vmpid);
1643 pb_rm_rf("$ENV{'PBBUILDDIR'}/$odir");
1644 }
1645 pb_log(2,"Before halt, vmexist: $vmexist, vmpid: $vmpid\n");
1646 if ((! $vmexist) && ($cmt =~ /^VM/)) {
1647 # If in setupvm then takes a snapshot just before halting
1648 if ($snapme != 0) {
1649 my ($vmmonport,$vmtype) = pb_conf_get("vmmonport","vmtype");
1650 # For monitoring control
1651 if ((($vmtype->{$ENV{'PBPROJ'}}) eq "kvm") || (($vmtype->{$ENV{'PBPROJ'}}) eq "qemu")) {
1652 require Net::Telnet;
1653 my $t = new Net::Telnet (Timeout => 120, Host => "localhost", Port => $vmmonport->{$ENV{'PBPROJ'}}) || die "Unable to dialog on the monitor";
1654 # move to monitor mode
1655 my @lines = $t->cmd("c");
1656 # Create a snapshot named pb
1657 @lines = $t->cmd("savevm pb");
1658 # Write the new status in the VM
1659 @lines = $t->cmd("commit all");
1660 # End
1661 @lines = $t->cmd("quit");
1662 }
1663 }
1664 my $hoption = "-p";
1665 my $hpath = "/sbin";
1666 # Solaris doesn't support -h and has halt elsewhere
1667 if ($dtype eq "pkg") {
1668 $hoption = "" ;
1669 $hpath = "/usr/sbin";
1670 }
1671 pb_system("$shcmd \"sudo $hpath/halt $hoption \"; sleep $tm ; echo \'if [ -d /proc/$vmpid ]; then kill -9 $vmpid; fi \' | bash ; sleep 10","VM $v halt (pid $vmpid)");
1672 }
1673 if (($cmt =~ /^VE/) && ($snapme != 0)) {
1674 ($odir,$over,$oarch) = split(/-/,$v);
1675 my $tpdir = "$vepath->{$ENV{'PBPROJ'}}/$odir/$over/$oarch";
1676 pb_system("sudo tar cz -f $vepath->{$ENV{'PBPROJ'}}/$odir-$over-$oarch.tar.gz -C $tpdir .","Creating a snapshot of $tpdir");
1677 }
1678}
1679
1680sub pb_script2v {
1681 my $pbscript=shift;
1682 my $vtype=shift;
1683 my $pbforce=shift || 0; # Force stop of VM. Default not
1684 my $vm1=shift || undef; # Only that VM to treat
1685 my $snapme=shift || 0; # Do we have to create a snapshot
1686 my $vm;
1687 my $all;
1688
1689 pb_log(2,"DEBUG: pb_script2v($pbscript,$vtype,$pbforce,".Dumper($vm1).",$snapme)\n");
1690 # Prepare the script to be executed on the VM
1691 # in $ENV{'PBDESTDIR'}/pbscript
1692 if ((defined $pbscript ) && ($pbscript ne "$ENV{'PBDESTDIR'}/pbscript")) {
1693 copy($pbscript,"$ENV{'PBDESTDIR'}/pbscript") || die "Unable to create $ENV{'PBDESTDIR'}/pbscript";
1694 chmod 0755,"$ENV{'PBDESTDIR'}/pbscript";
1695 }
1696
1697 if (not defined $vm1) {
1698 ($vm,$all) = pb_get2v($vtype);
1699 } else {
1700 @$vm = ($vm1);
1701 }
1702 my ($vmexist,$vmpid) = (undef,undef);
1703
1704 foreach my $v (@$vm) {
1705 # Launch VM/VE
1706 ($vmexist,$vmpid) = pb_launchv($vtype,$v,0,$snapme,$pbsnap);
1707
1708 if ($vtype eq "vm") {
1709 pb_log(2,"DEBUG: After pb_launchv, vmexist: $vmexist, vmpid: $vmpid\n");
1710
1711 # Skip that VM if something went wrong
1712 next if (($vmpid == 0) && ($vmexist == 0));
1713
1714 # If force stopping the VM then reset vmexist
1715 if ($pbforce == 1) {
1716 $vmpid = $vmexist;
1717 $vmexist = 0;
1718 }
1719 } else {
1720 #VE
1721 $vmexist = 0;
1722 $vmpid = 0;
1723 }
1724
1725 # Gather all required files to send them to the VM
1726 # and launch the build through pbscript
1727 pb_log(2,"DEBUG: Before send2target, vmexist: $vmexist, vmpid: $vmpid\n");
1728 pb_send2target(uc($vtype)."Script","$v",$vmexist,$vmpid,$snapme);
1729
1730 }
1731}
1732
1733sub pb_launchv {
1734 my $vtype = shift;
1735 my $v = shift;
1736 my $create = shift || 0; # By default do not create a VM/VE
1737 my $snapme = shift || 0; # By default do not snap a VM/VE
1738 my $usesnap = shift || 1; # By default study the usage of the snapshot feature of VM/VE
1739
1740 # If creation or snapshot creation mode, no snapshot usable
1741 if (($create == 1) || ($snapme == 1)) {
1742 $usesnap = 0;
1743 }
1744
1745 pb_log(2,"DEBUG: pb_launchv($vtype,$v,$create,$snapme,$usesnap)\n");
1746 die "No VM/VE defined, unable to launch" if (not defined $v);
1747 # Keep only the first VM in case many were given
1748 $v =~ s/,.*//;
1749
1750 my $arch = pb_get_arch();
1751
1752 # Launch the VMs/VEs
1753 if ($vtype eq "vm") {
1754 die "-i iso parameter needed" if (((not defined $iso) || ($iso eq "")) && ($create != 0));
1755
1756 # TODO: vmmonport should be optional
1757 my ($ptr,$ptr2,$vmpath,$vmport,$vmsize,$vmmonport) = pb_conf_get("vmtype","vmcmd","vmpath","vmport","vmsize","vmmonport");
1758 my ($vmopt,$vmtmout,$vmsnap) = pb_conf_get_if("vmopt","vmtmout","vmsnap");
1759
1760 my $vmtype = $ptr->{$ENV{'PBPROJ'}};
1761 my $vmcmd = $ptr2->{$ENV{'PBPROJ'}};
1762 if (not defined $ENV{'PBVMOPT'}) {
1763 $ENV{'PBVMOPT'} = "";
1764 }
1765 # Save the current status for later restoration
1766 $ENV{'PBOLDVMOPT'} = $ENV{'PBVMOPT'};
1767 # Set a default timeout of 2 minutes
1768 if (not defined $ENV{'PBVMTMOUT'}) {
1769 $ENV{'PBVMTMOUT'} = "120";
1770 }
1771 if (defined $vmopt->{$v}) {
1772 $ENV{'PBVMOPT'} .= " $vmopt->{$v}" if ($ENV{'PBVMOPT'} !~ / $vmopt->{$v}/);
1773 } elsif (defined $vmopt->{$ENV{'PBPROJ'}}) {
1774 $ENV{'PBVMOPT'} .= " $vmopt->{$ENV{'PBPROJ'}}" if ($ENV{'PBVMOPT'} !~ / $vmopt->{$ENV{'PBPROJ'}}/);
1775 }
1776
1777 # Are we allowed to use snapshot feature
1778 if ($usesnap == 1) {
1779 if ((defined $vmsnap->{$v}) && ($vmsnap->{$v} =~ /true/i)) {
1780 $ENV{'PBVMOPT'} .= " -snapshot";
1781 } elsif ((defined $vmsnap->{$ENV{'PBPROJ'}}) && ($vmsnap->{$ENV{'PBPROJ'}} =~ /true/i)) {
1782 $ENV{'PBVMOPT'} .= " -snapshot";
1783 } elsif ($pbsnap eq 1) {
1784 $ENV{'PBVMOPT'} .= " -snapshot";
1785 }
1786 }
1787 if ($snapme != 0) {
1788 if (($vmtype eq "kvm") || ($vmtype eq "qemu")) {
1789 # Configure the monitoring to automize the creation of the 'pb' snapshot
1790 $ENV{'PBVMOPT'} .= " -serial mon:telnet::$vmmonport->{$ENV{'PBPROJ'}},server,nowait";
1791 # In that case no snapshot call needed
1792 $ENV{'PBVMOPT'} =~ s/ -snapshot//;
1793 }
1794 }
1795 if (defined $vmtmout->{$v}) {
1796 $ENV{'PBVMTMOUT'} = $vmtmout->{$v};
1797 } elsif (defined $vmtmout->{$ENV{'PBPROJ'}}) {
1798 $ENV{'PBVMTMOUT'} = $vmtmout->{$ENV{'PBPROJ'}};
1799 }
1800 my $nport = $vmport->{$ENV{'PBPROJ'}};
1801 $nport = "$pbport" if (defined $pbport);
1802
1803 my $cmd;
1804 my $vmm; # has to be used for pb_check_ps
1805 if (($vmtype eq "qemu") || ($vmtype eq "kvm")) {
1806 $vmm = "$vmpath->{$ENV{'PBPROJ'}}/$v.qemu";
1807 if (($create != 0) || (defined $iso)) {
1808 $ENV{'PBVMOPT'} .= " -cdrom $iso -boot d";
1809 }
1810 # Always redirect the network and always try to use a 'pb' snapshot
1811 $cmd = "$vmcmd $ENV{'PBVMOPT'} -redir tcp:$nport:10.0.2.15:22 -loadvm pb $vmm"
1812 } elsif ($vmtype eq "xen") {
1813 } elsif ($vmtype eq "vmware") {
1814 } else {
1815 die "VM of type $vmtype not supported. Report to the dev team";
1816 }
1817 # Restore the ENV VAR Value
1818 $ENV{'PBVMOPT'} = $ENV{'PBOLDVMOPT'};
1819
1820 my ($tmpcmd,$void) = split(/ +/,$cmd);
1821 my $vmexist = pb_check_ps($tmpcmd,$vmm);
1822 my $vmpid = 0;
1823 if (! $vmexist) {
1824 if ($create != 0) {
1825 die("Found an existing Virtual machine $vmm. Won't overwrite") if (-r $vmm);
1826 if (($vmtype eq "qemu") || ($vmtype eq "xen") || ($vmtype eq "kvm")) {
1827 pb_system("/usr/bin/qemu-img create -f qcow2 $vmm $vmsize->{$ENV{'PBPROJ'}}","Creating the QEMU VM");
1828 } elsif ($vmtype eq "vmware") {
1829 } else {
1830 }
1831 }
1832 if (! -f "$vmm") {
1833 pb_log(0,"Unable to find VM $vmm\n");
1834 } else {
1835 pb_system("$cmd &","Launching the VM $vmm");
1836 pb_system("sleep $ENV{'PBVMTMOUT'}","Waiting $ENV{'PBVMTMOUT'} s for VM $v to come up");
1837 $vmpid = pb_check_ps($tmpcmd,$vmm);
1838 pb_log(0,"VM $vmm launched (pid $vmpid)\n");
1839 }
1840 } else {
1841 pb_log(0,"Found an existing VM $vmm (pid $vmexist)\n");
1842 }
1843 pb_log(2,"DEBUG: pb_launchv returns ($vmexist,$vmpid)\n");
1844 return($vmexist,$vmpid);
1845 # VE here
1846 } else {
1847 # Get distro context
1848 my ($name,$ver,$darch) = split(/-/,$v);
1849 chomp($darch);
1850 my ($ddir, $dver, $dfam, $dtype, $dos, $pbsuf) = pb_distro_init($name,$ver,$darch);
1851
1852 # Get VE context
1853 my ($ptr,$vepath) = pb_conf_get("vetype","vepath");
1854 my $vetype = $ptr->{$ENV{'PBPROJ'}};
1855
1856 # We can probably only get those params now we have the distro context
1857 my ($rbsb4pi,$rbspi,$vesnap,$oscodename,$osmindep,$verebuild,$rbsmirrorsrv) = pb_conf_get_if("rbsb4pi","rbspi","vesnap","oscodename","osmindep","verebuild","rbsmirrorsrv");
1858
1859 # We need to avoid umask propagation to the VE
1860 umask 0022;
1861
1862 if (($vetype eq "chroot") || ($vetype eq "schroot")) {
1863 # Architecture consistency
1864 if ($arch ne $darch) {
1865 die "Unable to launch a VE of architecture $darch on a $arch platform" if (($darch eq "x86_64") && ($arch =~ /i?86/));
1866 }
1867
1868 my ($verpmtype,$vedebtype) = pb_conf_get("verpmtype","vedebtype");
1869 if (($create != 0) || ((defined $verebuild) && ($verebuild->{$ENV{'PBPROJ'}} =~ /true/i)) || ($pbforce == 1)) {
1870 my ($rbsopt1) = pb_conf_get_if("rbsopt");
1871
1872 # We have to rebuild the chroot
1873 if ($dtype eq "rpm") {
1874
1875 # Which tool is used
1876 my $verpmstyle = $verpmtype->{$ENV{'PBPROJ'}};
1877
1878 # Get potential rbs option
1879 my $rbsopt = "";
1880 if (defined $rbsopt1) {
1881 if (defined $rbsopt1->{$verpmstyle}) {
1882 $rbsopt = $rbsopt1->{$verpmstyle};
1883 } elsif (defined $rbsopt1->{$ENV{'PBPROJ'}}) {
1884 $rbsopt = $rbsopt1->{$ENV{'PBPROJ'}};
1885 } else {
1886 $rbsopt = "";
1887 }
1888 }
1889
1890 my $postinstall = pb_get_postinstall($ddir,$dver,$darch,$rbspi,$verpmstyle);
1891 if ($verpmstyle eq "rinse") {
1892 # Need to reshape the mirrors generated with local before-post-install script
1893 my $b4post = "--before-post-install ";
1894 my $postparam = pb_distro_get_param($ddir,$dver,$darch,$rbsb4pi);
1895 if ($postparam eq "") {
1896 $b4post = "";
1897 } else {
1898 $b4post .= $postparam;
1899 }
1900
1901 # Need to reshape the package list for pb
1902 my $addpkgs;
1903 $postparam = "";
1904 $postparam .= pb_distro_get_param($ddir,$dver,$darch,$osmindep);
1905 if ($postparam eq "") {
1906 $addpkgs = "";
1907 } else {
1908 my $pkgfile = "$ENV{'PBTMP'}/addpkgs.lis";
1909 open(PKG,"> $pkgfile") || die "Unable to create $pkgfile";
1910 foreach my $p (split(/,/,$postparam)) {
1911 print PKG "$p\n";
1912 }
1913 close(PKG);
1914 $addpkgs = "--add-pkg-list $pkgfile";
1915 }
1916
1917 my $rinseverb = "";
1918 $rinseverb = "--verbose" if ($pbdebug gt 0);
1919 my ($rbsconf) = pb_conf_get("rbsconf");
1920
1921 pb_system("sudo /usr/sbin/rinse --directory \"$vepath->{$ENV{'PBPROJ'}}/$ddir/$dver/$darch\" --arch \"$darch\" --distribution \"$ddir-$dver\" --config \"$rbsconf->{$ENV{'PBPROJ'}}\" $b4post $postinstall $rbsopt $addpkgs $rinseverb","Creating the rinse VE for $ddir-$dver ($darch)", "verbose");
1922 } elsif ($verpmstyle eq "rpmbootstrap") {
1923 my $rbsverb = "";
1924 foreach my $i (1..$pbdebug) {
1925 $rbsverb .= " -v";
1926 }
1927 my $addpkgs = "";
1928 my $postparam = "";
1929 $postparam .= pb_distro_get_param($ddir,$dver,$darch,$osmindep);
1930 if ($postparam eq "") {
1931 $addpkgs = "";
1932 } else {
1933 $addpkgs = "-a $postparam";
1934 }
1935 pb_system("sudo /usr/bin/rpmbootstrap $rbsopt $postinstall $addpkgs $ddir-$dver-$darch $rbsverb","Creating the rpmbootstrap VE for $ddir-$dver ($darch)", "verbose");
1936 } elsif ($verpmstyle eq "mock") {
1937 my ($rbsconf) = pb_conf_get("rbsconf");
1938 pb_system("sudo /usr/sbin/mock --init --resultdir=\"/tmp\" --configdir=\"$rbsconf->{$ENV{'PBPROJ'}}\" -r $v $rbsopt","Creating the mock VE for $ddir-$dver ($darch)");
1939 # Once setup we need to install some packages, the pb account, ...
1940 pb_system("sudo /usr/sbin/mock --install --configdir=\"$rbsconf->{$ENV{'PBPROJ'}}\" -r $v su","Configuring the mock VE");
1941 } else {
1942 die "Unknown verpmtype type $verpmstyle. Report to dev team";
1943 }
1944 } elsif ($dtype eq "deb") {
1945 my $vedebstyle = $vedebtype->{$ENV{'PBPROJ'}};
1946
1947 my $codename = pb_distro_get_param($ddir,$dver,$darch,$oscodename);
1948 my $postparam = "";
1949 my $addpkgs;
1950 $postparam .= pb_distro_get_param($ddir,$dver,$darch,$osmindep);
1951 if ($postparam eq "") {
1952 $addpkgs = "";
1953 } else {
1954 $addpkgs = "--include $postparam";
1955 }
1956 my $debmir = "";
1957 $debmir .= pb_distro_get_param($ddir,$dver,$darch,$rbsmirrorsrv);
1958
1959 # Get potential rbs option
1960 my $rbsopt = "";
1961 if (defined $rbsopt1) {
1962 if (defined $rbsopt1->{$vedebstyle}) {
1963 $rbsopt = $rbsopt1->{$vedebstyle};
1964 } elsif (defined $rbsopt1->{$ENV{'PBPROJ'}}) {
1965 $rbsopt = $rbsopt1->{$ENV{'PBPROJ'}};
1966 } else {
1967 $rbsopt = "";
1968 }
1969 }
1970
1971 # debootstrap works with amd64 not x86_64
1972 my $debarch = $darch;
1973 $debarch = "amd64" if ($darch eq "x86_64");
1974 if ($vedebstyle eq "debootstrap") {
1975 my $dbsverb = "";
1976 $dbsverb = "--verbose" if ($pbdebug gt 0);
1977
1978 # Some perl modules are in Universe on Ubuntu
1979 $rbsopt .= " --components=main,universe" if ($ddir eq "ubuntu");
1980
1981 pb_system("sudo /usr/sbin/debootstrap $dbsverb $rbsopt --arch=$debarch $addpkgs $codename \"$vepath->{$ENV{'PBPROJ'}}/$ddir/$dver/$darch\" $debmir","Creating the debootstrap VE for $ddir-$dver ($darch)", "verbose");
1982 # debootstrap doesn't create an /etc/hosts file
1983 if (! -f "$vepath->{$ENV{'PBPROJ'}}/$ddir/$dver/$darch/etc/hosts" ) {
1984 pb_system("sudo cp /etc/hosts $vepath->{$ENV{'PBPROJ'}}/$ddir/$dver/$darch/etc/hosts");
1985 }
1986 } else {
1987 die "Unknown vedebtype type $vedebstyle. Report to dev team";
1988 }
1989 } elsif ($dtype eq "ebuild") {
1990 die "Please teach the dev team how to build gentoo chroot";
1991 } else {
1992 die "Unknown distribution type $dtype. Report to dev team";
1993 }
1994 }
1995 # Fix modes to allow access to the VE for pb user
1996 pb_system("sudo chmod 755 $vepath->{$ENV{'PBPROJ'}}/$ddir $vepath->{$ENV{'PBPROJ'}}/$ddir/$dver $vepath->{$ENV{'PBPROJ'}}/$ddir/$dver/$darch","Fixing permissions");
1997
1998 # Test if an existing snapshot exists and use it if appropriate
1999 # And also use it of no local extracted VE is present
2000 if ((-f "$vepath->{$ENV{'PBPROJ'}}/$ddir-$dver-$darch.tar.gz") &&
2001 (((defined $vesnap->{$v}) && ($vesnap->{$v} =~ /true/i)) ||
2002 ((defined $vesnap->{$ENV{'PBPROJ'}}) && ($vesnap->{$ENV{'PBPROJ'}} =~ /true/i)) ||
2003 ($pbsnap eq 1) ||
2004 (! -d "$vepath->{$ENV{'PBPROJ'}}/$ddir/$dver/$darch"))) {
2005 pb_system("sudo rm -rf $vepath->{$ENV{'PBPROJ'}}/$ddir/$dver/$darch ; sudo mkdir -p $vepath->{$ENV{'PBPROJ'}}/$ddir/$dver/$darch ; sudo tar xz -C $vepath->{$ENV{'PBPROJ'}}/$ddir/$dver/$darch -f $vepath->{$ENV{'PBPROJ'}}/$ddir-$dver-$darch.tar.gz","Extracting snapshot of $ddir-$dver-$darch.tar.gz under $vepath->{$ENV{'PBPROJ'}}/$ddir/$dver/$darch");
2006 }
2007 # Nothing more to do for VE. No real launch
2008 } else {
2009 die "VE of type $vetype not supported. Report to the dev team";
2010 }
2011 }
2012}
2013
2014# Return string for date synchro
2015sub pb_date2v {
2016
2017my $vtype = shift;
2018my $v = shift;
2019
2020my ($ntp) = pb_conf_get_if($vtype."ntp");
2021my $vntp = $ntp->{$ENV{'PBPROJ'}} if (defined $ntp);
2022my $ntpline;
2023
2024if (defined $vntp) {
2025 my ($ntpcmd) = pb_conf_get($vtype."ntpcmd");
2026 my $vntpcmd;
2027 if (defined $ntpcmd->{$v}) {
2028 $vntpcmd = $ntpcmd->{$v};
2029 } elsif (defined $ntpcmd->{$ENV{'PBPROJ'}}) {
2030 $vntpcmd = $ntpcmd->{$ENV{'PBPROJ'}};
2031 } else {
2032 $vntpcmd = "/bin/true";
2033 }
2034 $ntpline = "sudo $vntpcmd $vntp";
2035} else {
2036 $ntpline = undef;
2037}
2038# Force new date to be in the future compared to the date
2039# of the host by adding 1 minute
2040my @date=pb_get_date();
2041$date[1]++;
2042my $upddate = strftime("%m%d%H%M%Y", @date);
2043my $dateline = "sudo date $upddate";
2044return($ntpline,$dateline);
2045}
2046
2047sub pb_build2v {
2048
2049my $vtype = shift;
2050my $action = shift || "build";
2051
2052my ($v,$all) = pb_get2v($vtype);
2053
2054# Send tar files when we do a global generation
2055pb_build2ssh() if (($all == 1) && ($action eq "build"));
2056
2057my ($vmexist,$vmpid) = (undef,undef);
2058
2059foreach my $v (@$v) {
2060 # Prepare the script to be executed on the VM/VE
2061 # in $ENV{'PBDESTDIR'}/pbscript
2062 open(SCRIPT,"> $ENV{'PBDESTDIR'}/pbscript") || die "Unable to create $ENV{'PBDESTDIR'}/pbscript";
2063 print SCRIPT "#!/bin/bash\n";
2064
2065 # Transmit the verbosity level to the virtual env/mach.
2066 my $verbose = "";
2067 my $i = 0; # minimal debug level
2068 while ($i lt $pbdebug) {
2069 $verbose .= "-v ";
2070 $i++;
2071 }
2072 # Activate script verbosity if at least 2 for pbdebug
2073 print SCRIPT "set -x\n" if ($i gt 1);
2074 # Quiet if asked to be so on the original system
2075 $verbose = "-q" if ($pbdebug eq -1);
2076
2077 print SCRIPT "echo ... Execution needed\n";
2078 print SCRIPT "# This is in directory delivery\n";
2079 print SCRIPT "# Setup the variables required for building\n";
2080 print SCRIPT "export PBPROJ=$ENV{'PBPROJ'}\n";
2081
2082 if ($action eq "build") {
2083 print SCRIPT "# Preparation for pb\n";
2084 print SCRIPT "mv .pbrc \$HOME\n";
2085 print SCRIPT "cd ..\n";
2086 }
2087
2088 # VE needs a good /proc
2089 if ($vtype eq "ve") {
2090 print SCRIPT "sudo mount -t proc /proc /proc\n";
2091 }
2092
2093 my ($ntpline,$dateline) = pb_date2v($vtype,$v);
2094 print SCRIPT "# Time sync\n";
2095 print SCRIPT "echo 'setting up date with '";
2096 if (defined $ntpline) {
2097 print SCRIPT "echo $ntpline\n";
2098 print SCRIPT "$ntpline\n";
2099 } else {
2100 print SCRIPT "echo $dateline\n";
2101 print SCRIPT "$dateline\n";
2102 }
2103 # Use potential local proxy declaration in case we need it to download repo, pkgs, ...
2104 if (defined $ENV{'http_proxy'}) {
2105 print SCRIPT "export http_proxy=\"$ENV{'http_proxy'}\"\n";
2106 }
2107
2108 if (defined $ENV{'ftp_proxy'}) {
2109 print SCRIPT "export ftp_proxy=\"$ENV{'ftp_proxy'}\"\n";
2110 }
2111
2112 # Get list of packages to build/test and get some ENV vars as well
2113 my $ptr = pb_get_pkg();
2114 @pkgs = @$ptr;
2115 my $p = join(' ',@pkgs) if (@pkgs);
2116 print SCRIPT "export PBPROJVER=$ENV{'PBPROJVER'}\n";
2117 print SCRIPT "export PBPROJTAG=$ENV{'PBPROJTAG'}\n";
2118 print SCRIPT "export PBPACKAGER=\"$ENV{'PBPACKAGER'}\"\n";
2119
2120 # We may need to do some other tasks before building. Read a script here to finish setup
2121 if (-x "$ENV{'PBDESTDIR'}/pb$vtype".".pre") {
2122 print SCRIPT "# Special pre-instructions to be launched\n";
2123 print SCRIPT pb_get_content("$ENV{'PBDESTDIR'}/pb$vtype".".pre");
2124 }
2125
2126 if (-x "$ENV{'PBDESTDIR'}/pb$vtype"."$action.pre") {
2127 print SCRIPT "# Special pre-$action instructions to be launched\n";
2128 print SCRIPT pb_get_content("$ENV{'PBDESTDIR'}/pb$vtype"."$action.pre");
2129 }
2130
2131 print SCRIPT "# $action\n";
2132 print SCRIPT "echo $action"."ing packages on $vtype...\n";
2133
2134 if (($action eq "test") && (! -x "$ENV{'PBDESTDIR'}/pbtest")) {
2135 die "No test script ($ENV{'PBDESTDIR'}/pbtest) found when in test mode. Aborting ...";
2136 }
2137 print SCRIPT "pb $verbose -p $ENV{'PBPROJ'} $action"."2pkg $p\n";
2138
2139 if ($vtype eq "ve") {
2140 print SCRIPT "sudo umount /proc\n";
2141 }
2142
2143 # We may need to do some other tasks after building. Read a script here to exit properly
2144 if (-x "$ENV{'PBDESTDIR'}/pb$vtype"."$action.post") {
2145 print SCRIPT "# Special post-$action instructions to be launched\n";
2146 print SCRIPT pb_get_content("$ENV{'PBDESTDIR'}/pb$vtype"."$action.post");
2147 }
2148
2149 if (-x "$ENV{'PBDESTDIR'}/pb$vtype".".post") {
2150 print SCRIPT "# Special post-instructions to be launched\n";
2151 print SCRIPT pb_get_content("$ENV{'PBDESTDIR'}/pb$vtype".".post");
2152 }
2153
2154 close(SCRIPT);
2155 chmod 0755,"$ENV{'PBDESTDIR'}/pbscript";
2156
2157 # Launch the VM/VE
2158 ($vmexist,$vmpid) = pb_launchv($vtype,$v,0);
2159
2160 if ($vtype eq "vm") {
2161 # Skip that VM if it something went wrong
2162 next if (($vmpid == 0) && ($vmexist == 0));
2163 } else {
2164 # VE
2165 $vmexist = 0;
2166 $vmpid = 0;
2167 }
2168 # Gather all required files to send them to the VM/VE
2169 # and launch the build through pbscript
2170 pb_log(2,"Calling send2target $vtype,$v,$vmexist,$vmpid\n");
2171 pb_send2target(uc($vtype).$action,"$v",$vmexist,$vmpid);
2172}
2173}
2174
2175
2176sub pb_clean {
2177
2178 my $sleep=10;
2179 die "Unable to get env var PBDESTDIR" if (not defined $ENV{'PBDESTDIR'});
2180 die "Unable to get env var PBBUILDDIR" if (not defined $ENV{'PBBUILDDIR'});
2181 pb_log(0,"We will now wait $sleep s before removing both directories\n$ENV{'PBDESTDIR'} and $ENV{'PBBUILDDIR'}.\nPlease break me if this is wrong\n");
2182 sleep $sleep;
2183 pb_rm_rf($ENV{'PBDESTDIR'});
2184 pb_rm_rf($ENV{'PBBUILDDIR'});
2185}
2186
2187sub pb_newver {
2188
2189 die "-V Version parameter needed" if ((not defined $newver) || ($newver eq ""));
2190
2191 # Need this call for PBDIR
2192 my ($scheme2,$uri) = pb_cms_init($pbinit);
2193
2194 my ($pbconf,$pburl) = pb_conf_get("pbconfurl","pburl");
2195 $uri = $pbconf->{$ENV{'PBPROJ'}};
2196 my ($scheme, $account, $host, $port, $path) = pb_get_uri($uri);
2197
2198 # Checking CMS repositories status
2199 ($scheme2, $account, $host, $port, $path) = pb_get_uri($pburl->{$ENV{'PBPROJ'}});
2200
2201 if ($scheme !~ /^svn/) {
2202 die "Only SVN is supported at the moment";
2203 }
2204
2205 my $res = pb_cms_isdiff($scheme,$ENV{'PBROOTDIR'});
2206 die "ERROR: No differences accepted in CMS for $ENV{'PBROOTDIR'} before creating a new version" if ($res != 0);
2207
2208 $res = pb_cms_isdiff($scheme2,$ENV{'PBDIR'});
2209 die "ERROR: No differences accepted in CMS for $ENV{'PBDIR'} before creating a new version" if ($res != 0);
2210
2211 # Tree identical between PBCONFDIR and PBROOTDIR. The delta is what
2212 # we want to get for the root of the new URL
2213
2214 my $tmp = $ENV{'PBROOTDIR'};
2215 $tmp =~ s|^$ENV{'PBCONFDIR'}||;
2216
2217 my $newurl = "$uri/".dirname($tmp)."/$newver";
2218 # Should probably use projver in the old file
2219 my $oldver= basename($tmp);
2220
2221 # Duplicate and extract project-builder part
2222 pb_log(2,"Copying $uri/$tmp to $newurl\n");
2223 pb_cms_copy($scheme,"$uri/$tmp",$newurl);
2224 pb_log(2,"Checkout $newurl to $ENV{'PBROOTDIR'}/../$newver\n");
2225 pb_cms_up($scheme,"$ENV{'PBCONFDIR'}/..");
2226
2227 # Duplicate and extract project
2228 my $newurl2 = "$pburl->{$ENV{'PBPROJ'}}/".dirname($tmp)."/$newver";
2229
2230 pb_log(2,"Copying $pburl->{$ENV{'PBPROJ'}}/$tmp to $newurl2\n");
2231 pb_cms_copy($scheme2,"$pburl->{$ENV{'PBPROJ'}}/$tmp",$newurl2);
2232 pb_log(2,"Checkout $newurl2 to $ENV{'PBDIR'}/../$newver\n");
2233 pb_cms_up($scheme2,"$ENV{'PBDIR'}/..");
2234
2235 # Update the .pb file
2236 open(FILE,"$ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb") || die "Unable to open $ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb";
2237 open(OUT,"> $ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb.new") || die "Unable to write to $ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb.new";
2238 while(<FILE>) {
2239 s/^projver\s+$ENV{'PBPROJ'}\s*=\s*$oldver/projver $ENV{'PBPROJ'} = $newver/;
2240 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/);
2241 pb_log(0,"Commenting testver in $ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb\n") if (/^testver/);
2242 s/^testver/#testver/;
2243 print OUT $_;
2244 pb_log(0,"Please check delivery ($_) in $ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb\n") if (/^delivery/);
2245 }
2246 close(FILE);
2247 close(OUT);
2248 rename("$ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb.new","$ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb");
2249
2250 # Checking pbcl files
2251 foreach my $f (<$ENV{'PBROOTDIR'}/*/pbcl>) {
2252 # Compute new pbcl file
2253 my $f2 = $f;
2254 $f2 =~ s|$ENV{'PBROOTDIR'}|$ENV{'PBROOTDIR'}/../$newver/|;
2255 open(PBCL,$f) || die "Unable to open $f";
2256 my $foundnew = 0;
2257 while (<PBCL>) {
2258 $foundnew = 1 if (/^$newver \(/);
2259 }
2260 close(PBCL);
2261 open(OUT,"> $f2") || die "Unable to write to $f2: $!";
2262 open(PBCL,$f) || die "Unable to open $f";
2263 while (<PBCL>) {
2264 print OUT "$_" if (not /^$oldver \(/);
2265 if ((/^$oldver \(/) && ($foundnew == 0)) {
2266 print OUT "$newver ($pbdate)\n";
2267 print OUT "- TBD\n";
2268 print OUT "\n";
2269 pb_log(0,"WARNING: version $newver not found in $f so added to $f2...\n") if ($foundnew == 0);
2270 }
2271 }
2272 close(OUT);
2273 close(PBCL);
2274 }
2275
2276 pb_log(2,"Checkin $ENV{'PBROOTDIR'}/../$newver\n");
2277 pb_cms_checkin($scheme,"$ENV{'PBROOTDIR'}/../$newver",undef);
2278}
2279
2280#
2281# Return the list of VMs/VEs we are working on
2282# $all is a flag to know if we return all of them
2283# or only some (if all we publish also tar files in addition to pkgs
2284#
2285sub pb_get2v {
2286
2287my $vtype = shift;
2288my @v;
2289my $all = 0;
2290my $vlist;
2291my $pbv = 'PBV';
2292
2293if ($vtype eq "vm") {
2294 $vlist = "vmlist";
2295} elsif ($vtype eq "ve") {
2296 $vlist = "velist";
2297}
2298# Get VM/VE list
2299if ((not defined $ENV{$pbv}) || ($ENV{$pbv} =~ /^all$/)) {
2300 my ($ptr) = pb_conf_get($vlist);
2301 $ENV{$pbv} = $ptr->{$ENV{'PBPROJ'}};
2302 $all = 1;
2303}
2304pb_log(2,"$vtype: $ENV{$pbv}\n");
2305@v = split(/,/,$ENV{$pbv});
2306return(\@v,$all);
2307}
2308
2309# Function to create a potentialy missing pb account on the VM/VE, and adds it to sudo
2310# Needs to use root account to connect to the VM/VE
2311# pb will take your local public SSH key to access
2312# the pb account in the VM later on if needed
2313sub pb_setup2v {
2314
2315my $vtype = shift;
2316
2317my ($vm,$all) = pb_get2v($vtype);
2318
2319# Script generated
2320my $pbscript = "$ENV{'PBDESTDIR'}/setupv";
2321
2322foreach my $v (@$vm) {
2323 # Deal with date sync.
2324 my ($ntpline,$dateline) = pb_date2v($vtype,$v);
2325
2326 # Get distro context
2327 my ($name,$ver,$darch) = split(/-/,$v);
2328 chomp($darch);
2329 my ($ddir, $dver, $dfam, $dtype, $dos, $pbsuf, $pbupd, $pbins) = pb_distro_init($name,$ver,$darch);
2330
2331 # Name of the account to deal with for VM/VE
2332 # Do not use the one passed potentially with -a
2333 my ($pbac) = pb_conf_get($vtype."login");
2334 my ($key,$zero0,$zero1,$zero2);
2335 my ($vmexist,$vmpid);
2336
2337 # Prepare the script to be executed on the VM/VE
2338 # in $ENV{'PBDESTDIR'}/setupv
2339 open(SCRIPT,"> $pbscript") || die "Unable to create $pbscript";
2340
2341 print SCRIPT << 'EOF';
2342#!/usr/bin/perl -w
2343
2344use strict;
2345use File::Copy;
2346
2347# We should not need in this script more functions than what is provided
2348# by Base and Distribution to avoid problems at exec time.
2349# They are appended at the end.
2350
2351our $pbdebug;
2352our $pbLOG;
2353our $pbsynmsg = "pbscript";
2354our $pbdisplaytype = "text";
2355our $pblocale = "";
2356pb_log_init($pbdebug, $pbLOG);
2357pb_temp_init();
2358
2359EOF
2360
2361 # Launch the VM/VE - Usage of snapshot disabled
2362 ($vmexist,$vmpid) = pb_launchv($vtype,$v,0,0,0);
2363
2364 if ($vtype eq "vm") {
2365 # Prepare the key to be used and transfered remotely
2366 my $keyfile = pb_ssh_get(1);
2367
2368 my ($vmhost,$vmport,$vmntp) = pb_conf_get("vmhost","vmport","vmntp");
2369 my $nport = $vmport->{$ENV{'PBPROJ'}};
2370 $nport = "$pbport" if (defined $pbport);
2371
2372 # Skip that VM if something went wrong
2373 next if (($vmpid == 0) && ($vmexist == 0));
2374
2375 # Store the pub key part in a variable
2376 open(FILE,"$keyfile.pub") || die "Unable to open $keyfile.pub";
2377 ($zero0,$zero1,$zero2) = split(/ /,<FILE>);
2378 close(FILE);
2379
2380 $key = "\Q$zero1";
2381
2382 # We call true to avoid problems if SELinux is not activated, but chcon is present and returns in that case 1
2383 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 ; if [ -x /usr/bin/chcon ]; then /usr/bin/chcon -Rt home_ssh_t .ssh 2> /dev/null; /bin/true; fi\"","Copying local keys to $vtype. This may require the root password");
2384 # once this is done, we can do what we want on the VM remotely
2385 } elsif ($vtype eq "ve") {
2386 print SCRIPT << "EOF";
2387# For VE we need a good null dev
2388pb_system("rm -f /dev/null; mknod /dev/null c 1 3; chmod 777 /dev/null");
2389EOF
2390 print SCRIPT << "EOF";
2391# For VE we first need to mount some FS
2392pb_system("mount -t proc /proc /proc");
2393
2394EOF
2395 }
2396
2397if ($vtype eq "vm") {
2398 print SCRIPT << 'EOF';
2399# Removes duplicate in .ssh/authorized_keys of our key if needed
2400#
2401my $file1="$ENV{'HOME'}/.ssh/authorized_keys";
2402open(PBFILE,$file1) || die "Unable to open $file1";
2403open(PBOUT,"> $file1.new") || die "Unable to open $file1.new";
2404my $count = 0;
2405while (<PBFILE>) {
2406
2407EOF
2408 print SCRIPT << "EOF";
2409 if (/ $key /) {
2410 \$count++;
2411 }
2412print PBOUT \$_ if ((\$count <= 1) || (\$_ !~ / $key /));
2413}
2414close(PBFILE);
2415close(PBOUT);
2416rename("\$file1.new",\$file1);
2417chmod 0600,\$file1;
2418
2419# Sync date
2420EOF
2421 if (defined $ntpline) {
2422 print SCRIPT "pb_system(\"$ntpline\");\n";
2423 } else {
2424 print SCRIPT "pb_system(\"$dateline\");\n";
2425 }
2426 }
2427 print SCRIPT << 'EOF';
2428
2429# Adds $pbac->{$ENV{'PBPROJ'}} as an account if needed
2430#
2431my $file="/etc/passwd";
2432open(PBFILE,$file) || die "Unable to open $file";
2433my $found = 0;
2434while (<PBFILE>) {
2435EOF
2436 print SCRIPT << "EOF";
2437 \$found = 1 if (/^$pbac->{$ENV{'PBPROJ'}}:/);
2438EOF
2439
2440my $home = "/home";
2441# Solaris doesn't like that we use /home
2442$home = "/export/home" if ($dtype eq "pkg");
2443
2444 print SCRIPT << "EOF";
2445}
2446close(PBFILE);
2447
2448if ( \$found == 0 ) {
2449 if ( ! -d "$home" ) {
2450 pb_mkdir_p("$home");
2451 }
2452EOF
2453 print SCRIPT << "EOF";
2454pb_system("/usr/sbin/groupadd $pbac->{$ENV{'PBPROJ'}}","Adding group $pbac->{$ENV{'PBPROJ'}}");
2455pb_system("/usr/sbin/useradd -g $pbac->{$ENV{'PBPROJ'}} -m -d $home/$pbac->{$ENV{'PBPROJ'}} $pbac->{$ENV{'PBPROJ'}}","Adding user $pbac->{$ENV{'PBPROJ'}} (group $pbac->{$ENV{'PBPROJ'}} - home $home/$pbac->{$ENV{'PBPROJ'}})");
2456}
2457EOF
2458
2459 # Copy the content of our local conf file to the VM/VE
2460 my $content = pb_get_content(pb_distro_conffile());
2461 print SCRIPT << "EOF";
2462 #
2463 # Create a temporary local conf file for distribution support
2464 # This is created here before its use later. Its place is hardcoded, so no choice for the path
2465 #
2466 my \$tempconf = pb_distro_conffile();
2467 pb_mkdir_p(dirname(\$tempconf));
2468 open(CONF,"> \$tempconf") || die "Unable to create \$tempconf";
2469 print CONF q{$content};
2470 close(CONF);
2471EOF
2472
2473 if ($vtype eq "vm") {
2474 print SCRIPT << "EOF";
2475# allow ssh entry to build
2476#
2477mkdir "$home/$pbac->{$ENV{'PBPROJ'}}/.ssh",0700;
2478# Allow those accessing root to access the build account
2479copy("\$ENV{'HOME'}/.ssh/authorized_keys","$home/$pbac->{$ENV{'PBPROJ'}}/.ssh/authorized_keys");
2480chmod 0600,".ssh/authorized_keys";
2481pb_system("chown -R $pbac->{$ENV{'PBPROJ'}}:$pbac->{$ENV{'PBPROJ'}} $home/$pbac->{$ENV{'PBPROJ'}}","Finish setting up the account env for $pbac->{$ENV{'PBPROJ'}}");
2482
2483EOF
2484}
2485 print SCRIPT << 'EOF';
2486# No passwd for build account only keys
2487$file="/etc/shadow";
2488if (-f $file) {
2489 open(PBFILE,$file) || die "Unable to open $file";
2490 open(PBOUT,"> $file.new") || die "Unable to open $file.new";
2491 while (<PBFILE>) {
2492EOF
2493 print SCRIPT << "EOF";
2494 s/^$pbac->{$ENV{'PBPROJ'}}:\!\!:/$pbac->{$ENV{'PBPROJ'}}:*:/;
2495 s/^$pbac->{$ENV{'PBPROJ'}}:\!:/$pbac->{$ENV{'PBPROJ'}}:*:/; #SLES 9 e.g.
2496 s/^$pbac->{$ENV{'PBPROJ'}}:\\*LK\\*:/$pbac->{$ENV{'PBPROJ'}}:NP:/; #Solaris e.g.
2497EOF
2498 print SCRIPT << 'EOF';
2499 print PBOUT $_;
2500 }
2501 close(PBFILE);
2502 close(PBOUT);
2503 rename("$file.new",$file);
2504 chmod 0640,$file;
2505 }
2506
2507# Keep the VM in text mode
2508$file="/etc/inittab";
2509if (-f $file) {
2510 open(PBFILE,$file) || die "Unable to open $file";
2511 open(PBOUT,"> $file.new") || die "Unable to open $file.new";
2512 while (<PBFILE>) {
2513 s/^(..):5:initdefault:$/$1:3:initdefault:/;
2514 print PBOUT $_;
2515 }
2516 close(PBFILE);
2517 close(PBOUT);
2518 rename("$file.new",$file);
2519 chmod 0640,$file;
2520}
2521
2522# pb has to be added to portage group on gentoo
2523
2524# We need to have that pb_distro_init function
2525# Get it from Project-Builder::Distribution
2526# And we now need the conf file required for this to work created above
2527
2528my ($ddir, $dver, $dfam, $dtype, $dos, $pbsuf, $pbupd, $pbins, $darch) = pb_distro_init();
2529print "distro tuple: ".join(',',($ddir, $dver, $dfam, $dtype, $pbsuf, $pbupd, $pbins, $darch))."\n";
2530
2531# Adapt sudoers
2532# sudo is not default on Solaris and needs to be installed first
2533# from http://www.sunfreeware.com/programlistsparc10.html#sudo
2534if ($dtype eq "pkg") {
2535 $file="/usr/local/etc/sudoers";
2536} else {
2537 $file="/etc/sudoers";
2538}
2539open(PBFILE,$file) || die "Unable to open $file";
2540open(PBOUT,"> $file.new") || die "Unable to open $file.new";
2541while (<PBFILE>) {
2542EOF
2543 print SCRIPT << "EOF";
2544 next if (/^$pbac->{$ENV{'PBPROJ'}} /);
2545EOF
2546 print SCRIPT << 'EOF';
2547 s/Defaults[ \t]+requiretty//;
2548 print PBOUT $_;
2549}
2550close(PBFILE);
2551EOF
2552 print SCRIPT << "EOF";
2553# Some distro force requiretty at compile time, so disable here
2554print PBOUT "Defaults:$pbac->{$ENV{'PBPROJ'}} !requiretty\n";
2555print PBOUT "Defaults:root !requiretty\n";
2556# This is needed in order to be able to halt the machine from the $pbac->{$ENV{'PBPROJ'}} account at least
2557print PBOUT "Defaults:$pbac->{$ENV{'PBPROJ'}} env_keep += \\\"http_proxy ftp_proxy\\\"\n";
2558print PBOUT "$pbac->{$ENV{'PBPROJ'}} ALL=(ALL) NOPASSWD:ALL\n";
2559EOF
2560 print SCRIPT << 'EOF';
2561close(PBOUT);
2562rename("$file.new",$file);
2563chmod 0440,$file;
2564
2565EOF
2566
2567 # We may need a proxy configuration. Get it from the local env
2568
2569 if (defined $ENV{'http_proxy'}) {
2570 print SCRIPT "\$ENV\{'http_proxy'\}=\"$ENV{'http_proxy'}\";\n";
2571 }
2572
2573 if (defined $ENV{'ftp_proxy'}) {
2574 print SCRIPT "\$ENV\{'ftp_proxy'\}=\"$ENV{'ftp_proxy'}\";\n";
2575 }
2576
2577 print SCRIPT << 'EOF';
2578
2579# Suse wants sudoers as 640
2580if ((($ddir eq "sles") && (($dver =~ /10/) || ($dver =~ /9/))) || (($ddir eq "opensuse") && ($dver =~ /10.[012]/))) {
2581 chmod 0640,$file;
2582}
2583
2584# First install all required packages
2585pb_system("yum clean all","Cleaning yum env") if (($ddir eq "fedora") || ($ddir eq "asianux") || ($ddir eq "rhel"));
2586my ($ospkgdep) = pb_conf_get_if("ospkgdep");
2587
2588my $pkgdep = pb_distro_get_param($ddir,$dver,$darch,$ospkgdep,$dfam,$dtype,$dos);
2589pb_distro_installdeps(undef,$dtype,$pbins,pb_distro_only_deps_needed($dtype,join(' ',split(/,/,$pkgdep))));
2590
2591EOF
2592 my $itype = pb_conf_get("pbinstalltype");
2593 if ($itype->{$ENV{'PBPROJ'}} =~ /^file/) {
2594 print SCRIPT << 'EOF';
2595# Then install manually the missing perl modules
2596my ($osperldep,$osperlver) = pb_conf_get_if("osperldep","osperlver");
2597
2598my $perldep = pb_distro_get_param($ddir,$dver,$darch,$osperldep,$dfam,$dtype,$dos);
2599foreach my $m (split(/,/,$perldep)) {
2600 # Skip empty deps
2601 next if ($m =~ /^\s*$/);
2602 my $dir = $m;
2603 $dir =~ s/-.*//;
2604 pb_system("echo \"rm -rf $m* ; wget http://search.cpan.org/CPAN/modules/by-module/$dir/$m-$osperlver->{$m}.tar.gz ; gzip -cd $m-$osperlver->{$m}.tar.gz | tar xf - ; cd $m* ; if [ -f Build.PL ]; then perl Build.PL; ./Build ; ./Build install ; else perl Makefile.PL; make ; make install ; fi; cd .. ; rm -rf $m*\" | bash" ,"Installing perl module $m-$osperlver->{$m}");
2605}
2606
2607pb_system("rm -rf ProjectBuilder-* ; wget --passive-ftp ftp://ftp.mondorescue.org/src/ProjectBuilder-latest.tar.gz ; gzip -cd ProjectBuilder-latest.tar.gz | tar xf - ; cd ProjectBuilder-* ; perl Makefile.PL ; make ; make install ; cd .. ; rm -rf ProjectBuilder-* ; rm -rf project-builder-* ; wget --passive-ftp ftp://ftp.mondorescue.org/src/project-builder-latest.tar.gz ; gzip -cd project-builder-latest.tar.gz | tar xf - ; cd project-builder-* ; perl Makefile.PL ; make ; make install ; cd .. ; rm -rf project-builder-* ;","Building Project-Builder");
2608EOF
2609 } elsif ($itype->{$ENV{'PBPROJ'}} =~ /^pkg/) {
2610 # pkg based install. We need to point to the project-builder.org repository
2611 print SCRIPT << 'EOF';
2612my ($pbpkg) = pb_conf_get_if("pbpkg");
2613
2614my $pkgforpb = pb_distro_get_param($ddir,$dver,$darch,$pbpkg,$dfam,$dtype,$depdos);
2615pb_distro_setuprepo($ddir,$dver,$darch,$dtype);
2616pb_distro_installdeps(undef,$dtype,$pbins,pb_distro_only_deps_needed($dtype,join(' ',split(/,/,$pkgforpb))));
2617EOF
2618 } else {
2619 # Unknown install type
2620 die("Unknown install type $itype->{$ENV{'PBPROJ'}} for param pbinstalltype");
2621 }
2622 print SCRIPT << 'EOF';
2623pb_system("pb 2>&1 | head -5",undef,"verbose");
2624EOF
2625 if ($vtype eq "ve") {
2626 print SCRIPT << 'EOF';
2627# For VE we need to umount some FS at the end
2628
2629pb_system("umount /proc");
2630
2631# Create a basic network file if not already there
2632
2633my $nf="/etc/sysconfig/network";
2634if ((! -f $nf) && ($dtype eq "rpm")) {
2635 open(NF,"> $nf") || die "Unable to create $nf";
2636 print NF "NETWORKING=yes\n";
2637 print NF "HOSTNAME=localhost\n";
2638 close(NF);
2639}
2640chmod 0755,$nf;
2641EOF
2642 }
2643
2644 # Adds pb_distro_init and all functions needed from ProjectBuilder::Distribution and Base
2645 foreach my $d (@INC) {
2646 my @f = ("$d/ProjectBuilder/Base.pm","$d/ProjectBuilder/Distribution.pm","$d/ProjectBuilder/Conf.pm");
2647 foreach my $f (@f) {
2648 if (-f "$f") {
2649 open(PBD,"$f") || die "Unable to open $f";
2650 while (<PBD>) {
2651 next if (/^package/);
2652 next if (/^use Exporter/);
2653 next if (/^use ProjectBuilder::/);
2654 next if (/^our /);
2655 print SCRIPT $_;
2656 }
2657 close(PBD);
2658 }
2659 }
2660 }
2661 close(SCRIPT);
2662 chmod 0755,"$pbscript";
2663
2664 # That build script needs to be run as root and force stop of VM at end
2665 $pbaccount = "root";
2666
2667 # Force shutdown of VM except if it was already launched
2668 my $pbforce = 0;
2669 if ((! $vmexist) && ($vtype eq "vm")) {
2670 $pbforce = 1;
2671 }
2672
2673 pb_script2v($pbscript,$vtype,$pbforce,$v);
2674}
2675return;
2676}
2677
2678# Function to create a snapshot named 'pb' for VMs and a compressed tar for VEs
2679sub pb_snap2v {
2680
2681my $vtype = shift;
2682
2683my ($vm,$all) = pb_get2v($vtype);
2684
2685# Script generated
2686my $pbscript = "$ENV{'PBDESTDIR'}/snapv";
2687
2688my ($pbac) = pb_conf_get($vtype."login");
2689
2690foreach my $v (@$vm) {
2691 # Get distro context
2692 my ($name,$ver,$darch) = split(/-/,$v);
2693 chomp($darch);
2694 my ($ddir, $dver, $dfam, $dtype, $dos, $pbsuf) = pb_distro_init($name,$ver,$darch);
2695 my ($vepath) = pb_conf_get("vepath");
2696
2697 # Test if an existing snapshot exists and remove it if there is a VE
2698 if ((-f "$vepath->{$ENV{'PBPROJ'}}/$ddir-$dver-$darch.tar.gz") &&
2699 (! -d "$vepath->{$ENV{'PBPROJ'}}/$ddir/$dver/$darch")) {
2700 pb_system("sudo rm -f $vepath->{$ENV{'PBPROJ'}}/$ddir-$dver-$darch.tar.gz","Removing previous snapshot $ddir-$dver-$darch.tar.gz");
2701 }
2702
2703 # Prepare the script to be executed on the VM/VE
2704 # in $ENV{'PBDESTDIR'}/setupv
2705 open(SCRIPT,"> $pbscript") || die "Unable to create $pbscript";
2706
2707 print SCRIPT << 'EOF';
2708 #!/bin/bash
2709 sleep 2
2710EOF
2711 close(SCRIPT);
2712 chmod 0755,"$pbscript";
2713
2714 # Force shutdown of VM/VE
2715 # Force snapshot of VM/VE
2716 pb_script2v($pbscript,$vtype,1,$v,1);
2717}
2718return;
2719}
2720
2721# Function to update a VMs or VEs with the latest distribution content
2722sub pb_update2v {
2723
2724my $vtype = shift;
2725
2726my ($vm,$all) = pb_get2v($vtype);
2727
2728# Script generated
2729my $pbscript = "$ENV{'PBDESTDIR'}/updatev";
2730
2731my ($pbac) = pb_conf_get($vtype."login");
2732
2733foreach my $v (@$vm) {
2734 # Get distro context
2735 my ($name,$ver,$darch) = split(/-/,$v);
2736 chomp($darch);
2737 my ($ddir, $dver, $dfam, $dtype, $dos, $pbsuf, $pbupd, $pbins) = pb_distro_init($name,$ver,$darch);
2738
2739 # Prepare the script to be executed on the VM/VE
2740 # in $ENV{'PBDESTDIR'}/updatev
2741 open(SCRIPT,"> $pbscript") || die "Unable to create $pbscript";
2742
2743 print SCRIPT << 'EOF';
2744 #!/bin/bash
2745 sleep 2
2746EOF
2747 # VE needs a good /proc
2748 if ($vtype eq "ve") {
2749 print SCRIPT "sudo mount -t proc /proc /proc\n";
2750 }
2751 print SCRIPT "$pbupd\n";
2752 if ($vtype eq "ve") {
2753 print SCRIPT "sudo umount /proc\n";
2754 }
2755 close(SCRIPT);
2756 chmod 0755,"$pbscript";
2757
2758 # Force shutdown of VM except
2759 pb_script2v($pbscript,$vtype,1,$v);
2760}
2761return;
2762}
2763
2764sub pb_announce {
2765
2766 # Get all required parameters
2767 my ($pbpackager,$pbrepo,$pbml,$pbsmtp) = pb_conf_get("pbpackager","pbrepo","pbml","pbsmtp");
2768 my ($pkgv, $pkgt, $testver) = pb_conf_get_if("pkgver","pkgtag","testver");
2769 my $pkg = pb_cms_get_pkg($defpkgdir,$extpkgdir);
2770 my @pkgs = @$pkg;
2771 my %pkgs;
2772 my $first = 0;
2773
2774 # Command to find packages on repo
2775 my $findstr = "find . ";
2776 # Generated announce files
2777 my @files;
2778
2779 foreach my $pbpkg (@pkgs) {
2780 if ($first != 0) {
2781 $findstr .= "-o ";
2782 }
2783 $first++;
2784 if ((defined $pkgv) && (defined $pkgv->{$pbpkg})) {
2785 $pbver = $pkgv->{$pbpkg};
2786 } else {
2787 $pbver = $ENV{'PBPROJVER'};
2788 }
2789 if ((defined $pkgt) && (defined $pkgt->{$pbpkg})) {
2790 $pbtag = $pkgt->{$pbpkg};
2791 } else {
2792 $pbtag = $ENV{'PBPROJTAG'};
2793 }
2794
2795 # TODO: use virtual/real names here now
2796 $findstr .= "-name \'$pbpkg-$pbver-$pbtag\.*.rpm\' -o -name \'$pbpkg"."_$pbver*\.deb\' -o -name \'$pbpkg-$pbver*\.ebuild\' ";
2797
2798 my $chglog;
2799
2800 # Get project info on log file and generate tmp files used later on
2801 pb_cms_init($pbinit);
2802 $chglog = "$ENV{'PBROOTDIR'}/$pbpkg/pbcl";
2803 $chglog = "$ENV{'PBROOTDIR'}/pbcl" if (! -f $chglog);
2804 $chglog = undef if (! -f $chglog);
2805
2806 open(OUT,"> $ENV{'PBTMP'}/$pbpkg.ann") || die "Unable to create $ENV{'PBTMP'}/$pbpkg.ann: $!";
2807 my %pb;
2808 $pb{'dtype'} = "announce";
2809 $pb{'realpkg'} = $pbpkg;
2810 $pb{'ver'} = $pbver;
2811 $pb{'tag'} = $pbtag;
2812 $pb{'suf'} = "N/A"; # Should not be empty even if unused
2813 $pb{'date'} = $pbdate;
2814 $pb{'chglog'} = $chglog;
2815 $pb{'packager'} = $pbpackager;
2816 $pb{'proj'} = $ENV{'PBPROJ'};
2817 $pb{'repo'} = $pbrepo;
2818 pb_changelog(\%pb,\*OUT,"yes");
2819 close(OUT);
2820 push(@files,"$ENV{'PBTMP'}/$pbpkg.ann");
2821 }
2822 $findstr .= " | grep -Ev \'src.rpm\'";
2823
2824 # Prepare the command to run and execute it
2825 open(PBS,"> $ENV{'PBTMP'}/pbscript") || die "Unable to create $ENV{'PBTMP'}/pbscript";
2826 print PBS "$findstr\n";
2827 close(PBS);
2828 chmod 0755,"$ENV{'PBTMP'}/pbscript";
2829 pb_send2target("Announce");
2830
2831 # Get subject line
2832 my $sl = "Project $ENV{'PBPROJ'} version $ENV{'PBPROJVER'} is now available";
2833 pb_log(0,"Please enter the title of your announce\n");
2834 pb_log(0,"(By default: $sl)\n");
2835 my $sl2 = <STDIN>;
2836 $sl = $sl2 if ($sl2 !~ /^$/);
2837
2838 # Prepare a template of announce
2839 open(ANN,"> $ENV{'PBTMP'}/announce.html") || die "Unable to create $ENV{'PBTMP'}/announce.html: $!";
2840 print ANN << "EOF";
2841$sl</p>
2842
2843<p>The project team is happy to announce the availability of a newest version of $ENV{'PBPROJ'} $ENV{'PBPROJVER'}. Enjoy it as usual!</p>
2844<p>
2845Now available at <a href="$pbrepo->{$ENV{'PBPROJ'}}">$pbrepo->{$ENV{'PBPROJ'}}</a>
2846</p>
2847<p>
2848EOF
2849 open(LOG,"$ENV{'PBTMP'}/system.log") || die "Unable to read $ENV{'PBTMP'}/system.log: $!";
2850 my $col = 2;
2851 my $i = 1;
2852 print ANN << 'EOF';
2853<TABLE WIDTH="700" CELLPADDING="0" CELLSPACING="0" BORDER="0">
2854<TR>
2855EOF
2856 while (<LOG>) {
2857 print ANN "<TD><A HREF=\"$pbrepo->{$ENV{'PBPROJ'}}/$_\">$_</A></TD>";
2858 $i++;
2859 if ($i > $col) {
2860 print ANN "</TR>\n<TR>";
2861 $i = 1;
2862 }
2863 }
2864 close(LOG);
2865 print ANN << "EOF";
2866</TR>
2867</TABLE>
2868</p>
2869
2870<p>As usual source packages are also available in the same directory.</p>
2871
2872<p>
2873Changes are :
2874</p>
2875<p>
2876EOF
2877 # Get each package changelog content
2878 foreach my $f (sort(@files)) {
2879 open(IN,"$f") || die "Unable to read $f:$!";
2880 while (<IN>) {
2881 print ANN $_;
2882 }
2883 close(IN);
2884 print ANN "</p><p>\n";
2885 }
2886 print ANN "</p>\n";
2887 close(ANN);
2888
2889 # Allow for modification
2890 my $editor = "vi";
2891 $editor = $ENV{'EDITOR'} if (defined $ENV{'EDITOR'});
2892 pb_system("$editor $ENV{'PBTMP'}/announce.html","Allowing modification of the announce","noredir");
2893
2894 # Store it in DB for external usage (Web pages generation)
2895 my $db = "$ENV{'PBCONFDIR'}/announces3.sql";
2896
2897 my $precmd = "";
2898 if (! -f $db) {
2899 $precmd = "CREATE TABLE announces (id INTEGER PRIMARY KEY AUTOINCREMENT, date DATE, announce VARCHAR[65535])";
2900 }
2901
2902 my $dbh = DBI->connect("dbi:SQLite:dbname=$db","","",
2903 { RaiseError => 1, AutoCommit => 1 })
2904 || die "Unable to connect to $db";
2905
2906 if ($precmd ne "") {
2907 my $sth = $dbh->prepare(qq{$precmd})
2908 || die "Unable to create table into $db";
2909 $sth->execute();
2910 }
2911
2912 # To read whole file
2913 local $/;
2914 open(ANN,"$ENV{'PBTMP'}/announce.html") || die "Unable to read $ENV{'PBTMP'}/announce.html: $!";
2915 my $announce = <ANN>;
2916 close(ANN);
2917
2918 pb_log(2,"INSERT INTO announces VALUES (NULL, $pbdate, $announce)");
2919 my $sth = $dbh->prepare(qq{INSERT INTO announces VALUES (NULL,?,?)})
2920 || die "Unable to insert into $db";
2921 $sth->execute($pbdate, $announce);
2922 $sth->finish();
2923 $dbh->disconnect;
2924
2925 # Then deliver it on the Web
2926 # $TOOLHOME/livwww www
2927
2928 # Mail it to project's ML
2929 open(ML,"| w3m -dump -T text/html > $ENV{'PBTMP'}/announce.txt") || die "Unable to create $ENV{'PBTMP'}/announce.txt: $!";
2930 print ML << 'EOF';
2931<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/x html1/DTD/xhtml1-strict.dtd">
2932
2933<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" xml:lang="en" lang="en">
2934 <head>
2935 </head>
2936 <body>
2937 <p>
2938EOF
2939 open(ANN,"$ENV{'PBTMP'}/announce.html") || die "Unable to read $ENV{'PBTMP'}/announce.html: $!";
2940 while(<ANN>) {
2941 print ML $_;
2942 }
2943 print ML << 'EOF';
2944</body>
2945</html>
2946EOF
2947 close(ML);
2948
2949 # To read whole file
2950 local $/;
2951 open(ANN,"$ENV{'PBTMP'}/announce.txt") || die "Unable to read $ENV{'PBTMP'}/announce.txt: $!";
2952 my $msg = <ANN>;
2953 close(ANN);
2954
2955 # Preparation of headers
2956 require Mail::Sendmail;
2957
2958 my %mail = (
2959 To => $pbml->{$ENV{'PBPROJ'}},
2960 From => $pbpackager->{$ENV{'PBPROJ'}},
2961 Smtp => $pbsmtp->{$ENV{'PBPROJ'}},
2962 Body => $msg,
2963 Subject => "[ANNOUNCE] $sl",
2964 );
2965
2966 # Send mail
2967 if (! sendmail(%mail)) {
2968 if ((defined $Mail::Sendmail::error) and (defined $Mail::Sendmail::log)) {
2969 die "Unable to send mail ($Mail::Sendmail::error): $Mail::Sendmail::log";
2970 }
2971 }
2972}
2973
2974#
2975# Creates a set of HTML file containing the news for the project
2976# based on what has been generated by the pb_announce function
2977#
2978sub pb_web_news2html {
2979
2980 my $dest = shift || $ENV{'PBTMP'};
2981
2982 # Get all required parameters
2983 my ($pkgv, $pkgt) = pb_conf_get_if("pkgver","pkgtag");
2984
2985 # DB of announces for external usage (Web pages generation)
2986 my $db = "$ENV{'PBCONFDIR'}/announces3.sql";
2987
2988 my $dbh = DBI->connect("dbi:SQLite:dbname=$db","","",
2989 { RaiseError => 1, AutoCommit => 1 })
2990 || die "Unable to connect to $db";
2991 # For date handling
2992 $ENV{LANGUAGE}="C";
2993 my $firstjan = strftime("%Y-%m-%d", 0, 0, 0, 1, 0, localtime->year(), 0, 0, -1);
2994 my $oldfirst = strftime("%Y-%m-%d", 0, 0, 0, 1, 0, localtime->year()-1, 0, 0, -1);
2995 pb_log(2,"firstjan: $firstjan, oldfirst: $oldfirst, pbdate:$pbdate\n");
2996 my $all = $dbh->selectall_arrayref("SELECT id,date,announce FROM announces ORDER BY date DESC");
2997 my %news;
2998 $news{"cy"} = ""; # current year's news
2999 $news{"ly"} = ""; # last year news
3000 $news{"py"} = ""; # previous years news
3001 $news{"fp"} = ""; # first page news
3002 my $cpt = 4; # how many news for first page
3003 # Extract info from DB
3004 foreach my $row (@$all) {
3005 my ($id, $date, $announce) = @$row;
3006 $news{"cy"} = $news{"cy"}."<p><B>$date</B> $announce\n" if ((($date cmp $pbdate) le 0) && (($firstjan cmp $date) le 0));
3007 $news{"ly"} = $news{"ly"}."<p><B>$date</B> $announce\n" if ((($date cmp $firstjan) le 0) && (($oldfirst cmp $date) le 0));
3008 $news{"py"} = $news{"py"}."<p><B>$date</B> $announce\n" if (($date cmp $oldfirst) le 0);
3009 $news{"fp"} = $news{"fp"}."<p><B>$date</B> $announce\n" if ($cpt > 0);
3010 $cpt--;
3011 }
3012 pb_log(1,"news{fp}: ".$news{"fp"}."\n");
3013 $dbh->disconnect;
3014
3015 # Generate the HTML content
3016 foreach my $pref (keys %news) {
3017 open(NEWS,"> $dest/pb_web_$pref"."news.html") || die "Unable to create $dest/pb_web_$pref"."news.html: $!";
3018 print NEWS "$news{$pref}";
3019 close(NEWS);
3020 }
3021}
3022
3023
3024# Return the SSH key file to use
3025# Potentially create it if needed
3026
3027sub pb_ssh_get {
3028
3029my $create = shift || 0; # Do not create keys by default
3030
3031# Check the SSH environment
3032my $keyfile = undef;
3033
3034# We have specific keys by default
3035$keyfile = "$ENV{'HOME'}/.ssh/pb_dsa";
3036if (!(-e $keyfile) && ($create eq 1)) {
3037 pb_system("ssh-keygen -q -b 1024 -N '' -f $keyfile -t dsa","Generating SSH keys for pb");
3038}
3039
3040$keyfile = "$ENV{'HOME'}/.ssh/id_rsa" if (-s "$ENV{'HOME'}/.ssh/id_rsa");
3041$keyfile = "$ENV{'HOME'}/.ssh/id_dsa" if (-s "$ENV{'HOME'}/.ssh/id_dsa");
3042$keyfile = "$ENV{'HOME'}/.ssh/pb_dsa" if (-s "$ENV{'HOME'}/.ssh/pb_dsa");
3043die "Unable to find your public ssh key under $keyfile" if (not defined $keyfile);
3044return($keyfile);
3045}
3046
3047
3048# Returns the pid of a running VM command using a specific VM file
3049sub pb_check_ps {
3050 my $vmcmd = shift;
3051 my $vmm = shift;
3052 my $vmexist = 0; # FALSE by default
3053
3054 open(PS, "ps auxhww|") || die "Unable to call ps";
3055 while (<PS>) {
3056 next if (! /$vmcmd/);
3057 next if (! /$vmm/);
3058 my ($void1, $void2);
3059 ($void1, $vmexist, $void2) = split(/ +/);
3060 last;
3061 }
3062 return($vmexist);
3063}
3064
3065
3066sub pb_extract_build_files {
3067
3068my $src=shift;
3069my $dir=shift;
3070my $ddir=shift;
3071my $mandatory=shift || "spec";
3072my @files;
3073
3074my $flag = "mayfail" if ($mandatory eq "patch");
3075my $res;
3076
3077if ($src =~ /tar\.gz$/) {
3078 $res = pb_system("tar xfpz $src $dir","Extracting $mandatory files from $src",$flag);
3079} elsif ($src =~ /tar\.bz2$/) {
3080 $res = pb_system("tar xfpj $src $dir","Extracting $mandatory files from $src",$flag);
3081} else {
3082 die "Unknown compression algorithm for $src";
3083}
3084# If not mandatory return now
3085return() if (($res != 0) and ($mandatory eq "patch"));
3086opendir(DIR,"$dir") || die "Unable to open directory $dir";
3087foreach my $f (readdir(DIR)) {
3088 next if ($f =~ /^\./);
3089 # Skip potential patch dir
3090 next if ($f =~ /^pbpatch/);
3091 move("$dir/$f","$ddir") || die "Unable to move $dir/$f to $ddir";
3092 pb_log(2,"mv $dir/$f $ddir\n");
3093 push @files,"$ddir/$f";
3094}
3095closedir(DIR);
3096# Not enough but still a first cleanup
3097pb_rm_rf("$dir");
3098return(@files);
3099}
3100
3101sub pb_list_bfiles {
3102
3103my $dir = shift;
3104my $pbpkg = shift;
3105my $bfiles = shift;
3106my $pkgfiles = shift;
3107my $supfiles = shift;
3108
3109opendir(BDIR,"$dir") || die "Unable to open dir $dir: $!";
3110foreach my $f (readdir(BDIR)) {
3111 next if ($f =~ /^\./);
3112 if (-d $f) {
3113 # Recurse for directories (Debian 3.0 format e.g.)
3114 pb_list_bfiles($f,$pbpkg,$bfiles,$pkgfiles,$supfiles);
3115 next;
3116 }
3117 $bfiles->{$f} = "$dir/$f";
3118 $bfiles->{$f} =~ s~$ENV{'PBROOTDIR'}~~;
3119 if (defined $supfiles->{$pbpkg}) {
3120 $pkgfiles->{$f} = "$dir/$f" if ($f =~ /$supfiles->{$pbpkg}/);
3121 }
3122}
3123closedir(BDIR);
3124}
3125
3126
3127#
3128# Return the list of packages we are working on in a non CMS action
3129#
3130sub pb_get_pkg {
3131
3132my @pkgs = ();
3133
3134my ($var) = pb_conf_read("$ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb","pbpkg");
3135@pkgs = keys %$var;
3136
3137pb_log(0,"Packages: ".join(',',@pkgs)."\n");
3138return(\@pkgs);
3139}
3140
3141#
3142# Return the postinstall line if needed
3143#
3144
3145sub pb_get_postinstall {
3146
3147my $ddir = shift;
3148my $dver = shift;
3149my $darch = shift;
3150my $rbspi = shift;
3151my $vestyle = shift;
3152my $post = "";
3153
3154# Do we have a local post-install script
3155if ($vestyle eq "rinse") {
3156 $post = "--post-install ";
3157} elsif ($vestyle eq "rpmbootstrap") {
3158 $post = "-s ";
3159}
3160
3161my $postparam = pb_distro_get_param($ddir,$dver,$darch,$rbspi);
3162if ($postparam eq "") {
3163 $post = "";
3164} else {
3165 $post .= $postparam;
3166}
3167return($post);
3168}
3169
31701;
Note: See TracBrowser for help on using the repository browser.