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

Last change on this file since 1480 was 1480, checked in by Bruno Cornec, 12 years ago

r4694@localhost: bruno | 2012-04-19 00:23:38 +0200

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