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

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