source: devel/pb/bin/pb @ 1350

Last change on this file since 1350 was 1350, checked in by bruno, 8 years ago

r4380@localhost: bruno | 2011-10-26 15:30:49 +0200

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