[976] | 1 | #!/usr/bin/perl -w
|
---|
| 2 | #
|
---|
| 3 | # rpmbootstrap application, a debootstrap like for RPM distros
|
---|
| 4 | #
|
---|
| 5 | # $Id$
|
---|
| 6 | #
|
---|
[2488] | 7 | # Copyright B. Cornec 2010-today
|
---|
[1534] | 8 | # Eric Anderson's changes are (c) Copyright 2012 Hewlett Packard
|
---|
[976] | 9 | # Provided under the GPL v2
|
---|
| 10 |
|
---|
| 11 | # Syntax: see at end
|
---|
| 12 |
|
---|
| 13 | use strict 'vars';
|
---|
| 14 | use Getopt::Long qw(:config auto_abbrev no_ignore_case);
|
---|
| 15 | use Data::Dumper;
|
---|
| 16 | use English;
|
---|
| 17 | use LWP::UserAgent;
|
---|
[984] | 18 | use File::Basename;
|
---|
| 19 | use File::Copy;
|
---|
| 20 | use File::Find;
|
---|
[976] | 21 | use ProjectBuilder::Version;
|
---|
| 22 | use ProjectBuilder::Base;
|
---|
| 23 | use ProjectBuilder::Env;
|
---|
| 24 | use ProjectBuilder::Conf;
|
---|
| 25 | use ProjectBuilder::Distribution;
|
---|
| 26 |
|
---|
| 27 | # Global variables
|
---|
| 28 | my %opts; # CLI Options
|
---|
| 29 |
|
---|
| 30 | =pod
|
---|
| 31 |
|
---|
| 32 | =head1 NAME
|
---|
| 33 |
|
---|
| 34 | rpmbootstrap - creates a chrooted RPM based distribution a la debootstrap, aka Virtual Environment (VE)
|
---|
| 35 |
|
---|
| 36 | =head1 DESCRIPTION
|
---|
| 37 |
|
---|
[1082] | 38 | rpmbootstrap creates a chroot environment (Virtual Environment or VE)
|
---|
| 39 | with a minimal distribution in it, suited for building packages for example.
|
---|
| 40 | It's very much like debootstrap but for RPM based distribution.
|
---|
| 41 | It aims at supporting all distributions supported by project-builder.org
|
---|
| 42 | (RHEL, RH, Fedora, OpeSUSE, SLES, Mandriva, ...)
|
---|
[976] | 43 |
|
---|
[1082] | 44 | It is inspired by work done by Steve Kemp for rinse (http://www.steve.org.uk/),
|
---|
[1326] | 45 | and similar to mock or febootstrap, but fully integrated with project-builder.org
|
---|
| 46 | (which also supports rinse and mock). Contrary to these, rpmbootstrap creates
|
---|
| 47 | an environment where the packages commands are usable after build, as described
|
---|
| 48 | hereafter.
|
---|
[976] | 49 |
|
---|
[1315] | 50 | rpmbootstrap works in 2 phases. The first one is used to download all
|
---|
| 51 | the required packages to have a working package management system in the
|
---|
[2279] | 52 | chroot working. This list of packages is stored in /etc/pb/pb.yml under
|
---|
[1315] | 53 | the rbsmindep parameter (aka rpmbootstrap minimal dependencies). Once the
|
---|
| 54 | packages have been downloaded from the mirror, they are extracted with
|
---|
| 55 | rpm2cpio. At that point you should be able to use yum on Fedora, urpmi
|
---|
| 56 | on Mandriva/Mageia and zypper on OpenSuSE.
|
---|
| 57 | The second phase uses exactly the previous mentioned tools to install
|
---|
| 58 | exactly the same package list to have a coherent RPM db at the end.
|
---|
| 59 |
|
---|
| 60 | rpmbootstrap has additional options to execute a post-install script
|
---|
| 61 | (-s) or to add packages (-a). Then pb can use the chroot to perform even
|
---|
| 62 | more actions in it.
|
---|
| 63 |
|
---|
[976] | 64 | =head1 SYNOPSIS
|
---|
| 65 |
|
---|
[1900] | 66 | rpmbootstrap [-vhmqpdk][-s script][-i image][-a pkg1[,pkg2,...]] distribution-version-arch [target-dir] [mirror [script]]
|
---|
[976] | 67 |
|
---|
[1082] | 68 | rpmbootstrap [--verbose][--help][--man][--quiet][--print-rpms][--download-only]
|
---|
[1900] | 69 | [--keep][--script script][--image image][--add pkg1,[pkg2,...]] distribution-version-arch [target-dir] [mirror [script]]
|
---|
[976] | 70 |
|
---|
| 71 | =head1 OPTIONS
|
---|
| 72 |
|
---|
| 73 | =over 4
|
---|
| 74 |
|
---|
| 75 | =item B<-v|--verbose>
|
---|
| 76 |
|
---|
| 77 | Print a brief help message and exits.
|
---|
| 78 |
|
---|
| 79 | =item B<-h|--help>
|
---|
| 80 |
|
---|
| 81 | Print a brief help message and exits.
|
---|
| 82 |
|
---|
| 83 | =item B<--man>
|
---|
| 84 |
|
---|
| 85 | Prints the manual page and exits.
|
---|
| 86 |
|
---|
| 87 | =item B<-q|--quiet>
|
---|
| 88 |
|
---|
| 89 | Do not print any output.
|
---|
| 90 |
|
---|
| 91 | =item B<-p|--print-rpms>
|
---|
| 92 |
|
---|
[1082] | 93 | Print the packages to be installed, and exit.
|
---|
| 94 | Note that a target directory must be specified so rpmbootstrap can determine
|
---|
| 95 | which packages should be installed, and to resolve dependencies.
|
---|
| 96 | The target directory will be deleted.
|
---|
[976] | 97 |
|
---|
| 98 | =item B<-d|--download-only>
|
---|
| 99 |
|
---|
| 100 | Download packages, but don't perform installation.
|
---|
| 101 |
|
---|
| 102 | =item B<-k|--keep>
|
---|
| 103 |
|
---|
| 104 | Keep packages in the cache dir for later reuse. By default remove them.
|
---|
| 105 |
|
---|
| 106 | =item B<-s|--script script>
|
---|
| 107 |
|
---|
| 108 | Name of the script you want to execute on the related VEs after the installation.
|
---|
[1082] | 109 | It is executed in host environment.
|
---|
| 110 | You can use the chroot command to execute actions in the VE.
|
---|
[976] | 111 |
|
---|
[1900] | 112 | =item B<-i|--image image>
|
---|
[976] | 113 |
|
---|
[1900] | 114 | Name of the ISO image or the docker image of the distribution you want to install on the related VE.
|
---|
[976] | 115 |
|
---|
[991] | 116 | =item B<-a|--add pkg1[,pkg2,...]>
|
---|
| 117 |
|
---|
[1082] | 118 | Additional packages to add from the distribution you want to install on the related VE
|
---|
| 119 | at the end of the chroot build.
|
---|
[991] | 120 |
|
---|
[1531] | 121 | =item B<--no-stop-on-error>
|
---|
| 122 |
|
---|
| 123 | Continue through errors with best effort.
|
---|
| 124 |
|
---|
[976] | 125 | =back
|
---|
| 126 |
|
---|
| 127 | =head1 ARGUMENTS
|
---|
| 128 |
|
---|
[1044] | 129 | =over 4
|
---|
| 130 |
|
---|
[976] | 131 | =item B<distribution-version-arch>
|
---|
| 132 |
|
---|
| 133 | Full name of the distribution that needs to be installed in the VE. E.g. fedora-11-x86_64.
|
---|
| 134 |
|
---|
| 135 | =item B<target-dir>
|
---|
| 136 |
|
---|
[1082] | 137 | This is the target directory under which the VE will be created.
|
---|
| 138 | Created on the fly if needed.
|
---|
| 139 | If none is given use the default directory hosting VE for project-builder.org
|
---|
[2252] | 140 | (Cf: vepath parameter in $HOME/.pbrc.yml)
|
---|
[976] | 141 |
|
---|
[1044] | 142 | =back
|
---|
| 143 |
|
---|
[976] | 144 | =head1 EXAMPLE
|
---|
| 145 |
|
---|
| 146 | To setup a Fedora 12 distribution with an i386 architecture issue:
|
---|
| 147 |
|
---|
| 148 | rpmbootstrap fedora-12-i386 /tmp/fedora/12/i386
|
---|
| 149 |
|
---|
| 150 | =head1 WEB SITES
|
---|
| 151 |
|
---|
[1082] | 152 | The main Web site of the project is available at L<http://www.project-builder.org/>.
|
---|
| 153 | Bug reports should be filled using the trac instance of the project at L<http://trac.project-builder.org/>.
|
---|
[976] | 154 |
|
---|
| 155 | =head1 USER MAILING LIST
|
---|
| 156 |
|
---|
[1082] | 157 | Cf: L<http://www.mondorescue.org/sympa/info/pb-announce> for announces and
|
---|
| 158 | L<http://www.mondorescue.org/sympa/info/pb-devel> for the development of the pb project.
|
---|
[976] | 159 |
|
---|
| 160 | =head1 CONFIGURATION FILE
|
---|
| 161 |
|
---|
[2279] | 162 | Uses Project-Builder.org configuration file (/etc/pb/pb.yml or /usr/local/etc/pb/pb.yml)
|
---|
[976] | 163 |
|
---|
| 164 | =head1 AUTHORS
|
---|
| 165 |
|
---|
| 166 | The Project-Builder.org team L<http://trac.project-builder.org/> lead by Bruno Cornec L<mailto:bruno@project-builder.org>.
|
---|
| 167 |
|
---|
| 168 | =head1 COPYRIGHT
|
---|
| 169 |
|
---|
| 170 | Project-Builder.org is distributed under the GPL v2.0 license
|
---|
| 171 | described in the file C<COPYING> included with the distribution.
|
---|
| 172 |
|
---|
| 173 | =cut
|
---|
| 174 |
|
---|
| 175 | # ---------------------------------------------------------------------------
|
---|
| 176 |
|
---|
[1531] | 177 | $Global::pb_stop_on_error = 1;
|
---|
[976] | 178 | my ($projectbuilderver,$projectbuilderrev) = pb_version_init();
|
---|
| 179 | my $appname = "rpmbootstrap";
|
---|
[983] | 180 | $ENV{'PBPROJ'} = $appname;
|
---|
[976] | 181 |
|
---|
| 182 | # Initialize the syntax string
|
---|
| 183 |
|
---|
| 184 | pb_syntax_init("$appname Version $projectbuilderver-$projectbuilderrev\n");
|
---|
[984] | 185 | pb_temp_init();
|
---|
[2496] | 186 | pb_conf_init($appname);
|
---|
[976] | 187 |
|
---|
| 188 | GetOptions("help|?|h" => \$opts{'h'},
|
---|
[1177] | 189 | "man|m" => \$opts{'man'},
|
---|
| 190 | "verbose|v+" => \$opts{'v'},
|
---|
| 191 | "quiet|q" => \$opts{'q'},
|
---|
| 192 | "log-files|l=s" => \$opts{'l'},
|
---|
| 193 | "script|s=s" => \$opts{'s'},
|
---|
| 194 | "print-rpms|p" => \$opts{'p'},
|
---|
| 195 | "download-only|d" => \$opts{'d'},
|
---|
| 196 | "keep|k" => \$opts{'k'},
|
---|
[1900] | 197 | "image|i=s" => \$opts{'i'},
|
---|
[1177] | 198 | "add|a=s" => \$opts{'a'},
|
---|
| 199 | "version|V=s" => \$opts{'V'},
|
---|
[1531] | 200 | "stop-on-error!" => \$Global::pb_stop_on_error,
|
---|
[976] | 201 | ) || pb_syntax(-1,0);
|
---|
| 202 |
|
---|
| 203 | if (defined $opts{'h'}) {
|
---|
| 204 | pb_syntax(0,1);
|
---|
| 205 | }
|
---|
| 206 | if (defined $opts{'man'}) {
|
---|
| 207 | pb_syntax(0,2);
|
---|
| 208 | }
|
---|
| 209 | if (defined $opts{'v'}) {
|
---|
| 210 | $pbdebug = $opts{'v'};
|
---|
| 211 | }
|
---|
| 212 | if (defined $opts{'q'}) {
|
---|
| 213 | $pbdebug=-1;
|
---|
| 214 | }
|
---|
| 215 | if (defined $opts{'l'}) {
|
---|
| 216 | open(pbLOG,"> $opts{'l'}") || die "Unable to log to $opts{'l'}: $!";
|
---|
| 217 | $pbLOG = \*pbLOG;
|
---|
| 218 | $pbdebug = 0 if ($pbdebug == -1);
|
---|
[1177] | 219 | }
|
---|
[976] | 220 | pb_log_init($pbdebug, $pbLOG);
|
---|
[981] | 221 | #pb_display_init("text","");
|
---|
[976] | 222 |
|
---|
[981] | 223 | #if (defined $opts{'s'}) {
|
---|
| 224 | #$pbscript = $opts{'s'};
|
---|
| 225 | #}
|
---|
| 226 | #if (defined $opts{'i'}) {
|
---|
[1900] | 227 | #$image = $opts{'i'};
|
---|
[981] | 228 | #}
|
---|
[976] | 229 |
|
---|
| 230 | # Get VE name
|
---|
| 231 | $ENV{'PBV'} = shift @ARGV;
|
---|
| 232 | die pb_syntax(-1,1) if (not defined $ENV{'PBV'});
|
---|
| 233 |
|
---|
| 234 | die "Needs to be run as root" if ($EFFECTIVE_USER_ID != 0);
|
---|
| 235 |
|
---|
| 236 | #
|
---|
| 237 | # Initialize distribution info from pb conf file
|
---|
| 238 | #
|
---|
[984] | 239 | pb_log(0,"Starting VE build for $ENV{'PBV'}\n");
|
---|
[1177] | 240 | my $pbos = pb_distro_get_context($ENV{'PBV'});
|
---|
[976] | 241 |
|
---|
| 242 | #
|
---|
| 243 | # Check target dir
|
---|
| 244 | # Create if not existent and use default if none given
|
---|
| 245 | #
|
---|
[2252] | 246 | pb_env_init_pbrc(); # to get content of HOME/.pbrc.yml
|
---|
[976] | 247 | my $vepath = shift @ARGV;
|
---|
| 248 |
|
---|
[982] | 249 | #
|
---|
| 250 | # Check for command requirements
|
---|
| 251 | #
|
---|
| 252 | my ($req,$opt) = pb_conf_get_if("oscmd","oscmdopt");
|
---|
[1128] | 253 | pb_check_requirements($req,$opt,$appname);
|
---|
[982] | 254 |
|
---|
[976] | 255 | if (not defined $vepath) {
|
---|
[1181] | 256 | my ($vestdpath) = pb_conf_get("vepath");
|
---|
[1531] | 257 | $vepath = pb_path_expand("$vestdpath->{'default'}/$pbos->{'name'}/$pbos->{'version'}/$pbos->{'arch'}") if (defined $vestdpath->{'default'});
|
---|
[976] | 258 | }
|
---|
| 259 |
|
---|
[981] | 260 | die pb_log(0,"No target-dir specified and no default vepath found in $ENV{'PBETC'}\n") if (not defined $vepath);
|
---|
[976] | 261 |
|
---|
[1815] | 262 | # Cleanup first
|
---|
| 263 | if ( -d $vepath) {
|
---|
| 264 | pb_rm_rf($vepath);
|
---|
| 265 | }
|
---|
| 266 | pb_mkdir_p($vepath);
|
---|
[976] | 267 |
|
---|
| 268 | #
|
---|
| 269 | # Get the package list to download, store them in a cache directory
|
---|
| 270 | #
|
---|
[1402] | 271 | my ($rbscachedir) = pb_conf_get_if("cachedir");
|
---|
[2488] | 272 | my ($pkgs,$mirror) = pb_distro_get($pbos,("rbsmindep","rbsmirrorsrv"));
|
---|
| 273 | my ($updater) = pb_distro_get_if($pbos,"rbsmirrorupd");
|
---|
[1531] | 274 | die "No packages defined for $pbos->{name}-$pbos->{version}-$pbos->{arch}" unless $pkgs =~ /\w/;
|
---|
[976] | 275 |
|
---|
| 276 | my $cachedir = "/var/cache/rpmbootstrap";
|
---|
| 277 | $cachedir = $rbscachedir->{'default'} if (defined $rbscachedir->{'default'});
|
---|
[1402] | 278 | $cachedir = $rbscachedir->{$appname} if (defined $rbscachedir->{$appname});
|
---|
[976] | 279 |
|
---|
| 280 | # Point to the right subdir and create it if needed
|
---|
[1177] | 281 | $cachedir .= "/$pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}";
|
---|
[976] | 282 | pb_mkdir_p($cachedir) if (! -d $cachedir);
|
---|
| 283 |
|
---|
| 284 | # Get the complete package name from the mirror
|
---|
| 285 | #
|
---|
| 286 | my $ua = LWP::UserAgent->new;
|
---|
| 287 | $ua->timeout(10);
|
---|
| 288 | $ua->env_proxy;
|
---|
| 289 |
|
---|
[1314] | 290 | die "No mirror defined for $pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}" if ((not defined $mirror) || ($mirror =~ /^\t*$/));
|
---|
[1802] | 291 | my $resp;
|
---|
[1815] | 292 | my $repo;
|
---|
[1892] | 293 | my %list_pkg;
|
---|
[976] | 294 |
|
---|
[1815] | 295 | ($repo,$resp) = rbs_mirror_response($mirror);
|
---|
[1892] | 296 | foreach my $r (split(/\n/,$resp->as_string())) {
|
---|
| 297 | $list_pkg{$r} = $mirror;
|
---|
| 298 | }
|
---|
[1031] | 299 |
|
---|
[1802] | 300 | # If an update source is availble add it after so that these pkgs update the main ones
|
---|
| 301 | if (defined $updater) {
|
---|
[1815] | 302 | my $void;
|
---|
| 303 | ($void,$resp) = rbs_mirror_response($mirror.$updater);
|
---|
[1892] | 304 | foreach my $r (split(/\n/,$resp->as_string())) {
|
---|
| 305 | $list_pkg{$r} = $mirror.$updater;
|
---|
| 306 | }
|
---|
[1031] | 307 | }
|
---|
| 308 |
|
---|
[983] | 309 | # Manages architectures specificities
|
---|
[1177] | 310 | my $parch = $pbos->{'arch'};
|
---|
| 311 | $parch = "i[3456]86" if ($pbos->{'arch'} eq "i386");
|
---|
[983] | 312 |
|
---|
| 313 | # Get the list of packages and their URL in this hash
|
---|
| 314 | my %url;
|
---|
[1812] | 315 | my %done;
|
---|
[1892] | 316 | foreach my $l (keys %list_pkg) {
|
---|
[1802] | 317 | my ($url,$desc) = rbs_find_pkg($l,$parch,"pkg");
|
---|
| 318 | if (defined $url) {
|
---|
[1892] | 319 | $url{$url} = "$list_pkg{$l}/$desc";
|
---|
[1802] | 320 | } else {
|
---|
| 321 | pb_log(3,"not a package, maybe a dir containing packages\n");
|
---|
[1812] | 322 | ($url,$desc) = rbs_find_pkg($l,$parch,"dir");
|
---|
| 323 | if ((defined $desc) and (not defined $done{$desc})) {
|
---|
| 324 | my $response1 = $ua->get("$mirror/$desc");
|
---|
| 325 | # Check if we have a fedora 17/18 type of repo
|
---|
| 326 | if ($response1->is_success) {
|
---|
| 327 | $done{$desc} = "true";
|
---|
| 328 | foreach my $d (split(/\n/,$response1->as_string())) {
|
---|
| 329 | my ($url2,$desc2) = rbs_find_pkg($d,$parch,"pkg");
|
---|
| 330 | if (defined $url2) {
|
---|
| 331 | # Here we have the dir in which are packages
|
---|
| 332 | $url{$url2} = "$mirror/$desc/$desc2";
|
---|
| 333 | } else {
|
---|
| 334 | pb_log(3,"not a package, and not a dir containing packages\n");
|
---|
[1802] | 335 | }
|
---|
| 336 | }
|
---|
[1812] | 337 | } else {
|
---|
[1802] | 338 | }
|
---|
[983] | 339 | }
|
---|
| 340 | }
|
---|
[976] | 341 | }
|
---|
| 342 |
|
---|
[984] | 343 | #
|
---|
| 344 | # Prepare early the yum cache env for the VE in order to copy in it packages on the fly
|
---|
| 345 | #
|
---|
[990] | 346 | my $oscachedir = "/tmp";
|
---|
| 347 | my $osupdcachedir;
|
---|
| 348 | my $osupdname = "";
|
---|
| 349 |
|
---|
[1177] | 350 | if ($pbos->{'install'} =~ /yum/) {
|
---|
[990] | 351 | $oscachedir = "$vepath/var/cache/yum/core/packages/";
|
---|
| 352 | $osupdcachedir = "$vepath/var/cache/yum/updates-released/packages/";
|
---|
| 353 | $osupdname = "YUM";
|
---|
| 354 | # Recent Fedora release use a new yum cache dir
|
---|
[1177] | 355 | if (($pbos->{'name'} eq "fedora") && ($pbos->{'version'} > 8)) {
|
---|
| 356 | $oscachedir = "$vepath/var/cache/yum/$pbos->{'arch'}/$pbos->{'version'}/fedora/packages";
|
---|
[2012] | 357 | #$osupdcachedir = "$vepath/var/cache/yum/$pbos->{'arch'}/$pbos->{'version'}/updates/packages";
|
---|
[990] | 358 | $osupdcachedir = "$vepath/var/cache/yum/updates-released/packages/";
|
---|
| 359 | }
|
---|
[2012] | 360 | } elsif ($pbos->{'install'} =~ /dnf/) {
|
---|
| 361 | $osupdname = "DNF";
|
---|
| 362 | $oscachedir = "$vepath/var/cache/dnf/$pbos->{'arch'}/$pbos->{'version'}/fedora/packages";
|
---|
| 363 | $osupdcachedir = "$vepath/var/cache/dnf/updates-released/packages/";
|
---|
[1177] | 364 | } elsif ($pbos->{'install'} =~ /zypper/) {
|
---|
| 365 | $oscachedir = "$vepath/var/cache/zypp/packages/opensuse/suse/$pbos->{'arch'}";
|
---|
[990] | 366 | $osupdname = "Zypper";
|
---|
[1177] | 367 | } elsif ($pbos->{'install'} =~ /urpmi/) {
|
---|
[992] | 368 | $oscachedir = "$vepath/var/cache/urpmi/rpms";
|
---|
| 369 | $osupdname = "URPMI";
|
---|
[984] | 370 | }
|
---|
[991] | 371 | pb_log(1,"Setting up $osupdname cache in VE\n");
|
---|
[990] | 372 | pb_mkdir_p($oscachedir);
|
---|
| 373 | pb_mkdir_p($osupdcachedir) if (defined $osupdcachedir);
|
---|
[983] | 374 |
|
---|
[976] | 375 | # For each package to process, get it, put it in the cache dir
|
---|
| 376 | # and extract it in the target dir. If not asked to keep, remove it
|
---|
| 377 | # Just download if asked so.
|
---|
| 378 |
|
---|
[983] | 379 | my $warning = 0;
|
---|
| 380 | my $lwpkg ="";
|
---|
[1531] | 381 | my @installed_packages;
|
---|
| 382 |
|
---|
[1815] | 383 | # On systemd systems, the pkg needs to be first
|
---|
| 384 | # to have the correct links made first
|
---|
| 385 | if ($pkgs =~ /,filesystem,/) {
|
---|
| 386 | $pkgs =~ s/,filesystem,/,/;
|
---|
| 387 | $pkgs = "filesystem,".$pkgs;
|
---|
| 388 | }
|
---|
| 389 |
|
---|
[981] | 390 | foreach my $p (split(/,/,$pkgs)) {
|
---|
[1532] | 391 | $p =~ s/\s+//go;
|
---|
[983] | 392 | pb_log(1,"Processing package $p ...\n");
|
---|
| 393 | # Just print packages names if asked so.
|
---|
[984] | 394 | if (defined $url{$p}) {
|
---|
| 395 | if ($opts{'p'}) {
|
---|
[983] | 396 | pb_log(0,"$url{$p}\n");
|
---|
[984] | 397 | next;
|
---|
[983] | 398 | } else {
|
---|
[984] | 399 | # Now download if not already in cache
|
---|
| 400 | my $p1 = basename($url{$p});
|
---|
| 401 | if (! -f "$cachedir/$p1") {
|
---|
[1892] | 402 | pb_system("wget --tries=5 --quiet -O $cachedir/$p1-new $url{$p}","Downloading package $p1 ...");
|
---|
[1532] | 403 | rename("$cachedir/$p1-new", "$cachedir/$p1") || die "mv $cachedir/$p1-new $cachedir/$p1 failed: $!";
|
---|
[984] | 404 | } else {
|
---|
| 405 | pb_log(1,"Package $p1 already in cache\n");
|
---|
| 406 | }
|
---|
[1177] | 407 |
|
---|
[984] | 408 | # End if download only
|
---|
| 409 | if ($opts{'d'}) {
|
---|
| 410 | next;
|
---|
| 411 | }
|
---|
[1177] | 412 |
|
---|
[984] | 413 | #
|
---|
[990] | 414 | # Copy the cached .RPM files into the oscachedir directory, so that os doesn't need to download them again.
|
---|
[984] | 415 | #
|
---|
[990] | 416 | pb_log(1,"Link package into $oscachedir\n");
|
---|
[1177] | 417 | copy("$cachedir/$p1",$oscachedir) if (defined $oscachedir);
|
---|
| 418 | symlink("$oscachedir/$p1","$osupdcachedir/p1") if (defined $osupdcachedir);
|
---|
[984] | 419 |
|
---|
| 420 | # And extract it to the finale dir
|
---|
[1982] | 421 | pb_system("cd $vepath ; rpm2cpio $cachedir/$p1 | cpio -ivdum --extract-over-symlinks","Extracting package $p1 into $vepath");
|
---|
[1177] | 422 |
|
---|
[984] | 423 | # Remove cached package if not asked to keep
|
---|
| 424 | if (! $opts{'k'}) {
|
---|
| 425 | unlink("$cachedir/$p1");
|
---|
| 426 | }
|
---|
[1531] | 427 | push(@installed_packages, $p);
|
---|
[983] | 428 | }
|
---|
[984] | 429 | } else {
|
---|
| 430 | pb_log(0,"WARNING: unable to find URL for $p\n");
|
---|
| 431 | $warning++;
|
---|
| 432 | $lwpkg .= " $p";
|
---|
[976] | 433 | }
|
---|
[983] | 434 | }
|
---|
| 435 |
|
---|
| 436 | if ($warning ge 1) {
|
---|
[1177] | 437 | pb_log(0,"$warning WARNINGS found.\nMaybe you should review your package list for $pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}\nand remove$lwpkg\n");
|
---|
[983] | 438 | }
|
---|
| 439 |
|
---|
[984] | 440 | # Stop here if we just print
|
---|
[983] | 441 | if ($opts{'p'}) {
|
---|
[1661] | 442 | pb_exit(0);
|
---|
[983] | 443 | }
|
---|
[984] | 444 |
|
---|
| 445 | # Now executes the VE finalization steps required for it to work correctly
|
---|
| 446 | pb_log(0,"VE post configuration\n");
|
---|
| 447 |
|
---|
| 448 | # yum needs that distro-release package be installed, so force it
|
---|
[2012] | 449 | if (($pbos->{'install'} =~ /yum/) || ($pbos->{'install'} =~ /dnf/)) {
|
---|
[1177] | 450 | my $ddir = $pbos->{'name'};
|
---|
[990] | 451 | foreach my $p1 (<$cachedir/($ddir|redhat)-release-*.rpm>) {
|
---|
| 452 | copy("$cachedir/$p1","$vepath/tmp");
|
---|
| 453 | pb_system("chroot $vepath rpm -ivh --force --nodeps /tmp/$p1","Forcing RPM installation of $p1");
|
---|
| 454 | unlink("$vepath/tmp/$p1");
|
---|
| 455 | }
|
---|
[1652] | 456 | # RedHat 6.2 has a buggy termcap setup and doesn't support usage of setarch, so still returns x86_64 in a chroot
|
---|
| 457 | } elsif (($pbos->{'name'} =~ /redhat/) && ( $pbos->{'version'} =~ /^6/)) {
|
---|
[1645] | 458 | pb_system("chroot $vepath ldconfig","Forcing ldconfig on $pbos->{'name'} $pbos->{'version'}");
|
---|
[1652] | 459 | pb_system("chroot $vepath echo 'arch_canon: x86_64: x86_64 1' >> /etc/rpmrc","Forcing ldconfig on $pbos->{'name'} $pbos->{'version'}");
|
---|
| 460 | pb_system("chroot $vepath echo 'arch_compat: x86_64: i386' >> /etc/rpmrc","Forcing ldconfig on $pbos->{'name'} $pbos->{'version'}");
|
---|
| 461 | pb_system("chroot $vepath echo 'buildarch_compat: x86_64: i386' >> /etc/rpmrc","Forcing ldconfig on $pbos->{'name'} $pbos->{'version'}");
|
---|
| 462 | pb_system("chroot $vepath echo 'buildarchtranslate: x86_64: i386' >> /etc/rpmrc","Forcing ldconfig on $pbos->{'name'} $pbos->{'version'}");
|
---|
[984] | 463 | }
|
---|
| 464 | #
|
---|
| 465 | # Make sure there is a resolv.conf file present, such that DNS lookups succeed.
|
---|
| 466 | #
|
---|
| 467 | pb_log(1,"Creating resolv.conf\n");
|
---|
| 468 | pb_mkdir_p("$vepath/etc");
|
---|
| 469 | copy("/etc/resolv.conf","$vepath/etc/");
|
---|
| 470 |
|
---|
| 471 | #
|
---|
| 472 | # BUGFIX:
|
---|
| 473 | #
|
---|
[1177] | 474 | if ((($pbos->{'name'} eq "centos") || ($pbos->{'name'} eq "rhel")) && ($pbos->{'version'} eq "5")) {
|
---|
[984] | 475 | pb_log(1,"BUGFIX for centos-5\n");
|
---|
| 476 | pb_mkdir_p("$vepath/usr/lib/python2.4/site-packages/urlgrabber.skx");
|
---|
| 477 | foreach my $i (<$vepath/usr/lib/python2.4/site-packages/urlgrabber/keepalive.*>) {
|
---|
[1531] | 478 | move($i,"$vepath/usr/lib/python2.4/site-packages/urlgrabber.skx/");
|
---|
[984] | 479 | }
|
---|
| 480 | }
|
---|
| 481 |
|
---|
| 482 | #
|
---|
| 483 | # /proc needed
|
---|
| 484 | #
|
---|
| 485 | pb_mkdir_p("$vepath/proc");
|
---|
[1564] | 486 | pb_system("mount -o bind /proc $vepath/proc","Mounting /proc") unless (-d "$vepath/proc/$$");
|
---|
[984] | 487 |
|
---|
| 488 | #
|
---|
| 489 | # Some devices may be needed
|
---|
| 490 | #
|
---|
[992] | 491 | pb_mkdir_p("$vepath/dev");
|
---|
[1029] | 492 | chmod 0755,"$vepath/dev";
|
---|
[984] | 493 | pb_system("mknod -m 644 $vepath/dev/random c 1 8","Creating $vepath/dev/random") if (! -c "$vepath/dev/random");
|
---|
| 494 | pb_system("mknod -m 644 $vepath/dev/urandom c 1 9","Creating $vepath/dev/urandom") if (! -c "$vepath/dev/urandom");
|
---|
| 495 | pb_system("mknod -m 666 $vepath/dev/zero c 1 5","Creating $vepath/dev/zero") if (! -c "$vepath/dev/zero");
|
---|
[1309] | 496 | pb_system("mknod -m 666 $vepath/dev/null c 1 3","Creating $vepath/dev/null") if (! -c "$vepath/dev/null");
|
---|
[984] | 497 |
|
---|
[1812] | 498 | # Where is bash
|
---|
| 499 | my $bash = "/usr/bin/bash";
|
---|
| 500 | if (! -x "$vepath/$bash" ) {
|
---|
| 501 | $bash = "/bin/bash";
|
---|
| 502 | if (! -x "$vepath/$bash" ) {
|
---|
| 503 | die "No bash found in usual places. Please report to dev team";
|
---|
| 504 | }
|
---|
| 505 | }
|
---|
| 506 |
|
---|
| 507 |
|
---|
[990] | 508 | my $minipkglist;
|
---|
| 509 |
|
---|
[1027] | 510 | pb_log(1,"Adapting $osupdname repository entries\n");
|
---|
[2012] | 511 | if (($pbos->{'install'} =~ /yum/) || ($pbos->{'install'} =~ /dnf/)) {
|
---|
[984] | 512 | #
|
---|
[2012] | 513 | # Force the architecture for yum/dnf
|
---|
[984] | 514 | # The goal is to allow i386 chroot on x86_64
|
---|
| 515 | #
|
---|
[2012] | 516 | # FIX: Not sufficient to have yum/dnf working
|
---|
[984] | 517 | # mirrorlist is not usable
|
---|
| 518 | # $releasever also needs to be filtered
|
---|
| 519 | # yum.conf as well
|
---|
[2012] | 520 | foreach my $i (<$vepath/etc/yum.repos.d/*.repo>,"$vepath/etc/yum.conf","$vepath/etc/dnf/dnf.conf") {
|
---|
[1177] | 521 | pb_system("sed -i -e 's/\$basearch/$pbos->{'arch'}/g' $i","","quiet");
|
---|
| 522 | pb_system("sed -i -e 's/\$releasever/$pbos->{'version'}/g' $i","","quiet");
|
---|
[984] | 523 | pb_system("sed -i -e 's/^mirrorlist/#mirrorlist/' $i","","quiet");
|
---|
[1817] | 524 | pb_system("sed -i -e 's/^metalink/#metalink/' $i","","quiet");
|
---|
[1015] | 525 | # rather use neutral separators here
|
---|
[1815] | 526 | pb_system("sed -i -e 's|^#baseurl.*\$|baseurl=$repo|' $i","","quiet");
|
---|
[984] | 527 | }
|
---|
[2012] | 528 | my $pkgmgr = "";
|
---|
| 529 | if ($pbos->{'install'} =~ /yum/) {
|
---|
| 530 | $pkgmgr = "yum";
|
---|
| 531 | }
|
---|
| 532 | if ($pbos->{'install'} =~ /dnf/) {
|
---|
| 533 | $pkgmgr = "dnf";
|
---|
| 534 | }
|
---|
| 535 | $minipkglist = "ldconfig $pkgmgr passwd vim-minimal dhclient authconfig";
|
---|
[1177] | 536 | } elsif ($pbos->{'install'} =~ /zypper/) {
|
---|
[990] | 537 | pb_mkdir_p("$vepath/etc/zypp/repos.d");
|
---|
[1177] | 538 | open(REPO,"> $vepath/etc/zypp/repos.d/$pbos->{'name'}-$pbos->{'version'}") || die "Unable to create repo file";
|
---|
[990] | 539 | my $baseurl = dirname(dirname($mirror));
|
---|
[992] | 540 | # Setup the repo
|
---|
[1177] | 541 | if ($pbos->{'version'} eq "10.2") {
|
---|
[1812] | 542 | pb_system("chroot $vepath $bash -c \"yes | /usr/bin/zypper sa $baseurl $pbos->{'name'}-$pbos->{'version'}\"","Bootstrapping Zypper");
|
---|
[1299] | 543 | } else {
|
---|
[1603] | 544 | # don't care if remove fails if add succeeds.
|
---|
[1812] | 545 | pb_system("chroot $vepath $bash -c \"/usr/bin/zypper rr $pbos->{'name'}-$pbos->{'version'}\"","Bootstrapping Zypper","mayfail");
|
---|
| 546 | pb_system("chroot $vepath $bash -c \"/usr/bin/zypper ar $baseurl $pbos->{'name'}-$pbos->{'version'}\"","Bootstrapping Zypper");
|
---|
[990] | 547 | }
|
---|
[1299] | 548 | #print REPO << "EOF";
|
---|
| 549 | #[opensuse]
|
---|
| 550 | #name=$pbos->{'name'}-$pbos->{'version'}
|
---|
| 551 | #baseurl=$baseurl
|
---|
| 552 | #enabled=1
|
---|
| 553 | #gpgcheck=1
|
---|
| 554 | #
|
---|
| 555 | #EOF
|
---|
| 556 | close(REPO);
|
---|
[1603] | 557 | $minipkglist = "zypper aaa_base";
|
---|
[1531] | 558 | # TODO: Re-installing packages missing and necessary on opensuse 11.4 to get /etc/passwd created.
|
---|
[1177] | 559 | } elsif ($pbos->{'install'} =~ /urpmi/) {
|
---|
[992] | 560 | # Setup the repo
|
---|
[993] | 561 | my $baseurl = dirname(dirname(dirname($mirror)));
|
---|
[1812] | 562 | pb_system("chroot $vepath $bash -c \"urpmi.addmedia --distrib $baseurl\"","Bootstrapping URPMI");
|
---|
[1531] | 563 | # TODO here too ?
|
---|
[1894] | 564 | $minipkglist = "ldconfig urpmi bash passwd vim-minimal dhcp-client";
|
---|
[1645] | 565 | } elsif ($pbos->{'install'} =~ /\/rpm/) {
|
---|
| 566 | opendir(CDIR,$cachedir) || die "Unable to open directory $cachedir: $!";
|
---|
| 567 | foreach my $p (@installed_packages) {
|
---|
| 568 | foreach my $f (readdir(CDIR)) {
|
---|
[1894] | 569 | # find an rpm package ref name-ver-tag.arch.rpm
|
---|
| 570 | next if ($f =~ /^\./);
|
---|
[1645] | 571 | if ($f =~ /^$p-([^-]+)-([^-]+)\.(noarch|$parch)\.rpm$/) {
|
---|
| 572 | # Copy it to the chroot and reference it
|
---|
| 573 | copy("$cachedir/$f","$vepath/var/cache");
|
---|
| 574 | $minipkglist .= " /var/cache/$f";
|
---|
| 575 | last;
|
---|
| 576 | }
|
---|
| 577 | }
|
---|
| 578 | rewinddir(CDIR);
|
---|
| 579 | }
|
---|
| 580 | closedir(CDIR);
|
---|
[984] | 581 | }
|
---|
| 582 |
|
---|
| 583 | #
|
---|
[990] | 584 | # Run "install the necessary modules".
|
---|
| 585 | # No need for sudo here
|
---|
| 586 | #
|
---|
[1177] | 587 | $pbos->{'install'} =~ s/sudo//g;
|
---|
[2287] | 588 | if (((defined $ENV{'http_proxy'}) && ($ENV{'http_proxy'} ne '')) || ((defined $ENV{'https_proxy'}) && ($ENV{'https_proxy'} ne '')) || ((defined $ENV{'ftp_proxy'}) && ($ENV{'ftp_proxy'} ne ''))) {
|
---|
[1533] | 589 | if ($pbos->{'name'} eq "opensuse") {
|
---|
| 590 | # For opensuse 11.4 or 12.1 -- one of them didn't work with http_proxy or HTTP_PROXY set.
|
---|
| 591 | open(PROXY, "> $vepath/etc/sysconfig/proxy") || die "can't open $vepath/etc/sysconfig/proxy: $!";
|
---|
[2287] | 592 | print PROXY "HTTP_PROXY=$ENV{'http_proxy'}\n" if ((defined $ENV{'http_proxy'}) && ($ENV{'http_proxy'} ne ''));
|
---|
| 593 | print PROXY "HTTPS_PROXY=$ENV{'https_proxy'}\n" if ((defined $ENV{'https_proxy'}) && ($ENV{'https_proxy'} ne ''));
|
---|
| 594 | print PROXY "FTP_PROXY=$ENV{'ftp_proxy'}\n" if ((defined $ENV{'ftp_proxy'}) && ($ENV{'ftp_proxy'} ne ''));
|
---|
[1533] | 595 | close(PROXY);
|
---|
| 596 | }
|
---|
| 597 | }
|
---|
| 598 |
|
---|
| 599 | # Keep redhat variants from destroying nis domain on install
|
---|
[1812] | 600 | #pb_system("chroot $vepath $bash -e -c \"ln -snf /bin/true /bin/domainname\"");
|
---|
[1533] | 601 |
|
---|
| 602 | #if ($pbos->{'name'} =~ /fedora/i) { # hack to prevent fedora from destroying NIS settings on host
|
---|
| 603 | # open (AUTH, ">$vepath/etc/pam.d/system-auth-ac") || die "unable to open $vepath/etc/pam.d/system-auth-ac for write: $!";
|
---|
| 604 | # print AUTH "#pam_systemd -- will fix later in bootstrap\n";
|
---|
| 605 | # close(AUTH);
|
---|
| 606 | #}
|
---|
[1812] | 607 | pb_system("chroot $vepath $bash -c \"$pbos->{'install'} $minipkglist \"","Bootstrapping OS by running $pbos->{'install'} $minipkglist");
|
---|
[990] | 608 |
|
---|
[1531] | 609 | # CentOS6 will replace the yum.repos.d files; oddly it will leave the yum.conf file alone and make the new one ".rpmnew"
|
---|
| 610 | if (($pbos->{'name'} eq "centos") && ($pbos->{'version'} =~ /^6.*/)) {
|
---|
| 611 | pb_log(0,"Fixing $pbos->{'name'} $pbos->{'version'} bug for yum conf files");
|
---|
| 612 | foreach my $from (<$vepath/etc/yum.repos.d/*.rpmorig>) {
|
---|
| 613 | my $to = $from;
|
---|
| 614 | $to =~ s/.rpmorig$//;
|
---|
| 615 | pb_system("mv $from $to", "Recover $from");
|
---|
| 616 | }
|
---|
| 617 | }
|
---|
| 618 |
|
---|
[990] | 619 | #
|
---|
[984] | 620 | # make 'passwd' work.
|
---|
| 621 | #
|
---|
| 622 | pb_log(1,"Authfix\n");
|
---|
[1533] | 623 | # TODO: Not generic enough to be done like that IMHO
|
---|
| 624 | # In case it was changed during the install
|
---|
[1812] | 625 | #pb_system("chroot $vepath $bash -e -c \"ln -snf /bin/true /bin/domainname\"");
|
---|
| 626 | pb_system("chroot $vepath $bash -c \"if [ -x /usr/bin/authconfig ]; then /usr/bin/authconfig --enableshadow --update --nostart; fi\"","Calling authconfig");
|
---|
[984] | 627 |
|
---|
[991] | 628 | # Installed additional packages we were asked to
|
---|
| 629 | if (defined $opts{'a'}) {
|
---|
| 630 | $opts{'a'} =~ s/,/ /g;
|
---|
[1812] | 631 | pb_system("chroot $vepath $bash -c \"$pbos->{'install'} $opts{'a'} \"","Adding packages to OS by running $pbos->{'install'} $opts{'a'}");
|
---|
[991] | 632 | }
|
---|
| 633 |
|
---|
[984] | 634 | #
|
---|
| 635 | # Clean up
|
---|
| 636 | #
|
---|
| 637 | pb_log(1,"Cleaning up\n");
|
---|
[1177] | 638 | if ($pbos->{'install'} =~ /yum/) {
|
---|
[984] | 639 | pb_system("chroot $vepath /usr/bin/yum clean all","Cleaning yum");
|
---|
| 640 | }
|
---|
[2012] | 641 | if ($pbos->{'install'} =~ /dnf/) {
|
---|
| 642 | pb_system("chroot $vepath /usr/bin/dnf clean all","Cleaning dnf");
|
---|
| 643 | }
|
---|
[984] | 644 | pb_system("umount $vepath/proc","Unmounting /proc");
|
---|
| 645 | find(\&unlink_old_conf, $vepath);
|
---|
| 646 |
|
---|
| 647 | # Executes post-install step if asked for
|
---|
| 648 | if ($opts{'s'}) {
|
---|
| 649 | pb_system("$opts{'s'} $vepath","Executing the post-install script: $opts{'s'} $vepath");
|
---|
| 650 | }
|
---|
| 651 |
|
---|
[1531] | 652 | if ($warning > 0) {
|
---|
| 653 | pb_log(0,"\n\n\n\n$warning WARNINGS found.\nMaybe you should review your package list for $pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}\nand remove$lwpkg\n");
|
---|
| 654 | pb_log(0,"waiting 60 seconds to give you a chance to notice.\n");
|
---|
| 655 | sleep(60);
|
---|
| 656 | }
|
---|
| 657 |
|
---|
[1661] | 658 | pb_exit();
|
---|
| 659 |
|
---|
[984] | 660 | # Function for File::Find
|
---|
| 661 | sub unlink_old_conf {
|
---|
| 662 |
|
---|
| 663 | unlink($_) if ($_ =~ /\.rpmorig$/);
|
---|
| 664 | unlink($_) if ($_ =~ /\.rpmnew$/);
|
---|
| 665 | }
|
---|
[1802] | 666 |
|
---|
| 667 | # Function to store packages found on Web pages
|
---|
| 668 |
|
---|
| 669 | sub rbs_find_pkg {
|
---|
| 670 |
|
---|
| 671 | my $l = shift;
|
---|
| 672 | my $parch = shift;
|
---|
| 673 | my $type = shift;
|
---|
| 674 |
|
---|
| 675 | pb_log(2,"Entering rbs_find_pkg with l=$l and parch=$parch\n");
|
---|
| 676 | # Find a href ref in first pos
|
---|
| 677 | if ($l =~ /<a href="([^<>]*)">([^<>]*)<\/a>/i) {
|
---|
| 678 | my $pkg = $1;
|
---|
| 679 | my $desc = $2;
|
---|
| 680 | pb_log(3,"Found desc URL $desc: ");
|
---|
| 681 | # find an rpm package ref name-ver-tag.arch.rpm
|
---|
| 682 | if (($type eq "pkg") && ($pkg =~ /(.+)-([^-]+)-([^-]+)\.(noarch|$parch)\.rpm$/)) {
|
---|
| 683 | pb_log(3,"package ($1 + $2 + $3 + $4)\n");
|
---|
| 684 | my $url = $1;
|
---|
| 685 | pb_log(2,"Exiting rbs_find_pkg with url=$url and desc=$desc\n");
|
---|
[1964] | 686 | return($url,$pkg);
|
---|
[1802] | 687 | } elsif (($type eq "dir") && ($pkg =~ /([0-z])\//)) {
|
---|
| 688 | my $url = $1;
|
---|
| 689 | pb_log(3,"dir ($1)\n");
|
---|
| 690 | return($url,$1);
|
---|
| 691 | } else {
|
---|
| 692 | pb_log(3,"not a package\n");
|
---|
| 693 | }
|
---|
| 694 | }
|
---|
| 695 | pb_log(2,"Exiting rbs_find_pkg with undef\n");
|
---|
| 696 | return(undef,undef);
|
---|
| 697 | }
|
---|
| 698 |
|
---|
| 699 | sub rbs_mirror_response {
|
---|
| 700 |
|
---|
| 701 | my $mirror = shift;
|
---|
| 702 |
|
---|
| 703 | pb_log(0,"Downloading package list from $mirror ...\n");
|
---|
| 704 | my $response = $ua->get($mirror);
|
---|
| 705 | if (! $response->is_success) {
|
---|
| 706 | if ($mirror =~ /i386/) {
|
---|
| 707 | # Some distro have an i586 or i686 mirror dir instead for i386
|
---|
| 708 | warn "Unable to download package from $mirror for $pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}.".$response->status_line;
|
---|
| 709 | $mirror =~ s|/i386/|/i586/|;
|
---|
| 710 | pb_log(0,"Downloading now package list from $mirror ...\n");
|
---|
| 711 | $response = $ua->get($mirror);
|
---|
| 712 | if (! $response->is_success) {
|
---|
| 713 | die "Unable to download package from $mirror for $pbos->{'name'}-$pbos->{'version'}-$pbos->{'arch'}".$response->status_line;
|
---|
| 714 | }
|
---|
| 715 | }
|
---|
| 716 | }
|
---|
| 717 | pb_log(3,"Mirror $mirror gave answer: ".Dumper($response->dump(maxlength => 0))."\n");
|
---|
| 718 |
|
---|
| 719 | # Try to find where the repodata structure is for later usage
|
---|
| 720 | my $repo = $mirror;
|
---|
| 721 | my $found = 0;
|
---|
[2012] | 722 | if (($pbos->{'install'} =~ /yum/) || ($pbos->{'install'} =~ /dnf/)) {
|
---|
[1802] | 723 | my $response1;
|
---|
| 724 | while ($found == 0) {
|
---|
| 725 | $response1 = $ua->get("$repo/repodata");
|
---|
| 726 | pb_log(2,"REPO analyzed: $repo\n");
|
---|
| 727 | if (! $response1->is_success) {
|
---|
| 728 | $repo = dirname($repo);
|
---|
| 729 |
|
---|
| 730 | # There is a limit to the loop, when / is reached and nothing found
|
---|
| 731 | my ($scheme, $account, $host, $port, $path) = pb_get_uri($repo);
|
---|
| 732 | die "Unable to find the repodata structure of the mirror $mirror\nPlease check the URL or warn the dev team.\n" if (($path =~ /^[\/]+$/) || ($path =~ /^$/));
|
---|
| 733 |
|
---|
| 734 | # / not reached, so looping
|
---|
| 735 | next;
|
---|
| 736 | } else {
|
---|
| 737 | # repodata found $repo is correct
|
---|
| 738 | $found = 1;
|
---|
| 739 | pb_log(2,"REPO found: $repo\n");
|
---|
| 740 | last;
|
---|
| 741 | }
|
---|
| 742 | }
|
---|
| 743 | }
|
---|
[1815] | 744 | return($repo,$response);
|
---|
[1802] | 745 | }
|
---|
| 746 |
|
---|