source: devel/pb/bin/pb @ 1374

Last change on this file since 1374 was 1374, checked in by bruno, 8 years ago
  • Start to add CPAN upload support to solve #101 - Needs to be tested now with an official version
  • Property svn:executable set to *
File size: 123.9 KB
RevLine 
[5]1#!/usr/bin/perl -w
2#
3# Project Builder main application
4#
5# $Id$
6#
[1248]7# Copyright B. Cornec 2007-2011
[5]8# Provided under the GPL v2
9
[22]10# Syntax: see at end
[9]11
[18]12use strict 'vars';
[1107]13
14# The modules mentioned here are required by pb when used both
[1176]15# locally or inside a VE/VM/RM
[1107]16# Additional required modules only used locally are called with a require
17# in their respective section
[331]18use Getopt::Long qw(:config auto_abbrev no_ignore_case);
[9]19use Data::Dumper;
20use English;
[16]21use File::Basename;
[26]22use File::Copy;
[395]23use File::stat;
24use File::Temp qw(tempdir);
[872]25use File::Find;
[547]26use Time::localtime qw(localtime);
[13]27use POSIX qw(strftime);
[17]28use lib qw (lib);
[329]29use ProjectBuilder::Version;
[318]30use ProjectBuilder::Base;
[512]31use ProjectBuilder::Display;
[405]32use ProjectBuilder::Conf;
33use ProjectBuilder::Distribution;
34use ProjectBuilder::CMS;
[416]35use ProjectBuilder::Env;
[405]36use ProjectBuilder::Filter;
[473]37use ProjectBuilder::Changelog;
[1348]38use ProjectBuilder::VE;
[473]39
[397]40# Global variables
[5]41my %opts;                   # CLI Options
[9]42my $action;                 # action to realize
[320]43my $test = "FALSE";         # Not used
[748]44my $pbforce = 0;            # Force VE/VM rebuild
[968]45my $pbsnap = 0;             # Do not use snapshot mode for VM/VE by default
[320]46my $option = "";            # Not used
47my @pkgs;                   # list of packages
[95]48my $pbtag;                  # Global Tag variable
49my $pbver;                  # Global Version variable
[141]50my $pbscript;               # Name of the script
[77]51my %pbver;                  # per package
52my %pbtag;                  # per package
[53]53my $pbrev;                  # Global REVISION variable
[1176]54my $pbaccount;              # Login to use to connect to the VM/RM
[1120]55my $pbtarget;               # Target os-ver-arch you want to build for
[1176]56my $pbport;                 # Port to use to connect to the VM/RM
[199]57my $newver;                 # New version to create
[792]58my $iso = undef;            # ISO image for the VM to create
[5]59
[320]60my @date = pb_get_date();
61my $pbdate = strftime("%Y-%m-%d", @date);
[5]62
[331]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)
[748]73such as Subversion, CVS, Git, Mercurial... or being a simple reference to a compressed tar file.
[331]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
[1124]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> ...]
[331]82
[1158]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> ...]
[331]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
[748]101=item B<-S|--snapshot>
102
103Use the snapshot mode of VMs or VEs
104
[331]105=item B<--man>
106
107Prints the manual page and exits.
108
[1120]109=item B<-t|--target os-ver-arch>
[331]110
[1120]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
[1176]116Name of the Virtual Machines (VM), Virtual Environments (VE) or Remote Machines (RM)
117you want to build on (coma separated).
[331]118All if none precised (or use the env variable PBV).
119
120=item B<-s|--script script>
121
[1176]122Name of the script you want to execute on the related VMs/VEs/RMs.
[331]123
[1158]124=item B<-g|--nographic>
[1124]125
126Do not launch VMs in graphical mode.
127
[331]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
[1176]134Name of the account to use to connect on the related VMs/RMs.
[331]135
136=item B<-P|--port port_number>
137
[1176]138Port number to use to connect on the related VMs/RMs.";
[331]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
[1097]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
[331]168=item B<cms2build>
169
170Create tar files for the project under your CMS.
[1097]171Current state of the CMS is taken.
172CMS supported are SVN, SVK, CVS, Git and Mercurial
[331]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
[1097]184=item B<sbx2pkg>
185
186sbx2build + build2pkg
187
[331]188=item B<build2ssh>
189
190Send the tar files to a SSH host
191
[1097]192=item B<sbx2ssh>
193
194sbx2build + build2ssh
195
[331]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
[1176]208VM type supported are QEMU and KVM
[331]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
[1176]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
[1097]222=item B<sbx2vm>
223
224sbx2build + build2vm
225
226=item B<sbx2ve>
227
228sbx2build + build2ve
229
[1176]230=item B<sbx2rm>
231
232sbx2build + build2rm
233
[331]234=item B<cms2vm>
235
236cms2build + build2vm
237
238=item B<cms2ve>
239
240cms2build + build2ve
241
[1176]242=item B<cms2rm>
243
244cms2build + build2rm
245
[331]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
[1176]263=item B<script2rm>
264
265Execute a script on a remote machine
266
[331]267=item B<newvm>
268
269Create a new virtual machine
270
271=item B<newve>
272
273Create a new virtual environment
274
[346]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
[1176]283=item B<setuprm>
284
285Setup a remote machine for pb usage
286
[1140]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
[1176]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
[748]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
[1111]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
[1176]318=item B<updaterm>
319
320Update the distribution in the remote machine
321
[783]322=item B<test2pkg>
323
324Test a package locally
325
[772]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
[1176]334=item B<test2rm>
335
336Test a package in a remote machine
337
[331]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
[471]348=item B<announce>
349
350Announce the availability of the project through various means
351
[1117]352=item B<sbx2webssh>
[557]353
[1117]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.
[557]357
[1117]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
[739]372=item B<clean>
373
374Purge the build and delivery directories related to the current project
375
[557]376=back
377
[331]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
[75]453my ($projectbuilderver,$projectbuilderrev) = pb_version_init();
[974]454my $appname = "pb";
[331]455
[397]456# Initialize the syntax string
457
[974]458pb_syntax_init("$appname (aka project-builder.org) Version $projectbuilderver-$projectbuilderrev\n");
[397]459
[331]460GetOptions("help|?|h" => \$opts{'h'}, 
461        "man" => \$opts{'man'},
462        "verbose|v+" => \$opts{'v'},
[748]463        "snapshot|S" => \$opts{'S'},
[331]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'},
[1120]471        "target|t=s" => \$opts{'t'},
[1158]472        "nographic|g" => \$opts{'g'},
[331]473        "port|P=i" => \$opts{'P'},
474        "project|p=s" => \$opts{'p'},
475        "iso|i=s" => \$opts{'i'},
[815]476        "version|V=s" => \$opts{'V'},
[331]477) || pb_syntax(-1,0);
478
[21]479if (defined $opts{'h'}) {
[331]480    pb_syntax(0,1);
[21]481}
[331]482if (defined $opts{'man'}) {
483    pb_syntax(0,2);
484}
[21]485if (defined $opts{'v'}) {
[495]486    $pbdebug = $opts{'v'};
[21]487}
[320]488if (defined $opts{'f'}) {
[748]489    $pbforce=1;
[320]490}
[21]491if (defined $opts{'q'}) {
[495]492    $pbdebug=-1;
[21]493}
[748]494if (defined $opts{'S'}) {
495    $pbsnap=1;
496}
[22]497if (defined $opts{'l'}) {
[495]498    open(pbLOG,"> $opts{'l'}") || die "Unable to log to $opts{'l'}: $!";
499    $pbLOG = \*pbLOG;
500    $pbdebug = 0  if ($pbdebug == -1);
[22]501    }
[495]502pb_log_init($pbdebug, $pbLOG);
503pb_display_init("text","");
[315]504
[67]505# Handle root of the project if defined
506if (defined $opts{'r'}) {
[340]507    $ENV{'PBROOTDIR'} = $opts{'r'};
[67]508}
[91]509# Handle virtual machines if any
510if (defined $opts{'m'}) {
[320]511    $ENV{'PBV'} = $opts{'m'};
[91]512}
[141]513if (defined $opts{'s'}) {
514    $pbscript = $opts{'s'};
515}
[152]516if (defined $opts{'a'}) {
517    $pbaccount = $opts{'a'};
[347]518    die "option -a requires a -s script option" if (not defined $pbscript);
[152]519}
[162]520if (defined $opts{'P'}) {
521    $pbport = $opts{'P'};
522}
[199]523if (defined $opts{'V'}) {
524    $newver = $opts{'V'};
525}
[262]526if (defined $opts{'i'}) {
527    $iso = $opts{'i'};
528}
[1120]529if (defined $opts{'t'}) {
530    $pbtarget = $opts{'t'};
531}
[108]532
533# Get Action
534$action = shift @ARGV;
[331]535die pb_syntax(-1,1) if (not defined $action);
[108]536
[314]537my ($filteredfiles, $supfiles, $defpkgdir, $extpkgdir);
[273]538my $pbinit = undef;
539$pbinit = 1 if ($action =~ /^newproj$/);
[108]540
[59]541# Handles project name if any
[108]542# And get global params
[353]543($filteredfiles, $supfiles, $defpkgdir, $extpkgdir) = pb_env_init($opts{'p'},$pbinit,$action);
[59]544
[982]545#
546# Check for command requirements
547#
[1126]548my ($req,$opt,$pbpara) = pb_conf_get_if("oscmd","oscmdopt","pbparallel");
[1128]549pb_check_requirements($req,$opt,$appname);
[982]550
[1125]551#
552# Check if we can launch some actions in // with Parallel::ForkManager
553#
[1126]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
[1153]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");
[1126]564        $pbparallel = 1;
565    } else {
566        # Using the number of cores
567        $pbparallel = Sys::CPU::cpu_count();
[1153]568        pb_log(1,"Using parallel mode with $pbparallel processes\n");
[1126]569    }
570}
571
[1125]572eval
573{
574    require Parallel::ForkManager;
575    Parallel::ForkManager->import();
576};
577# Parallel::ForkManager not found so no // actions
578if ($@) {
579    $pbparallel = undef;
[1153]580    pb_log(1,"ADVISE: Install Parallel::ForkManager to benefit from automatic parallelism optimization.\nOnly 1 process at a time for the moment\n");
[1125]581}
582
[315]583pb_log(0,"Project: $ENV{'PBPROJ'}\n");
584pb_log(0,"Action: $action\n");
[9]585
586# Act depending on action
587if ($action =~ /^cms2build$/) {
[1097]588    pb_cms2build("CMS");
589} elsif ($action =~ /^sbx2build$/) {
590    pb_cms2build("SandBox");
[77]591} elsif ($action =~ /^build2pkg$/) {
592    pb_build2pkg();
593} elsif ($action =~ /^cms2pkg$/) {
[1097]594    pb_cms2build("CMS");
[77]595    pb_build2pkg();
[1097]596} elsif ($action =~ /^sbx2pkg$/) {
597    pb_cms2build("SandBox");
598    pb_build2pkg();
[88]599} elsif ($action =~ /^build2ssh$/) {
600    pb_build2ssh();
[220]601} elsif ($action =~ /^cms2ssh$/) {
[1097]602    pb_cms2build("CMS");
[220]603    pb_build2ssh();
[1102]604} elsif ($action =~ /^sbx2ssh$/) {
[1097]605    pb_cms2build("SandBox");
606    pb_build2ssh();
[88]607} elsif ($action =~ /^pkg2ssh$/) {
608    pb_pkg2ssh();
[1176]609} elsif ($action =~ /^build2rm$/) {
610    pb_build2v("rm","build");
[320]611} elsif ($action =~ /^build2ve$/) {
[772]612    pb_build2v("ve","build");
[91]613} elsif ($action =~ /^build2vm$/) {
[772]614    pb_build2v("vm","build");
[1176]615} elsif ($action =~ /^cms2rm$/) {
616    pb_cms2build("CMS");
617    pb_build2v("rm","build");
[320]618} elsif ($action =~ /^cms2ve$/) {
[1097]619    pb_cms2build("CMS");
[772]620    pb_build2v("ve","build");
[1176]621} elsif ($action =~ /^sbx2rm$/) {
622    pb_cms2build("SandBox");
623    pb_build2v("rm","build");
[1097]624} elsif ($action =~ /^sbx2ve$/) {
625    pb_cms2build("SandBox");
626    pb_build2v("ve","build");
[91]627} elsif ($action =~ /^cms2vm$/) {
[1097]628    pb_cms2build("CMS");
[772]629    pb_build2v("vm","build");
[1097]630} elsif ($action =~ /^sbx2vm$/) {
631    pb_cms2build("SandBox");
632    pb_build2v("vm","build");
[141]633} elsif ($action =~ /^launchvm$/) {
[320]634    pb_launchv("vm",$ENV{'PBV'},0);
635} elsif ($action =~ /^launchve$/) {
636    pb_launchv("ve",$ENV{'PBV'},0);
[142]637} elsif ($action =~ /^script2vm$/) {
[320]638    pb_script2v($pbscript,"vm");
639} elsif ($action =~ /^script2ve$/) {
640    pb_script2v($pbscript,"ve");
[1176]641} elsif ($action =~ /^script2rm$/) {
642    pb_script2v($pbscript,"rm");
[199]643} elsif ($action =~ /^newver$/) {
644    pb_newver();
[320]645} elsif ($action =~ /^newve$/) {
646    pb_launchv("ve",$ENV{'PBV'},1);
[262]647} elsif ($action =~ /^newvm$/) {
[320]648    pb_launchv("vm",$ENV{'PBV'},1);
[909]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");
[1105]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");
[1072]653    pb_log(0, "You should then be able to login with ssh -p VMPORT root\@localhost (if VM started with pb)\n");
[1176]654} elsif ($action =~ /^setuprm$/) {
655    pb_setup2v("rm");
[346]656} elsif ($action =~ /^setupve$/) {
[772]657    pb_setup2v("ve");
[346]658} elsif ($action =~ /^setupvm$/) {
[772]659    pb_setup2v("vm");
[1176]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");
[1140]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");
[1176]672} elsif ($action =~ /^updaterm$/) {
673    pb_update2v("rm");
[1111]674} elsif ($action =~ /^updateve$/) {
675    pb_update2v("ve");
676} elsif ($action =~ /^updatevm$/) {
677    pb_update2v("vm");
[748]678} elsif ($action =~ /^snapve$/) {
[772]679    pb_snap2v("ve");
[748]680} elsif ($action =~ /^snapvm$/) {
[772]681    pb_snap2v("vm");
[783]682} elsif ($action =~ /^test2pkg$/) {
683    pb_test2pkg();
[1176]684} elsif ($action =~ /^test2rm$/) {
685    pb_build2v("rm","test");
[772]686} elsif ($action =~ /^test2ve$/) {
687    pb_build2v("ve","test");
688} elsif ($action =~ /^test2vm$/) {
689    pb_build2v("vm","test");
[273]690} elsif ($action =~ /^newproj$/) {
691    # Nothing to do - already done in pb_env_init
[106]692} elsif ($action =~ /^clean$/) {
[739]693    pb_clean();
[471]694} elsif ($action =~ /^announce$/) {
[498]695    # For announce only. Require avoids the systematic load of these modules
696    require DBI;
[557]697    require DBD::SQLite;
[498]698
[471]699    pb_announce();
[1117]700} elsif ($action =~ /^sbx2webpkg$/) {
[547]701    require DBI;
[557]702    require DBD::SQLite;
[547]703
[1117]704    pb_cms2build("SandBox","Web");
705} elsif ($action =~ /^sbx2webssh$/) {
706    require DBI;
707    require DBD::SQLite;
708
709    pb_cms2build("SandBox","Web");
[556]710    pb_send2target("Web");
[1117]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");
[77]722} else {
[315]723    pb_log(0,"\'$action\' is not available\n");
[331]724    pb_syntax(-2,1);
[77]725}
726
727sub pb_cms2build {
728
[556]729    my $param = shift || undef;
[1117]730    my $web = shift || undef;
[556]731
732    my $pkg;
733    my @pkgs;
[557]734    my $webdir;
[556]735
[557]736    my %pkgs;
[1186]737    my $pb;             # Structure to store conf info
[557]738
[1117]739    die "pb_cms2build requires a parameter: SandBox or CMS" if (not defined $param);
[1097]740
[556]741    # If Website, then pkg is only the website
[1117]742    if (defined $web) {
[557]743        ($webdir) = pb_conf_get("webdir");
744        pb_log(2,"webdir: ".Dumper($webdir)."\n");
745        $pkgs[0] = $webdir->{$ENV{'PBPROJ'}};
[556]746        $extpkgdir = $webdir;
[557]747        pb_log(0,"Package: $pkgs[0]\n");
[556]748    } else {
749        $pkg = pb_cms_get_pkg($defpkgdir,$extpkgdir);
750        @pkgs = @$pkg;
751    }
752
[1097]753    my ($scheme, $uri) = pb_cms_init($pbinit,$param);
[331]754
[898]755    # We need 2 lines here
756    my ($pkgv, $pkgt, $testver) = pb_conf_get_if("pkgver","pkgtag","testver");
[174]757
[429]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'}};
[1203]762    my ($delivery) = pb_conf_get_if("delivery");
763    $delivery->{$ENV{'PBPROJ'}} = "" if (not defined $delivery->{$ENV{'PBPROJ'}});
[174]764
[27]765    foreach my $pbpkg (@pkgs) {
[115]766        $ENV{'PBPKG'} = $pbpkg;
[728]767
[98]768        if ((defined $pkgv) && (defined $pkgv->{$pbpkg})) {
769            $pbver = $pkgv->{$pbpkg};
[9]770        } else {
[353]771            $pbver = $ENV{'PBPROJVER'};
[9]772        }
[728]773        # If it's a test version, then tag == 0.date
[897]774        if ((defined $testver) && (defined $testver->{$ENV{'PBPROJ'}}) && ($testver->{$ENV{'PBPROJ'}} =~ /true/i)) {
[728]775            $pbtag = "0.".strftime("%Y%m%d%H%M%S", @date);
776            $ENV{'PBPROJTAG'} = $pbtag;
777        } elsif ((defined $pkgt) && (defined $pkgt->{$pbpkg})) {
[98]778            $pbtag = $pkgt->{$pbpkg};
[9]779        } else {
[353]780            $pbtag = $ENV{'PBPROJTAG'};
[9]781        }
[95]782
[16]783        $pbrev = $ENV{'PBREVISION'};
[319]784        pb_log(0,"\n");
785        pb_log(0,"Management of $pbpkg $pbver-$pbtag (rev $pbrev)\n");
[9]786        die "Unable to get env var PBDESTDIR" if (not defined $ENV{'PBDESTDIR'});
[539]787
[1173]788        my $dest = "$ENV{'PBDESTDIR'}/$pbpkg-$pbver";
789        # Create the structure if needed
790        pb_mkdir_p($dest);
[16]791        # Clean up dest if necessary. The export will recreate it
[74]792        pb_rm_rf($dest) if (-d $dest);
[9]793
794        # Export CMS tree for the concerned package to dest
795        # And generate some additional files
796        $OUTPUT_AUTOFLUSH=1;
[29]797
[9]798        # computes in which dir we have to work
[113]799        my $dir = $defpkgdir->{$pbpkg};
800        $dir = $extpkgdir->{$pbpkg} if (not defined $dir);
[1117]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);
[1260]803        pb_log(2,"def:".Dumper($defpkgdir)."ext: ".Dumper($extpkgdir)."dir: $dir\n");
[9]804
[537]805        # Exporting content from CMS
[1097]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
[1174]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"; 
[1260]817                $sourceuri =~ s|^$ENV{'PBPROJDIR'}/|$uri/|;
[1174]818            }
[1097]819        }
820        my $preserve = pb_cms_export($sourceuri,$sourcedir,$dest);
[315]821
[435]822        # Generated fake content for test versions to speed up stuff
823        my $chglog;
[285]824
[448]825        # Get project info on authors and log file
[1185]826        # TODO: Make it CMS aware
[448]827        $chglog = "$ENV{'PBROOTDIR'}/$pbpkg/pbcl";
828        $chglog = "$ENV{'PBROOTDIR'}/pbcl" if (! -f $chglog);
829        $chglog = undef if (! -f $chglog);
[285]830
[1185]831        # TODO: Make it CMS aware
[448]832        my $authors = "$ENV{'PBROOTDIR'}/$pbpkg/pbauthors";
833        $authors = "$ENV{'PBROOTDIR'}/pbauthors" if (! -f $authors);
834        $authors = "/dev/null" if (! -f $authors);
[435]835
[448]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";
[285]840        }
[448]841        pb_cms_log($scheme,"$ENV{'PBDIR'}/$dir",$dest,$chglog,$authors,$testver);
[29]842
[21]843        my %build;
[865]844        # We want to at least build for the underlying distro
[1120]845        # except if a target was given, in which case we only build for it
[1177]846        my $pbos = pb_distro_get_context($pbtarget);
[1282]847        my $tmpl = pb_get_distros($pbos,$pbtarget);
[1120]848
[1186]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;
[1192]854        $pb->{'suf'} = $pbos->{'suffix'};
[1186]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'};
[1200]862        $pb->{'repo'} = "$ENV{'PBREPO'}/$delivery->{$ENV{'PBPROJ'}}";
[1186]863        $pb->{'patches'} = ();
864        $pb->{'sources'} = ();
[556]865   
[1185]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
[556]872        # Do not do that for website
[1117]873        if (not defined $web) {
[665]874            my %virt;
[1176]875            # De-duplicate similar VM/VE/RM
[556]876            foreach my $d (split(/,/,$tmpl)) {
[766]877                # skip ill-formatted vms (name-ver-arch)
878                next if ($d !~ /-/);
[665]879                $virt{$d} = $d;
880            }
881
[1125]882            # Try to use // processing here
[1350]883            my $pm = new Parallel::ForkManager($pbparallel) if (defined $pbparallel);
[1125]884
[1189]885            pb_log(0,"Preparing delivery ...\n");
[1177]886            foreach my $v (keys %virt) {
[1125]887                $pm->start and next if (defined $pbparallel);
[1177]888
889                # Distro context
890                my $pbos = pb_distro_get_context($v);
[1207]891   
[1186]892                $pb->{'pbos'} = $pbos;
[1189]893                $pb->{'suf'} = $pbos->{'suffix'};
[1186]894                pb_log(3,"DEBUG: pb: ".Dumper($pb)."\n");
[1185]895
896                # Get all filters to apply
[1192]897                $ptr = pb_get_filters($pbpkg,$pbos);
[1185]898   
[556]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
[1177]902                my $pbrealpkg = pb_cms_get_real_pkg($pbpkg,$pbos->{'type'});
[1186]903                $pb->{'realpkg'} = $pbrealpkg;
[1177]904                pb_log(1,"Virtual package $pbpkg has a real package name of $pbrealpkg on $pbos->{'name'}-$pbos->{'version'}\n") if ($pbrealpkg ne $pbpkg);
[556]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 = ();
[1185]913                # Used in Filter.pm by pb_filter_file
914
[1363]915                $build{$v} = "no";
[1185]916                if (-d "$ENV{'PBROOTDIR'}/$pbpkg/$pbos->{'os'}") {
917                    pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$pbos->{'os'}",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
[1363]918                    $build{$v} = "yes";
919                } 
920                if (-d "$ENV{'PBROOTDIR'}/$pbpkg/$pbos->{'type'}") {
[1177]921                    pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$pbos->{'type'}",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
[1363]922                    $build{$v} = "yes";
923                } 
924                if (-d "$ENV{'PBROOTDIR'}/$pbpkg/$pbos->{'family'}") {
[1177]925                    pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$pbos->{'family'}",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
[1363]926                    $build{$v} = "yes";
927                } 
928                if (-d "$ENV{'PBROOTDIR'}/$pbpkg/$pbos->{'name'}") {
[1177]929                    pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$pbos->{'name'}",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
[1363]930                    $build{$v} = "yes";
931                } 
932                if (-d "$ENV{'PBROOTDIR'}/$pbpkg/$pbos->{'name'}-$pbos->{'version'}") {
[1177]933                    pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$pbos->{'name'}-$pbos->{'version'}",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
[1363]934                    $build{$v} = "yes";
935                } 
936                if (-d "$ENV{'PBROOTDIR'}/$pbpkg/$pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}") {
[1177]937                    pb_list_bfiles("$ENV{'PBROOTDIR'}/$pbpkg/$pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}",$pbpkg,\%bfiles,\%pkgfiles,$supfiles);
[1363]938                    $build{$v} = "yes";
[500]939                }
[1186]940                pb_log(2,"DEBUG($v) bfiles: ".Dumper(\%bfiles)."\n");
[556]941   
[1185]942                if ($build{$v} ne "no") {
943                    # Apply now all the filters on all the files concerned
944                    # destination dir depends on the type of file
[556]945                    # For patch support
[1185]946                    # TODO: Make it CMS aware
[1186]947                    $pb->{'patches'} = pb_list_sfiles("$ENV{'PBROOTDIR'}/$pbpkg/pbpatch", $pb->{'patches'}, $pbos, "$ENV{'PBROOTDIR'}/$pbpkg/pbextpatch");
948                    pb_log(2,"DEBUG($v) patches: ".Dumper($pb->{'patches'})."\n");
[1185]949                    # TODO: Make it CMS aware
[1186]950                    $pb->{'sources'} = pb_list_sfiles("$ENV{'PBROOTDIR'}/$pbpkg/pbsrc", $pb->{'sources'}, $pbos, "$ENV{'PBROOTDIR'}/$pbpkg/pbextsrc");
951                    pb_log(2,"DEBUG($v) sources: ".Dumper($pb->{'sources'})."\n");
[1185]952   
[1186]953                    if (defined $pb->{'patches'}->{$v}) {
[1185]954                        # Filter potential patches (local + remote)
955                        pb_mkdir_p("$dest/pbconf/$v/pbpatch");
[1367]956                        # If Debian based distribution, then prepare what will be done at build time
957                        my ($patchcmd,$patchopt);
958                        if ($pbos->{'type'} eq "deb") {
959                            ($patchcmd,$patchopt) = pb_distro_get_param($pbos,pb_conf_get_if("ospatchcmd","ospatchopt"));
960                            open(SCRIPT,"> $dest/pbconf/$v/pbpatch/pbapplypatch") || die "Unable to create $dest/pbconf/$v/pbpatch/pbapplypatch";
961                            print SCRIPT "#!/bin/bash\n";
962                            print SCRIPT "set -x\n" if ($pbdebug gt 1);
963                        }
[1186]964                        foreach my $pf (split(/,/,$pb->{'patches'}->{$v})) {
[1185]965                            my $pp = basename($pf);
966                            pb_cms_export($pf,undef,"$dest/pbconf/$v/pbpatch");
[1186]967                            pb_filter_file_inplace($ptr,"$dest/pbconf/$v/pbpatch/$pp",$pb);
[1185]968                            pb_system("gzip -9f $dest/pbconf/$v/pbpatch/$pp","","quiet");
[1367]969                            if ($pbos->{'type'} eq "deb") {
970                                # If Debian based distribution, then prepare what will be done at build time
971                                # by applying the patches that will be available under the debian/patches dir
972                                print SCRIPT "$patchcmd $patchopt \< debian/patches/$pp\n";
973                            }
[1185]974                        }
[1367]975                        if ($pbos->{'type'} eq "deb") {
976                            close(SCRIPT);
977                            chmod 0755,"$dest/pbconf/$v/pbpatch/pbapplypatch";
978                        }
979                        #pb_system("cat $dest/pbconf/$v/pbpatch/pbapplypatch","APPLY","verbose");
[1185]980                    }
[1186]981                    if (defined $pb->{'sources'}->{$v}) {
[1185]982                        pb_mkdir_p("$dest/pbconf/$v/pbsrc");
[1186]983                        foreach my $pf (split(/,/,$pb->{'sources'}->{$v})) {
[1185]984                            my $pp = basename($pf);
985                            pb_cms_export($pf,undef,"$dest/pbconf/$v/pbsrc");
[1186]986                            pb_filter_file_inplace($ptr,"$dest/pbconf/$v/pbsrc/$pp",$pb);
[1185]987                        }
988                    }
[1186]989                    # Filter build files at the end, as they depend on patches and sources
[1363]990                    foreach my $f (keys %bfiles) {
991                        pb_filter_file("$ENV{'PBROOTDIR'}/$bfiles{$f}",$ptr,"$dest/pbconf/$v/$f",$pb);
[1186]992                    }
[1363]993                    foreach my $f (keys %pkgfiles) {
994                        pb_filter_file("$ENV{'PBROOTDIR'}/$pkgfiles{$f}",$ptr,"$dest/pbconf/$v/$f",$pb);
995                    }
[556]996                }
[1130]997
[1185]998                if (defined $pbparallel) {
999                    # Communicate results back to parent
1000                    my $str = "";
1001                    $str .= "build $v = $build{$v}\n" if (defined $build{$v});
[1186]1002                    $str .= "patches $v = $pb->{'patches'}->{$v}\n" if (defined $pb->{'patches'}->{$v});
1003                    $str .= "sources $v = $pb->{'sources'}->{$v}\n" if (defined $pb->{'sources'}->{$v});
[1185]1004                    pb_set_content("$tmpd/$$","$str");
1005                    $pm->finish;
1006                }
[15]1007            }
[1185]1008            # In the parent, we need to get the result from the children
[1125]1009            $pm->wait_all_children if (defined $pbparallel);
[1185]1010            my $made = "";
1011            my %h = ();
1012            my %tmp;
[1186]1013            my %tmp2;
[1185]1014            my $pt;
1015            my $k;
1016
1017            foreach $k (<$tmpd/*>) {
1018                $made .= pb_get_content($k);
[556]1019            }
[1185]1020            pb_rm_rf($tmpd);
1021            pb_log(3,"MADE:\n$made");
[500]1022
[1185]1023            # Rebuild local hashes
1024            foreach $k (split(/\n/,$made)) {
1025                if ($k =~ /^\s*([A-z0-9-_]+)\s+([[A-z0-9-_.]+)\s*=\s*(.+)$/) {
1026                    $h{$1}->{$2}=$3;
1027                }
1028            }
[1186]1029            pb_log(2,"HASH: ".Dumper(%h));
[236]1030
[1185]1031            # Patches
1032            pb_log(0,"Delivered and compressed patches ");
1033            $pt = $h{'patches'};
[1186]1034            foreach $k (keys %$pt) {
1035                foreach my $v1 (split(/,/,$pt->{$k})) {
1036                    $tmp{$v1} = "";
1037                }
[1185]1038            }
[1186]1039            if (keys %tmp) {
1040                foreach $k (keys %tmp) {
1041                    pb_log(0,"$k ");
1042                }
1043            } else {
1044                pb_log(0,"N/A");
[1185]1045            }
1046            pb_log(0,"\n");
[236]1047
[1185]1048            # Sources
1049            pb_log(0,"Delivered additional sources ");
1050            $pt = $h{'sources'};
[1186]1051            foreach $k (keys %$pt) {
1052                foreach my $v1 (split(/,/,$pt->{$k})) {
1053                    $tmp2{$v1} = "";
1054                }
[236]1055            }
[1186]1056            if (keys %tmp2) {
1057                foreach $k (keys %tmp2) {
1058                    pb_log(0,"$k ");
1059                }
1060            } else {
1061                pb_log(0,"N/A");
[1185]1062            }
1063            pb_log(0,"\n");
[236]1064
[1185]1065            # Build files
1066            my @found;
1067            my @notfound;
1068            $pt = $h{'build'};
1069            foreach my $b (keys %$pt) {
1070                push @found,$b if ($pt->{$b} =~ /yes/);
1071                push @notfound,$b if ($pt->{$b} =~ /no/);
1072            }
1073            pb_log(0,"Build files have been generated for ... ".join(',',sort(@found))."\n") if (@found);
1074            pb_log(0,"No Build files found for ".join(',',sort(@notfound))."\n") if (@notfound);
1075
[556]1076        } else {
1077            # Instead call News generation
1078            pb_web_news2html($dest);
[559]1079            # And create an empty pbconf
1080            pb_mkdir_p("$dest/pbconf");
[560]1081            # And prepare the pbscript to execute remotely
[1138]1082            open(SCRIPT,"> $ENV{'PBTMP'}/pbscript") || die "Unable to create $ENV{'PBTMP'}/pbscript";
[560]1083            print SCRIPT "#!/bin/bash\n";
1084            print SCRIPT "#set -x\n";
1085            print SCRIPT "echo ... Extracting Website content\n";
1086            print SCRIPT "find . -type f | grep -Ev '^./$pbpkg-$pbver.tar.gz|^./pbscript' | xargs rm -f non-existent\n";
1087            print SCRIPT "find * -type d -depth | xargs rmdir 2> /dev/null \n";
1088            print SCRIPT "tar xfz $pbpkg-$pbver.tar.gz\n";
1089            print SCRIPT "mv $pbpkg-$pbver/* .\n";
1090            print SCRIPT "rm -f $pbpkg-$pbver.tar.gz\n";
1091            print SCRIPT "rmdir $pbpkg-$pbver\n";
1092            close(SCRIPT);
[1165]1093            chmod 0755,"$ENV{'PBTMP'}/pbscript";
[499]1094        }
1095
[1259]1096        # Apply filters to the non-build files
1097        my $liste ="";
1098        if (defined $filteredfiles->{$pbpkg}) {
1099            foreach my $f (split(/,/,$filteredfiles->{$pbpkg})) {
1100                pb_filter_file_inplace($ptr,"$dest/$f",$pb);
1101                $liste = "$f $liste";
1102            }
1103        }
1104        pb_log(2,"Files ".$liste."have been filtered\n");
1105
1106        # TODO: Make it CMS aware
1107        # Execute the pbinit script if any
1108        if (-x "$ENV{'PBROOTDIR'}/$pbpkg/pbinit") {
1109            pb_filter_file("$ENV{'PBROOTDIR'}/$pbpkg/pbinit",$ptr,"$ENV{'PBTMP'}/pbinit",$pb);
1110            chmod 0755,"$ENV{'PBTMP'}/pbinit";
1111            pb_system("cd $dest ; $ENV{'PBTMP'}/pbinit","Executing init script from $ENV{'PBROOTDIR'}/$pbpkg/pbinit under $dest","verbose");
1112        }
1113
1114        # Do we have additional script to run to prepare the environement for the project ?
1115        # Then include it in the pbconf delivery
1116        foreach my $pbvf (<$ENV{'PBROOTDIR'}/pbv*.pre>,<$ENV{'PBROOTDIR'}/pbv*.post>, <$ENV{'PBROOTDIR'}/pbtest*>) {
1117            if (-x "$pbvf") {
1118                my $target = "$ENV{'PBDESTDIR'}/".basename($pbvf);
1119                pb_filter_file("$pbvf",$ptr,$target,$pb);
1120                chmod 0755,"$target";
1121            }
1122        }
1123
[265]1124        # Prepare the dest directory for archive
[69]1125        chdir "$ENV{'PBDESTDIR'}" || die "Unable to change dir to $ENV{'PBDESTDIR'}";
[537]1126        if (defined $preserve) {
1127            # In that case we want to preserve the original tar file for checksum purposes
1128            # The one created is btw equivalent in that case to this one
1129            # Maybe check basename of both to be sure they are the same ?
1130            pb_log(0,"Preserving original tar file ");
1131            move("$preserve","$pbpkg-$pbver.tar.gz");
1132        } else {
1133            # Possibility to look at PBSRC to guess more the filename
1134            pb_system("tar cfz $pbpkg-$pbver.tar.gz --exclude=$pbpkg-$pbver/pbconf $pbpkg-$pbver","Creating $pbpkg tar files compressed");
1135        }
[344]1136        pb_log(0,"Under $ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz\n");
[493]1137        pb_system("tar cfz $pbpkg-$pbver.pbconf.tar.gz $pbpkg-$pbver/pbconf","Creating pbconf tar files compressed");
1138        pb_log(0,"Under $ENV{'PBDESTDIR'}/$pbpkg-$pbver.pbconf.tar.gz\n");
[83]1139
[357]1140        # Keep track of version-tag per pkg
1141        $pkgs{$pbpkg} = "$pbver-$pbtag";
[83]1142
[288]1143        # Final cleanup
1144        pb_rm_rf($dest) if (-d $dest);
[9]1145    }
[357]1146
1147    # Keep track of per package version
1148    pb_log(2,"DEBUG pkgs: ".Dumper(%pkgs)."\n");
1149    open(PKG,"> $ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb") || die "Unable to create $ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb";
[539]1150    foreach my $pbpkg (keys %pkgs) {
[357]1151        print PKG "pbpkg $pbpkg = $pkgs{$pbpkg}\n";
1152    }
1153    close(PKG);
1154
1155    # Keep track of what is generated by default
1156    # We need to store the dir and info on version-tag
1157    # Base our content on the existing .pb file
1158    copy("$ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb","$ENV{'PBDESTDIR'}/pbrc");
1159    open(LAST,">> $ENV{'PBDESTDIR'}/pbrc") || die "Unable to create $ENV{'PBDESTDIR'}/pbrc";
1160    print LAST "pbroot $ENV{'PBPROJ'} = $ENV{'PBROOTDIR'}\n";
[702]1161    print LAST "projver $ENV{'PBPROJ'} = $ENV{'PBPROJVER'}\n";
1162    print LAST "projtag $ENV{'PBPROJ'} = $ENV{'PBPROJTAG'}\n";
[357]1163    print LAST "pbpackager $ENV{'PBPROJ'} = $ENV{'PBPACKAGER'}\n";
1164    close(LAST);
[77]1165}
[22]1166
[772]1167sub pb_test2pkg {
1168    # Get the running distro to test on
[1177]1169    my $pbos = pb_distro_get_context();
[772]1170
1171    # Get list of packages to test
1172    # Get content saved in cms2build
1173    my $ptr = pb_get_pkg();
1174    @pkgs = @$ptr;
1175
1176    # Additional potential repo
[1177]1177    pb_distro_setuprepo($pbos);
[772]1178    foreach my $pbpkg (@pkgs) {
1179        # We need to install the package to test, and deps brought with it
[1177]1180        pb_distro_installdeps(undef,$pbos,$pbpkg);
[772]1181        pb_system("$ENV{'PBDESTDIR'}/pbtest","Launching test for $pbpkg","verbose");
1182    }
1183}
1184
[77]1185sub pb_build2pkg {
1186
[22]1187    # Get the running distro to build on
[1177]1188    my $pbos = pb_distro_get_context();
[22]1189
[1137]1190    # If needed we may add repository to the build env
[1177]1191    pb_distro_setuprepo($pbos);
[1137]1192
[353]1193    # Get list of packages to build
1194    my $ptr = pb_get_pkg();
1195    @pkgs = @$ptr;
1196
[898]1197    # Get content saved in cms2build
[353]1198    my ($pkg) = pb_conf_read("$ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb","pbpkg");
[83]1199    $pkg = { } if (not defined $pkg);
1200
[1212]1201    pb_mkdir_p("$ENV{'PBBUILDDIR'}") if (! -d "$ENV{'PBBUILDDIR'}");
[1208]1202    chdir "$ENV{'PBBUILDDIR'}" || die "Unable to chdir to $ENV{'PBBUILDDIR'}";
[126]1203    my $made = ""; # pkgs made during build
[1176]1204    my $pm;
1205    $pm = new Parallel::ForkManager($pbparallel) if (defined $pbparallel);
[1137]1206
1207    # We need to communicate info back from the children if parallel so prepare a dir for that
1208    my $tmpd = "$ENV{'PBTMP'}/build.$$";
1209    pb_mkdir_p($tmpd) if (defined $pbparallel);
1210
[27]1211    foreach my $pbpkg (@pkgs) {
[1137]1212        $pm->start and next if (defined $pbparallel);
1213
[88]1214        my $vertag = $pkg->{$pbpkg};
[77]1215        # get the version of the current package - maybe different
1216        ($pbver,$pbtag) = split(/-/,$vertag);
1217
[27]1218        my $src="$ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz";
[493]1219        my $src2="$ENV{'PBDESTDIR'}/$pbpkg-$pbver.pbconf.tar.gz";
[315]1220        pb_log(2,"Source file: $src\n");
[493]1221        pb_log(2,"Pbconf file: $src2\n");
[25]1222
[315]1223        pb_log(2,"Working directory: $ENV{'PBBUILDDIR'}\n");
[1177]1224        if ($pbos->{'type'} eq "rpm") {
[25]1225            foreach my $d ('RPMS','SRPMS','SPECS','SOURCES','BUILD') {
[28]1226                if (! -d "$ENV{'PBBUILDDIR'}/$d") {
[1212]1227                    pb_mkdir_p("$ENV{'PBBUILDDIR'}/$d");
[28]1228                }
[25]1229            }
1230
[315]1231            # Remove in case a previous link/file was there
[301]1232            unlink "$ENV{'PBBUILDDIR'}/SOURCES/".basename($src);
[188]1233            symlink "$src","$ENV{'PBBUILDDIR'}/SOURCES/".basename($src) || die "Unable to symlink $src in $ENV{'PBBUILDDIR'}/SOURCES";
[25]1234            # We need to first extract the spec file
[1177]1235            my @specfile = pb_extract_build_files($src2,"$pbpkg-$pbver/pbconf/$pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}/","$ENV{'PBBUILDDIR'}/SPECS","spec");
[25]1236
[493]1237            # We need to handle potential patches to upstream sources
[1177]1238            pb_extract_build_files($src2,"$pbpkg-$pbver/pbconf/$pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}/pbpatch/","$ENV{'PBBUILDDIR'}/SOURCES","patch");
[493]1239
[1219]1240            # We need to handle potential additional sources to upstream sources
1241            pb_extract_build_files($src2,"$pbpkg-$pbver/pbconf/$pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}/pbsrc/","$ENV{'PBBUILDDIR'}/SOURCES","src");
1242
[315]1243            pb_log(2,"specfile: ".Dumper(\@specfile)."\n");
[25]1244            # set LANGUAGE to check for correct log messages
1245            $ENV{'LANGUAGE'}="C";
[459]1246            # Older Redhat use _target_platform in %configure incorrectly
1247            my $specialdef = "";
[1177]1248            if (($pbos->{'name'} eq "redhat") || (($pbos->{'name'} eq "rhel") && ($pbos->{'version'} eq "2.1"))) {
[459]1249                $specialdef = "--define \'_target_platform \"\"\'";
1250            }
[702]1251
[28]1252            foreach my $f (@specfile) {
1253                if ($f =~ /\.spec$/) {
[1137]1254                    # This could cause an issue in // mode
[1177]1255                    pb_distro_installdeps($f,$pbos);
[1085]1256                    pb_system("rpmbuild $specialdef --define \"packager $ENV{'PBPACKAGER'}\" --define \"_topdir $ENV{'PBBUILDDIR'}\" -ba $f","Building package with $f under $ENV{'PBBUILDDIR'}","verbose");
[28]1257                    last;
1258                }
1259            }
[540]1260            # Get the name of the generated packages
[1137]1261            open(LOG,"$ENV{'PBTMP'}/system.$$.log") || die "Unable to open $ENV{'PBTMP'}/system.$$.log";
[540]1262            while (<LOG>) {
[572]1263                chomp($_);
[540]1264                next if ($_ !~ /^Wrote:/);
1265                s|.*/([S]*RPMS.*)|$1|;
[572]1266                $made .=" $_";
[540]1267            }
[541]1268            close(LOG);
[540]1269
[1177]1270        } elsif ($pbos->{'type'} eq "deb") {
[274]1271            pb_system("tar xfz $src","Extracting sources");
[493]1272            pb_system("tar xfz $src2","Extracting pbconf");
[149]1273
1274            chdir "$pbpkg-$pbver" || die "Unable to chdir to $pbpkg-$pbver";
[310]1275            pb_rm_rf("debian");
[1177]1276            symlink "pbconf/$pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}","debian" || die "Unable to symlink to pbconf/$pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}";
[199]1277            chmod 0755,"debian/rules";
[544]1278
[1359]1279            # We need to handle potential patches to upstream sources
[1363]1280            pb_mkdir_p("debian/patches");
1281            my @f = pb_extract_build_files($src2,"$pbpkg-$pbver/pbconf/$pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}/pbpatch/","debian/patches","patch");
1282
[1367]1283            # By default we use format 1.0 - Cf man dpkg-source
1284            my $debsrcfmt = "1.0";
1285            my $debsrcfile = "debian/source/format";
1286            if (-f $debsrcfile) {
1287                $debsrcfmt = pb_get_content($debsrcfile);
1288            }
1289               
1290            if ($debsrcfmt =~ /^3.*quilt/) {
1291                # If we use quilt to manage patches, we then setup the env correctly
1292                # as per http://pkg-perl.alioth.debian.org/howto/quilt.html
1293                # Generate Debian patch series for quilt
1294                open(SERIE,"> debian/patches/series") || die "Unable to write in debian/patches/series";
1295                $ENV{'QUILT_PATCHES'}="debian/patches";
1296            } else {
1297                # If we use dpatch to manage patches, we then setup the 00list file as well
1298                open(SERIE,"> debian/patches/00list") || die "Unable to write in debian/patches/00list";
1299            }
[1363]1300            foreach my $f (sort @f) {
[1367]1301                # Skip the script made to apply the patches to the Debian tree
1302                next if ($f =~ /pbapplypatch/);
1303                # We also need to uncompress them
1304                pb_system("gzip -d $f","","quiet");
1305                $f =~ s/\.gz$//;
[1359]1306                print SERIE "$f\n";
1307            }
1308            close(SERIE);
[1367]1309            if ($debsrcfmt =~ /^1.*/) {
1310                # In that case we need to apply the patches ourselves locally
1311                pb_system("cat debian/patches/pbapplypatch","APPLY","verbose");
1312                pb_system("debian/patches/pbapplypatch","Applying patches to $pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'} tree");
1313            }
1314            if (@f) {
1315                # We have patches, so modify the name of files to be Debian compliant
1316                move("../$src","../$pbpkg-$pbver.orig.tar.gz");
1317            }
[1359]1318
1319            # We need to handle potential additional sources to upstream sources
1320            #pb_extract_build_files($src2,"$pbpkg-$pbver/pbconf/$pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}/pbsrc/","$ENV{'PBBUILDDIR'}/debian","src");
1321
[1177]1322            pb_distro_installdeps("debian/control",$pbos);
[544]1323            pb_system("dpkg-buildpackage -us -uc -rfakeroot","Building package","verbose");
1324            # Get the name of the generated packages
[1137]1325            open(LOG,"$ENV{'PBTMP'}/system.$$.log") || die "Unable to open $ENV{'PBTMP'}/system.$$.log";
[544]1326            while (<LOG>) {
1327                chomp();
1328                my $tmp = $_;
[567]1329                next if ($tmp !~ /^dpkg-deb.*:/);
[1234]1330                $tmp =~ s|.*\.\./(.*)_(.*).deb.*|$1|;
[544]1331                $made="$made $tmp.dsc $tmp.tar.gz $tmp"."_*.deb $tmp"."_*.changes";
[448]1332            }
[544]1333            close(LOG);
[1234]1334            chdir ".." || die "Unable to chdir to parent dir";
1335            pb_system("rm -rf $pbpkg-$pbver", "Cleanup");
[1177]1336        } elsif ($pbos->{'type'} eq "ebuild") {
[149]1337            my @ebuildfile;
1338            # For gentoo we need to take pb as subsystem name
[295]1339            # We put every apps here under sys-apps. hope it's correct
[435]1340            # We use pb's home dir in order to have a single OVERLAY line
[1185]1341            my $tmpe = "$ENV{'HOME'}/portage/pb/sys-apps/$pbpkg";
1342            pb_mkdir_p($tmpe) if (! -d "$tmpe");
[295]1343            pb_mkdir_p("$ENV{'HOME'}/portage/distfiles") if (! -d "$ENV{'HOME'}/portage/distfiles");
[149]1344
[295]1345            # We need to first extract the ebuild file
[1185]1346            @ebuildfile = pb_extract_build_files($src2,"$pbpkg-$pbver/pbconf/$pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}/","$tmpe","ebuild");
[149]1347
1348            # Prepare the build env for gentoo
1349            my $found = 0;
[295]1350            my $pbbd = $ENV{'HOME'};
[150]1351            $pbbd =~ s|/|\\/|g;
[295]1352            if (-r "/etc/make.conf") {
1353                open(MAKE,"/etc/make.conf");
1354                while (<MAKE>) {
1355                    $found = 1 if (/$pbbd\/portage/);
1356                }
1357                close(MAKE);
[149]1358            }
1359            if ($found == 0) {
[295]1360                pb_system("sudo sh -c 'echo PORTDIR_OVERLAY=\"$ENV{'HOME'}/portage\" >> /etc/make.conf'");
[149]1361            }
[295]1362            #$found = 0;
1363            #if (-r "/etc/portage/package.keywords") {
1364            #open(KEYW,"/etc/portage/package.keywords");
1365            #while (<KEYW>) {
1366            #$found = 1 if (/portage\/pb/);
1367            #}
1368            #close(KEYW);
1369            #}
1370            #if ($found == 0) {
1371            #pb_system("sudo sh -c \"echo portage/pb >> /etc/portage/package.keywords\"");
1372            #}
[149]1373
1374            # Build
1375            foreach my $f (@ebuildfile) {
1376                if ($f =~ /\.ebuild$/) {
[1177]1377                    pb_distro_installdeps($f,$pbos);
[1185]1378                    move($f,"$tmpe/$pbpkg-$pbver.ebuild");
1379                    pb_system("cd $tmpe ; ebuild $pbpkg-$pbver.ebuild clean ; ebuild $pbpkg-$pbver.ebuild digest ; ebuild $pbpkg-$pbver.ebuild package","verbose");
[295]1380                    # Now move it where pb expects it
1381                    pb_mkdir_p("$ENV{'PBBUILDDIR'}/portage/pb/sys-apps/$pbpkg");
[1174]1382                    if ($pbtag =~ /^0\./) {
1383                        # This is a test version
1384                        my $ntag = $pbtag;
1385                        $ntag =~ s/^0\.//;
[1185]1386                        move("$tmpe/$pbpkg-$pbver.ebuild","$ENV{'PBBUILDDIR'}/portage/pb/sys-apps/$pbpkg/$pbpkg-$pbver"."_p$ntag.ebuild");
[1174]1387                        $made="$made portage/pb/sys-apps/$pbpkg/$pbpkg-$pbver"."_p$ntag.ebuild";
1388                    } else {
[1185]1389                        move("$tmpe/$pbpkg-$pbver.ebuild","$ENV{'PBBUILDDIR'}/portage/pb/sys-apps/$pbpkg/$pbpkg-$pbver-r$pbtag.ebuild");
[1174]1390                        $made="$made portage/pb/sys-apps/$pbpkg/$pbpkg-$pbver-r$pbtag.ebuild";
1391                    }
[149]1392                }
1393            }
1394
[1177]1395        } elsif ($pbos->{'type'} eq "tgz") {
[437]1396            # Slackware family
[435]1397            $made="$made $pbpkg/$pbpkg-$pbver-*-$pbtag.tgz";
1398
1399            pb_system("tar xfz $src","Extracting sources");
[493]1400            pb_system("tar xfz $src2","Extracting pbconf");
[435]1401            chdir "$pbpkg-$pbver" || die "Unable to chdir to $pbpkg-$pbver";
[1177]1402            symlink "pbconf/$pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}","install" || die "Unable to symlink to pbconf/$pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}";
[435]1403            if (-x "install/pbslack") {
[1177]1404                pb_distro_installdeps("./install/pbslack",$pbos);
[872]1405                pb_system("./install/pbslack","Building software");
[529]1406                pb_system("sudo /sbin/makepkg -p -l y -c y $pbpkg","Packaging $pbpkg","verbose");
[435]1407            }
[1234]1408            chdir ".." || die "Unable to chdir to parent dir";
1409            pb_system("rm -rf $pbpkg-$pbver", "Cleanup");
[1177]1410        } elsif ($pbos->{'type'} eq "pkg") {
[872]1411            # Solaris
[916]1412            $made="$made $pbpkg-$pbver-$pbtag.pkg.gz";
[873]1413            my $pkgdestdir="$ENV{'PBBUILDDIR'}/install";
[872]1414
1415            # Will host resulting packages
[1177]1416            pb_mkdir_p("$pbos->{'type'}");
[878]1417            pb_mkdir_p("$pkgdestdir/delivery");
[873]1418            pb_system("tar xfz $src","Extracting sources under $ENV{'PBBUILDDIR'}");
1419            pb_system("tar xfz $src2","Extracting pbconf under $ENV{'PBBUILDDIR'}");
[1242]1420            # We need to handle potential patches to upstream sources
[1280]1421            pb_extract_build_files($src2,"$pbpkg-$pbver/pbconf/$pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}/pbpatch/","$ENV{'PBBUILDDIR'}","patch");
[1242]1422
1423            # We need to handle potential additional sources to upstream sources
[1280]1424            pb_extract_build_files($src2,"$pbpkg-$pbver/pbconf/$pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}/pbsrc/","$ENV{'PBBUILDDIR'}","src");
[1242]1425
[872]1426            chdir "$pbpkg-$pbver" || die "Unable to chdir to $pbpkg-$pbver";
[1177]1427            if (-f "pbconf/$pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}/pbbuild") {
1428                chmod 0755,"pbconf/$pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}/pbbuild";
[872]1429                # pkginfo file is mandatory
[1177]1430                die "Unable to find pkginfo file in pbconf/$pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}" if (! -f "pbconf/$pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}/pkginfo");
[872]1431                # Build
[1177]1432                pb_system("pbconf/$pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}/pbbuild $pkgdestdir/delivery","Building software and installing under $pkgdestdir/delivery");
[872]1433                # Copy complementary files
[1177]1434                if (-f "pbconf/$pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}/prototype") {
1435                    copy("pbconf/$pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}/prototype", $pkgdestdir) 
[872]1436                } else {
1437                    # No prototype provided, calculating it
[878]1438                    open(PROTO,"> $pkgdestdir/prototype") || die "Unable to create prototype file";
[872]1439                    print PROTO "i pkginfo\n";
[1177]1440                    print PROTO "i depend\n" if (-f "pbconf/$pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}/depend");
[879]1441                    $ENV{'PBSOLDESTDIR'} = "$pkgdestdir/delivery";
1442                    find(\&create_solaris_prototype, "$pkgdestdir/delivery");
[872]1443                }
[1177]1444                copy("pbconf/$pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}/depend", $pkgdestdir) if (-f "pbconf/$pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}/depend");
1445                copy("pbconf/$pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}/pkginfo", $pkgdestdir);
1446                pb_system("cd $pkgdestdir/delivery ; pkgmk -o -f ../prototype -r $pkgdestdir/delivery -d $ENV{'PBBUILDDIR'}/$pbos->{'type'}","Packaging $pbpkg","verbose");
1447                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");
[916]1448                pb_system("cd $ENV{'PBBUILDDIR'} ;  gzip -9f $pbpkg-$pbver-$pbtag.pkg","Compressing $pbpkg-$pbver-$pbtag.pkg","verbose");
[913]1449            } else {
[1177]1450                pb_log(0,"No pbconf/$pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}/pbbuild file found for $pbpkg-$pbver in \n");
[872]1451            }
[874]1452            chdir ".." || die "Unable to chdir to parent dir";
[1177]1453            pb_system("rm -rf $pbpkg-$pbver $ENV{'PBBUILDDIR'}/$pbos->{'type'} $pkgdestdir", "Cleanup");
1454        } elsif ($pbos->{'type'} eq "hpux") {
[1174]1455            # HP-UX
1456            pb_system("tar xfz $src","Extracting sources");
1457            pb_system("tar xfz $src2","Extracting pbconf");
1458
1459            chdir "$pbpkg-$pbver" || die "Unable to chdir to $pbpkg-$pbver";
1460            pb_system("buildpackage ","Building package","verbose");
1461            # Get the name of the generated packages
1462            open(LOG,"$ENV{'PBTMP'}/system.$$.log") || die "Unable to open $ENV{'PBTMP'}/system.$$.log";
1463            while (<LOG>) {
1464                chomp();
1465                my $tmp = $_;
1466                next if ($tmp !~ /^SD BUILD.*:/);
1467                $tmp =~ s|.*../(.*)_(.*).sd.*|$1|;
[1279]1468                $made = "$made $tmp"."_*.sd";
[1174]1469            }
1470            close(LOG);
1471            $made="$made $pbpkg-$pbver-$pbtag.sd";
1472
[1234]1473            chdir ".." || die "Unable to chdir to parent dir";
[1174]1474            pb_system("rm -rf $pbpkg-$pbver", "Cleanup");
[87]1475        } else {
[1177]1476            die "Unknown OS type format $pbos->{'type'}";
[87]1477        }
[1137]1478        if (defined $pbparallel) {
1479            # Communicate results back to parent
1480            pb_set_content("$tmpd/$$",$made);
1481            $pm->finish;
1482        }
[87]1483    }
[1137]1484    if (defined $pbparallel) {
1485        # In the parent, we need to get the result from the children
1486        $pm->wait_all_children;
1487        foreach my $f (<$tmpd/*>) {
1488            $made .= " ".pb_get_content($f);
1489        }
1490        pb_rm_rf($tmpd);
1491    }
1492
[1278]1493    # Sign packages
1494    pb_sign_pkgs($pbos,$made);
1495
[1109]1496    # Find the appropriate check cmd/opts
[1177]1497    my ($chkcmd,$chkopt) = pb_distro_get_param($pbos,pb_conf_get_if("oschkcmd","oschkopt"));
[1109]1498
[541]1499    # Packages check if needed
[1177]1500    if ($pbos->{'type'} eq "rpm") {
1501        if ((defined  $chkcmd) && (-x $chkcmd)) {
1502            my $cmd = "$chkcmd";
1503            $cmd .= " $chkopt" if (defined $chkopt);
1504            $cmd .= " $made";
1505            pb_system("$cmd","Checking validity of rpms with $chkcmd","verbose");
[541]1506        }
[1098]1507        my $rpms ="";
1508        my $srpms ="";
1509        foreach my $f (split(/ /,$made)) {
1510            $rpms .= "$ENV{'PBBUILDDIR'}/$f " if ($f =~ /^RPMS\//);
1511            $srpms .= "$ENV{'PBBUILDDIR'}/$f " if ($f =~ /^SRPMS\//);
1512        }
1513        pb_log(0,"SRPM packages generated: $srpms\n");
1514        pb_log(0,"RPM packages generated: $rpms\n");
[1177]1515    } elsif ($pbos->{'type'} eq "deb") {
[572]1516        my $made2 = "";
[971]1517        foreach my $f (split(/ /,$made)) {
[1234]1518            $made2 .= "$f " if ($f =~ /\.deb$/);
[971]1519        }
[1109]1520        if (-x $chkcmd) {
1521            pb_system("$chkcmd $chkopt $made2","Checking validity of debs with $chkcmd","verbose");
[541]1522        }
[1234]1523        pb_log(0,"deb packages generated: $made2\n");
[541]1524    } else {
[1177]1525        pb_log(0,"No check done for $pbos->{'type'} yet\n");
[572]1526        pb_log(0,"Packages generated: $made\n");
[541]1527    }
1528
[1176]1529    # Keep track of what is generated so that we can get them back from VMs/RMs
[1189]1530    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'}";
[118]1531    print KEEP "$made\n";
1532    close(KEEP);
[87]1533}
1534
[874]1535sub create_solaris_prototype {
[872]1536
[873]1537    my $uidgid = "bin bin";
[877]1538    my $pkgdestdir = $ENV{'PBSOLDESTDIR'};
[872]1539
[878]1540    return if ($_ =~ /^$pkgdestdir$/);
[875]1541    if (-d $_) {
1542        my $n = $File::Find::name;
1543        $n =~ s~$pkgdestdir/~~;
1544        print PROTO "d none $n 0755 $uidgid\n";
[877]1545    } elsif (-x $_) {
[875]1546        my $n = $File::Find::name;
1547        $n =~ s~$pkgdestdir/~~;
1548        print PROTO "f none $n 0755 $uidgid\n";
[872]1549    } elsif (-f $_) {
[875]1550        my $n = $File::Find::name;
1551        $n =~ s~$pkgdestdir/~~;
1552        print PROTO "f none $n 0644 $uidgid\n";
[872]1553    }
1554}
1555
[88]1556sub pb_build2ssh {
[320]1557    pb_send2target("Sources");
[1374]1558    pb_send2target("CPAN");
[90]1559}
[87]1560
[90]1561sub pb_pkg2ssh {
[320]1562    pb_send2target("Packages");
[90]1563}
1564
[108]1565# By default deliver to the the public site hosting the
[1176]1566# ftp structure (or whatever) or a VM/VE/RM
[320]1567sub pb_send2target {
[90]1568
1569    my $cmt = shift;
[320]1570    my $v = shift || undef;
[142]1571    my $vmexist = shift || 0;           # 0 is FALSE
[200]1572    my $vmpid = shift || 0;             # 0 is FALSE
[748]1573    my $snapme = shift || 0;            # 0 is FALSE
[320]1574
[444]1575    pb_log(2,"DEBUG: pb_send2target($cmt,".Dumper($v).",$vmexist,$vmpid)\n");
[320]1576    my $host = "sshhost";
1577    my $login = "sshlogin";
1578    my $dir = "sshdir";
1579    my $port = "sshport";
1580    my $conf = "sshconf";
[883]1581    my $tmout = undef;
1582    my $path = undef;
[772]1583    if ($cmt =~ /^VM/) {
[320]1584        $login = "vmlogin";
[322]1585        $dir = "pbdefdir";
[320]1586        # Specific VM
[883]1587        $tmout = "vmtmout";
1588        $path = "vmpath";
[320]1589        $host = "vmhost";
1590        $port = "vmport";
[1176]1591    } elsif ($cmt =~ /^RM/) {
1592        $login = "rmlogin";
1593        $dir = "pbdefdir";
1594        # Specific RM
1595        $tmout = "rmtmout";
1596        $path = "rmpath";
1597        $host = "rmhost";
1598        $port = "rmport";
[772]1599    } elsif ($cmt =~ /^VE/) {
[320]1600        $login = "velogin";
[322]1601        $dir = "pbdefdir";
[320]1602        # Specific VE
1603        $path = "vepath";
[986]1604        $conf = "rbsconf";
[556]1605    } elsif ($cmt eq "Web") {
1606        $host = "websshhost";
1607        $login = "websshlogin";
1608        $dir = "websshdir";
1609        $port = "websshport";
[1374]1610    } elsif ($cmt eq "CPAN") {
1611        $host = "cpanpause";
1612        $login = "";
1613        $dir = "cpandir";
1614        $port = "";
[320]1615    }
[158]1616    my $cmd = "";
[471]1617    my $src = "";
[1374]1618    my $cpanpkg = 0;
[1177]1619    my $pbos;
[90]1620
[471]1621    if ($cmt ne "Announce") {
[898]1622        # Get list of packages to build
[471]1623        my $ptr = pb_get_pkg();
1624        @pkgs = @$ptr;
[87]1625
[471]1626        # Get the running distro to consider
[1177]1627        $pbos = pb_distro_get_context($v);
[87]1628
[471]1629        # Get list of packages to build
1630        # Get content saved in cms2build
1631        my ($pkg) = pb_conf_read("$ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb","pbpkg");
1632        $pkg = { } if (not defined $pkg);
[87]1633
[1212]1634        pb_mkdir_p("$ENV{'PBBUILDDIR'}") if (! -d "$ENV{'PBBUILDDIR'}");
[1208]1635        chdir "$ENV{'PBBUILDDIR'}" || die "Unable to chdir to $ENV{'PBBUILDDIR'}";
[471]1636        foreach my $pbpkg (@pkgs) {
1637            my $vertag = $pkg->{$pbpkg};
1638            # get the version of the current package - maybe different
1639            ($pbver,$pbtag) = split(/-/,$vertag);
[87]1640
[1179]1641            if (($cmt eq "Sources") || ($cmt =~ /(V[EM]|RM)build/)) {
[493]1642                $src = "$src $ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz $ENV{'PBDESTDIR'}/$pbpkg-$pbver.pbconf.tar.gz";
[471]1643                if ($cmd eq "") {
1644                    $cmd = "ln -sf $pbpkg-$pbver.tar.gz $pbpkg-latest.tar.gz";
1645                } else {
1646                    $cmd = "$cmd ; ln -sf $pbpkg-$pbver.tar.gz $pbpkg-latest.tar.gz";
1647                }
[560]1648            } elsif ($cmt eq "Web") {
1649                $src = "$src $ENV{'PBDESTDIR'}/$pbpkg-$pbver.tar.gz"
[166]1650            }
[1374]1651
1652            # Do we have one perl package
1653            my @nametype = pb_conf_get_if("namingtype");
1654            my $type = $nametype[0]->{$pbpkg};
1655            if ((defined $type) && ($type eq "perl")) {
1656                $cpanpkg = 1;
1657            }
[118]1658        }
[471]1659        # Adds conf file for availability of conf elements
1660        pb_conf_add("$ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb");
[118]1661    }
[1374]1662    my ($rbsconf,$testver,$delivery) = pb_conf_get_if($conf,"testver","delivery");
1663    if ($cmt =~ /CPAN/) {
1664        # Do not deliver on Pause if this is a test version
1665        return if ($testver =~ /true/);
1666        # Do not deliver on Pause if this is not a perl package
1667        return if ($cpanpkg == 0);
1668    }
[417]1669
[1176]1670    if ($cmt =~ /(V[EM]|RM)build/) {
[1138]1671        $src="$src $ENV{'PBROOTDIR'}/$ENV{'PBPROJ'}.pb $ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb $ENV{'PBETC'} $ENV{'PBDESTDIR'}/pbrc $ENV{'PBDESTDIR'}/pbscript.$$";
[1176]1672    } elsif ($cmt =~ /(V[EM]|RM)Script/) {
[1138]1673        $src="$src $ENV{'PBDESTDIR'}/pbscript.$$";
[1176]1674    } elsif ($cmt =~ /(V[EM]|RM)test/) {
[1138]1675        $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";
[1374]1676    } elsif (($cmt eq "Announce") || ($cmt eq "Web") || ($cmt eq "CPAN")) {
[471]1677        $src="$src $ENV{'PBTMP'}/pbscript";
[118]1678    } elsif ($cmt eq "Packages") {
1679        # Get package list from file made during build2pkg
[1189]1680        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'}";
[126]1681        $src = <KEEP>;
[118]1682        chomp($src);
1683        close(KEEP);
[1279]1684        $src = "$src $ENV{'PBBUILDDIR'}/pbscript.$$";
[87]1685    }
[1374]1686    if (($cmt eq "Sources") || ($cmt eq "Packages") || ($cmt eq "CPAN")) {
[1279]1687        my ($pbpackager) = pb_conf_get("pbpackager");
1688        $ENV{'PBPACKAGER'} = $pbpackager->{$ENV{'PBPROJ'}};
1689        pb_log(0,"Exporting public key for $ENV{'PBPACKAGER'}\n");
1690        # Using pb_system is not working due to redirection below
1691        system("gpg --export -a \'$ENV{'PBPACKAGER'}\' > $ENV{'PBDESTDIR'}/$ENV{'PBPROJ'}.pubkey");
1692        chmod 0644,"$ENV{'PBDESTDIR'}/$ENV{'PBPROJ'}.pubkey";
1693        $src = "$src $ENV{'PBDESTDIR'}/$ENV{'PBPROJ'}.pubkey";
1694    }
[320]1695    # Remove potential leading spaces (cause problem with basename)
[132]1696    $src =~ s/^ *//;
[129]1697    my $basesrc = "";
[131]1698    foreach my $i (split(/ +/,$src)) {
1699        $basesrc .= " ".basename($i);
[130]1700    }
[118]1701
[320]1702    pb_log(0,"Sources handled ($cmt): $src\n");
[987]1703    pb_log(2,"values: ".Dumper(($host,$login,$dir,$port,$tmout,$path,$conf))."\n");
[883]1704    my ($sshhost,$sshlogin,$sshdir,$sshport) = pb_conf_get($host,$login,$dir,$port);
1705    # Not mandatory...
[1102]1706    $delivery->{$ENV{'PBPROJ'}} = "" if (not defined $delivery->{$ENV{'PBPROJ'}});
[883]1707    my ($vtmout,$vepath);
1708    # ...Except those in virtual context
1709    if ($cmt =~ /^VE/) {
1710        ($vepath) = pb_conf_get($path);
1711    }
[1176]1712    if ($cmt =~ /^(V|R)M/) {
[1218]1713        $vtmout = pb_distro_get_param($pbos,pb_conf_get_if($tmout));
[883]1714    }
[1216]1715    my $remhost = $sshhost->{$ENV{'PBPROJ'}};
1716    my $remdir = $sshdir->{$ENV{'PBPROJ'}};
1717    if ($cmt =~ /^V[EM]|RM/) {
1718        # In that case our real host is in the xxhost with the OS as key, not project as above
1719        $remhost = pb_distro_get_param($pbos,$sshhost);
[1176]1720    }
[1217]1721    pb_log(2,"ssh: ".Dumper(($remhost,$sshlogin,$remdir,$sshport,$vepath,$rbsconf))."\n");
1722    pb_log(2,"ssh: ".Dumper($vtmout)."\n") if (defined $vtmout);
[320]1723
1724    my $mac;
[772]1725    if ($cmt !~ /^VE/) {
[1216]1726        $mac = "$sshlogin->{$ENV{'PBPROJ'}}\@$remhost";
[320]1727        # Overwrite account value if passed as parameter
[1216]1728        $mac = "$pbaccount\@$remhost" if (defined $pbaccount);
[355]1729        pb_log(2, "DEBUG: pbaccount: $pbaccount => mac: $mac\n") if (defined $pbaccount);
[681]1730    } else {
1731        # VE
[1138]1732        # Overwrite account value if passed as parameter (typically for setup2v)
[681]1733        $mac = $sshlogin->{$ENV{'PBPROJ'}};
1734        $mac = $pbaccount if (defined $pbaccount);
[320]1735    }
1736
[108]1737    my $tdir;
[136]1738    my $bdir;
[1176]1739    if (($cmt eq "Sources") || ($cmt =~ /(V[EM]|RM)Script/)) {
[1216]1740        $tdir = "$remdir/$delivery->{$ENV{'PBPROJ'}}/src";
[1374]1741    } elsif ($cmt eq "CPAN") {
1742        $tdir = "$remdir";
[1176]1743    } elsif ($cmt =~ /(V[EM]|RM)(build|test)/) {
[1216]1744        $tdir = $remdir."/$ENV{'PBPROJ'}/delivery";
1745        $bdir = $remdir."/$ENV{'PBPROJ'}/build";
[136]1746        # Remove a potential $ENV{'HOME'} as bdir should be relative to pb's home
1747        $bdir =~ s|\$ENV.+\}/||;
[471]1748    } elsif ($cmt eq "Announce") {
[1216]1749        $tdir = "$remdir/$delivery->{$ENV{'PBPROJ'}}";
[556]1750    } elsif ($cmt eq "Web") {
[1216]1751        $tdir = "$remdir/$delivery->{$ENV{'PBPROJ'}}";
[90]1752    } elsif ($cmt eq "Packages") {
[1192]1753        if (($pbos->{'type'} eq "rpm") || ($pbos->{'type'} eq "pkg") || ($pbos->{'type'} eq "hpux") || ($pbos->{'type'} eq "tgz")) {
1754            # put packages under an arch subdir
[1216]1755            $tdir = "$remdir/$delivery->{$ENV{'PBPROJ'}}/$pbos->{'name'}/$pbos->{'version'}/$pbos->{'arch'}";
[1192]1756        } elsif (($pbos->{'type'} eq "deb") || ($pbos->{'type'} eq "ebuild")) {
1757            # No need for an arch subdir
[1216]1758            $tdir = "$remdir/$delivery->{$ENV{'PBPROJ'}}/$pbos->{'name'}/$pbos->{'version'}";
[1192]1759        } else {
1760            die "Please teach the dev team where to deliver ($pbos->{'type'} type of packages\n";
1761        }
[429]1762
1763        my $repodir = $tdir;
[1216]1764        $repodir =~ s|^$remdir/||;
[429]1765
1766        my ($pbrepo) = pb_conf_get("pbrepo");
1767
1768        # Repository management
[1189]1769        open(PBS,"> $ENV{'PBBUILDDIR'}/pbscript.$$") || die "Unable to create $ENV{'PBBUILDDIR'}/pbscript.$$";
[1177]1770        if ($pbos->{'type'} eq "rpm") {
[1276]1771            my $pbsha = pb_distro_get_param($pbos,pb_conf_get("ossha"));
[429]1772            # Also make a pbscript to generate yum/urpmi bases
1773            print PBS << "EOF";
[433]1774#!/bin/bash
[429]1775# Prepare a script to ease yum setup
[1298]1776EOF
1777            print PBS "set -x\n" if ($pbdebug gt 1);
1778            print PBS << "EOF";
[429]1779cat > $ENV{'PBPROJ'}.repo << EOT
1780[$ENV{'PBPROJ'}]
[1177]1781name=$pbos->{'name'} $pbos->{'version'} $pbos->{'arch'} - $ENV{'PBPROJ'} Vanilla Packages
[433]1782baseurl=$pbrepo->{$ENV{'PBPROJ'}}/$repodir
[429]1783enabled=1
[1289]1784gpgcheck=1
[1335]1785gpgkey=$pbrepo->{$ENV{'PBPROJ'}}/$repodir/$ENV{'PBPROJ'}.pubkey
[429]1786EOT
1787chmod 644 $ENV{'PBPROJ'}.repo
1788
1789# Clean up old repo content
1790rm -rf headers/ repodata/
1791# Create yum repo
[1102]1792if [ -x /usr/bin/yum-arch ]; then
1793    yum-arch .
1794fi
[429]1795# Create repodata
[1276]1796createrepo -s $pbsha .
[1365]1797# Link to the key
1798ln -sf $ENV{'PBPROJ'}.pubkey repodata/repomd.xml.key
1799# sign the repomd (at least useful for SLES - which requires a local key)
1800# gpg -a --detach-sign repodata/repomd.xml
1801# SLES also looks for media.1/info.txt
[429]1802EOF
[1177]1803            if ($pbos->{'family'} eq "md") {
[429]1804                # For Mandriva add urpmi management
1805                print PBS << "EOF";
1806# Prepare a script to ease urpmi setup
1807cat > $ENV{'PBPROJ'}.addmedia << EOT
[1003]1808urpmi.addmedia $ENV{'PBPROJ'} $pbrepo->{$ENV{'PBPROJ'}}/$repodir with media_info/hdlist.cz
[429]1809EOT
1810chmod 755 $ENV{'PBPROJ'}.addmedia
1811
1812# Clean up old repo content
[437]1813rm -f hdlist.cz synthesis.hdlist.cz
[429]1814# Create urpmi repo
[1002]1815genhdlist2 --clean .
1816if [ \$\? -ne 0 ]; then
1817    genhdlist .
1818fi
[429]1819EOF
1820            }
[1177]1821            if ($pbos->{'name'} eq "fedora") {
[484]1822                # Extract the spec file to please Fedora maintainers :-(
1823                print PBS << "EOF";
1824for p in $basesrc; do
1825    echo \$p | grep -q 'src.rpm'
1826    if [ \$\? -eq 0 ]; then
1827        rpm2cpio \$p | cpio -ivdum --quiet '*.spec'
1828    fi
1829done
1830EOF
1831            }
[1177]1832            if ($pbos->{'family'} eq "novell") {
[1089]1833                # Add ymp scripts for one-click install on SuSE
1834                print PBS << "EOF";
1835# Prepare a script to ease SuSE one-click install
[1090]1836# Cf: http://de.opensuse.org/1-Klick-Installation/ISV
1837#
[1089]1838cat > $ENV{'PBPROJ'}.ymp << EOT
[1096]1839<?xml version="1.0" encoding="utf-8"?>
1840<!-- vim: set sw=2 ts=2 ai et: -->
[1089]1841<metapackage xmlns:os="http://opensuse.org/Standards/One_Click_Install" xmlns="http://opensuse.org/Standards/One_Click_Install">
1842    <group><!-- The group of software, typically one for project-builder.org -->
1843        <name>$ENV{'PBPROJ'} Bundle</name> <!-- Name of the software group -->
1844        <summary>Software bundle for the $ENV{'PBPROJ'} project</summary> <!--This message is shown to the user and should describe the whole bundle -->
[1095]1845        <description>This is the summary of the $ENV{'PBPROJ'} Project
[1089]1846             
[1095]1847            Details are available on a per package basis below
1848
[1089]1849        </description><!--This is also shown to the user -->
1850        <remainSubscribed>false</remainSubscribed> <!-- Don't know what it mean -->
1851        <repositories><!-- List of needed repositories -->
1852            <repository>
1853                <name>$ENV{'PBPROJ'} Repository</name> <!-- Name of the repository  -->
1854                <summary>This repository contains the $ENV{'PBPROJ'} project packages.</summary> <!-- Summary of the repository -->
1855                <description>This repository contains the $ENV{'PBPROJ'} project packages.</description><!-- This description is shown to the user -->
1856                <url>$pbrepo->{$ENV{'PBPROJ'}}/$repodir</url><!--URL of repository, which is added -->
1857            </repository>
1858        </repositories>
1859        <software><!-- A List of packages, which should be added through the one-click-installation -->
1860EOT
1861for p in $basesrc; do
1862    sum=`rpm -q --qf '%{SUMMARY}' \$p`
[1096]1863    name=`rpm -q --qf '%{NAME}' \$p`
[1089]1864    desc=`rpm -q --qf '%{description}' \$p`
1865    cat >> $ENV{'PBPROJ'}.ymp << EOT
1866            <item>
[1096]1867                <name>\$name</name><!-- Name of the package, is shown to the user and used to identify the package at the repository -->
[1089]1868                <summary>\$sum</summary> <!-- Summary of the package -->
1869                <description>\$desc</description> <!-- Description, is shown to the user -->
1870            </item>
1871EOT
1872done
1873cat >> $ENV{'PBPROJ'}.ymp << EOT
1874        </software>
1875    </group>
1876</metapackage>
1877EOT
1878chmod 644 $ENV{'PBPROJ'}.ymp
1879EOF
1880            }
[1177]1881        } elsif ($pbos->{'type'} eq "deb") {
[429]1882            # Also make a pbscript to generate apt bases
[460]1883            # Cf: http://www.debian.org/doc/manuals/repository-howto/repository-howto.fr.html
[1246]1884            # This dirname removes ver
[1283]1885            my $debarch = $pbos->{'arch'};
[1287]1886            $debarch = "amd64" if ($pbos->{'arch'} eq "x86_64");
[465]1887            my $rpd = dirname("$pbrepo->{$ENV{'PBPROJ'}}/$repodir");
[1357]1888            # Remove extra . in path to fix #522
1889            $rpd =~ s|/./|/|g;
[460]1890            print PBS << "EOF";
[465]1891#!/bin/bash
1892# Prepare a script to ease apt setup
1893cat > $ENV{'PBPROJ'}.sources.list << EOT
[1177]1894deb $rpd $pbos->{'version'} contrib
1895deb-src $rpd $pbos->{'version'} contrib
[460]1896EOT
[465]1897chmod 644 $ENV{'PBPROJ'}.sources.list
[460]1898
[1112]1899# Up two levels to deal with the dist dir cross versions
[1192]1900cd ..
[1275]1901mkdir -p dists/$pbos->{'version'}/contrib/binary-$debarch dists/$pbos->{'version'}/contrib/source
[1112]1902
[460]1903# Prepare a script to create apt info file
[1192]1904# Reuse twice after
[1112]1905TMPD=`mktemp -d /tmp/pb.XXXXXXXXXX` || exit 1
1906mkdir -p \$TMPD
1907cat > \$TMPD/Release << EOT
1908Archive: unstable
1909Component: contrib
1910Origin: $ENV{'PBPROJ'}
1911Label: $ENV{'PBPROJ'} dev repository $pbrepo->{$ENV{'PBPROJ'}}
1912EOT
1913
[1275]1914echo "Creating Packages metadata ($pbos->{'arch'} aka $debarch)"
1915dpkg-scanpackages -a$debarch $pbos->{'version'} /dev/null | gzip -c9 > dists/$pbos->{'version'}/contrib/binary-$debarch/Packages.gz
1916dpkg-scanpackages -a$debarch $pbos->{'version'} /dev/null | bzip2 -c9 > dists/$pbos->{'version'}/contrib/binary-$debarch/Packages.bz2
[1192]1917echo "Creating Contents metadata"
1918apt-ftparchive contents $pbos->{'version'} | gzip -c9 > dists/$pbos->{'version'}/Contents.gz
[1275]1919echo "Creating Release metadata ($pbos->{'arch'} aka $debarch)"
1920cat \$TMPD/Release > dists/$pbos->{'version'}/contrib/binary-$debarch/Release
[1279]1921echo "Architecture: $debarch" >> dists/$pbos->{'version'}/contrib/binary-$debarch/Release
[1112]1922echo "Creating Source metadata"
[1192]1923dpkg-scansources $pbos->{'version'} /dev/null | gzip -c9 > dists/$pbos->{'version'}/contrib/source/Sources.gz
[1177]1924cat \$TMPD/Release > dists/$pbos->{'version'}/contrib/source/Release
1925echo "Architecture: Source" >> dists/$pbos->{'version'}/contrib/source/Release
[1112]1926echo "Creating Release metadata"
[1177]1927apt-ftparchive release dists/$pbos->{'version'} > dists/$pbos->{'version'}/Release
[1112]1928rm -rf \$TMPD
[460]1929EOF
[1177]1930        } elsif ($pbos->{'type'} eq "ebuild") {
[586]1931            # make a pbscript to generate links to latest version
1932            print PBS << "EOF";
1933#!/bin/bash
1934# Prepare a script to create correct links
1935for p in $src; do
1936    echo \$p | grep -q '.ebuild'
1937    if [ \$\? -eq 0 ]; then
1938        j=`basename \$p`
1939        pp=`echo \$j | cut -d'-' -f1`
1940        ln -sf \$j \$pp.ebuild
1941    fi
1942done
1943EOF
[429]1944        }
1945        close(PBS);
[1189]1946        chmod 0755,"$ENV{'PBBUILDDIR'}/pbscript.$$";
[90]1947    } else {
1948        return;
[22]1949    }
[239]1950
[1143]1951    # Useless for VE
[1179]1952    my $nport = pb_get_port($sshport,$pbos,$cmt) if ($cmt !~ /^VE/);
[320]1953
[136]1954    # Remove a potential $ENV{'HOME'} as tdir should be relative to pb's home
[132]1955    $tdir =~ s|\$ENV.+\}/||;
1956
[1217]1957    my $tm = "";
[1176]1958    if ($cmt =~ /^(V|R)M/) {
[1218]1959        $tm = "sleep $vtmout" if (defined $vtmout);
[883]1960    }
[320]1961
[1374]1962    # ssh communication if not VE or CPAN
[349]1963    # should use a hash instead...
[320]1964    my ($shcmd,$cpcmd,$cptarget,$cp2target);
[1374]1965    if ($cmt =~ /^VE/) {
[320]1966        my $tp = $vepath->{$ENV{'PBPROJ'}};
[1179]1967        my $tpdir = "$tp/$pbos->{'name'}/$pbos->{'version'}/$pbos->{'arch'}";
[681]1968        my ($ptr) = pb_conf_get("vetype");
1969        my $vetype = $ptr->{$ENV{'PBPROJ'}};
1970        if ($vetype eq "chroot") {
[1179]1971            $shcmd = "sudo /usr/sbin/chroot $tpdir /bin/su - $mac -c ";
[681]1972        } elsif ($vetype eq "schroot") {
1973            $shcmd = "schroot $tp -u $mac -- ";
1974        }
[1179]1975        $cpcmd = "sudo /bin/cp -r ";
[681]1976        # We need to get the home dir of the target account to deliver in the right place
1977        open(PASS,"$tpdir/etc/passwd") || die "Unable to open $tpdir/etc/passwd";
1978        my $homedir = "";
1979        while (<PASS>) {
1980            my ($c1,$c2,$c3,$c4,$c5,$c6,$c7) = split(/:/);
1981            $homedir = $c6 if ($c1 =~ /^$mac$/);
1982            pb_log(3,"Homedir: $homedir - account: $c6\n");
1983        }
1984        close(PASS);
1985        $cptarget = "$tpdir/$homedir/$tdir";
[773]1986        if ($cmt eq "VEbuild") {
[681]1987            $cp2target = "$tpdir/$homedir/$bdir";
1988        }
1989        pb_log(2,"On VE using $cptarget as target dir to copy to\n");
[1374]1990    } elsif ($cmt =~ /^CPAN/) {
1991        my $ftpput = ps_check_req("ncftpput",1);
1992        my $ftpget = ps_check_req("wget",1);
1993        my ($cpanuser,$cpanpasswd) = pb_conf_get("cpanuser","cpanpasswd");
1994        my ($cpansubdir) = pb_conf_get_if("cpansubdir");
1995        $shcmd = "$ftpget --post-data \'HIDDENNAME=".$cpanuser;
1996        $shcmd .= "&user=".$cpanuser;
1997        $shcmd .= "&password=".$cpanpasswd;
1998        $shcmd .= "&SUBMIT_pause99_add_uri_upload=\"Upload the checked files\"";
1999        $shcmd .= "&pause99_add_uri_subdirtext=".$cpansubdir if (defined $cpansubdir);
2000        foreach my $s (split(/ /,$src)) {
2001            $shcmd .= "&pause99_add_uri_upload=".basename($s);
2002        }
2003        $shcmd .= "'";
2004        $cpcmd = "$ftpput $host $dir";
2005        $cptarget = "CPAN";
2006    } else {
2007        my $keyfile = pb_ssh_get(0);
2008        my $sshcmd = ps_check_req("ssh",1);
2009        my $scpcmd = ps_check_req("scp",1);
2010        $shcmd = "$sshcmd -i $keyfile -q -o UserKnownHostsFile=/dev/null -p $nport $mac";
2011        $cpcmd = "$scpcmd -i $keyfile -p -o UserKnownHostsFile=/dev/null -P $nport";
2012        $cptarget = "$mac:$tdir";
2013        if ($cmt =~ /^(V|R)Mbuild/) {
2014            $cp2target = "$mac:$bdir";
2015        }
[320]2016    }
[1374]2017   
[471]2018    my $logres = "";
2019    # Do not touch when just announcing
[1374]2020    if (($cmt ne "Announce") && ($cmt ne "CPAN")) {
[908]2021        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");
[471]2022    } else {
2023        $logres = "> ";
2024    }
[320]2025    pb_system("cd $ENV{'PBBUILDDIR'} ; $cpcmd $src $cptarget 2> /dev/null","$cmt delivery in $cptarget");
[444]2026
[681]2027    # For VE we need to change the owner manually
[772]2028    if ($cmt =~ /^VE/) {
[681]2029        pb_system("$shcmd \"sudo chown -R $mac $tdir\"","Adapt owner in $tdir to $mac");
2030    }
2031
[1140]2032    # Use the right script name depending on context
2033    my $pbscript;
[1189]2034    if (($cmt =~ /^(V[EM]|RM)/) || ($cmt =~ /Packages/)){
[1140]2035        $pbscript = "pbscript.$$";
2036    } else {
2037        $pbscript = "pbscript";
2038    }
2039
[1374]2040    # It's already ready for CPAN
2041    if ($cmt !~ /^CPAN/) {
2042        $shcmd .= "\"echo \'cd $tdir ; if [ -x $pbscript ]; then ./$pbscript; fi ; rm -f ./$pbscript\' | bash\"";
2043    }
2044    pb_system("$shcmd","Executing pbscript on $cptarget if needed","verbose");
[1176]2045    if ($cmt =~ /^(V[EM]|RM)build/) {
2046        # Get back info on pkg produced, compute their name and get them from the VM/RM
[1189]2047        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");
[681]2048        # For VE we need to change the owner manually
[772]2049        if ($cmt eq "VEbuild") {
[1138]2050            pb_system("sudo chown $UID $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.$$","Adapt owner in $tdir to $UID");
[681]2051        }
[1138]2052        if (not -f "$ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.$$") {
[1176]2053            pb_log(0,"Problem with VM/RM $v on $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.$$");
[1156]2054        } else {
2055            open(KEEP,"$ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.$$") || die "Unable to read $ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.$$";
2056            my $src = <KEEP>;
2057            chomp($src);
2058            close(KEEP);
2059            unlink("$ENV{'PBBUILDDIR'}/pbgen-$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.$$");
[1138]2060
[1156]2061            $src =~ s/^ *//;
[1179]2062            pb_mkdir_p("$ENV{'PBBUILDDIR'}/$pbos->{'name'}/$pbos->{'version'}/$pbos->{'arch'}");
[1156]2063            # Change pgben to make the next send2target happy
2064            my $made = "";
2065   
[1176]2066            # For VM/RM we don't want shell expansion to hapen locally but remotely
[1156]2067            my $delim = '\'';
2068            if ($cmt =~ /^VEbuild/) {
2069                # For VE we need to support shell expansion locally
2070                $delim = "";
2071            }   
[1138]2072
[1189]2073            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'}";
[1156]2074            foreach my $p (split(/ +/,$src)) {
2075                my $j = basename($p);
[1179]2076                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'}");
2077                $made="$made $pbos->{'name'}/$pbos->{'version'}/$pbos->{'arch'}/$j"; # if (($pbos->{'type'} ne "rpm") || ($j !~ /.src.rpm$/));
[1156]2078            }
2079            print KEEP "$made\n";
2080            close(KEEP);
2081            pb_system("$shcmd \"rm -rf $tdir $bdir\"","$cmt cleanup");
[1138]2082
[1156]2083            # Sign packages locally
[1278]2084            pb_sign_pkgs($pbos,$made);
[1156]2085
2086            # We want to send them to the ssh account so overwrite what has been done before
2087            undef $pbaccount;
2088            pb_log(2,"Before sending pkgs, vmexist: $vmexist, vmpid: $vmpid\n");
[1179]2089            pb_send2target("Packages",$pbos->{'name'}."-".$pbos->{'version'}."-".$pbos->{'arch'},$vmexist,$vmpid);
2090            pb_rm_rf("$ENV{'PBBUILDDIR'}/$pbos->{'name'}/$pbos->{'version'}/$pbos->{'arch'}");
[623]2091        }
[108]2092    }
[1189]2093    unlink("$ENV{'PBDESTDIR'}/pbscript.$$") if (($cmt =~ /^(V[ME]|RM)/) || ($cmt =~ /Packages/));
[1139]2094
[442]2095    pb_log(2,"Before halt, vmexist: $vmexist, vmpid: $vmpid\n");
[772]2096    if ((! $vmexist) && ($cmt =~ /^VM/)) {
[748]2097        # If in setupvm then takes a snapshot just before halting
2098        if ($snapme != 0) {
2099            my ($vmmonport,$vmtype) = pb_conf_get("vmmonport","vmtype");
2100            # For monitoring control
2101            if ((($vmtype->{$ENV{'PBPROJ'}}) eq "kvm") || (($vmtype->{$ENV{'PBPROJ'}}) eq "qemu")) {
[1153]2102                eval
2103                {
[804]2104                require Net::Telnet;
[1153]2105                Net::Telnet->import();
2106                };
2107                if ($@) {
2108                    # Net::Telnet not found
2109                    pb_log(1,"ADVISE: Install Net::Telnet to benefit from monitoring control and snapshot feature.\nWARNING: No snapshot created");
2110                } else {
2111                    my $t = new Net::Telnet (Timeout => 120, Host => "localhost", Port => $vmmonport->{$ENV{'PBPROJ'}}) || die "Unable to dialog on the monitor";
2112                    # move to monitor mode
2113                    my @lines = $t->cmd("c");
2114                    # Create a snapshot named pb
2115                    @lines = $t->cmd("savevm pb");
2116                    # Write the new status in the VM
2117                    @lines = $t->cmd("commit all");
2118                    # End
2119                    @lines = $t->cmd("quit");
2120                }
[748]2121            }
2122        }
[914]2123        my $hoption = "-p";
[1197]2124        my $hpath = pb_distro_get_param($pbos,pb_conf_get("ospathcmd-halt"));
[1194]2125        # Solaris doesn't support -p of halt
[1177]2126        if ($pbos->{'type'} eq "pkg") {
[1091]2127            $hoption = "" ;
2128        }
[1217]2129        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)");
[442]2130    }
[772]2131    if (($cmt =~ /^VE/) && ($snapme != 0)) {
[1179]2132        my $tpdir = "$vepath->{$ENV{'PBPROJ'}}/$pbos->{'name'}/$pbos->{'version'}/$pbos->{'arch'}";
2133        pb_system("sudo tar cz -C $tpdir -f $vepath->{$ENV{'PBPROJ'}}/$pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}.tar.gz .","Creating a snapshot of $tpdir");
[752]2134    }
[9]2135}
[16]2136
[320]2137sub pb_script2v {
[142]2138    my $pbscript=shift;
[320]2139    my $vtype=shift;
[1138]2140    my $pbforce=shift || 0; # Force stop of VM. Default not.
[1176]2141    my $vm1=shift || undef; # Only that VM/VE/RM to treat. Default all.
[1138]2142    my $snapme=shift || 0;  # Do we have to create a snapshot. Default not.
[442]2143    my $vm;
2144    my $all;
[141]2145
[767]2146    pb_log(2,"DEBUG: pb_script2v($pbscript,$vtype,$pbforce,".Dumper($vm1).",$snapme)\n");
[1176]2147    # Prepare the script to be executed on the VM/VE/RM
[1138]2148    # in $ENV{'PBDESTDIR'}/pbscript.$$
2149    if ((defined $pbscript ) && ($pbscript ne "$ENV{'PBDESTDIR'}/pbscript.$$")) {
2150        copy($pbscript,"$ENV{'PBDESTDIR'}/pbscript.$$") || die "Unable to create $ENV{'PBDESTDIR'}/pbscript.$$";
2151        chmod 0755,"$ENV{'PBDESTDIR'}/pbscript.$$";
[142]2152    }
[141]2153
[442]2154    if (not defined $vm1) {
[772]2155        ($vm,$all) = pb_get2v($vtype);
[442]2156    } else {
2157        @$vm = ($vm1);
2158    }
[320]2159    my ($vmexist,$vmpid) = (undef,undef);
[142]2160
[141]2161    foreach my $v (@$vm) {
[968]2162        # Launch VM/VE
2163        ($vmexist,$vmpid) = pb_launchv($vtype,$v,0,$snapme,$pbsnap);
[755]2164
[320]2165        if ($vtype eq "vm") {
[442]2166            pb_log(2,"DEBUG: After pb_launchv, vmexist: $vmexist, vmpid: $vmpid\n");
[141]2167
[1176]2168            # Skip that VM/RM if something went wrong
[442]2169            next if (($vmpid == 0) && ($vmexist == 0));
2170
2171            # If force stopping the VM then reset vmexist
[748]2172            if ($pbforce == 1) {
[442]2173                $vmpid = $vmexist;
2174                $vmexist = 0;
2175            }
[670]2176        } else {
2177            #VE
2178            $vmexist = 0;
2179            $vmpid = 0;
[320]2180        }
[274]2181
[1176]2182        # Gather all required files to send them to the VM/VE/RM
[320]2183        # and launch the build through pbscript
[442]2184        pb_log(2,"DEBUG: Before send2target, vmexist: $vmexist, vmpid: $vmpid\n");
[748]2185        pb_send2target(uc($vtype)."Script","$v",$vmexist,$vmpid,$snapme);
[169]2186
[142]2187    }
2188}
2189
[320]2190sub pb_launchv {
2191    my $vtype = shift;
2192    my $v = shift;
[1176]2193    my $create = shift || 0;        # By default do not create a VM/VE/RM
2194    my $snapme = shift || 0;        # By default do not snap a VM/VE/RM
[1349]2195    my $usesnap = shift || 1;       # By default study the usage of the snapshot feature of VM/VE/RM   
[310]2196
[773]2197    # If creation or snapshot creation mode, no snapshot usable
2198    if (($create == 1) || ($snapme == 1)) {
2199        $usesnap = 0;
2200    }
2201
2202    pb_log(2,"DEBUG: pb_launchv($vtype,$v,$create,$snapme,$usesnap)\n");
[1176]2203    die "No VM/VE/RM defined, unable to launch" if (not defined $v);
[320]2204    # Keep only the first VM in case many were given
2205    $v =~ s/,.*//;
[310]2206
[1179]2207    my $pbos = pb_distro_get_context($v);
[1348]2208   
[320]2209    # Launch the VMs/VEs
2210    if ($vtype eq "vm") {
2211        die "-i iso parameter needed" if (((not defined $iso) || ($iso eq "")) && ($create != 0));
[310]2212
[940]2213        # TODO: vmmonport should be optional
[1249]2214        my ($ptr,$ptr2,$vmpath,$vmport,$vms,$vmmonport) = pb_conf_get("vmtype","vmcmd","vmpath","vmport","vmsize","vmmonport");
[1322]2215        my ($vmopt,$vmmm,$vmtmout,$vmsnap,$vmbuildtm) = pb_conf_get_if("vmopt","vmmem","vmtmout","vmsnap","vmbuildtm");
[1249]2216        my $vmsize = pb_distro_get_param($pbos,$vms);
[320]2217
2218        my $vmtype = $ptr->{$ENV{'PBPROJ'}};
[1072]2219        my $vmcmd = $ptr2->{$ENV{'PBPROJ'}};
[1124]2220
2221        if (defined $opts{'g'}) {
2222            if (($vmtype eq "kvm") || ($vmtype eq "qemu")) {
[1158]2223                $ENV{'PBVMOPT'} = "--nographic";
[1124]2224            }
2225        }
[320]2226        if (not defined $ENV{'PBVMOPT'}) {
2227            $ENV{'PBVMOPT'} = "";
[310]2228        }
[639]2229        # Save the current status for later restoration
2230        $ENV{'PBOLDVMOPT'} = $ENV{'PBVMOPT'};
[483]2231        # Set a default timeout of 2 minutes
2232        if (not defined $ENV{'PBVMTMOUT'}) {
2233            $ENV{'PBVMTMOUT'} = "120";
2234        }
2235        if (defined $vmopt->{$v}) {
2236            $ENV{'PBVMOPT'} .= " $vmopt->{$v}" if ($ENV{'PBVMOPT'} !~ / $vmopt->{$v}/);
2237        } elsif (defined $vmopt->{$ENV{'PBPROJ'}}) {
[320]2238            $ENV{'PBVMOPT'} .= " $vmopt->{$ENV{'PBPROJ'}}" if ($ENV{'PBVMOPT'} !~ / $vmopt->{$ENV{'PBPROJ'}}/);
2239        }
[773]2240
[1143]2241        # How much memory to allocate for VMs
[1322]2242        my $vmmem = pb_distro_get_param($pbos,$vmmm);
2243        if (defined $vmmem) {
2244            $ENV{'PBVMOPT'} .= " -m $vmmem";
[1143]2245        }
2246
[773]2247        # Are we allowed to use snapshot feature
2248        if ($usesnap == 1) {
[748]2249            if ((defined $vmsnap->{$v}) && ($vmsnap->{$v} =~ /true/i)) {
[1070]2250                $ENV{'PBVMOPT'} .= " -snapshot";
[748]2251            } elsif ((defined $vmsnap->{$ENV{'PBPROJ'}}) && ($vmsnap->{$ENV{'PBPROJ'}} =~ /true/i)) {
[1070]2252                $ENV{'PBVMOPT'} .= " -snapshot";
[748]2253            } elsif ($pbsnap eq 1) {
[1070]2254                $ENV{'PBVMOPT'} .= " -snapshot";
[748]2255            }
[767]2256        } 
2257        if ($snapme != 0) {
[748]2258            if (($vmtype eq "kvm") || ($vmtype eq "qemu")) {
[1138]2259                # Configure the monitoring to automate the creation of the 'pb' snapshot
[1070]2260                $ENV{'PBVMOPT'} .= " -serial mon:telnet::$vmmonport->{$ENV{'PBPROJ'}},server,nowait";
[773]2261                # In that case no snapshot call needed
[1070]2262                $ENV{'PBVMOPT'} =~ s/ -snapshot//;
[748]2263            }
2264        }
[483]2265        if (defined $vmtmout->{$v}) {
2266            $ENV{'PBVMTMOUT'} = $vmtmout->{$v};
2267        } elsif (defined $vmtmout->{$ENV{'PBPROJ'}}) {
2268            $ENV{'PBVMTMOUT'} = $vmtmout->{$ENV{'PBPROJ'}};
2269        }
[1179]2270        my $nport = pb_get_port($vmport,$pbos,$vtype);
[320]2271   
2272        my $cmd;
2273        my $vmm;        # has to be used for pb_check_ps
[677]2274        if (($vmtype eq "qemu") || ($vmtype eq "kvm")) {
2275            $vmm = "$vmpath->{$ENV{'PBPROJ'}}/$v.qemu";
[792]2276            if (($create != 0) || (defined $iso)) {
[677]2277                $ENV{'PBVMOPT'} .= " -cdrom $iso -boot d";
[320]2278            }
[748]2279            # Always redirect the network and always try to use a 'pb' snapshot
[1340]2280            #$cmd = "$vmcmd $ENV{'PBVMOPT'} -net user,hostfwd=tcp:$nport:10.0.2.15:22 -loadvm pb $vmm"
2281            $cmd = "$vmcmd $ENV{'PBVMOPT'} -redir tcp:$nport:10.0.2.15:22 -loadvm pb $vmm"
[320]2282        } elsif ($vmtype eq "xen") {
2283        } elsif ($vmtype eq "vmware") {
[310]2284        } else {
[320]2285            die "VM of type $vmtype not supported. Report to the dev team";
[310]2286        }
[639]2287        # Restore the ENV VAR Value
[641]2288        $ENV{'PBVMOPT'} = $ENV{'PBOLDVMOPT'};
[639]2289
[320]2290        my ($tmpcmd,$void) = split(/ +/,$cmd);
2291        my $vmexist = pb_check_ps($tmpcmd,$vmm);
2292        my $vmpid = 0;
2293        if (! $vmexist) {
2294            if ($create != 0) {
[653]2295                die("Found an existing Virtual machine $vmm. Won't overwrite") if (-r $vmm);
[677]2296                if (($vmtype eq "qemu") || ($vmtype eq "xen") || ($vmtype eq "kvm")) {
[1127]2297                    my $command = pb_check_req("qemu-img",0);
[1249]2298                    pb_system("$command create -f qcow2 $vmm $vmsize","Creating the QEMU VM");
[320]2299                } elsif ($vmtype eq "vmware") {
2300                } else {
2301                }
2302            }
2303            if (! -f "$vmm") {
2304                pb_log(0,"Unable to find VM $vmm\n");
2305            } else {
[1153]2306                # Is the SSH port free? if not kill the existing process using it after a build timeout period
2307                my $vmssh = pb_check_ps($tmpcmd,"tcp:$nport:10.0.2.15:22");
2308                if ($vmssh) {
2309                    my $buildtm = $ENV{'PBVMTMOUT'};
2310                    if (defined $vmbuildtm->{$v}) {
2311                        $buildtm = $vmbuildtm->{$v};
2312                    } elsif (defined $vmbuildtm->{$ENV{'PBPROJ'}}) {
2313                        $buildtm = $vmbuildtm->{$ENV{'PBPROJ'}};
2314                    }
2315
2316                    sleep $buildtm;
2317                    pb_log(0,"WARNING: Killing the process ($vmssh) using port $nport (previous failed VM ?)\n");
2318                    kill 15,$vmssh;
[1154]2319                    # Let it time to exit
2320                    sleep 5;
[1153]2321                }
[320]2322                pb_system("$cmd &","Launching the VM $vmm");
[1153]2323                # Using system allows to kill it externaly if needed
[483]2324                pb_system("sleep $ENV{'PBVMTMOUT'}","Waiting $ENV{'PBVMTMOUT'} s for VM $v to come up");
[320]2325                $vmpid = pb_check_ps($tmpcmd,$vmm);
[357]2326                pb_log(0,"VM $vmm launched (pid $vmpid)\n");
[320]2327            }
[310]2328        } else {
[320]2329            pb_log(0,"Found an existing VM $vmm (pid $vmexist)\n");
[310]2330        }
[442]2331        pb_log(2,"DEBUG: pb_launchv returns ($vmexist,$vmpid)\n");
[320]2332        return($vmexist,$vmpid);
[1176]2333    } elsif ($vtype eq "ve") {
[1360]2334        # Force the creation of the VE and no snapshot usable
2335        pb_ve_launch($v,1,0);
[1176]2336    } else {
2337        # RM here
2338        # Get distro context
[1177]2339        my $pbos = pb_distro_get_context($v);
[1176]2340
2341        # Get RM context
2342        my ($ptr,$rmpath) = pb_conf_get("rmtype","rmpath");
2343
2344        # Nothing more to do for RM. No real launch
2345        # For the moment we support the RM is already running
2346        # For ProLiant may be able to power them on if needed later on as an example.
[141]2347    }
2348}
[142]2349
[639]2350# Return string for date synchro
[772]2351sub pb_date2v {
[639]2352
2353my $vtype = shift;
[1216]2354my $pbos = shift;
[639]2355
[986]2356my ($ntp) = pb_conf_get_if($vtype."ntp");
2357my $vntp = $ntp->{$ENV{'PBPROJ'}} if (defined $ntp);
[1221]2358my $ntpline = undef;
[639]2359
2360if (defined $vntp) {
[1221]2361    # ntp command depends on pbos
2362    my $vntpcmd = pb_distro_get_param($pbos,pb_conf_get($vtype."ntpcmd"));
[652]2363    $ntpline = "sudo $vntpcmd $vntp";
[639]2364}
2365# Force new date to be in the future compared to the date
2366# of the host by adding 1 minute
2367my @date=pb_get_date();
2368$date[1]++;
2369my $upddate = strftime("%m%d%H%M%Y", @date);
[1179]2370my $dateline = "sudo /bin/date $upddate";
[1190]2371if (defined $ntpline) {
2372    return($ntpline);
2373} else {
2374    return($dateline);
[639]2375}
[1190]2376}
[639]2377
[320]2378sub pb_build2v {
[118]2379
[320]2380my $vtype = shift;
[772]2381my $action = shift || "build";
[142]2382
[772]2383my ($v,$all) = pb_get2v($vtype);
[320]2384
2385# Send tar files when we do a global generation
[772]2386pb_build2ssh() if (($all == 1) && ($action eq "build"));
[320]2387
[1143]2388# Adapt // mode to memory size
2389$pbparallel = pb_set_parallel($vtype);
2390
[320]2391my ($vmexist,$vmpid) = (undef,undef);
[1176]2392my $pm;
2393if (defined $pbparallel) {
2394    $pm = new Parallel::ForkManager($pbparallel);
[320]2395
[1176]2396    # Set which port the VM/RM will use to communicate
2397    $pm->run_on_start(\&pb_set_port);
2398}
[1143]2399
2400my $counter = 0;
[320]2401foreach my $v (@$v) {
[1143]2402    $counter++;
[1153]2403    # Modulo 2 * pbparallel (to avoid synchronization problems)
[1176]2404    $counter = 1 if ((defined $pbparallel) && ($counter > 2 * $pbparallel));
[1143]2405    $pm->start($counter) and next if (defined $pbparallel);
[1176]2406    # Prepare the script to be executed on the VM/VE/RM
[1138]2407    # in $ENV{'PBDESTDIR'}/pbscript.$$
2408    open(SCRIPT,"> $ENV{'PBDESTDIR'}/pbscript.$$") || die "Unable to create $ENV{'PBDESTDIR'}/pbscript.$$";
[652]2409    print SCRIPT "#!/bin/bash\n";
[721]2410
2411    # Transmit the verbosity level to the virtual env/mach.
2412    my $verbose = "";
2413    my $i = 0;                          # minimal debug level
2414    while ($i lt $pbdebug) {
2415        $verbose .= "-v ";
2416        $i++;
2417    }
2418    # Activate script verbosity if at least 2 for pbdebug
2419    print SCRIPT "set -x\n" if ($i gt 1);
2420    # Quiet if asked to be so on the original system
2421    $verbose = "-q" if ($pbdebug eq -1);
2422
[652]2423    print SCRIPT "echo ... Execution needed\n";
2424    print SCRIPT "# This is in directory delivery\n";
2425    print SCRIPT "# Setup the variables required for building\n";
2426    print SCRIPT "export PBPROJ=$ENV{'PBPROJ'}\n";
[686]2427
[772]2428    if ($action eq "build") {
2429        print SCRIPT "# Preparation for pb\n";
2430        print SCRIPT "mv .pbrc \$HOME\n";
2431        print SCRIPT "cd ..\n";
2432    }
2433
[686]2434    # VE needs a good /proc
[687]2435    if ($vtype eq "ve") {
[1179]2436        print SCRIPT "sudo /bin/mount -t proc /proc /proc\n";
[686]2437    }
[652]2438
[1216]2439    # Get distro context
2440    my $pbos = pb_distro_get_context($v);
2441   
2442    my $ntpline = pb_date2v($vtype,$pbos);
[652]2443    print SCRIPT "# Time sync\n";
[725]2444    print SCRIPT "echo 'setting up date with '";
[1190]2445    print SCRIPT "echo $ntpline\n";
2446    print SCRIPT "$ntpline\n";
[721]2447    # Use potential local proxy declaration in case we need it to download repo, pkgs, ...
2448    if (defined $ENV{'http_proxy'}) {
2449        print SCRIPT "export http_proxy=\"$ENV{'http_proxy'}\"\n";
2450    }
[652]2451
[721]2452    if (defined $ENV{'ftp_proxy'}) {
2453        print SCRIPT "export ftp_proxy=\"$ENV{'ftp_proxy'}\"\n";
[652]2454    }
2455
[772]2456    # Get list of packages to build/test and get some ENV vars as well
2457    my $ptr = pb_get_pkg();
2458    @pkgs = @$ptr;
2459    my $p = join(' ',@pkgs) if (@pkgs);
2460    print SCRIPT "export PBPROJVER=$ENV{'PBPROJVER'}\n";
2461    print SCRIPT "export PBPROJTAG=$ENV{'PBPROJTAG'}\n";
2462    print SCRIPT "export PBPACKAGER=\"$ENV{'PBPACKAGER'}\"\n";
[721]2463
2464    # We may need to do some other tasks before building. Read a script here to finish setup
[772]2465    if (-x "$ENV{'PBDESTDIR'}/pb$vtype".".pre") {
2466        print SCRIPT "# Special pre-instructions to be launched\n";
2467        print SCRIPT pb_get_content("$ENV{'PBDESTDIR'}/pb$vtype".".pre");
[721]2468    }
2469
[772]2470    if (-x "$ENV{'PBDESTDIR'}/pb$vtype"."$action.pre") {
2471        print SCRIPT "# Special pre-$action instructions to be launched\n";
2472        print SCRIPT pb_get_content("$ENV{'PBDESTDIR'}/pb$vtype"."$action.pre");
2473    }
2474
2475    print SCRIPT "# $action\n";
2476    print SCRIPT "echo $action"."ing packages on $vtype...\n";
2477
2478    if (($action eq "test") && (! -x "$ENV{'PBDESTDIR'}/pbtest")) {
2479            die "No test script ($ENV{'PBDESTDIR'}/pbtest) found when in test mode. Aborting ...";
2480    }
2481    print SCRIPT "pb $verbose -p $ENV{'PBPROJ'} $action"."2pkg $p\n";
2482
[687]2483    if ($vtype eq "ve") {
[1179]2484        print SCRIPT "sudo /bin/umount /proc\n";
[686]2485    }
[721]2486
2487    # We may need to do some other tasks after building. Read a script here to exit properly
[772]2488    if (-x "$ENV{'PBDESTDIR'}/pb$vtype"."$action.post") {
2489        print SCRIPT "# Special post-$action instructions to be launched\n";
2490        print SCRIPT pb_get_content("$ENV{'PBDESTDIR'}/pb$vtype"."$action.post");
[721]2491    }
2492
[772]2493    if (-x "$ENV{'PBDESTDIR'}/pb$vtype".".post") {
2494        print SCRIPT "# Special post-instructions to be launched\n";
2495        print SCRIPT pb_get_content("$ENV{'PBDESTDIR'}/pb$vtype".".post");
2496    }
2497
[652]2498    close(SCRIPT);
[1138]2499    chmod 0755,"$ENV{'PBDESTDIR'}/pbscript.$$";
[652]2500   
[1176]2501    # Launch the VM/VE/RM
[755]2502    ($vmexist,$vmpid) = pb_launchv($vtype,$v,0);
2503
[1139]2504
[320]2505    if ($vtype eq "vm") {
[1143]2506        # Skip that VM if something went wrong
[1139]2507        if (($vmpid == 0) && ($vmexist == 0)) {
2508            $pm->finish if (defined $pbparallel);
2509            next;
2510        }
[658]2511    } else {
[1176]2512        # VE/RM
[658]2513        $vmexist = 0;
2514        $vmpid = 0;
[118]2515    }
[320]2516    # Gather all required files to send them to the VM/VE
[347]2517    # and launch the build through pbscript
[357]2518    pb_log(2,"Calling send2target $vtype,$v,$vmexist,$vmpid\n");
[772]2519    pb_send2target(uc($vtype).$action,"$v",$vmexist,$vmpid);
[1139]2520    $pm->finish if (defined $pbparallel);
[105]2521}
[1176]2522$pm->wait_all_children if (defined $pbparallel);
[320]2523}
[105]2524
[262]2525
[739]2526sub pb_clean {
2527
2528    my $sleep=10;
2529    die "Unable to get env var PBDESTDIR" if (not defined $ENV{'PBDESTDIR'});
2530    die "Unable to get env var PBBUILDDIR" if (not defined $ENV{'PBBUILDDIR'});
2531    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");
2532    sleep $sleep;
2533    pb_rm_rf($ENV{'PBDESTDIR'});
2534    pb_rm_rf($ENV{'PBBUILDDIR'});
2535}
2536
[199]2537sub pb_newver {
2538
[204]2539    die "-V Version parameter needed" if ((not defined $newver) || ($newver eq ""));
[340]2540
[366]2541    # Need this call for PBDIR
2542    my ($scheme2,$uri) = pb_cms_init($pbinit);
[361]2543
[898]2544    my ($pbconf,$pburl) = pb_conf_get("pbconfurl","pburl");
[366]2545    $uri = $pbconf->{$ENV{'PBPROJ'}};
2546    my ($scheme, $account, $host, $port, $path) = pb_get_uri($uri);
2547
[361]2548    # Checking CMS repositories status
[366]2549    ($scheme2, $account, $host, $port, $path) = pb_get_uri($pburl->{$ENV{'PBPROJ'}});
[340]2550
2551    if ($scheme !~ /^svn/) {
[199]2552        die "Only SVN is supported at the moment";
2553    }
[483]2554
[358]2555    my $res = pb_cms_isdiff($scheme,$ENV{'PBROOTDIR'});
[361]2556    die "ERROR: No differences accepted in CMS for $ENV{'PBROOTDIR'} before creating a new version" if ($res != 0);
[358]2557
2558    $res = pb_cms_isdiff($scheme2,$ENV{'PBDIR'});
[361]2559    die "ERROR: No differences accepted in CMS for $ENV{'PBDIR'} before creating a new version" if ($res != 0);
[358]2560
2561    # Tree identical between PBCONFDIR and PBROOTDIR. The delta is what
2562    # we want to get for the root of the new URL
2563
2564    my $tmp = $ENV{'PBROOTDIR'};
2565    $tmp =~ s|^$ENV{'PBCONFDIR'}||;
2566
2567    my $newurl = "$uri/".dirname($tmp)."/$newver";
[366]2568    # Should probably use projver in the old file
2569    my $oldver= basename($tmp);
[361]2570
[366]2571    # Duplicate and extract project-builder part
[361]2572    pb_log(2,"Copying $uri/$tmp to $newurl\n");
[366]2573    pb_cms_copy($scheme,"$uri/$tmp",$newurl);
2574    pb_log(2,"Checkout $newurl to $ENV{'PBROOTDIR'}/../$newver\n");
[383]2575    pb_cms_up($scheme,"$ENV{'PBCONFDIR'}/..");
[361]2576
[366]2577    # Duplicate and extract project
2578    my $newurl2 = "$pburl->{$ENV{'PBPROJ'}}/".dirname($tmp)."/$newver";
2579
2580    pb_log(2,"Copying $pburl->{$ENV{'PBPROJ'}}/$tmp to $newurl2\n");
[632]2581    pb_cms_copy($scheme2,"$pburl->{$ENV{'PBPROJ'}}/$tmp",$newurl2);
[366]2582    pb_log(2,"Checkout $newurl2 to $ENV{'PBDIR'}/../$newver\n");
[632]2583    pb_cms_up($scheme2,"$ENV{'PBDIR'}/..");
[366]2584
[361]2585    # Update the .pb file
[358]2586    open(FILE,"$ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb") || die "Unable to open $ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb";
2587    open(OUT,"> $ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb.new") || die "Unable to write to $ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb.new";
[208]2588    while(<FILE>) {
[361]2589        s/^projver\s+$ENV{'PBPROJ'}\s*=\s*$oldver/projver $ENV{'PBPROJ'} = $newver/;
2590        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/);
[897]2591        pb_log(0,"Commenting testver in $ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb\n") if (/^testver/);
[361]2592        s/^testver/#testver/;
[211]2593        print OUT $_;
[1165]2594        pb_log(0,"Please check delivery (".chomp($_).") in $ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb\n") if (/^delivery/);
[208]2595    }
2596    close(FILE);
[211]2597    close(OUT);
[358]2598    rename("$ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb.new","$ENV{'PBROOTDIR'}/../$newver/$ENV{'PBPROJ'}.pb");
[363]2599
[479]2600    # Checking pbcl files
2601    foreach my $f (<$ENV{'PBROOTDIR'}/*/pbcl>) {
[590]2602        # Compute new pbcl file
2603        my $f2 = $f;
2604        $f2 =~ s|$ENV{'PBROOTDIR'}|$ENV{'PBROOTDIR'}/../$newver/|;
[479]2605        open(PBCL,$f) || die "Unable to open $f";
2606        my $foundnew = 0;
2607        while (<PBCL>) {
2608            $foundnew = 1 if (/^$newver \(/);
2609        }
2610        close(PBCL);
[590]2611        open(OUT,"> $f2") || die "Unable to write to $f2: $!";
[479]2612        open(PBCL,$f) || die "Unable to open $f";
2613        while (<PBCL>) {
[480]2614            print OUT "$_" if (not /^$oldver \(/);
[479]2615            if ((/^$oldver \(/) && ($foundnew == 0)) {
2616                print OUT "$newver ($pbdate)\n";
2617                print OUT "- TBD\n";
2618                print OUT "\n";
[590]2619                pb_log(0,"WARNING: version $newver not found in $f so added to $f2...\n") if ($foundnew == 0);
[479]2620            }
2621        }
2622        close(OUT);
2623        close(PBCL);
2624    }
2625
[358]2626    pb_log(2,"Checkin $ENV{'PBROOTDIR'}/../$newver\n");
[452]2627    pb_cms_checkin($scheme,"$ENV{'PBROOTDIR'}/../$newver",undef);
[199]2628}
2629
[293]2630#
[1176]2631# Return the list of VMs/VEs/RMs we are working on
[105]2632# $all is a flag to know if we return all of them
2633# or only some (if all we publish also tar files in addition to pkgs
2634#
[772]2635sub pb_get2v {
[91]2636
[320]2637my $vtype = shift;
2638my @v;
[105]2639my $all = 0;
[320]2640my $pbv = 'PBV';
[1176]2641my $vlist = $vtype."list";
[91]2642
[320]2643# Get VM/VE list
2644if ((not defined $ENV{$pbv}) || ($ENV{$pbv} =~ /^all$/)) {
2645    my ($ptr) = pb_conf_get($vlist);
2646    $ENV{$pbv} = $ptr->{$ENV{'PBPROJ'}};
[105]2647    $all = 1;
[91]2648}
[320]2649pb_log(2,"$vtype: $ENV{$pbv}\n");
2650@v = split(/,/,$ENV{$pbv});
2651return(\@v,$all);
[91]2652}
2653
[1176]2654# Function to create a potentialy missing pb account on the VM/VE/RM, and adds it to sudo
2655# Needs to use root account to connect to the VM/VE/RM
[320]2656# pb will take your local public SSH key to access
[1176]2657# the pb account in the VM/VE/RM later on if needed
[772]2658sub pb_setup2v {
[320]2659
2660my $vtype = shift;
[1140]2661my $sbx = shift || undef;
[320]2662
[772]2663my ($vm,$all) = pb_get2v($vtype);
[353]2664
[346]2665# Script generated
2666my $pbscript = "$ENV{'PBDESTDIR'}/setupv";
[320]2667
[1143]2668# Adapt // mode to memory size
2669$pbparallel = pb_set_parallel($vtype);
2670
[1176]2671my $pm;
2672if (defined $pbparallel) {
2673    $pm = new Parallel::ForkManager($pbparallel);
[1143]2674
[1176]2675    # Set which port the VM/RM will use to communicate
2676    $pm->run_on_start(\&pb_set_port);
2677}
[1143]2678
2679my $counter = 0;
[652]2680foreach my $v (@$vm) {
[1143]2681    $counter++;
2682    # Modulo pbparallel
[1176]2683    $counter = 1 if ((defined $pbparallel) && ($counter > $pbparallel));
[1143]2684    $pm->start($counter) and next if (defined $pbparallel);
2685
[891]2686    # Get distro context
[1177]2687    my $pbos = pb_distro_get_context($v);
[891]2688   
[1216]2689    # Deal with date sync.
2690    my $ntpline = pb_date2v($vtype,$pbos);
2691
[1176]2692    # Name of the account to deal with for VM/VE/RM
[353]2693    # Do not use the one passed potentially with -a
2694    my ($pbac) = pb_conf_get($vtype."login");
[354]2695    my ($key,$zero0,$zero1,$zero2);
[639]2696    my ($vmexist,$vmpid);
[346]2697
[1176]2698    # Prepare the script to be executed on the VM/VE/RM
[681]2699    # in $ENV{'PBDESTDIR'}/setupv
2700    open(SCRIPT,"> $pbscript") || die "Unable to create $pbscript";
2701   
2702    print SCRIPT << 'EOF';
2703#!/usr/bin/perl -w
2704
2705use strict;
2706use File::Copy;
2707
2708# We should not need in this script more functions than what is provided
[1140]2709# by Base, Conf and Distribution to avoid problems at exec time.
[681]2710# They are appended at the end.
2711
[1156]2712# Define mandatory global vars
[681]2713our $pbdebug;
2714our $pbLOG;
2715our $pbsynmsg = "pbscript";
2716our $pbdisplaytype = "text";
2717our $pblocale = "";
2718pb_log_init($pbdebug, $pbLOG);
2719pb_temp_init();
2720
2721EOF
2722
[1176]2723    # Launch the VM/VE/RM - Usage of snapshot disabled
[773]2724    ($vmexist,$vmpid) = pb_launchv($vtype,$v,0,0,0);
[755]2725
[1156]2726    my $keyfile;
2727    my $nport;
2728    my $vmhost;
2729
[1255]2730    # Prepare the key to be used and transfered remotely
2731    $keyfile = pb_ssh_get(1);
2732       
[1176]2733    if ($vtype =~ /(v|r)m/) {
[1215]2734        my ($vmport);
2735        ($vmhost,$vmport) = pb_conf_get($vtype."host",$vtype."port");
[1179]2736        $nport = pb_get_port($vmport,$pbos,$vtype);
[347]2737   
[1176]2738        # Skip that VM/RM if something went wrong
[442]2739        next if (($vmpid == 0) && ($vmexist == 0));
[353]2740   
[354]2741        # Store the pub key part in a variable
2742        open(FILE,"$keyfile.pub") || die "Unable to open $keyfile.pub";
2743        ($zero0,$zero1,$zero2) = split(/ /,<FILE>);
2744        close(FILE);
2745
2746        $key = "\Q$zero1";
2747
[1105]2748        # We call true to avoid problems if SELinux is not activated, but chcon is present and returns in that case 1
2749        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");
[1176]2750        # once this is done, we can do what we need on the VM/RM remotely
[681]2751    } elsif ($vtype eq "ve") {
[1029]2752        print SCRIPT << "EOF";
[940]2753# For VE we need a good null dev
2754pb_system("rm -f /dev/null; mknod /dev/null c 1 3; chmod 777 /dev/null");
2755EOF
[1029]2756        print SCRIPT << "EOF";
[681]2757# For VE we first need to mount some FS
2758pb_system("mount -t proc /proc /proc");
[346]2759
[354]2760EOF
[681]2761    }
[1029]2762
[1190]2763    if ($vtype =~ /(v|r)m/) {
[354]2764        print SCRIPT << 'EOF';
2765# Removes duplicate in .ssh/authorized_keys of our key if needed
2766#
2767my $file1="$ENV{'HOME'}/.ssh/authorized_keys";
2768open(PBFILE,$file1) || die "Unable to open $file1";
2769open(PBOUT,"> $file1.new") || die "Unable to open $file1.new";
2770my $count = 0;
2771while (<PBFILE>) {
[517]2772
[354]2773EOF
2774        print SCRIPT << "EOF";
2775    if (/ $key /) {
2776        \$count++;
2777    }
2778print PBOUT \$_ if ((\$count <= 1) || (\$_ !~ / $key /));
2779}
2780close(PBFILE);
2781close(PBOUT);
2782rename("\$file1.new",\$file1);
2783chmod 0600,\$file1;
[517]2784
[354]2785EOF
2786    }
2787    print SCRIPT << 'EOF';
2788
2789# Adds $pbac->{$ENV{'PBPROJ'}} as an account if needed
2790#
[346]2791my $file="/etc/passwd";
[320]2792open(PBFILE,$file) || die "Unable to open $file";
2793my $found = 0;
2794while (<PBFILE>) {
[346]2795EOF
[353]2796    print SCRIPT << "EOF";
2797    \$found = 1 if (/^$pbac->{$ENV{'PBPROJ'}}:/);
[346]2798EOF
[891]2799
[1176]2800# TODO: use an external parameter
[891]2801my $home = "/home";
2802# Solaris doesn't like that we use /home
[1177]2803$home = "/export/home" if ($pbos->{'type'} eq "pkg");
[891]2804
2805    print SCRIPT << "EOF";
[320]2806}
2807close(PBFILE);
2808
[891]2809if ( \$found == 0 ) {
2810    if ( ! -d "$home" ) {
2811        pb_mkdir_p("$home");
[320]2812    }
[346]2813EOF
[1179]2814    # TODO: Level of portability of these cmds ? Critical now for RM
[1255]2815    # TODO: Check existence before adding to avoid errors
[353]2816    print SCRIPT << "EOF";
[1051]2817pb_system("/usr/sbin/groupadd $pbac->{$ENV{'PBPROJ'}}","Adding group $pbac->{$ENV{'PBPROJ'}}");
2818pb_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'}})");
[427]2819}
[661]2820EOF
[320]2821
[1176]2822    # Copy the content of our local conf file to the VM/VE/RM
[891]2823    my $content = pb_get_content(pb_distro_conffile());
2824    print SCRIPT << "EOF";
2825    #
2826    # Create a temporary local conf file for distribution support
2827    # This is created here before its use later. Its place is hardcoded, so no choice for the path
2828    #
2829    my \$tempconf = pb_distro_conffile();
2830    pb_mkdir_p(dirname(\$tempconf));
2831    open(CONF,"> \$tempconf") || die "Unable to create \$tempconf";
2832    print CONF q{$content};
2833    close(CONF);
2834EOF
2835
[1176]2836    if ($vtype =~ /(v|r)m/) {
[661]2837        print SCRIPT << "EOF";
[354]2838# allow ssh entry to build
2839#
[891]2840mkdir "$home/$pbac->{$ENV{'PBPROJ'}}/.ssh",0700;
[347]2841# Allow those accessing root to access the build account
[891]2842copy("\$ENV{'HOME'}/.ssh/authorized_keys","$home/$pbac->{$ENV{'PBPROJ'}}/.ssh/authorized_keys");
[320]2843chmod 0600,".ssh/authorized_keys";
[891]2844pb_system("chown -R $pbac->{$ENV{'PBPROJ'}}:$pbac->{$ENV{'PBPROJ'}} $home/$pbac->{$ENV{'PBPROJ'}}","Finish setting up the account env for $pbac->{$ENV{'PBPROJ'}}");
[320]2845
[346]2846EOF
[661]2847}
[353]2848    print SCRIPT << 'EOF';
[347]2849# No passwd for build account only keys
[320]2850$file="/etc/shadow";
[684]2851if (-f $file) {
2852    open(PBFILE,$file) || die "Unable to open $file";
2853    open(PBOUT,"> $file.new") || die "Unable to open $file.new";
2854    while (<PBFILE>) {
[346]2855EOF
[353]2856    print SCRIPT << "EOF";
[684]2857        s/^$pbac->{$ENV{'PBPROJ'}}:\!\!:/$pbac->{$ENV{'PBPROJ'}}:*:/;
2858        s/^$pbac->{$ENV{'PBPROJ'}}:\!:/$pbac->{$ENV{'PBPROJ'}}:*:/; #SLES 9 e.g.
[910]2859        s/^$pbac->{$ENV{'PBPROJ'}}:\\*LK\\*:/$pbac->{$ENV{'PBPROJ'}}:NP:/;  #Solaris e.g.
[346]2860EOF
[684]2861        print SCRIPT << 'EOF';
2862        print PBOUT $_;
2863    }
2864    close(PBFILE);
2865    close(PBOUT);
2866    rename("$file.new",$file);
2867    chmod 0640,$file;
2868    }
[320]2869
[448]2870# Keep the VM in text mode
2871$file="/etc/inittab";
[450]2872if (-f $file) {
2873    open(PBFILE,$file) || die "Unable to open $file";
2874    open(PBOUT,"> $file.new") || die "Unable to open $file.new";
2875    while (<PBFILE>) {
2876        s/^(..):5:initdefault:$/$1:3:initdefault:/;
2877        print PBOUT $_;
2878    }
2879    close(PBFILE);
2880    close(PBOUT);
2881    rename("$file.new",$file);
2882    chmod 0640,$file;
[448]2883}
2884
[320]2885# pb has to be added to portage group on gentoo
2886
[1177]2887# We need to have that pb_distro_get_context function
[888]2888# Get it from Project-Builder::Distribution
[891]2889# And we now need the conf file required for this to work created above
[888]2890
[1177]2891my $pbos = pb_distro_get_context(); 
2892print "distro tuple: ".Dumper($pbos)."\n";
[891]2893
[346]2894# Adapt sudoers
[888]2895# sudo is not default on Solaris and needs to be installed first
2896# from http://www.sunfreeware.com/programlistsparc10.html#sudo
[1177]2897if ($pbos->{'type'} eq "pkg") {
[888]2898    $file="/usr/local/etc/sudoers";
2899} else {
2900    $file="/etc/sudoers";
2901}
[346]2902open(PBFILE,$file) || die "Unable to open $file";
2903open(PBOUT,"> $file.new") || die "Unable to open $file.new";
2904while (<PBFILE>) {
2905EOF
[1190]2906    # Skip what will be generated
[353]2907    print SCRIPT << "EOF";
[1190]2908    next if (/^$pbac->{$ENV{'PBPROJ'}}\\s+/);
2909    next if (/^Defaults:$pbac->{$ENV{'PBPROJ'}}\\s+/);
2910    next if (/^Defaults:root \!requiretty/);
[346]2911EOF
[353]2912    print SCRIPT << 'EOF';
[346]2913    s/Defaults[ \t]+requiretty//;
2914    print PBOUT $_;
2915}
2916close(PBFILE);
2917EOF
[353]2918    print SCRIPT << "EOF";
[1032]2919# Some distro force requiretty at compile time, so disable here
2920print PBOUT "Defaults:$pbac->{$ENV{'PBPROJ'}} !requiretty\n";
[1035]2921print PBOUT "Defaults:root !requiretty\n";
[1179]2922# Keep proxy configuration while using sudo
[1198]2923print PBOUT "Defaults:$pbac->{$ENV{'PBPROJ'}}    env_keep += \\\"http_proxy ftp_proxy\\\"\n";
[1179]2924EOF
2925    # Try to restrict security to what is really needed
2926    if ($vtype =~ /^vm/) {
[1197]2927        my $hpath = pb_distro_get_param($pbos,pb_conf_get("ospathcmd-halt"));
[1198]2928        my @sudocmds = pb_get_sudocmds($pbos,$ntpline,"sudo $hpath");
[1179]2929        print SCRIPT << "EOF";
2930# This is needed in order to be able on VM to halt the machine from the $pbac->{$ENV{'PBPROJ'}} account at least
2931# Build account $pbac->{$ENV{'PBPROJ'}} in VM also needs to setup date and install deps.
2932# Nothing else should be needed
2933EOF
[1189]2934        foreach my $c (@sudocmds) {
[1192]2935            print SCRIPT "print PBOUT \"$pbac->{$ENV{'PBPROJ'}}   ALL = NOPASSWD: $c\n\";";
[1179]2936        }
2937    } elsif ($vtype =~ /^rm/) {
[1190]2938        my @sudocmds = pb_get_sudocmds($pbos,$ntpline);
[1179]2939        print SCRIPT << "EOF";
2940# Build account $pbac->{$ENV{'PBPROJ'}} in RM only needs to setup date and install deps if needed each time
2941EOF
[1189]2942        foreach my $c (@sudocmds) {
[1192]2943            print SCRIPT "print PBOUT \"$pbac->{$ENV{'PBPROJ'}}   ALL = NOPASSWD: $c\n\";";
[1179]2944        }
2945    } else {
2946        print SCRIPT << "EOF";
2947# Build account $pbac->{$ENV{'PBPROJ'}} for VE needs to do a lot in the host (and chroot), so allow without restriction for now
[353]2948print PBOUT "$pbac->{$ENV{'PBPROJ'}}   ALL=(ALL) NOPASSWD:ALL\n";
[346]2949EOF
[1179]2950}
[353]2951    print SCRIPT << 'EOF';
[346]2952close(PBOUT);
2953rename("$file.new",$file);
2954chmod 0440,$file;
2955
2956EOF
[891]2957
[1190]2958    if ($vtype =~ /(v|r)m/) {
2959        # Sync date
2960        # do it after sudoers is setup
2961        print SCRIPT "pb_system(\"$ntpline\");\n";
2962    }
[891]2963    # We may need a proxy configuration. Get it from the local env
2964
2965    if (defined $ENV{'http_proxy'}) {
2966        print SCRIPT "\$ENV\{'http_proxy'\}=\"$ENV{'http_proxy'}\";\n";
2967    }
2968
2969    if (defined $ENV{'ftp_proxy'}) {
2970        print SCRIPT "\$ENV\{'ftp_proxy'\}=\"$ENV{'ftp_proxy'}\";\n";
2971    }
2972
2973    print SCRIPT << 'EOF';
[353]2974   
[346]2975# Suse wants sudoers as 640
[1177]2976if ((($pbos->{'name'} eq "sles") && (($pbos->{'version'} =~ /10/) || ($pbos->{'version'} =~ /9/))) || (($pbos->{'name'} eq "opensuse") && ($pbos->{'version'} =~ /10.[012]/))) {
[346]2977    chmod 0640,$file;
2978}
2979
[1109]2980# First install all required packages
[1177]2981pb_system("yum clean all","Cleaning yum env") if (($pbos->{'name'} eq "fedora") || ($pbos->{'name'} eq "asianux") || ($pbos->{'name'} eq "rhel"));
[1109]2982my ($ospkgdep) = pb_conf_get_if("ospkgdep");
2983   
[1177]2984my $pkgdep = pb_distro_get_param($pbos,$ospkgdep);
2985pb_distro_installdeps(undef,$pbos,pb_distro_only_deps_needed($pbos,join(' ',split(/,/,$pkgdep))));
[1109]2986
2987EOF
[1177]2988    my $itype = pb_distro_get_param($pbos,pb_conf_get("pbinstalltype"));
[1176]2989    # Install from sandbox mean a file base install
2990    $itype = "file" if (defined $sbx);
[1132]2991    if ($itype =~ /^file/) {
[1140]2992        my $cmdget;
2993        if (defined $sbx) {
2994            # Install from sandbox mean using the result of the just passed sbx2build command
2995            # Get content saved in cms2build
2996            my ($pkg) = pb_conf_read("$ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb","pbpkg");
2997            die "Unable to get package list" if (not defined $pkg);
2998
2999            # We consider 2 specific packages
3000            my $vertag1 = $pkg->{"ProjectBuilder"};
3001            my $vertag2 = $pkg->{"project-builder"};
3002            # get the version of the current package - maybe different
3003            my ($pbver1,$tmp1) = split(/-/,$vertag1);
3004            my ($pbver2,$tmp2) = split(/-/,$vertag2);
[1156]3005            # Copy inside the VE
3006            if ($vtype eq "ve") {
3007                my ($vepath) = pb_conf_get("vepath");
[1177]3008                copy("$ENV{'PBDESTDIR'}/ProjectBuilder-$pbver1.tar.gz","$vepath->{$ENV{'PBPROJ'}}/$pbos->{'name'}/$pbos->{'version'}/$pbos->{'arch'}/tmp");
3009                copy("$ENV{'PBDESTDIR'}/project-builder-$pbver2.tar.gz","$vepath->{$ENV{'PBPROJ'}}/$pbos->{'name'}/$pbos->{'version'}/$pbos->{'arch'}/tmp");
[1156]3010            } else {
3011                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.");
3012            }
[1140]3013            $cmdget = "mv /tmp/ProjectBuilder-$pbver1.tar.gz ProjectBuilder-latest.tar.gz ; mv /tmp/project-builder-$pbver2.tar.gz project-builder-latest.tar.gz";
3014        } else {
3015            $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";
3016        }
[1109]3017        print SCRIPT << 'EOF';
3018# Then install manually the missing perl modules
3019my ($osperldep,$osperlver) = pb_conf_get_if("osperldep","osperlver");
3020   
[1177]3021my $perldep = pb_distro_get_param($pbos,$osperldep);
[1109]3022foreach my $m (split(/,/,$perldep)) {
3023    # Skip empty deps
3024    next if ($m =~ /^\s*$/);
3025    my $dir = $m;
3026    $dir =~ s/-.*//;
3027    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}");
3028}
[1140]3029EOF
[1109]3030
[1140]3031        print SCRIPT << "EOF";
3032pb_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");
[1109]3033EOF
[1132]3034    } elsif ($itype =~ /^pkg/) {
[1109]3035        # pkg based install. We need to point to the project-builder.org repository
3036        print SCRIPT << 'EOF';
[1177]3037my $pkgforpb = pb_distro_get_param($pbos,pb_conf_get_if("ospkg"));
3038pb_distro_setuposrepo($pbos);
3039pb_distro_installdeps(undef,$pbos,pb_distro_only_deps_needed($pbos,join(' ',split(/,/,$pkgforpb))));
[1109]3040EOF
3041    } else {
3042        # Unknown install type
3043        die("Unknown install type $itype->{$ENV{'PBPROJ'}} for param pbinstalltype");
3044    }
3045    print SCRIPT << 'EOF';
[902]3046pb_system("pb 2>&1 | head -5",undef,"verbose");
[1189]3047pb_system("pbdistrocheck",undef,"verbose");
[357]3048EOF
[681]3049    if ($vtype eq "ve") {
3050            print SCRIPT << 'EOF';
3051# For VE we need to umount some FS at the end
3052
3053pb_system("umount /proc");
[696]3054