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

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