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

Milan Zazrivec mzazrivec at redhat.com
Fri May 14 14:06:54 UTC 2010


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')) {
         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') {
+            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
+                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') {
+            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]', '']])");
+            } 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);
+        };
+
+        $self->_augeas_error($@) if ($@);
+
+        # 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];
     } 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();
     };
 
     $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




More information about the Libguestfs mailing list