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

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

r4735@localhost: bruno | 2012-05-07 03:46:39 +0200

  • Conf.pm largely rewritten to cache all conf files into a local $h hash in which conf files are added in reverse order.

The new pb_conf_hash stores a configuration file into a hash structure passed in parameter.
pb_conf_add now triggers the computation of the hash structure with pb_conf_cache and adds it to the main $h hash.
pb_conf_read_if now just uses the content in the $h hash to return its table.
pb_conf_get_in_hash_if function added to do the same as pb_conf_read_if on the cached $h hash instead of a configuration file.
pb_conf_get_if now uses pb_conf_get_in_hash_if and the $h hash without re-reading conf files
pb_conf_add_last_in_hash adds the content of a hash behind the content of the $h main hash (was done in pb_conf_get before)
pb_env_init now calls pb_conf_init to have PBPROJ defined when needed.
pb seems to work with this new version (builds itself)

  • Add a new getconf option to pb in order to see the state of the current configuration parameters (now in memory)
  • 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);
[681]2797
2798EOF
2799
[1176]2800 # Launch the VM/VE/RM - Usage of snapshot disabled
[773]2801 ($vmexist,$vmpid) = pb_launchv($vtype,$v,0,0,0);
[755]2802
[1156]2803 my $keyfile;
2804 my $nport;
2805 my $vmhost;
2806
[1255]2807 # Prepare the key to be used and transfered remotely
2808 $keyfile = pb_ssh_get(1);
2809
[1176]2810 if ($vtype =~ /(v|r)m/) {
[1215]2811 my ($vmport);
2812 ($vmhost,$vmport) = pb_conf_get($vtype."host",$vtype."port");
[1179]2813 $nport = pb_get_port($vmport,$pbos,$vtype);
[347]2814
[1176]2815 # Skip that VM/RM if something went wrong
[442]2816 next if (($vmpid == 0) && ($vmexist == 0));
[353]2817
[354]2818 # Store the pub key part in a variable
2819 open(FILE,"$keyfile.pub") || die "Unable to open $keyfile.pub";
2820 ($zero0,$zero1,$zero2) = split(/ /,<FILE>);
2821 close(FILE);
2822
2823 $key = "\Q$zero1";
2824
[1105]2825 # We call true to avoid problems if SELinux is not activated, but chcon is present and returns in that case 1
2826 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]2827 # once this is done, we can do what we need on the VM/RM remotely
[681]2828 } elsif ($vtype eq "ve") {
[1029]2829 print SCRIPT << "EOF";
[940]2830# For VE we need a good null dev
2831pb_system("rm -f /dev/null; mknod /dev/null c 1 3; chmod 777 /dev/null");
2832EOF
[1029]2833 print SCRIPT << "EOF";
[681]2834# For VE we first need to mount some FS
2835pb_system("mount -t proc /proc /proc");
[346]2836
[354]2837EOF
[681]2838 }
[1029]2839
[1190]2840 if ($vtype =~ /(v|r)m/) {
[354]2841 print SCRIPT << 'EOF';
2842# Removes duplicate in .ssh/authorized_keys of our key if needed
2843#
2844my $file1="$ENV{'HOME'}/.ssh/authorized_keys";
2845open(PBFILE,$file1) || die "Unable to open $file1";
2846open(PBOUT,"> $file1.new") || die "Unable to open $file1.new";
2847my $count = 0;
2848while (<PBFILE>) {
[517]2849
[354]2850EOF
2851 print SCRIPT << "EOF";
2852 if (/ $key /) {
2853 \$count++;
2854 }
2855print PBOUT \$_ if ((\$count <= 1) || (\$_ !~ / $key /));
2856}
2857close(PBFILE);
2858close(PBOUT);
2859rename("\$file1.new",\$file1);
2860chmod 0600,\$file1;
[517]2861
[354]2862EOF
2863 }
2864 print SCRIPT << 'EOF';
2865
2866# Adds $pbac->{$ENV{'PBPROJ'}} as an account if needed
2867#
[346]2868my $file="/etc/passwd";
[320]2869open(PBFILE,$file) || die "Unable to open $file";
2870my $found = 0;
2871while (<PBFILE>) {
[346]2872EOF
[353]2873 print SCRIPT << "EOF";
2874 \$found = 1 if (/^$pbac->{$ENV{'PBPROJ'}}:/);
[346]2875EOF
[891]2876
[1176]2877# TODO: use an external parameter
[891]2878my $home = "/home";
2879# Solaris doesn't like that we use /home
[1177]2880$home = "/export/home" if ($pbos->{'type'} eq "pkg");
[891]2881
2882 print SCRIPT << "EOF";
[320]2883}
2884close(PBFILE);
2885
[891]2886if ( \$found == 0 ) {
2887 if ( ! -d "$home" ) {
2888 pb_mkdir_p("$home");
[320]2889 }
[346]2890EOF
[1179]2891 # TODO: Level of portability of these cmds ? Critical now for RM
[1255]2892 # TODO: Check existence before adding to avoid errors
[353]2893 print SCRIPT << "EOF";
[1051]2894pb_system("/usr/sbin/groupadd $pbac->{$ENV{'PBPROJ'}}","Adding group $pbac->{$ENV{'PBPROJ'}}");
2895pb_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]2896}
[661]2897EOF
[320]2898
[1176]2899 # Copy the content of our local conf file to the VM/VE/RM
[891]2900 my $content = pb_get_content(pb_distro_conffile());
2901 print SCRIPT << "EOF";
2902 #
2903 # Create a temporary local conf file for distribution support
2904 # This is created here before its use later. Its place is hardcoded, so no choice for the path
2905 #
2906 my \$tempconf = pb_distro_conffile();
2907 pb_mkdir_p(dirname(\$tempconf));
2908 open(CONF,"> \$tempconf") || die "Unable to create \$tempconf";
2909 print CONF q{$content};
2910 close(CONF);
2911EOF
2912
[1176]2913 if ($vtype =~ /(v|r)m/) {
[661]2914 print SCRIPT << "EOF";
[354]2915# allow ssh entry to build
2916#
[891]2917mkdir "$home/$pbac->{$ENV{'PBPROJ'}}/.ssh",0700;
[347]2918# Allow those accessing root to access the build account
[891]2919copy("\$ENV{'HOME'}/.ssh/authorized_keys","$home/$pbac->{$ENV{'PBPROJ'}}/.ssh/authorized_keys");
[320]2920chmod 0600,".ssh/authorized_keys";
[891]2921pb_system("chown -R $pbac->{$ENV{'PBPROJ'}}:$pbac->{$ENV{'PBPROJ'}} $home/$pbac->{$ENV{'PBPROJ'}}","Finish setting up the account env for $pbac->{$ENV{'PBPROJ'}}");
[320]2922
[346]2923EOF
[661]2924}
[353]2925 print SCRIPT << 'EOF';
[347]2926# No passwd for build account only keys
[320]2927$file="/etc/shadow";
[684]2928if (-f $file) {
2929 open(PBFILE,$file) || die "Unable to open $file";
2930 open(PBOUT,"> $file.new") || die "Unable to open $file.new";
2931 while (<PBFILE>) {
[346]2932EOF
[353]2933 print SCRIPT << "EOF";
[684]2934 s/^$pbac->{$ENV{'PBPROJ'}}:\!\!:/$pbac->{$ENV{'PBPROJ'}}:*:/;
2935 s/^$pbac->{$ENV{'PBPROJ'}}:\!:/$pbac->{$ENV{'PBPROJ'}}:*:/; #SLES 9 e.g.
[910]2936 s/^$pbac->{$ENV{'PBPROJ'}}:\\*LK\\*:/$pbac->{$ENV{'PBPROJ'}}:NP:/; #Solaris e.g.
[346]2937EOF
[684]2938 print SCRIPT << 'EOF';
2939 print PBOUT $_;
2940 }
2941 close(PBFILE);
2942 close(PBOUT);
2943 rename("$file.new",$file);
2944 chmod 0640,$file;
2945 }
[320]2946
[448]2947# Keep the VM in text mode
2948$file="/etc/inittab";
[450]2949if (-f $file) {
2950 open(PBFILE,$file) || die "Unable to open $file";
2951 open(PBOUT,"> $file.new") || die "Unable to open $file.new";
2952 while (<PBFILE>) {
2953 s/^(..):5:initdefault:$/$1:3:initdefault:/;
2954 print PBOUT $_;
2955 }
2956 close(PBFILE);
2957 close(PBOUT);
2958 rename("$file.new",$file);
2959 chmod 0640,$file;
[448]2960}
2961
[320]2962# pb has to be added to portage group on gentoo
2963
[1177]2964# We need to have that pb_distro_get_context function
[888]2965# Get it from Project-Builder::Distribution
[891]2966# And we now need the conf file required for this to work created above
[888]2967
[1177]2968my $pbos = pb_distro_get_context();
2969print "distro tuple: ".Dumper($pbos)."\n";
[891]2970
[346]2971# Adapt sudoers
[888]2972# sudo is not default on Solaris and needs to be installed first
2973# from http://www.sunfreeware.com/programlistsparc10.html#sudo
[1177]2974if ($pbos->{'type'} eq "pkg") {
[888]2975 $file="/usr/local/etc/sudoers";
2976} else {
2977 $file="/etc/sudoers";
2978}
[346]2979open(PBFILE,$file) || die "Unable to open $file";
2980open(PBOUT,"> $file.new") || die "Unable to open $file.new";
2981while (<PBFILE>) {
2982EOF
[1190]2983 # Skip what will be generated
[353]2984 print SCRIPT << "EOF";
[1190]2985 next if (/^$pbac->{$ENV{'PBPROJ'}}\\s+/);
2986 next if (/^Defaults:$pbac->{$ENV{'PBPROJ'}}\\s+/);
2987 next if (/^Defaults:root \!requiretty/);
[346]2988EOF
[353]2989 print SCRIPT << 'EOF';
[346]2990 s/Defaults[ \t]+requiretty//;
2991 print PBOUT $_;
2992}
2993close(PBFILE);
2994EOF
[353]2995 print SCRIPT << "EOF";
[1032]2996# Some distro force requiretty at compile time, so disable here
2997print PBOUT "Defaults:$pbac->{$ENV{'PBPROJ'}} !requiretty\n";
[1035]2998print PBOUT "Defaults:root !requiretty\n";
[1179]2999# Keep proxy configuration while using sudo
[1198]3000print PBOUT "Defaults:$pbac->{$ENV{'PBPROJ'}} env_keep += \\\"http_proxy ftp_proxy\\\"\n";
[1179]3001EOF
3002 # Try to restrict security to what is really needed
3003 if ($vtype =~ /^vm/) {
[1197]3004 my $hpath = pb_distro_get_param($pbos,pb_conf_get("ospathcmd-halt"));
[1198]3005 my @sudocmds = pb_get_sudocmds($pbos,$ntpline,"sudo $hpath");
[1179]3006 print SCRIPT << "EOF";
3007# This is needed in order to be able on VM to halt the machine from the $pbac->{$ENV{'PBPROJ'}} account at least
3008# Build account $pbac->{$ENV{'PBPROJ'}} in VM also needs to setup date and install deps.
3009# Nothing else should be needed
3010EOF
[1189]3011 foreach my $c (@sudocmds) {
[1426]3012 print SCRIPT "print PBOUT \"$pbac->{$ENV{'PBPROJ'}} ALL = NOPASSWD: $c\\n\";\n";
[1179]3013 }
3014 } elsif ($vtype =~ /^rm/) {
[1190]3015 my @sudocmds = pb_get_sudocmds($pbos,$ntpline);
[1179]3016 print SCRIPT << "EOF";
3017# Build account $pbac->{$ENV{'PBPROJ'}} in RM only needs to setup date and install deps if needed each time
3018EOF
[1189]3019 foreach my $c (@sudocmds) {
[1426]3020 print SCRIPT "print PBOUT \"$pbac->{$ENV{'PBPROJ'}} ALL = NOPASSWD: $c\\n\";\n";
[1179]3021 }
3022 } else {
3023 print SCRIPT << "EOF";
3024# Build account $pbac->{$ENV{'PBPROJ'}} for VE needs to do a lot in the host (and chroot), so allow without restriction for now
[353]3025print PBOUT "$pbac->{$ENV{'PBPROJ'}} ALL=(ALL) NOPASSWD:ALL\n";
[346]3026EOF
[1179]3027}
[353]3028 print SCRIPT << 'EOF';
[346]3029close(PBOUT);
3030rename("$file.new",$file);
3031chmod 0440,$file;
3032
3033EOF
[891]3034
[1190]3035 if ($vtype =~ /(v|r)m/) {
3036 # Sync date
3037 # do it after sudoers is setup
3038 print SCRIPT "pb_system(\"$ntpline\");\n";
3039 }
[891]3040 # We may need a proxy configuration. Get it from the local env
3041
3042 if (defined $ENV{'http_proxy'}) {
3043 print SCRIPT "\$ENV\{'http_proxy'\}=\"$ENV{'http_proxy'}\";\n";
3044 }
3045
3046 if (defined $ENV{'ftp_proxy'}) {
3047 print SCRIPT "\$ENV\{'ftp_proxy'\}=\"$ENV{'ftp_proxy'}\";\n";
3048 }
3049
3050 print SCRIPT << 'EOF';
[353]3051
[346]3052# Suse wants sudoers as 640
[1177]3053if ((($pbos->{'name'} eq "sles") && (($pbos->{'version'} =~ /10/) || ($pbos->{'version'} =~ /9/))) || (($pbos->{'name'} eq "opensuse") && ($pbos->{'version'} =~ /10.[012]/))) {
[346]3054 chmod 0640,$file;
3055}
3056
[1109]3057# First install all required packages
[1177]3058pb_system("yum clean all","Cleaning yum env") if (($pbos->{'name'} eq "fedora") || ($pbos->{'name'} eq "asianux") || ($pbos->{'name'} eq "rhel"));
[1109]3059my ($ospkgdep) = pb_conf_get_if("ospkgdep");
3060
[1177]3061my $pkgdep = pb_distro_get_param($pbos,$ospkgdep);
3062pb_distro_installdeps(undef,$pbos,pb_distro_only_deps_needed($pbos,join(' ',split(/,/,$pkgdep))));
[1109]3063
3064EOF
[1177]3065 my $itype = pb_distro_get_param($pbos,pb_conf_get("pbinstalltype"));
[1176]3066 # Install from sandbox mean a file base install
3067 $itype = "file" if (defined $sbx);
[1132]3068 if ($itype =~ /^file/) {
[1140]3069 my $cmdget;
3070 if (defined $sbx) {
3071 # Install from sandbox mean using the result of the just passed sbx2build command
3072 # Get content saved in cms2build
3073 my ($pkg) = pb_conf_read("$ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb","pbpkg");
[1432]3074 my $pbextdir = pb_get_extdir();
[1140]3075 die "Unable to get package list" if (not defined $pkg);
3076
3077 # We consider 2 specific packages
3078 my $vertag1 = $pkg->{"ProjectBuilder"};
3079 my $vertag2 = $pkg->{"project-builder"};
3080 # get the version of the current package - maybe different
[1459]3081 pb_log(2,"Vertag1: $vertag1\n");
3082 pb_log(2,"Vertag2: $vertag2\n");
[1140]3083 my ($pbver1,$tmp1) = split(/-/,$vertag1);
3084 my ($pbver2,$tmp2) = split(/-/,$vertag2);
[1156]3085 # Copy inside the VE
3086 if ($vtype eq "ve") {
3087 my ($vepath) = pb_conf_get("vepath");
[1432]3088 copy("$ENV{'PBDESTDIR'}/ProjectBuilder-$pbver1$pbextdir.tar.gz","$vepath->{$ENV{'PBPROJ'}}/$pbos->{'name'}/$pbos->{'version'}/$pbos->{'arch'}/tmp");
3089 copy("$ENV{'PBDESTDIR'}/project-builder-$pbver2$pbextdir.tar.gz","$vepath->{$ENV{'PBPROJ'}}/$pbos->{'name'}/$pbos->{'version'}/$pbos->{'arch'}/tmp");
[1156]3090 } else {
[1432]3091 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]3092 }
[1432]3093 $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]3094 } else {
3095 $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";
3096 }
[1109]3097 print SCRIPT << 'EOF';
3098# Then install manually the missing perl modules
3099my ($osperldep,$osperlver) = pb_conf_get_if("osperldep","osperlver");
3100
[1177]3101my $perldep = pb_distro_get_param($pbos,$osperldep);
[1109]3102foreach my $m (split(/,/,$perldep)) {
3103 # Skip empty deps
3104 next if ($m =~ /^\s*$/);
3105 my $dir = $m;
3106 $dir =~ s/-.*//;
3107 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}");
3108}
[1140]3109EOF
[1425]3110 print SCRIPT << 'EOF';
3111pb_system("rm -rf ProjectBuilder-* ; rm -rf project-builder-* ; rm -rf `perl -V:installvendorlib | awk -F\"'\" '{print \$2}'`/ProjectBuilder ;
[1109]3112EOF
[1425]3113 print SCRIPT " $cmdget ; ";
3114 print SCRIPT << 'EOF'
3115gzip -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");
3116EOF
[1132]3117 } elsif ($itype =~ /^pkg/) {
[1109]3118 # pkg based install. We need to point to the project-builder.org repository
3119 print SCRIPT << 'EOF';
[1177]3120my $pkgforpb = pb_distro_get_param($pbos,pb_conf_get_if("ospkg"));
3121pb_distro_setuposrepo($pbos);
3122pb_distro_installdeps(undef,$pbos,pb_distro_only_deps_needed($pbos,join(' ',split(/,/,$pkgforpb))));
[1109]3123EOF
3124 } else {
3125 # Unknown install type
3126 die("Unknown install type $itype->{$ENV{'PBPROJ'}} for param pbinstalltype");
3127 }
3128 print SCRIPT << 'EOF';
[902]3129pb_system("pb 2>&1 | head -5",undef,"verbose");
[1189]3130pb_system("pbdistrocheck",undef,"verbose");
[357]3131EOF
[681]3132 if ($vtype eq "ve") {
3133 print SCRIPT << 'EOF';
3134# For VE we need to umount some FS at the end
3135
3136pb_system("umount /proc");
[696]3137
3138# Create a basic network file if not already there
3139
3140my $nf="/etc/sysconfig/network";
[1177]3141if ((! -f $nf) && ($pbos->{'type'} eq "rpm")) {
[696]3142 open(NF,"> $nf") || die "Unable to create $nf";
3143 print NF "NETWORKING=yes\n";
3144 print NF "HOSTNAME=localhost\n";
3145 close(NF);
3146}
3147chmod 0755,$nf;
[681]3148EOF
3149 }
3150
[1177]3151 # Adds pb_distro_get_context and all functions needed from ProjectBuilder::Distribution, Conf and Base
[353]3152 foreach my $d (@INC) {
[891]3153 my @f = ("$d/ProjectBuilder/Base.pm","$d/ProjectBuilder/Distribution.pm","$d/ProjectBuilder/Conf.pm");
[405]3154 foreach my $f (@f) {
3155 if (-f "$f") {
3156 open(PBD,"$f") || die "Unable to open $f";
3157 while (<PBD>) {
[891]3158 next if (/^package/);
3159 next if (/^use Exporter/);
3160 next if (/^use ProjectBuilder::/);
3161 next if (/^our /);
[405]3162 print SCRIPT $_;
3163 }
3164 close(PBD);
[353]3165 }
[347]3166 }
3167 }
[1156]3168 # Use a fake pb_version_init version here
3169 print SCRIPT << "EOF";
3170sub pb_version_init {
3171
3172return("$projectbuilderver","$projectbuilderrev");
3173}
31741;
3175EOF
[353]3176 close(SCRIPT);
3177 chmod 0755,"$pbscript";
3178
[442]3179 # That build script needs to be run as root and force stop of VM at end
[353]3180 $pbaccount = "root";
[442]3181
[1111]3182 # Force shutdown of VM except if it was already launched
[748]3183 my $pbforce = 0;
[442]3184 if ((! $vmexist) && ($vtype eq "vm")) {
[748]3185 $pbforce = 1;
[442]3186 }
3187
[748]3188 pb_script2v($pbscript,$vtype,$pbforce,$v);
[1143]3189 $pm->finish if (defined $pbparallel);
[347]3190}
[1176]3191$pm->wait_all_children if (defined $pbparallel);
[353]3192return;
[346]3193}
3194
[772]3195# Function to create a snapshot named 'pb' for VMs and a compressed tar for VEs
3196sub pb_snap2v {
[748]3197
3198my $vtype = shift;
3199
[772]3200my ($vm,$all) = pb_get2v($vtype);
[748]3201
3202# Script generated
3203my $pbscript = "$ENV{'PBDESTDIR'}/snapv";
3204
[898]3205my ($pbac) = pb_conf_get($vtype."login");
3206
[748]3207foreach my $v (@$vm) {
[1138]3208 if ($vtype eq "ve") {
3209 # Get distro context
[1177]3210 my $pbos = pb_distro_get_context($v);
[1138]3211 my ($vepath) = pb_conf_get("vepath");
[971]3212
[1138]3213 # Test if an existing snapshot exists and remove it if there is a VE
[1177]3214 if ((-f "$vepath->{$ENV{'PBPROJ'}}/$pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}.tar.gz") &&
3215 (! -d "$vepath->{$ENV{'PBPROJ'}}/$pbos->{'name'}/$pbos->{'version'}/$pbos->{'arch'}")) {
3216 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]3217 }
[971]3218 }
3219
[748]3220 # Prepare the script to be executed on the VM/VE
3221 open(SCRIPT,"> $pbscript") || die "Unable to create $pbscript";
3222 print SCRIPT << 'EOF';
3223 #!/bin/bash
[776]3224 sleep 2
[748]3225EOF
3226 close(SCRIPT);
3227 chmod 0755,"$pbscript";
3228
3229 # Force shutdown of VM/VE
3230 # Force snapshot of VM/VE
[773]3231 pb_script2v($pbscript,$vtype,1,$v,1);
[748]3232}
3233return;
3234}
3235
[1176]3236# Function to update VMs/VEs/RMs with the latest distribution content
[1111]3237sub pb_update2v {
3238
3239my $vtype = shift;
3240
3241my ($vm,$all) = pb_get2v($vtype);
3242
3243# Script generated
3244my $pbscript = "$ENV{'PBDESTDIR'}/updatev";
3245
3246my ($pbac) = pb_conf_get($vtype."login");
3247
3248foreach my $v (@$vm) {
3249 # Get distro context
[1177]3250 my $pbos = pb_distro_get_context($v);
[1111]3251
[1176]3252 # Prepare the script to be executed on the VM/VE/RM
[1111]3253 # in $ENV{'PBDESTDIR'}/updatev
3254 open(SCRIPT,"> $pbscript") || die "Unable to create $pbscript";
3255
3256 print SCRIPT << 'EOF';
3257 #!/bin/bash
3258 sleep 2
3259EOF
3260 # VE needs a good /proc
3261 if ($vtype eq "ve") {
[1179]3262 print SCRIPT "sudo /bin/mount -t proc /proc /proc\n";
[1111]3263 }
[1177]3264 print SCRIPT "$pbos->{'update'}\n";
[1111]3265 if ($vtype eq "ve") {
[1179]3266 print SCRIPT "sudo /bin/umount /proc\n";
[1111]3267 }
3268 close(SCRIPT);
3269 chmod 0755,"$pbscript";
3270
3271 # Force shutdown of VM except
3272 pb_script2v($pbscript,$vtype,1,$v);
3273}
3274return;
3275}
3276
[471]3277sub pb_announce {
3278
[1386]3279 my $antype = shift;
3280
[473]3281 # Get all required parameters
[477]3282 my ($pbpackager,$pbrepo,$pbml,$pbsmtp) = pb_conf_get("pbpackager","pbrepo","pbml","pbsmtp");
[1392]3283 my ($pkgv, $pkgt, $testver) = pb_conf_get_if("pkgver","pkgtag","testver");
3284 if (((not defined $testver) || (not defined $testver->{$ENV{'PBPROJ'}}) || ($testver->{$ENV{'PBPROJ'}} !~ /true/i)) && ($antype eq "Clean")) {
3285 # We just clean for test versions
3286 pb_log(0,"Unable to clean SSH repository for non testver version\n");
3287 return;
3288 }
[471]3289 my $pkg = pb_cms_get_pkg($defpkgdir,$extpkgdir);
3290 my @pkgs = @$pkg;
3291 my %pkgs;
3292 my $first = 0;
3293
[1282]3294 # Get all distros concerned
3295 my $pbos = pb_distro_get_context();
3296 my $distrolist = pb_get_distros($pbos,undef);
3297 my %dl;
[1386]3298 my %theorlist;
3299 my %archlist;
[1282]3300 foreach my $d (split(/,/,$distrolist)) {
[1386]3301 my ($d1,$d2,$d3) = split(/-/,$d);
[1282]3302 $dl{$d1}++;
3303 }
3304
[473]3305 # Command to find packages on repo
[1282]3306 my $findstr = "find ".join(" ",keys %dl)." ";
[1392]3307 my $srcstr = "";
[473]3308 # Generated announce files
3309 my @files;
[471]3310
3311 foreach my $pbpkg (@pkgs) {
3312 if ($first != 0) {
3313 $findstr .= "-o ";
3314 }
3315 $first++;
3316 if ((defined $pkgv) && (defined $pkgv->{$pbpkg})) {
3317 $pbver = $pkgv->{$pbpkg};
3318 } else {
3319 $pbver = $ENV{'PBPROJVER'};
3320 }
3321 if ((defined $pkgt) && (defined $pkgt->{$pbpkg})) {
3322 $pbtag = $pkgt->{$pbpkg};
3323 } else {
3324 $pbtag = $ENV{'PBPROJTAG'};
3325 }
3326
[547]3327 # TODO: use virtual/real names here now
[1285]3328 my $pbrealpkg = $pbpkg;
3329 my $pbrealpkgrpm = pb_cms_get_real_pkg($pbpkg,"rpm");
3330 my $pbrealpkgdeb = pb_cms_get_real_pkg($pbpkg,"deb");
[1392]3331 if ($antype eq "Clean") {
[1432]3332 # We only clean test versions anyway
3333 $pbtag = "0";
3334 my $nver = $pbver;
3335 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]";
3336 $pbver .= $ntag;
3337 $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]3338 $srcstr .= "src/$pbrealpkg-$pbver.tar.gz src/$pbrealpkg-$pbver.pbconf.tar.gz ";
[1392]3339 } else {
[1420]3340 my @date=pb_get_date();
3341 # the matching is only done on packages made the same day for test version. Hopefully this is enough
[1432]3342 my $nver = $pbver;
3343 if ((defined $testver) && (defined $testver->{$ENV{'PBPROJ'}}) && ($testver->{$ENV{'PBPROJ'}} =~ /true/i) && ($antype eq "Check")) {
3344 $pbtag = "0";
3345 my $ntag .= strftime("%Y%m%d*", @date);
3346 $nver = $pbver."_p$ntag";
3347 $pbver .= $ntag;
3348 }
3349 $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]3350 }
[473]3351
[1386]3352 if ($antype eq "Announce") {
3353 my $chglog;
[473]3354
[1386]3355 pb_cms_init($pbinit);
3356 # Get project info on log file and generate tmp files used later on
3357 $chglog = "$ENV{'PBROOTDIR'}/$pbpkg/pbcl";
3358 $chglog = "$ENV{'PBROOTDIR'}/pbcl" if (! -f $chglog);
3359 $chglog = undef if (! -f $chglog);
[473]3360
[1386]3361 open(OUT,"> $ENV{'PBTMP'}/$pbpkg.ann") || die "Unable to create $ENV{'PBTMP'}/$pbpkg.ann: $!";
3362 my $pb;
3363 $pb->{'realpkg'} = $pbrealpkg;
3364 $pb->{'ver'} = $pbver;
3365 $pb->{'tag'} = $pbtag;
3366 $pb->{'date'} = $pbdate;
[1432]3367 $pb->{'extdir'} = pb_get_extdir();
[1386]3368 $pb->{'chglog'} = $chglog;
3369 $pb->{'packager'} = $pbpackager;
3370 $pb->{'proj'} = $ENV{'PBPROJ'};
3371 $pb->{'repo'} = $pbrepo;
3372 $pb->{'pbos'}->{'type'} = "announce";
3373 $pb->{'pbos'}->{'suffix'} = "none";
3374 pb_changelog($pb,\*OUT,"yes");
3375 close(OUT);
3376 push(@files,"$ENV{'PBTMP'}/$pbpkg.ann");
[1392]3377 } elsif ($antype eq "Check") {
[1386]3378 # For the check we also build the theoritical complete list we should get
3379 foreach my $d (split(/,/,$distrolist)) {
3380 $pbos = pb_distro_get_context($d);
3381 if ($pbos->{'type'} eq "rpm") {
3382 $theorlist{"$pbos->{'name'}/$pbos->{'version'}/$pbos->{'arch'}/$pbrealpkgrpm-$pbver-$pbtag$pbos->{'suffix'}"} = 0;
3383 } elsif ($pbos->{'type'} eq "deb") {
3384 $theorlist{"$pbos->{'name'}/$pbos->{'version'}/$pbrealpkgdeb"."_$pbver-$pbtag"} = 0;
[1420]3385 # TODO are we always using the last arch ?
[1386]3386 $archlist{"$pbos->{'name'}/$pbos->{'version'}/$pbrealpkgdeb"."_$pbver-$pbtag"} = "$pbos->{'arch'}";
3387 } elsif ($pbos->{'type'} eq "ebuild") {
[1424]3388 my $prefix = "-r";
3389 $prefix = "_p" if ((defined $testver) && (defined $testver->{$ENV{'PBPROJ'}}) && ($testver->{$ENV{'PBPROJ'}} =~ /true/i));
3390 $theorlist{"$pbos->{'name'}/$pbos->{'version'}/$pbrealpkg-$pbver$prefix$pbtag.ebuild"} = 0;
3391 $archlist{"$pbos->{'name'}/$pbos->{'version'}/$pbrealpkg-$pbver$prefix$pbtag.ebuild"} = "$pbos->{'arch'}";
[1386]3392 } elsif ($pbos->{'type'} eq "pkg") {
3393 $theorlist{"$pbos->{'name'}/$pbos->{'version'}/$pbos->{'arch'}/$pbrealpkg-$pbver-$pbtag.pkg"} = 0;
3394 } else {
3395 pb_log(1,"No theoritical list possible for type $pbos->{'type'}\n");
3396 }
3397 }
3398 }
3399 pb_log(2,"theorlist : ".Dumper(%theorlist)."\n");
[471]3400 }
[1392]3401 if ($antype eq "Announce") {
3402 $findstr .= " | grep -Ev \'src.rpm\'";
3403 } elsif ($antype eq "Clean") {
3404 $findstr .= " | xargs rm -f -v $srcstr ";
3405 }
[471]3406
3407 # Prepare the command to run and execute it
3408 open(PBS,"> $ENV{'PBTMP'}/pbscript") || die "Unable to create $ENV{'PBTMP'}/pbscript";
[1392]3409 print PBS "#!/bin/bash\n";
[1282]3410 print PBS "set -x\n" if ($pbdebug gt 1);
[1295]3411 print PBS "$findstr | sort 2> /dev/null\n";
[471]3412 close(PBS);
3413 chmod 0755,"$ENV{'PBTMP'}/pbscript";
3414 pb_send2target("Announce");
3415
[490]3416 my $sl = "Project $ENV{'PBPROJ'} version $ENV{'PBPROJVER'} is now available";
[1386]3417 if ($antype eq "Announce") {
3418 # Get subject line
3419 pb_log(0,"Please enter the title of your announce\n");
3420 pb_log(0,"(By default: $sl)\n");
3421 my $sl2 = <STDIN>;
3422 $sl = $sl2 if ($sl2 !~ /^$/);
[490]3423
[1386]3424 # Prepare a template of announce
3425 open(ANN,"> $ENV{'PBTMP'}/announce.html") || die "Unable to create $ENV{'PBTMP'}/announce.html: $!";
3426 print ANN << "EOF";
[490]3427$sl</p>
[471]3428
[473]3429<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]3430<p>
3431Now available at <a href="$pbrepo->{$ENV{'PBPROJ'}}">$pbrepo->{$ENV{'PBPROJ'}}</a>
3432</p>
3433<p>
3434EOF
[1386]3435 }
3436
[1137]3437 open(LOG,"$ENV{'PBTMP'}/system.$$.log") || die "Unable to read $ENV{'PBTMP'}/system.$$.log: $!";
[1386]3438 if ($antype eq "Announce") {
3439 my $col = 2;
3440 my $i = 1;
3441 print ANN << 'EOF';
[1440]3442<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0">
[473]3443<TR>
3444EOF
[1386]3445 while (<LOG>) {
3446 print ANN "<TD><A HREF=\"$pbrepo->{$ENV{'PBPROJ'}}/$_\">$_</A></TD>";
3447 $i++;
3448 if ($i > $col) {
3449 print ANN "</TR>\n<TR>";
3450 $i = 1;
3451 }
[473]3452 }
[1393]3453 } elsif ($antype eq "Clean") {
3454 while (<LOG>) {
3455 # skip errors
3456 next if ($_ !~ /^removed /);
3457 pb_log(0,"$_");
3458 }
[1386]3459 } else {
3460 # In Check mode we need to compare the 2 lists (real and theoritical)
3461 while (<LOG>) {
3462 # Get package name and remove what is in extra for the theoritical list (arch at the end)
3463 chomp();
3464 # skip find errors
3465 next if (/^find:/);
3466 my $p = $_;
3467 $p =~ s/\.(i[3456]86|x86_64|noarch|src)\.rpm$//;
3468 $p =~ s/_(i[3456]86|amd64|all).deb$//;
[1424]3469 $p =~ s/(-0\.[0-9]{8})[0-9]{6}/$1*/ if ((defined $testver) && (defined $testver->{$ENV{'PBPROJ'}}) && ($testver->{$ENV{'PBPROJ'}} =~ /true/i));
3470 $p =~ s/(-r|_p[0-9]+)\.ebuild/$1*/ if ((defined $testver) && (defined $testver->{$ENV{'PBPROJ'}}) && ($testver->{$ENV{'PBPROJ'}} =~ /true/i));
[1386]3471 $theorlist{$p} = -2 if (not defined $theorlist{$p});
3472 $theorlist{$p} = $theorlist{$p} + 1;
3473 }
3474 pb_log(2,"theorlist : ".Dumper(%theorlist)."\n");
[471]3475 }
3476 close(LOG);
[1386]3477
[1393]3478 # Nothing more for the cleanssh case
3479 return if ($antype eq "Clean");
3480
[1386]3481 if ($antype eq "Check") {
3482 my ($chkex) = pb_conf_get_if("checkexclude");
3483 my $vmbuildlist = "";
3484 my $vebuildlist = "";
3485 my $rmbuildlist = "";
3486 my @pt = pb_conf_get_if("vmlist","velist","rmlist");
3487 foreach my $t (sort keys %theorlist) {
3488 if (defined $theorlist{$t} and $theorlist{$t} >= 1) {
3489 pb_log(1,"Packages found for $t\n");
3490 } elsif (defined $theorlist{$t} and $theorlist{$t} < 0) {
3491 pb_log(0,"Extra Package found for $t\n");
3492 } else {
[1420]3493 pb_log(2,"Analyzing $t\n");
[1386]3494 my ($os,$ver,$arch,$package) = split(/\//,$t);
3495 # Some distro have no arch subdir
3496 if (not defined $package) {
3497 $package = $arch;
3498 # TODO: If both arch have failed, we just make the last one
3499 $arch = $archlist{$t};
3500 }
3501 my $pbos = pb_distro_get_context("$os-$ver-$arch");
3502 my $pkgn = $package;
3503 if ($pbos->{'type'} ne "deb") {
3504 # package name is more easily found from the end for non deb
3505 # as '-' is the separator, but it can also be used in names
3506 $pkgn = reverse($package);
3507 # search the second '-' and isolate the now last part which is the full name
3508 $pkgn =~ s/([^-]+)-([^-]+)-([\S])+$/$3/;
3509 } else {
3510 $pkgn =~ s/([^_]+)_([\S])+$/$2/;
3511 }
3512 my $found = 0;
3513 # Handle the exclusion of OSes
3514 my $excl = "";
3515 $excl .= $chkex->{$pkgn} if (defined $chkex->{$pkgn});
3516 $excl .= $chkex->{"all"} if (defined $chkex->{"all"});
3517 foreach my $ex (split(/,/,$excl)) {
3518 $found = 1 if ("$os-$ver-$arch" =~ /^$ex/);
3519 }
3520 # Skip as excluded
3521 next if ($found == 1);
[1388]3522 pb_log(0,"Package NOT found for $t\n");
3523 # Avoid duplicates in list
[1386]3524 next if ($vmbuildlist =~ /$os-$ver-$arch/);
3525 next if ($vebuildlist =~ /$os-$ver-$arch/);
3526 next if ($rmbuildlist =~ /$os-$ver-$arch/);
3527 # check with which method we need to build
3528 if ((defined $pt[0]->{$ENV{'PBPROJ'}}) and ($pt[0]->{$ENV{'PBPROJ'}} =~ /$os-$ver-$arch/)) {
3529 $vmbuildlist = "$os-$ver-$arch" if ($vmbuildlist eq "");
[1388]3530 $vmbuildlist .= ",$os-$ver-$arch" if ($vmbuildlist !~ /$os-$ver-$arch/);
3531 next;
[1386]3532 }
3533 if ((defined $pt[1]->{$ENV{'PBPROJ'}}) and ($pt[1]->{$ENV{'PBPROJ'}} =~ /$os-$ver-$arch/)) {
3534 $vebuildlist = "$os-$ver-$arch" if ($vebuildlist eq "");
[1388]3535 $vebuildlist .= ",$os-$ver-$arch" if ($vebuildlist !~ /$os-$ver-$arch/);
3536 next;
[1386]3537 }
3538 if ((defined $pt[2]->{$ENV{'PBPROJ'}}) and ($pt[2]->{$ENV{'PBPROJ'}} =~ /$os-$ver-$arch/)) {
3539 $rmbuildlist = "$os-$ver-$arch" if ($rmbuildlist eq "");
[1388]3540 $rmbuildlist .= ",$os-$ver-$arch" if ($rmbuildlist !~ /$os-$ver-$arch/);
[1386]3541 }
3542 }
3543 }
3544 # If we want to rebuild automatically, let's do it
3545 if (defined $opts{'rebuild'}) {
3546 # SandBox or CMS
3547 pb_log(0,"Rebuilding from SandBox\n");
3548 pb_log(0,"for VMs: $vmbuildlist\n") if ($vmbuildlist ne "");
3549 pb_log(0,"for VEs: $vebuildlist\n") if ($vebuildlist ne "");
3550 pb_log(0,"for RMs: $rmbuildlist\n") if ($rmbuildlist ne "");
3551 pb_cms2build("SandBox");
3552 # Which mode
3553 $ENV{'PBV'} = $vmbuildlist;
3554 pb_build2v("vm","build") if ($vmbuildlist ne "");
3555 $ENV{'PBV'} = $vebuildlist;
3556 pb_build2v("ve","build") if ($vebuildlist ne "");
3557 $ENV{'PBV'} = $rmbuildlist;
3558 pb_build2v("rm","build") if ($rmbuildlist ne "");
3559 }
3560 # For the check part this is now finished
3561 return;
3562 }
3563
[473]3564 print ANN << "EOF";
3565</TR>
3566</TABLE>
3567</p>
[471]3568
[473]3569<p>As usual source packages are also available in the same directory.</p>
3570
3571<p>
3572Changes are :
3573</p>
3574<p>
3575EOF
3576 # Get each package changelog content
3577 foreach my $f (sort(@files)) {
3578 open(IN,"$f") || die "Unable to read $f:$!";
3579 while (<IN>) {
3580 print ANN $_;
3581 }
3582 close(IN);
3583 print ANN "</p><p>\n";
3584 }
3585 print ANN "</p>\n";
[471]3586 close(ANN);
[473]3587
3588 # Allow for modification
[974]3589 my $editor = "vi";
3590 $editor = $ENV{'EDITOR'} if (defined $ENV{'EDITOR'});
3591 pb_system("$editor $ENV{'PBTMP'}/announce.html","Allowing modification of the announce","noredir");
[473]3592
3593 # Store it in DB for external usage (Web pages generation)
3594 my $db = "$ENV{'PBCONFDIR'}/announces3.sql";
3595
3596 my $precmd = "";
3597 if (! -f $db) {
3598 $precmd = "CREATE TABLE announces (id INTEGER PRIMARY KEY AUTOINCREMENT, date DATE, announce VARCHAR[65535])";
3599 }
3600
3601 my $dbh = DBI->connect("dbi:SQLite:dbname=$db","","",
3602 { RaiseError => 1, AutoCommit => 1 })
3603 || die "Unable to connect to $db";
3604
3605 if ($precmd ne "") {
3606 my $sth = $dbh->prepare(qq{$precmd})
3607 || die "Unable to create table into $db";
3608 $sth->execute();
3609 }
3610
3611 # To read whole file
3612 local $/;
3613 open(ANN,"$ENV{'PBTMP'}/announce.html") || die "Unable to read $ENV{'PBTMP'}/announce.html: $!";
3614 my $announce = <ANN>;
3615 close(ANN);
3616
3617 pb_log(2,"INSERT INTO announces VALUES (NULL, $pbdate, $announce)");
3618 my $sth = $dbh->prepare(qq{INSERT INTO announces VALUES (NULL,?,?)})
3619 || die "Unable to insert into $db";
3620 $sth->execute($pbdate, $announce);
[698]3621 $sth->finish();
[473]3622 $dbh->disconnect;
3623
3624 # Then deliver it on the Web
3625 # $TOOLHOME/livwww www
3626
3627 # Mail it to project's ML
3628 open(ML,"| w3m -dump -T text/html > $ENV{'PBTMP'}/announce.txt") || die "Unable to create $ENV{'PBTMP'}/announce.txt: $!";
3629 print ML << 'EOF';
3630<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/x html1/DTD/xhtml1-strict.dtd">
3631
3632<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" xml:lang="en" lang="en">
3633 <head>
3634 </head>
3635 <body>
3636 <p>
3637EOF
3638 open(ANN,"$ENV{'PBTMP'}/announce.html") || die "Unable to read $ENV{'PBTMP'}/announce.html: $!";
3639 while(<ANN>) {
3640 print ML $_;
3641 }
3642 print ML << 'EOF';
3643</body>
3644</html>
3645EOF
3646 close(ML);
3647
[477]3648 # To read whole file
3649 local $/;
3650 open(ANN,"$ENV{'PBTMP'}/announce.txt") || die "Unable to read $ENV{'PBTMP'}/announce.txt: $!";
3651 my $msg = <ANN>;
3652 close(ANN);
3653
3654 # Preparation of headers
[1134]3655 eval
3656 {
3657 require Mail::Sendmail;
3658 Mail::Sendmail->import();
3659 };
3660 if ($@) {
3661 # Mail::Sendmail not found not sending mail !
3662 pb_log(0,"No Mail::Sendmail module found so not sending any mail !\n");
3663 } else {
3664 my %mail = (
[477]3665 To => $pbml->{$ENV{'PBPROJ'}},
3666 From => $pbpackager->{$ENV{'PBPROJ'}},
3667 Smtp => $pbsmtp->{$ENV{'PBPROJ'}},
3668 Body => $msg,
[490]3669 Subject => "[ANNOUNCE] $sl",
[477]3670 );
3671
[1134]3672 # Send mail
3673 if (! sendmail(%mail)) {
3674 if ((defined $Mail::Sendmail::error) and (defined $Mail::Sendmail::log)) {
3675 die "Unable to send mail ($Mail::Sendmail::error): $Mail::Sendmail::log";
3676 }
[1109]3677 }
3678 }
[471]3679}
3680
[547]3681#
3682# Creates a set of HTML file containing the news for the project
3683# based on what has been generated by the pb_announce function
3684#
3685sub pb_web_news2html {
3686
[556]3687 my $dest = shift || $ENV{'PBTMP'};
3688
[547]3689 # Get all required parameters
[1064]3690 my ($pkgv, $pkgt) = pb_conf_get_if("pkgver","pkgtag");
[547]3691
3692 # DB of announces for external usage (Web pages generation)
3693 my $db = "$ENV{'PBCONFDIR'}/announces3.sql";
3694
3695 my $dbh = DBI->connect("dbi:SQLite:dbname=$db","","",
3696 { RaiseError => 1, AutoCommit => 1 })
3697 || die "Unable to connect to $db";
3698 # For date handling
3699 $ENV{LANGUAGE}="C";
[559]3700 my $firstjan = strftime("%Y-%m-%d", 0, 0, 0, 1, 0, localtime->year(), 0, 0, -1);
3701 my $oldfirst = strftime("%Y-%m-%d", 0, 0, 0, 1, 0, localtime->year()-1, 0, 0, -1);
3702 pb_log(2,"firstjan: $firstjan, oldfirst: $oldfirst, pbdate:$pbdate\n");
[547]3703 my $all = $dbh->selectall_arrayref("SELECT id,date,announce FROM announces ORDER BY date DESC");
[556]3704 my %news;
3705 $news{"cy"} = ""; # current year's news
3706 $news{"ly"} = ""; # last year news
3707 $news{"py"} = ""; # previous years news
3708 $news{"fp"} = ""; # first page news
[547]3709 my $cpt = 4; # how many news for first page
3710 # Extract info from DB
3711 foreach my $row (@$all) {
3712 my ($id, $date, $announce) = @$row;
[559]3713 $news{"cy"} = $news{"cy"}."<p><B>$date</B> $announce\n" if ((($date cmp $pbdate) le 0) && (($firstjan cmp $date) le 0));
3714 $news{"ly"} = $news{"ly"}."<p><B>$date</B> $announce\n" if ((($date cmp $firstjan) le 0) && (($oldfirst cmp $date) le 0));
3715 $news{"py"} = $news{"py"}."<p><B>$date</B> $announce\n" if (($date cmp $oldfirst) le 0);
[556]3716 $news{"fp"} = $news{"fp"}."<p><B>$date</B> $announce\n" if ($cpt > 0);
[547]3717 $cpt--;
3718 }
[556]3719 pb_log(1,"news{fp}: ".$news{"fp"}."\n");
[547]3720 $dbh->disconnect;
[556]3721
3722 # Generate the HTML content
3723 foreach my $pref (keys %news) {
3724 open(NEWS,"> $dest/pb_web_$pref"."news.html") || die "Unable to create $dest/pb_web_$pref"."news.html: $!";
3725 print NEWS "$news{$pref}";
3726 close(NEWS);
3727 }
[547]3728}
3729
[556]3730
[347]3731# Return the SSH key file to use
3732# Potentially create it if needed
3733
3734sub pb_ssh_get {
3735
3736my $create = shift || 0; # Do not create keys by default
3737
3738# Check the SSH environment
3739my $keyfile = undef;
3740
3741# We have specific keys by default
3742$keyfile = "$ENV{'HOME'}/.ssh/pb_dsa";
[348]3743if (!(-e $keyfile) && ($create eq 1)) {
[347]3744 pb_system("ssh-keygen -q -b 1024 -N '' -f $keyfile -t dsa","Generating SSH keys for pb");
3745}
3746
3747$keyfile = "$ENV{'HOME'}/.ssh/id_rsa" if (-s "$ENV{'HOME'}/.ssh/id_rsa");
3748$keyfile = "$ENV{'HOME'}/.ssh/id_dsa" if (-s "$ENV{'HOME'}/.ssh/id_dsa");
3749$keyfile = "$ENV{'HOME'}/.ssh/pb_dsa" if (-s "$ENV{'HOME'}/.ssh/pb_dsa");
3750die "Unable to find your public ssh key under $keyfile" if (not defined $keyfile);
3751return($keyfile);
3752}
3753
3754
[145]3755# Returns the pid of a running VM command using a specific VM file
[142]3756sub pb_check_ps {
3757 my $vmcmd = shift;
3758 my $vmm = shift;
3759 my $vmexist = 0; # FALSE by default
3760
3761 open(PS, "ps auxhww|") || die "Unable to call ps";
3762 while (<PS>) {
3763 next if (! /$vmcmd/);
3764 next if (! /$vmm/);
3765 my ($void1, $void2);
3766 ($void1, $vmexist, $void2) = split(/ +/);
3767 last;
3768 }
3769 return($vmexist);
3770}
3771
3772
[77]3773sub pb_extract_build_files {
[25]3774
3775my $src=shift;
3776my $dir=shift;
[26]3777my $ddir=shift;
[500]3778my $mandatory=shift || "spec";
[28]3779my @files;
[25]3780
[1219]3781my $flag = "mayfail" if (($mandatory eq "patch") || ($mandatory eq "src"));
[500]3782my $res;
3783
[188]3784if ($src =~ /tar\.gz$/) {
[500]3785 $res = pb_system("tar xfpz $src $dir","Extracting $mandatory files from $src",$flag);
[188]3786} elsif ($src =~ /tar\.bz2$/) {
[500]3787 $res = pb_system("tar xfpj $src $dir","Extracting $mandatory files from $src",$flag);
[188]3788} else {
3789 die "Unknown compression algorithm for $src";
3790}
[500]3791# If not mandatory return now
[1220]3792return() if (($res != 0) and (($mandatory eq "patch") || ($mandatory eq "src")));
[1486]3793opendir(DIR,"$dir") || die "Unable to open directory $dir: $!";
[25]3794foreach my $f (readdir(DIR)) {
3795 next if ($f =~ /^\./);
[500]3796 # Skip potential patch dir
3797 next if ($f =~ /^pbpatch/);
[1219]3798 # Skip potential source dir
3799 next if ($f =~ /^pbsrc/);
[1480]3800 # Skip potential backup files
3801 next if ($f =~ /~$/);
[26]3802 move("$dir/$f","$ddir") || die "Unable to move $dir/$f to $ddir";
[315]3803 pb_log(2,"mv $dir/$f $ddir\n");
[28]3804 push @files,"$ddir/$f";
[25]3805}
3806closedir(DIR);
[26]3807# Not enough but still a first cleanup
[74]3808pb_rm_rf("$dir");
[28]3809return(@files);
[25]3810}
3811
[315]3812sub pb_list_bfiles {
3813
3814my $dir = shift;
3815my $pbpkg = shift;
3816my $bfiles = shift;
3817my $pkgfiles = shift;
3818my $supfiles = shift;
[1363]3819# subdir to keep if recursive mode, empty by default
3820my $subdir = shift || "";
[1367]3821# In a recursive function , we need a local var as DIR handle
3822my $bdir;
[315]3823
[1363]3824pb_log(2,"DEBUG: entering pb_list_bfiles in $dir: ".Dumper($bfiles)."\n");
[1367]3825opendir($bdir,"$dir") || die "Unable to open dir $dir: $!";
3826foreach my $f (readdir($bdir)) {
[1363]3827 pb_log(3,"DEBUG: pb_list_bfiles found $f\n");
[315]3828 next if ($f =~ /^\./);
[1363]3829 if (-d "$dir/$f") {
[1098]3830 # Recurse for directories (Debian 3.0 format e.g.)
[1363]3831 pb_log(2,"DEBUG: pb_list_bfiles recurse in $dir/$f\n");
3832 pb_list_bfiles("$dir/$f",$pbpkg,$bfiles,$pkgfiles,$supfiles,$f);
[1098]3833 next;
3834 }
[1363]3835
3836 my $key = $f;
3837 # if recursive then store also the subdir
3838 $key = "$subdir/$f" if ($subdir ne "");
3839 $bfiles->{$key} = "$dir/$f";
3840 $bfiles->{$key} =~ s~$ENV{'PBROOTDIR'}~~;
[315]3841 if (defined $supfiles->{$pbpkg}) {
[1363]3842 $pkgfiles->{$key} = "$dir/$f" if ($f =~ /$supfiles->{$pbpkg}/);
[315]3843 }
3844}
[1367]3845closedir($bdir);
[1185]3846pb_log(2,"DEBUG: exiting pb_list_bfiles: ".Dumper($bfiles)."\n");
[315]3847}
3848
[1185]3849sub pb_add_coma {
3850
3851my $str = shift;
3852my $addstr = shift;
3853
3854$str .= "," if (defined $str);
3855$str .= $addstr;
3856return($str);
3857}
3858
[1130]3859sub pb_list_sfiles {
[395]3860
[1130]3861my $sdir = shift;
[1185]3862my $ptr = shift;
[1177]3863my $pbos = shift;
[1130]3864my $extdir = shift;
3865
[1185]3866pb_log(2,"DEBUG: entering pb_list_sfiles: ".Dumper($ptr)."\n");
3867my $key = "$pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}";
3868
[1130]3869# Prepare local sources for this distro - They are always applied first - May be a problem one day
3870# This function works for both patches and additional sources
3871foreach my $p (sort(<$sdir/*>)) {
[1185]3872 $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]3873}
3874
3875# Prepare also remote sources to be included - Applied after the local ones
[1185]3876foreach my $p ("all","$pbos->{'os'}","$pbos->{'type'}","$pbos->{'family'}","$pbos->{'name'}","$pbos->{'name'}-$pbos->{'version'}","$pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}") {
[1130]3877 my $f = "$extdir.".".$p";
3878 next if (not -f $f);
3879 if (not open(PATCH,$f)) {
3880 pb_display("Unable to open existing external source file content $f\n");
3881 next;
3882 }
3883 while (<PATCH>) {
3884 chomp();
[1185]3885 $ptr->{$key} = pb_add_coma($ptr->{$key},"$_");
[1130]3886 }
3887 close(PATCH);
3888}
[1185]3889pb_log(2,"DEBUG: exiting pb_list_sfiles: ".Dumper($ptr)."\n");
[1186]3890return($ptr);
[1130]3891}
3892
[395]3893#
3894# Return the list of packages we are working on in a non CMS action
3895#
3896sub pb_get_pkg {
3897
3898my @pkgs = ();
3899
3900my ($var) = pb_conf_read("$ENV{'PBDESTDIR'}/$ENV{'PBPROJVER'}-$ENV{'PBPROJTAG'}.pb","pbpkg");
3901@pkgs = keys %$var;
3902
3903pb_log(0,"Packages: ".join(',',@pkgs)."\n");
3904return(\@pkgs);
3905}
3906
[1176]3907# Manages VM/RM SSH port communication
[1143]3908sub pb_get_port {
3909
3910my $port = shift;
[1179]3911my $pbos = shift;
[1143]3912my $cmt = shift;
[1179]3913my $nport;
[1143]3914
3915die "No port passed in parameter. Report to dev team\n" if (not defined $port);
[1179]3916# key is project on VM, but machine tuple for RM
3917if ($cmt =~ /^RM/i) {
3918 $nport = $port->{"$pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}"};
3919} else {
3920 $nport = $port->{$ENV{'PBPROJ'}};
3921}
3922pb_log(2,"pb_get_port with $nport\n");
[1143]3923# Maybe a port was given as parameter so overwrite
3924$nport = "$pbport" if (defined $pbport);
[1268]3925# 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]3926if (($cmt ne "Packages") && ($cmt !~ /^RM/i)) {
[1143]3927 $nport += $ENV{'PBVMPORT'} if ((defined $pbparallel) && (defined $ENV{'PBVMPORT'}));
3928}
[1146]3929pb_log(2,"pb_get_port returns $nport\n");
[1143]3930return($nport);
3931}
3932
3933sub pb_set_port {
3934
3935my ($pid,$ident) = @_;
[1146]3936pb_log(2,"pb_set_port for VM ($pid), id $ident\n");
[1143]3937$ENV{'PBVMPORT'} = $ident;
[1146]3938pb_log(2,"pb_set_port sets PBVMPORT in env to $ENV{'PBVMPORT'}\n");
[1143]3939}
3940
3941sub pb_set_parallel {
3942
3943my $vtype = shift;
3944
[1146]3945pb_log(2,"pb_set_parallel vtype: $vtype\n");
[1143]3946# Take care of memory size if VM, parallel mode and more than 1 action
3947if ((defined $pbparallel) && ($pbparallel ne 1) && ($vtype eq "vm")) {
3948 eval
3949 {
3950 require Linux::SysInfo;
3951 Linux::SysInfo->import();
3952 };
3953 if ($@) {
[1153]3954 # Linux::SysInfo not found
[1388]3955 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]3956 } else {
3957 # Using the memory size
3958 my $si = Linux::SysInfo::sysinfo();
3959 if (not defined $si) {
[1388]3960 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]3961 } else {
3962 # Keep the number of VM whose memory can be allocated
3963 my $ram = $si->{"totalram"}-$si->{"sharedram"}-$si->{"bufferram"};
3964 my $ram2;
[1153]3965 my ($vmmem) = pb_conf_get_if("vmmem");
[1146]3966
[1153]3967 my $v = "default";
3968 if ((defined $vmmem) and (defined $vmmem->{$v})) {
3969 $ram2 = $vmmem->{$v};
[1143]3970 } else {
3971 # Default for KVM/QEMU
3972 $ram2 = 128;
3973 }
3974 $pbparallel = sprintf("%d",$ram/$ram2);
3975 }
[1153]3976 pb_log(1,"Using $pbparallel processes at a time\n");
[1143]3977 }
3978}
[1176]3979pb_log(2,"pb_set_parallel returns: $pbparallel\n") if (defined $pbparallel);
[1143]3980return($pbparallel);
3981}
3982
[1179]3983sub pb_get_sudocmds {
3984
3985my $pbos = shift;
[1190]3986my %sudocmds;
[1143]3987
[1198]3988pb_log(2,"pb_get_sudocmds entering with lines:".Dumper(@_)."\n");
3989foreach my $c (split(/;/,$pbos->{'update'}),split(/;/,$pbos->{'install'}),@_) {
3990 pb_log(2,"pb_get_sudocmds analyses $c\n");
3991 next if ($c !~ /^\s*sudo/);
3992 # remove sudo and leading spaces
3993 $c =~ s/^\s*sudo\s+//;
[1192]3994 # keep only the command, not the params
3995 $c =~ s/([^\s]+)\s.*$/$1/;
[1190]3996 $sudocmds{$c} = "";
[1179]3997}
[1198]3998pb_log(2,"pb_get_sudocmds returns ".Dumper(keys %sudocmds)."\n");
[1190]3999return(keys %sudocmds);
[1179]4000}
4001
[1278]4002sub pb_sign_pkgs {
[1179]4003
[1278]4004my $pbos = shift;
4005my $made = shift;
4006
4007pb_log(2,"entering pb_sign_pkg: $made ".Dumper($pbos)."\n");
4008my ($passfile, $passphrase, $passpath) = pb_conf_get_if("pbpassfile","pbpassphrase","pbpasspath");
4009$ENV{'PBPASSPHRASE'} = $passphrase->{$ENV{'PBPROJ'}} if ((not defined $ENV{'PBPASSPHRASE'}) && (defined $passphrase->{$ENV{'PBPROJ'}}));
4010$ENV{'PBPASSFILE'} = $passfile->{$ENV{'PBPROJ'}} if ((not defined $ENV{'PBPASSFILE'})&& (defined $passfile->{$ENV{'PBPROJ'}})) ;
4011$ENV{'PBPASSPATH'} = $passpath->{$ENV{'PBPROJ'}} if ((not defined $ENV{'PBPASSPATH'})&& (defined $passpath->{$ENV{'PBPROJ'}})) ;
4012
[1279]4013# Remove extra spaces
4014$made =~ s/\s+/ /g;
4015$made =~ s/^\s//g;
4016$made =~ s/\s$//g;
4017
[1278]4018if ($pbos->{'type'} eq "rpm") {
4019 eval
4020 {
4021 require RPM4::Sign;
4022 RPM4::Sign->import();
4023 };
4024 if ($@) {
4025 # RPM4::Sign not found
4026 pb_log(1,"WARNING: Install RPM4::Sign to benefit from automatic package signing.\n");
4027 } else {
4028 return if ((not defined $ENV{'PBPASSPHRASE'}) and (not defined $ENV{'PBPASSFILE'}));
4029 my $sign = RPM4::Sign->new(
4030 passphrase => $ENV{'PBPASSPHRASE'},
4031 name => $ENV{'PBPACKAGER'},
4032 path => $ENV{'PBPASSPATH'},
4033 password_file => $ENV{'PBPASSFILE'},
4034 );
4035
4036 pb_log(0,"Signing RPM packages...\n");
4037 pb_log(2,"pb_sign_pkg: pkgs:".Dumper(split(/ /,$made))."\n");
4038 $sign->rpmssign(split(/ /,$made));
4039 }
4040} elsif ($pbos->{'type'} eq "deb") {
[1279]4041 my $changes = "";
4042 foreach my $c (split(/ /,$made)) {
4043 $changes .= " $ENV{'PBBUILDDIR'}/$c" if ($c =~ /\.changes$/);
4044 }
[1386]4045 my $debsigncmd = pb_check_req("debsign",1);
4046 pb_system("$debsigncmd -m\'$ENV{'PBPACKAGER'}\' $changes","Signing DEB packages");
[1278]4047} else {
4048 pb_log(0,"I don't know yet how to sign packages for type $pbos->{'type'}.\nPlease give feedback to dev team\n");
[1279]4049}
[1278]4050pb_log(2,"exiting pb_sign_pkg\n");
4051}
4052
[1282]4053# return list of all distributins supported, coma separated
4054sub pb_get_distros {
4055
4056my $pbos = shift;
4057my $pbtarget = shift;
4058
4059my $tmpl = "$pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'},";
4060
4061# Get list of distributions for which we need to generate build files if no target
[1402]4062if (not defined $pbtarget) {
[1282]4063 my @pt = pb_conf_get_if("vmlist","velist","rmlist");
4064 if (defined $pt[0]->{$ENV{'PBPROJ'}}) {
4065 $tmpl .= $pt[0]->{$ENV{'PBPROJ'}};
4066 }
4067 if (defined $pt[1]->{$ENV{'PBPROJ'}}) {
[1386]4068 # The 2 lists need to be grouped with a ',' separating them
[1282]4069 if ($tmpl ne "") {
4070 $tmpl .= ",";
4071 }
4072 $tmpl .= $pt[1]->{$ENV{'PBPROJ'}}
4073 }
4074 if (defined $pt[2]->{$ENV{'PBPROJ'}}) {
4075 # The lists needs to be grouped with a ',' separating them
4076 if ($tmpl ne "") {
4077 $tmpl .= ",";
4078 }
4079 $tmpl .= $pt[2]->{$ENV{'PBPROJ'}}
4080 }
4081}
4082return($tmpl);
4083}
4084
[1432]4085sub pb_get_extdir () {
4086
4087 # the pbrc file should contain it and whatever the key, we take it
4088 my ($ed) = pb_conf_read("$ENV{'PBDESTDIR'}/pbrc","pbextdir");
4089 pb_log(2,"ed: ".Dumper($ed)."\n");
4090 my $pbextdir = "";
4091 foreach my $k (keys %$ed) {
4092 $pbextdir = $ed->{$k};
[1459]4093 # In case we have an empty field, empty it completely
4094 pb_log(2,"pbextdir: ***$pbextdir***\n");
4095 $pbextdir =~ s/^\s*$//;
[1432]4096 }
[1459]4097 pb_log(2,"pbextdir: ***$pbextdir***\n");
[1432]4098 return($pbextdir);
4099}
4100
[395]41011;
Note: See TracBrowser for help on using the repository browser.