[Libguestfs] [PATCH] Use RHN to retrieve replacement packages

Milan Zazrivec mzazrivec at redhat.com
Mon May 17 10:25:33 UTC 2010


On Friday 14 May 2010 17:43:34 Matthew Booth wrote:
> Milan,
> 
> Some comments inline.
> 
> On 14/05/10 15:06, Milan Zazrivec wrote:
> > For guests registered with Red Hat Network, this patch allows for
> > the conversion process to use RHN to download appropriate kernel
> > package and its dependencies.
> >
> > We use yum on RHEL-5, up2date libraries on RHEL-4.
> >
> > We install matching kernel version whenever possible, latest available
> > kernel version otherwise.
> >
> > _discover_kernel routine has been extended to return version-release
> > of the default kernel found.
> > ---
> >  lib/Sys/VirtV2V/GuestOS/RedHat.pm |  166
> > ++++++++++++++++++++++++++++-------- 1 files changed, 129 insertions(+),
> > 37 deletions(-)
> >
> > diff --git a/lib/Sys/VirtV2V/GuestOS/RedHat.pm
> > b/lib/Sys/VirtV2V/GuestOS/RedHat.pm index 77f0f3a..38a485c 100644
> > --- a/lib/Sys/VirtV2V/GuestOS/RedHat.pm
> > +++ b/lib/Sys/VirtV2V/GuestOS/RedHat.pm
> > @@ -475,7 +475,7 @@ sub add_kernel
> >  {
> >      my $self = shift;
> >
> > -    my ($kernel_pkg, $kernel_arch) = $self->_discover_kernel();
> > +    my ($kernel_pkg, $kernel_ver, $kernel_arch) =
> > $self->_discover_kernel();
> >
> >      # If the guest is using a Xen PV kernel, choose an appropriate
> > normal kernel # replacement
> > @@ -547,56 +547,142 @@ sub add_kernel
> >          }
> >      }
> >
> > -    my ($app, $depnames);
> > -    eval {
> > +    my $version;
> > +
> > +    # systemid exists, assume the system is registered w/ RHN
> > +    if ($self->{g}->exists('/etc/sysconfig/rhn/systemid')) {
> 
> Can we make this less of an explicit check for RHN registration that a
> check for the availability of an update mechanism? I was thinking you'd
> check to see if up2date/yum was installed, and if it was, try to run it.
> If running it failed, fall back to the config.

This could be done I think.

> >          my $desc = $self->{desc};
> >
> > -        ($app, $depnames) =
> > -            $self->{config}->match_app($desc, $kernel_pkg,
> > $kernel_arch); -    };
> > -    # Return undef if we didn't find a kernel
> > -    if ($@) {
> > -        print STDERR $@;
> > -        return undef;
> > -    }
> > +        my ($min_virtio_ver, @kern_vr, @preinst_cmd, @inst_cmd,
> > $inst_fmt);
> >
> > -    my @missing;
> > -    if (!$self->{g}->exists($self->_transfer_path($app))) {
> > -        push(@missing, $app);
> > +        # filter out xen/xenU from release field
> > +        if ($kernel_ver =~ /^(\S+)-(\S+?)(xen)?(U)?$/) {
> > +            @kern_vr = ($1, $2);
> > +            $kernel_ver = join('-', @kern_vr);
> > +        }
> > +
> > +        # RHEL-5
> > +        if ($desc->{distro} eq 'rhel' && $desc->{major_version} eq '5')
> > {
> 
> Again, with these tests, could we just check for the existence of
> /usr/bin/yum? I guess we'd need to use up2date in preference to yum if
> it was installed, as the most likely scenario here is RHEL 3/4 using yum
> for non-core repos.

Yes, sounds reasonable.

> > +            if (_rpmvercmp($kernel_ver, '2.6.18-128.el5') >= 0) {
> > +                # Install matching kernel version
> > +                @inst_cmd = ('/usr/bin/yum', '-y', 'install',
> > +                             "$kernel_pkg-$kernel_ver");
> > +            } else {
> > +                # Install latest available kernel version
> > +                @inst_cmd = ('/usr/bin/yum', '-y', 'install',
> > $kernel_pkg); +
> > +                # We need to upgrade kernel deps. first to avoid
> > possible conflicts
> 
> Why can't yum do it all in one go?

yum can do it all in one go as long as you don't have both i386 & x86_64
ecryptfs-utils installed (standard rhel-5 installation on x86_64 for example).

You run 'yum install kernel' and it will correctly try to upgrade
ecryptfs-utils.x86_64, but the new kernel will still conflict with
ecryptfs-utils.i386 and the command fails.

> > +                my @deps;
> > +                my $deps = ($self->{config}->match_app($desc,
> > $kernel_pkg, $kernel_arch))[1]; +
> > +                if ($deps) {
> > +                    @preinst_cmd = (('/usr/bin/yum', '-y', 'upgrade'),
> > @$deps); +                }
> > +            }
> > +        }
> > +        # RHEL-4
> > +        elsif ($desc->{distro} eq 'rhel' && $desc->{major_version} eq
> > '4') {
> 
> Using RHEL version to distinguish between the methods below is ok, I
> guess, as nothing except RHEL used up2date (as far as I'm aware).
> 
> > +            if (_rpmvercmp($kernel_ver, '2.6.9-89.EL') >= 0) {
> > +                # Install matching kernel version
> > +                @inst_cmd = ('/usr/bin/python', '-c',
> > +                    "import sys; sys.path.append('/usr/share/rhn');" .
> > +                    "import actions.packages;" .
> > +                    "actions.packages.cfg['forceInstall'] = 1;" .
> > +                    "actions.packages.update([['$kernel_pkg', " .
> > +                    "'$kern_vr[0]', '$kern_vr[1]', '']])");
> 
> Yuk, but ok ;)
> 
> > +            } else {
> > +                # Install latest available kernel version
> > +                @inst_cmd = ('/usr/sbin/up2date', '-fi', $kernel_pkg);
> > +
> > +                # We need to upgrade kernel deps. first to avoid
> > possible conflicts +                my $deps =
> > ($self->{config}->match_app($desc, $kernel_pkg, $kernel_arch))[1]; +
> > +                if ($deps) {
> > +                    @preinst_cmd = (('/usr/sbin/up2date', '-fu'),
> > @$deps); +                }
> > +            }
> > +        }
> > +        else {
> > +            @inst_cmd = ('/usr/sbin/up2date', '-fi', $kernel_pkg);
> > +        }
> > +
> > +        my (@k_before, @k_new);
> > +
> > +        # List of kernels before the new kernel installation
> > +        @k_before = $self->{g}->glob_expand('/boot/vmlinuz-*');
> > +
> > +        eval {
> > +            # Upgrade dependencies if needed
> > +            if (@preinst_cmd) {
> > +                $self->{g}->command(\@preinst_cmd);
> > +            }
> > +            # Install new kernel
> > +            $self->{g}->command(\@inst_cmd);
> 
> Again, why can't we do these in a single transaction?

up2date is not that flexible (as far as I know).

Anyway, we're looking at rhel-4 world, where we don't have to worry
about the problems with new kernel dependencies.

I'd vote for removing the up2date -fu part completely.

> > +        };
> > +
> > +        $self->_augeas_error($@) if ($@);
> 
> Just ditch the eval {} block here. I recently ditched these elsewhere in
> the code.

Okay.

> > +
> > +        # Figure out which kernel has just been installed
> > +        foreach my $k ($self->{g}->glob_expand('/boot/vmlinuz-*')) {
> > +            grep(/^$k$/, @k_before) or push(@k_new, $k);
> > +        }
> > +
> > +        # version-release of the new kernel package
> > +        $version = ($self->{g}->command_lines(
> > +            ['rpm', '-qf', '--qf=%{VERSION}-%{RELEASE}',
> > $k_new[0]]))[0];
> 
> As above, can we arrange this block to fall-through if the execution of
> up2date/yum failed for some reason?

Okay.

> >      } else {
> > -        return undef if ($self->_newer_installed($app));
> > -    }
> >
> > -    my $user_arch = $kernel_arch eq 'i686' ? 'i386' : $kernel_arch;
> > +        my ($app, $depnames);
> > +        eval {
> > +            my $desc = $self->{desc};
> >
> > -    my @deps = $self->_get_deppaths(\@missing, $user_arch, @$depnames);
> > +            ($app, $depnames) =
> > +                $self->{config}->match_app($desc, $kernel_pkg,
> > $kernel_arch); +        };
> > +        # Return undef if we didn't find a kernel
> > +        if ($@) {
> > +            print STDERR $@;
> > +            return undef;
> > +        }
> >
> > -    # We can't proceed if there are any files missing
> > -    _die_missing(@missing) if (@missing > 0);
> > +        my @missing;
> > +        if (!$self->{g}->exists($self->_transfer_path($app))) {
> > +            push(@missing, $app);
> > +        } else {
> > +            return undef if ($self->_newer_installed($app));
> > +        }
> >
> > -    # Install any required kernel dependencies
> > -    $self->_install_rpms(1, @deps);
> > +        my $user_arch = $kernel_arch eq 'i686' ? 'i386' : $kernel_arch;
> >
> > -    # Inspect the rpm to work out what kernel version it contains
> > -    my $version;
> > -    my $g = $self->{g};
> > -    foreach my $file ($g->command_lines
> > -        (["rpm", "-qlp", $self->_transfer_path($app)]))
> > -    {
> > -        if($file =~ m{^/boot/vmlinuz-(.*)$}) {
> > -            $version = $1;
> > -            last;
> > +        my @deps = $self->_get_deppaths(\@missing, $user_arch,
> > @$depnames); +
> > +        # We can't proceed if there are any files missing
> > +        _die_missing(@missing) if (@missing > 0);
> > +
> > +        # Install any required kernel dependencies
> > +        $self->_install_rpms(1, @deps);
> > +
> > +        # Inspect the rpm to work out what kernel version it contains
> > +        my $g = $self->{g};
> > +        foreach my $file ($g->command_lines
> > +            (["rpm", "-qlp", $self->_transfer_path($app)]))
> > +        {
> > +            if($file =~ m{^/boot/vmlinuz-(.*)$}) {
> > +                $version = $1;
> > +                last;
> > +            }
> >          }
> > -    }
> >
> > -    die(user_message(__x("{path} doesn't contain a valid kernel",
> > -                         path => $app))) if(!defined($version));
> > +        die(user_message(__x("{path} doesn't contain a valid kernel",
> > +                             path => $app))) if(!defined($version));
> >
> > -    $self->_install_rpms(0, ($app));
> > +        $self->_install_rpms(0, ($app));
> > +
> > +    }
> >
> >      # Make augeas reload so it'll find the new kernel
> >      eval {
> > -        $g->aug_load();
> > +        $self->{g}->aug_load();
> 
> Why?

Because my $g = $self->{g}; is no longer valid here, but this could
be handled more nicely, I agree.

-Milan Zázrivec

> >      };
> >
> >      $self->_augeas_error($@) if ($@);
> > @@ -632,6 +718,7 @@ sub _discover_kernel
> >
> >      # Get a current bootable kernel, preferrably the default
> >      my $kernel_pkg;
> > +    my $kernel_ver;
> >      my $kernel_arch;
> >
> >      foreach my $i (@configs) {
> > @@ -647,6 +734,11 @@ sub _discover_kernel
> >
> >          # Get the kernel package name
> >          $kernel_pkg = $kernel->{package};
> > +
> > +        # Get the kernel package version
> > +        $kernel_ver = $kernel->{version};
> > +
> > +        last;
> >      }
> >
> >      # Default to 'kernel' if package name wasn't discovered
> > @@ -664,7 +756,7 @@ sub _discover_kernel
> >      # a very long time.
> >      $kernel_arch = 'i686' if('i386' eq $kernel_arch);
> >
> > -    return ($kernel_pkg, $kernel_arch);
> > +    return ($kernel_pkg, $kernel_ver, $kernel_arch);
> >  }
> >
> >  =item remove_kernel(version)
> > -- 1.7.1
> 
> Thanks,
> 
> Matt
> 




More information about the Libguestfs mailing list