1 | #!/usr/bin/perl -w
|
---|
2 | #
|
---|
3 | # Common functions for virtual environment
|
---|
4 | #
|
---|
5 | # Copyright B. Cornec 2007-2012
|
---|
6 | # Eric Anderson's changes are (c) Copyright 2012 Hewlett Packard
|
---|
7 | # Provided under the GPL v2
|
---|
8 | #
|
---|
9 | # $Id$
|
---|
10 | #
|
---|
11 |
|
---|
12 | package ProjectBuilder::VE;
|
---|
13 |
|
---|
14 | use strict;
|
---|
15 | use Data::Dumper;
|
---|
16 | use Carp 'confess';
|
---|
17 | use English;
|
---|
18 | use ProjectBuilder::Version;
|
---|
19 | use ProjectBuilder::Base;
|
---|
20 | use ProjectBuilder::Conf;
|
---|
21 | use ProjectBuilder::Distribution;
|
---|
22 |
|
---|
23 | # Global vars
|
---|
24 | # Inherit from the "Exporter" module which handles exporting functions.
|
---|
25 |
|
---|
26 | use vars qw($VERSION $REVISION @ISA @EXPORT);
|
---|
27 | use Exporter;
|
---|
28 |
|
---|
29 | # Export, by default, all the functions into the namespace of
|
---|
30 | # any code which uses this module.
|
---|
31 |
|
---|
32 | our @ISA = qw(Exporter);
|
---|
33 | our @EXPORT = qw(pb_ve_launch);
|
---|
34 |
|
---|
35 | ($VERSION,$REVISION) = pb_version_init();
|
---|
36 |
|
---|
37 | =pod
|
---|
38 |
|
---|
39 | =head1 NAME
|
---|
40 |
|
---|
41 | ProjectBuilder::VE, part of the project-builder.org - module dealing with Virtual Environment
|
---|
42 |
|
---|
43 | =head1 DESCRIPTION
|
---|
44 |
|
---|
45 | This modules provides functions to deal with Virtual Environements (VE), aka chroot.
|
---|
46 |
|
---|
47 | =head1 SYNOPSIS
|
---|
48 |
|
---|
49 | use ProjectBuilder::VE;
|
---|
50 |
|
---|
51 | #
|
---|
52 | # Return information on the running distro
|
---|
53 | #
|
---|
54 | my $pbos = pb_ve_launch();
|
---|
55 |
|
---|
56 | =head1 USAGE
|
---|
57 |
|
---|
58 | =over 4
|
---|
59 |
|
---|
60 | =item B<pb_ve_launch>
|
---|
61 |
|
---|
62 | This function launch a VE, creating it if necessary using multiple external potential tools.
|
---|
63 |
|
---|
64 | =cut
|
---|
65 |
|
---|
66 | sub pb_ve_launch {
|
---|
67 |
|
---|
68 | my $v = shift || undef;
|
---|
69 | my $pbforce = shift || 0; # By default do not rebuild VE
|
---|
70 | my $locsnap = shift || 0; # By default do not snap VE
|
---|
71 |
|
---|
72 | # Get distro context
|
---|
73 | my $pbos = pb_distro_get_context($v);
|
---|
74 |
|
---|
75 | # Get VE context
|
---|
76 | my ($ptr,$vepath) = pb_conf_get("vetype","vepath");
|
---|
77 | my $vetype = $ptr->{$ENV{'PBPROJ'}};
|
---|
78 |
|
---|
79 | confess "No vetype defined for $ENV{PBPROJ}" unless (defined $vetype);
|
---|
80 | pb_log(1, "Using vetype $vetype for $ENV{PBPROJ}\n");
|
---|
81 |
|
---|
82 | if (($vetype eq "chroot") || ($vetype eq "schroot")) {
|
---|
83 |
|
---|
84 | # We need to avoid umask propagation to the VE
|
---|
85 | umask 0022;
|
---|
86 |
|
---|
87 | # We can probably only get those params now we have the distro context
|
---|
88 | my ($rbsb4pi,$rbspi,$vesnap,$oscodename,$osmindep,$verebuild,$rbsmirrorsrv) = pb_conf_get_if("rbsb4pi","rbspi","vesnap","oscodename","osmindep","verebuild","rbsmirrorsrv");
|
---|
89 |
|
---|
90 | # Architecture consistency
|
---|
91 | my $arch = pb_get_arch();
|
---|
92 | if ($arch ne $pbos->{'arch'}) {
|
---|
93 | die "Unable to launch a VE of architecture $pbos->{'arch'} on a $arch platform" unless (($pbos->{'arch'} =~ /i?86/o) && ($arch eq "x86_64"));
|
---|
94 | }
|
---|
95 |
|
---|
96 | # If we are already root (from pbmkbm e.g.) don't use sudo, just call the command
|
---|
97 | my $sudocmd="";
|
---|
98 | if ($EFFECTIVE_USER_ID != 0) {
|
---|
99 | $sudocmd ="sudo ";
|
---|
100 | foreach my $proxy (qw/http_proxy ftp_proxy/) {
|
---|
101 | if (defined $ENV{$proxy}) {
|
---|
102 | open(CMD,"sudo sh -c 'echo \$$proxy' |") or die "can't run sudo sh?: $!";
|
---|
103 | $_ = <CMD>;
|
---|
104 | chomp();
|
---|
105 | die "sudo not passing through env var $proxy; '$ENV{$proxy}' != '$_'\nAdd line Defaults:`whoami` env_keep += \"$proxy\" to sudoers file?" unless $_ eq $ENV{$proxy};
|
---|
106 | close(CMD);
|
---|
107 | }
|
---|
108 | }
|
---|
109 | }
|
---|
110 |
|
---|
111 | # Handle cross arch on Intel based platforms
|
---|
112 | $sudocmd = "setarch i386 $sudocmd" if (($pbos->{'arch'} =~ /i[3456]86/) && ($arch eq 'x86_64'));
|
---|
113 |
|
---|
114 | my $root = pb_path_expand($vepath->{$ENV{PBPROJ}});
|
---|
115 | if (((defined $verebuild) && ($verebuild->{$ENV{'PBPROJ'}} =~ /true/i)) || ($pbforce == 1)) {
|
---|
116 | my ($verpmtype,$vedebtype) = pb_conf_get("verpmtype","vedebtype");
|
---|
117 | my ($rbsopt1) = pb_conf_get_if("rbsopt");
|
---|
118 |
|
---|
119 | # We have to rebuild the chroot
|
---|
120 | if ($pbos->{'type'} eq "rpm") {
|
---|
121 |
|
---|
122 | # Which tool is used
|
---|
123 | my $verpmstyle = $verpmtype->{$ENV{'PBPROJ'}};
|
---|
124 | die "No verpmtype defined for $ENV{PBPROJ}" unless (defined $verpmstyle);
|
---|
125 |
|
---|
126 | # Get potential rbs option
|
---|
127 | my $rbsopt = "";
|
---|
128 | if (defined $rbsopt1) {
|
---|
129 | if (defined $rbsopt1->{$verpmstyle}) {
|
---|
130 | $rbsopt = $rbsopt1->{$verpmstyle};
|
---|
131 | } elsif (defined $rbsopt1->{$ENV{'PBPROJ'}}) {
|
---|
132 | $rbsopt = $rbsopt1->{$ENV{'PBPROJ'}};
|
---|
133 | } else {
|
---|
134 | $rbsopt = "";
|
---|
135 | }
|
---|
136 | }
|
---|
137 |
|
---|
138 | my $postinstall = pb_ve_get_postinstall($pbos,$rbspi,$verpmstyle);
|
---|
139 | if ($verpmstyle eq "rinse") {
|
---|
140 | # Need to reshape the mirrors generated with local before-post-install script
|
---|
141 | my $b4post = "--before-post-install ";
|
---|
142 | my $postparam = pb_distro_get_param($pbos,$rbsb4pi);
|
---|
143 | if ($postparam eq "") {
|
---|
144 | $b4post = "";
|
---|
145 | } else {
|
---|
146 | $b4post .= $postparam;
|
---|
147 | }
|
---|
148 |
|
---|
149 | # Need to reshape the package list for pb
|
---|
150 | my $addpkgs;
|
---|
151 | $postparam = "";
|
---|
152 | $postparam .= pb_distro_get_param($pbos,$osmindep);
|
---|
153 | if ($postparam eq "") {
|
---|
154 | $addpkgs = "";
|
---|
155 | } else {
|
---|
156 | my $pkgfile = "$ENV{'PBTMP'}/addpkgs.lis";
|
---|
157 | open(PKG,"> $pkgfile") || die "Unable to create $pkgfile";
|
---|
158 | foreach my $p (split(/,/,$postparam)) {
|
---|
159 | print PKG "$p\n";
|
---|
160 | }
|
---|
161 | close(PKG);
|
---|
162 | $addpkgs = "--add-pkg-list $pkgfile";
|
---|
163 | }
|
---|
164 |
|
---|
165 | my $rinseverb = "";
|
---|
166 | $rinseverb = "--verbose" if ($pbdebug gt 0);
|
---|
167 | my ($rbsconf) = pb_conf_get("rbsconf");
|
---|
168 |
|
---|
169 | my $command = pb_check_req("rinse",0);
|
---|
170 | pb_system("$sudocmd $command --directory \"$root/$pbos->{'name'}/$pbos->{'version'}/$pbos->{'arch'}\" --arch \"$pbos->{'arch'}\" --distribution \"$pbos->{'name'}-$pbos->{'version'}\" --config \"$rbsconf->{$ENV{'PBPROJ'}}\" $b4post $postinstall $rbsopt $addpkgs $rinseverb","Creating the rinse VE for $pbos->{'name'}-$pbos->{'version'} ($pbos->{'arch'})", "verbose");
|
---|
171 | } elsif ($verpmstyle eq "rpmbootstrap") {
|
---|
172 | my $rbsverb = "";
|
---|
173 | foreach my $i (1..$pbdebug) {
|
---|
174 | $rbsverb .= " -v";
|
---|
175 | }
|
---|
176 | my $addpkgs = "";
|
---|
177 | my $postparam = "";
|
---|
178 | $postparam .= pb_distro_get_param($pbos,$osmindep);
|
---|
179 | if ($postparam eq "") {
|
---|
180 | $addpkgs = "";
|
---|
181 | } else {
|
---|
182 | $addpkgs = "-a $postparam";
|
---|
183 | }
|
---|
184 | my $command = pb_check_req("rpmbootstrap",0);
|
---|
185 | pb_system("$sudocmd $command $rbsopt $postinstall $addpkgs $pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'} $rbsverb","Creating the rpmbootstrap VE for $pbos->{'name'}-$pbos->{'version'} ($pbos->{'arch'})", "verbose");
|
---|
186 | pb_system("$sudocmd /bin/umount $root/$pbos->{'name'}/$pbos->{'version'}/$pbos->{'arch'}/proc","Umounting stale /proc","mayfail") if (-f "$root/$pbos->{'name'}/$pbos->{'version'}/$pbos->{'arch'}/proc/cpuinfo");
|
---|
187 | } elsif ($verpmstyle eq "mock") {
|
---|
188 | my ($rbsconf) = pb_conf_get("rbsconf");
|
---|
189 | my $command = pb_check_req("mock",0);
|
---|
190 | pb_system("$sudocmd $command --init --resultdir=\"/tmp\" --configdir=\"$rbsconf->{$ENV{'PBPROJ'}}\" -r $v $rbsopt","Creating the mock VE for $pbos->{'name'}-$pbos->{'version'} ($pbos->{'arch'})");
|
---|
191 | # Once setup we need to install some packages, the pb account, ...
|
---|
192 | pb_system("$sudocmd $command --install --configdir=\"$rbsconf->{$ENV{'PBPROJ'}}\" -r $v su","Configuring the mock VE");
|
---|
193 | } else {
|
---|
194 | die "Unknown verpmtype type $verpmstyle. Report to dev team";
|
---|
195 | }
|
---|
196 | } elsif ($pbos->{'type'} eq "deb") {
|
---|
197 | my $vedebstyle = $vedebtype->{$ENV{'PBPROJ'}};
|
---|
198 |
|
---|
199 | my $codename = pb_distro_get_param($pbos,$oscodename);
|
---|
200 | my $postparam = "";
|
---|
201 | my $addpkgs;
|
---|
202 | $postparam .= pb_distro_get_param($pbos,$osmindep);
|
---|
203 | if ($postparam eq "") {
|
---|
204 | $addpkgs = "";
|
---|
205 | } else {
|
---|
206 | $addpkgs = "--include $postparam";
|
---|
207 | }
|
---|
208 | my $debmir = "";
|
---|
209 | $debmir .= pb_distro_get_param($pbos,$rbsmirrorsrv);
|
---|
210 |
|
---|
211 | # Get potential rbs option
|
---|
212 | my $rbsopt = "";
|
---|
213 | if (defined $rbsopt1) {
|
---|
214 | if (defined $rbsopt1->{$vedebstyle}) {
|
---|
215 | $rbsopt = $rbsopt1->{$vedebstyle};
|
---|
216 | } elsif (defined $rbsopt1->{$ENV{'PBPROJ'}}) {
|
---|
217 | $rbsopt = $rbsopt1->{$ENV{'PBPROJ'}};
|
---|
218 | } else {
|
---|
219 | $rbsopt = "";
|
---|
220 | }
|
---|
221 | }
|
---|
222 |
|
---|
223 | # debootstrap works with amd64 not x86_64
|
---|
224 | my $debarch = $pbos->{'arch'};
|
---|
225 | $debarch = "amd64" if ($pbos->{'arch'} eq "x86_64");
|
---|
226 | if ($vedebstyle eq "debootstrap") {
|
---|
227 | my $dbsverb = "";
|
---|
228 | $dbsverb = "--verbose" if ($pbdebug gt 0);
|
---|
229 |
|
---|
230 | # Some perl modules are in Universe on Ubuntu
|
---|
231 | $rbsopt .= " --components=main,universe" if ($pbos->{'name'} eq "ubuntu");
|
---|
232 |
|
---|
233 | my $cmd1 = pb_check_req("mkdir",0);
|
---|
234 | my $cmd2 = pb_check_req("debootstrap",0);
|
---|
235 | pb_system("$sudocmd $cmd1 -p $root/$pbos->{name}/$pbos->{version}/$pbos->{arch} ; $sudocmd $cmd2 $dbsverb $rbsopt --arch=$debarch $addpkgs $codename \"$root/$pbos->{'name'}/$pbos->{'version'}/$pbos->{'arch'}\" $debmir","Creating the debootstrap VE for $pbos->{'name'}-$pbos->{'version'} ($pbos->{'arch'})", "verbose");
|
---|
236 | # debootstrap doesn't create an /etc/hosts file
|
---|
237 | if (! -f "$root/$pbos->{'name'}/$pbos->{'version'}/$pbos->{'arch'}/etc/hosts" ) {
|
---|
238 | my $cmd = pb_check_req("cp",0);
|
---|
239 | pb_system("$sudocmd $cmd /etc/hosts $root/$pbos->{'name'}/$pbos->{'version'}/$pbos->{'arch'}/etc/hosts");
|
---|
240 | }
|
---|
241 | } else {
|
---|
242 | die "Unknown vedebtype type $vedebstyle. Report to dev team";
|
---|
243 | }
|
---|
244 | } elsif ($pbos->{'type'} eq "ebuild") {
|
---|
245 | die "Please teach the dev team how to build gentoo chroot";
|
---|
246 | } else {
|
---|
247 | die "Unknown distribution type $pbos->{'type'}. Report to dev team";
|
---|
248 | }
|
---|
249 | }
|
---|
250 |
|
---|
251 | # Test if an existing snapshot exists and use it if appropriate
|
---|
252 | # And also use it of no local extracted VE is present
|
---|
253 | if ((-f "$root/$pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}.tar.gz") &&
|
---|
254 | (((defined $vesnap->{$v}) && ($vesnap->{$v} =~ /true/i)) ||
|
---|
255 | ((defined $vesnap->{$ENV{'PBPROJ'}}) && ($vesnap->{$ENV{'PBPROJ'}} =~ /true/i))) &&
|
---|
256 | ($locsnap eq 1) &&
|
---|
257 | (! -d "$root/$pbos->{'name'}/$pbos->{'version'}/$pbos->{'arch'}")) {
|
---|
258 | my $cmd1 = pb_check_req("rm",0);
|
---|
259 | my $cmd2 = pb_check_req("mkdir",0);
|
---|
260 | my $cmd3 = pb_check_req("tar",0);
|
---|
261 | pb_system("$sudocmd $cmd1 -rf $root/$pbos->{'name'}/$pbos->{'version'}/$pbos->{'arch'} ; $sudocmd $cmd2 -p $root/$pbos->{'name'}/$pbos->{'version'}/$pbos->{'arch'} ; $sudocmd $cmd3 xz -C $root/$pbos->{'name'}/$pbos->{'version'}/$pbos->{'arch'} -f $root/$pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}.tar.gz","Extracting snapshot of $pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}.tar.gz under $root/$pbos->{'name'}/$pbos->{'version'}/$pbos->{'arch'}");
|
---|
262 | }
|
---|
263 |
|
---|
264 | # Fix modes to allow access to the VE for pb user
|
---|
265 | my $command = pb_check_req("chmod",0);
|
---|
266 | pb_system("$sudocmd $command 755 $root/$pbos->{'name'} $root/$pbos->{'name'}/$pbos->{'version'} $root/$pbos->{'name'}/$pbos->{'version'}/$pbos->{'arch'}","Fixing permissions");
|
---|
267 |
|
---|
268 | # Nothing more to do for VE. No real launch
|
---|
269 | } else {
|
---|
270 | die "VE of type $vetype not supported. Report to the dev team";
|
---|
271 | }
|
---|
272 | }
|
---|
273 |
|
---|
274 | #
|
---|
275 | # Return the postinstall line if needed
|
---|
276 | #
|
---|
277 |
|
---|
278 | sub pb_ve_get_postinstall {
|
---|
279 |
|
---|
280 | my $pbos = shift;
|
---|
281 | my $rbspi = shift;
|
---|
282 | my $vestyle = shift;
|
---|
283 | my $post = "";
|
---|
284 |
|
---|
285 | # Do we have a local post-install script
|
---|
286 | if ($vestyle eq "rinse") {
|
---|
287 | $post = "--post-install ";
|
---|
288 | } elsif ($vestyle eq "rpmbootstrap") {
|
---|
289 | $post = "-s ";
|
---|
290 | }
|
---|
291 |
|
---|
292 | my $postparam = pb_distro_get_param($pbos,$rbspi);
|
---|
293 | if ($postparam eq "") {
|
---|
294 | $post = "";
|
---|
295 | } else {
|
---|
296 | $post .= $postparam;
|
---|
297 | }
|
---|
298 | return($post);
|
---|
299 | }
|
---|
300 |
|
---|
301 |
|
---|
302 | =head1 WEB SITES
|
---|
303 |
|
---|
304 | The 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/>.
|
---|
305 |
|
---|
306 | =head1 USER MAILING LIST
|
---|
307 |
|
---|
308 | None exists for the moment.
|
---|
309 |
|
---|
310 | =head1 AUTHORS
|
---|
311 |
|
---|
312 | The Project-Builder.org team L<http://trac.project-builder.org/> lead by Bruno Cornec L<mailto:bruno@project-builder.org>.
|
---|
313 |
|
---|
314 | =head1 COPYRIGHT
|
---|
315 |
|
---|
316 | Project-Builder.org is distributed under the GPL v2.0 license
|
---|
317 | described in the file C<COPYING> included with the distribution.
|
---|
318 |
|
---|
319 | =cut
|
---|
320 |
|
---|
321 |
|
---|
322 | 1;
|
---|