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