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