On Tuesday, October 08, 2013 10:05:17 AM Matthew Booth wrote:
Feel free to remove ^$path. However, for robustness I ditch the
leading
^ from your replacement. The difference will be down to a different
version of file included in the libguestfs appliance on SUSE.
I think I've addressed all the concerns you raised in the following patch. Can
you take a look and let me know if I've created any new ones? ;)
I have had to jump through a few hoops with regards to the SUSE -base kernel,
the kernel flavor, and an irritating build number... But I've been careful to
avoid changing variables for non-SUSE environments. There are a couple of
small places that could still happen (in _inspect_linux_kernel), but I think
there are enough safeguards in place that it shouldn't happen.
Thanks,
Mike
---
.../VirtConvert/Converter/{RedHat.pm => Linux.pm} | 797
++++++++++++++++-----
1 file changed, 632 insertions(+), 165 deletions(-)
rename lib/Sys/VirtConvert/Converter/{RedHat.pm => Linux.pm} (75%)
diff --git a/lib/Sys/VirtConvert/Converter/RedHat.pm
b/lib/Sys/VirtConvert/Converter/Linux.pm
similarity index 75%
rename from lib/Sys/VirtConvert/Converter/RedHat.pm
rename to lib/Sys/VirtConvert/Converter/Linux.pm
index 612ab2e..34752cf 100644
--- a/lib/Sys/VirtConvert/Converter/RedHat.pm
+++ b/lib/Sys/VirtConvert/Converter/Linux.pm
@@ -1,5 +1,6 @@
-# Sys::VirtConvert::Converter::RedHat
+# Sys::VirtConvert::Converter::Linux
# Copyright (C) 2009-2012 Red Hat Inc.
+# Copyright (C) 2013 SUSE Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
@@ -19,9 +20,9 @@ use strict;
use warnings;
-# Functions supported by grubby, and therefore common between gruby legacy
and
-# grub2
-package Sys::VirtConvert::Converter::RedHat::Grub;
+# Functions supported by grubby or perl-Bootloader, and therefore common
+# between grub legacy grub2
+package Sys::VirtConvert::Converter::Linux::Grub;
use Sys::VirtConvert::Util;
use Locale::TextDomain 'virt-v2v';
@@ -30,16 +31,85 @@ sub get_initrd
{
my $self = shift;
my ($path) = @_;
+ my $initrd;
my $g = $self->{g};
- foreach my $line ($g->command_lines(['grubby', '--info', $path]))
{
- return $1 if $line =~ /^initrd=(\S+)/;
+ if ($g->exists('/sbin/grubby')) {
+ foreach my $line ($g->command_lines(['grubby', '--info',
$path])) {
+ return $1 if $line =~ /^initrd=(\S+)/;
+ }
+ } else {
+ # If grubby did not work, try perl-Bootloader (for SUSE environments)
+ $initrd = eval { $g->command(['/usr/bin/perl',
+ '-MBootloader::Tools',
+ '-e', 'InitLibrary(); '.
+ 'my @sections = '.
+ 'GetSectionList(type=>image, image=>"'.$path.'");
'.
+ 'my $section = GetSection(@sections); '.
+ 'my $initrd = $section->{initrd}; '.
+ 'print $initrd;']) };
+
+ if (defined($initrd)) {
+ # If the initrd starts with (hdX,X), remove it.
+ $initrd =~ s/^\(hd.*\)//;
+ return $initrd if ($initrd =~ /^\//);
+ }
}
+ # If all else fails, use heuristics if the file exists
+ ($initrd = $path) =~ s/vmlinuz/initrd/;
+ return $initrd if ($g->exists($initrd));
+
v2vdie __x('Didn\'t find initrd for kernel {path}', path => $path);
}
+sub get_default_image
+{
+ my $self = shift;
+ my $default;
+
+ my $g = $self->{g};
+
+ if ($g->exists('/sbin/grubby')) {
+ $default = $g->command(['grubby', '--default-kernel']);
+ } else {
+ $default = eval { $g->command(['/usr/bin/perl',
+ '-MBootloader::Tools',
+ '-e', 'InitLibrary(); '.
+ 'my $default=Bootloader::Tools::GetDefaultSection(); '.
+ 'print $default->{image};']) };
+ # If the image starts with (hdX,X), remove it.
+ $default =~ s/^\(hd.*\)//;
+ }
+
+ chomp($default);
+ return $default;
+}
+
+sub set_default_image
+{
+ my $self = shift;
+ my ($path) = @_;
+
+ my $g = $self->{g};
+
+ if ($g->exists('/sbin/grubby')) {
+ $g->command(['grubby', '--set-default', $path]);
+ } else {
+ # Using the image path to set a default image is not always reliable.
+ # To be safe, get the image name, then set that as the default image.
+ eval { $g->command(['/usr/bin/perl',
+ '-MBootloader::Tools',
+ '-e', 'InitLibrary(); '.
+ 'my @sections = '.
+ 'GetSectionList(type=>image, image=>"'.$path.'");
'.
+ 'my $section = GetSection(@sections); '.
+ 'my $newdefault = $section->{name}; '.
+ 'SetGlobals(default, "$newdefault");']) };
+ }
+}
+
sub check_efi
{
my $self = shift;
@@ -61,15 +131,15 @@ sub check_efi
# Methods for inspecting and manipulating grub legacy
-package Sys::VirtConvert::Converter::RedHat::GrubLegacy;
+package Sys::VirtConvert::Converter::Linux::GrubLegacy;
-use Sys::VirtConvert::Util;
+use Sys::VirtConvert::Util qw(:DEFAULT augeas_error);
use File::Basename;
use Locale::TextDomain 'virt-v2v';
-@Sys::VirtConvert::Converter::RedHat::GrubLegacy::ISA =
- qw(Sys::VirtConvert::Converter::RedHat::Grub);
+@Sys::VirtConvert::Converter::Linux::GrubLegacy::ISA =
+ qw(Sys::VirtConvert::Converter::Linux::Grub);
sub new
{
@@ -127,7 +197,8 @@ sub new
# If it wasn't there, add it
unless ($found) {
- $g->aug_set("/augeas/load/Grub/incl[last()+1]", $self-
{grub_conf});
+
$g->aug_set("/augeas/load/Grub/incl[last()+1]",
+ $self-
{grub_conf});
# Make augeas pick up the new configuration
$g->aug_load();
@@ -236,7 +307,7 @@ sub update_console
sub check
{
my $self = shift;
- my ($path) = @_;
+ my ($path, $root) = @_;
my $g = $self->{g};
my $grub_conf = $self->{grub_conf};
@@ -247,19 +318,22 @@ sub check
my $grub_path = $1;
# Nothing to do if the kernel already has a grub entry
- my @entries = $g->aug_match("/files$grub_conf/title/kernel[. =
'$grub_path']");
+ my @entries = $g->aug_match("/files$grub_conf/title/kernel".
+ "[. = '$grub_path']");
return if scalar(@entries) > 0;
my $kernel =
- Sys::VirtConvert::Converter::RedHat::_inspect_linux_kernel($g,
$path);
+ Sys::VirtConvert::Converter::Linux::_inspect_linux_kernel($g, $path);
my $version = $kernel->{version};
my $grub_initrd = dirname($path)."/initrd-$version";
- # No point in dying if /etc/redhat-release can't be read
- my ($title) = eval { $g->read_lines('/etc/redhat-release') };
+ # No point in dying if /etc/(distro)-release can't be read
+ my ($title) = eval { $g->inspect_get_product_name($root) };
$title ||= 'Linux';
- # This is how new-kernel-pkg does it
+ # Remove codename or architecture
+ $title =~ s/ \(.*\)//;
+ # Remove release string and add version (like new-kernel-pkg)
$title =~ s/ release.*//;
$title .= " ($version)";
@@ -365,13 +439,13 @@ sub convert_efi
# attempt to use grub2's configuration because it's utterly insane. Instead,
# we reverse engineer the way the config is automatically generated and use
# that instead.
-package Sys::VirtConvert::Converter::RedHat::Grub2;
+package Sys::VirtConvert::Converter::Linux::Grub2;
use Sys::VirtConvert::Util qw(:DEFAULT augeas_error);
use Locale::TextDomain 'virt-v2v';
-@Sys::VirtConvert::Converter::RedHat::Grub2::ISA =
- qw(Sys::VirtConvert::Converter::RedHat::Grub);
+@Sys::VirtConvert::Converter::Linux::Grub2::ISA =
+ qw(Sys::VirtConvert::Converter::Linux::Grub);
sub new
{
@@ -407,8 +481,7 @@ sub list_kernels
my @kernels;
# Start by adding the default kernel
- my $default = $g->command(['grubby', '--default-kernel']);
- chomp($default);
+ my $default = $self->get_default_image();
push(@kernels, $default) if length($default) > 0;
# This is how the grub2 config generator enumerates kernels
@@ -430,8 +503,15 @@ sub update_console
my $g = $self->{g};
+ my $grub_cmdline;
+ if ($g->exists('/etc/sysconfig/grub')) {
+ $grub_cmdline = '/files/etc/sysconfig/grub/GRUB_CMDLINE_LINUX';
+ } else {
+ $grub_cmdline = '/files/etc/default/grub/GRUB_CMDLINE_LINUX_DEFAULT';
+ }
+
my $cmdline =
- eval { $g->aug_get('/files/etc/sysconfig/grub/GRUB_CMDLINE_LINUX') };
+ eval { $g->aug_get($grub_cmdline) };
if (defined($cmdline) && $cmdline =~ /\bconsole=(?:x|h)vc0\b/) {
if ($remove) {
@@ -441,7 +521,7 @@ sub update_console
}
eval {
- $g->aug_set('/files/etc/sysconfig/grub/GRUB_CMDLINE_LINUX',
$cmdline);
+ $g->aug_set($grub_cmdline, $cmdline);
$g->aug_save();
};
augeas_error($g, $@) if ($@);
@@ -463,11 +543,14 @@ sub write
my $g = $self->{g};
- my $default = $g->command(['grubby', '--default-kernel']);
- chomp($default);
+ my $default = $self->get_default_image();
if ($default ne $path) {
- $g->command(['grubby', '--set-default', $path]);
+ eval { $self->set_default_image($path) };
+ if ($@) {
+ logmsg WARN, __x('Unable to set default kernel to {path}',
+ path => $path);
+ }
}
}
@@ -486,7 +569,7 @@ sub convert_efi
# EFI systems boot using grub2-efi, and probably don't have the base grub2
# package installed.
- Sys::VirtConvert::Convert::RedHat::_install_any
+ Sys::VirtConvert::Convert::Linux::_install_any
(undef, ['grub2'], undef, $g, $self->{root}, $self->{config},
$self)
or v2vdie __x('Failed to install non-EFI grub2');
@@ -494,7 +577,8 @@ sub convert_efi
$g->part_set_gpt_type($device, 1,
'21686148-6449-6E6F-744E-656564454649');
# Delete the fstab entry for the EFI boot partition
- foreach my $node ($g->aug_match("/files/etc/fstab/*[file =
'/boot/efi']")) {
+ foreach my $node ($g->aug_match("/files/etc/fstab/*[file =
'/boot/efi']"))
+ {
$g->aug_rm($node);
}
eval { $g->aug_save(); };
@@ -509,7 +593,7 @@ sub convert_efi
}
-package Sys::VirtConvert::Converter::RedHat;
+package Sys::VirtConvert::Converter::Linux;
use Sys::VirtConvert::Util qw(:DEFAULT augeas_error scsi_first_cmp);
use Locale::TextDomain 'virt-v2v';
@@ -518,7 +602,7 @@ use Locale::TextDomain 'virt-v2v';
=head1 NAME
-Sys::VirtConvert::Converter::RedHat - Convert a Red Hat based guest to run on
KVM
+Sys::VirtConvert::Converter::Linux - Convert a Linux based guest to run on
KVM
=head1 SYNOPSIS
@@ -528,7 +612,7 @@ Sys::VirtConvert::Converter::RedHat - Convert a Red Hat
based guest to run on KV
=head1 DESCRIPTION
-Sys::VirtConvert::Converter::RedHat converts a Red Hat based guest to use
KVM.
+Sys::VirtConvert::Converter::Linux converts a Linux based guest to use KVM.
=head1 METHODS
@@ -541,12 +625,21 @@ sub _is_rhel_family
my ($g, $root) = @_;
return ($g->inspect_get_type($root) eq 'linux') &&
- ($g->inspect_get_distro($root) =~ /^(rhel|centos|scientificlinux|
redhat-based)$/);
+ ($g->inspect_get_distro($root) =~
+ /^(rhel|centos|scientificlinux|redhat-based)$/);
+}
+
+sub _is_suse_family
+{
+ my ($g, $root) = @_;
+
+ return ($g->inspect_get_type($root) eq 'linux') &&
+ ($g->inspect_get_distro($root) =~ /^(sles|suse-based|opensuse)$/);
}
-=item Sys::VirtConvert::Converter::RedHat->can_handle(g, root)
+=item Sys::VirtConvert::Converter::Linux->can_handle(g, root)
-Return 1 if Sys::VirtConvert::Converter::RedHat can convert the given guest
+Return 1 if Sys::VirtConvert::Converter::Linux can convert the given guest
=cut
@@ -556,13 +649,17 @@ sub can_handle
my ($g, $root) = @_;
- return ($g->inspect_get_type($root) eq 'linux' &&
- (_is_rhel_family($g, $root) || $g->inspect_get_distro($root) eq
'fedora'));
+ if ($g->inspect_get_type($root) eq 'linux') {
+ return (_is_rhel_family($g, $root) ||
+ ($g->inspect_get_distro($root) eq 'fedora') ||
+ _is_suse_family($g, $root));
+ }
}
-=item Sys::VirtConvert::Converter::RedHat->convert(g, root, config, meta,
options)
+=item Sys::VirtConvert::Converter::Linux->convert(g, root, config, meta,
+ options)
-Convert a Red Hat based guest. Assume that can_handle has previously returned
1.
+Convert a Linux based guest. Assume that can_handle has previously returned
1.
=over
@@ -601,8 +698,10 @@ sub convert
_init_augeas($g);
my $grub;
- $grub = eval { Sys::VirtConvert::Converter::RedHat::Grub2->new($g, $root,
$config) };
- $grub = eval { Sys::VirtConvert::Converter::RedHat::GrubLegacy->new($g,
$root) }
+ $grub = eval
+ { Sys::VirtConvert::Converter::Linux::Grub2->new($g, $root, $config) };
+ $grub = eval
+ { Sys::VirtConvert::Converter::Linux::GrubLegacy->new($g, $root) }
unless defined($grub);
v2vdie __('No grub configuration found') unless defined($grub);
@@ -611,13 +710,15 @@ sub convert
_unconfigure_hv($g, $root);
# Try to install the virtio capability
- my $virtio = _install_capability('virtio', $g, $root, $config, $meta,
$grub);
+ my $virtio =
+ _install_capability('virtio', $g, $root, $config, $meta, $grub);
# Get an appropriate kernel, or install one if none is available
my $kernel = _configure_kernel($virtio, $g, $root, $config, $meta, $grub);
# Install user custom packages
- if (! _install_capability('user-custom', $g, $root, $config, $meta,
$grub)) {
+ if (! _install_capability('user-custom',
+ $g, $root, $config, $meta, $grub)) {
logmsg WARN, __('Failed to install user-custom packages');
}
@@ -625,8 +726,9 @@ sub convert
my $remove_serial_console = exists($options->{NO_SERIAL_CONSOLE});
_configure_console($g, $grub, $remove_serial_console);
- _configure_display_driver($g, $root, $config, $meta, $grub);
- _remap_block_devices($meta, $virtio, $g, $root);
+ my $driver = _get_display_driver($g, $root);
+ _configure_display_driver($g, $root, $config, $meta, $grub, $driver);
+ _remap_block_devices($meta, $virtio, $g, $root, $grub);
_configure_kernel_modules($g, $virtio);
_configure_boot($kernel, $virtio, $g, $root, $grub);
@@ -647,8 +749,9 @@ sub _init_selinux
# Assume SELinux isn't in use if load_policy isn't available
return if(!$g->exists('/usr/sbin/load_policy'));
- # Actually loading the policy has proven to be problematic. We make
whatever
- # changes are necessary, and make the guest relabel on the next boot.
+ # Actually loading the policy has proven to be problematic. We make
+ # whatever changes are necessary, and make the guest relabel on the
+ # next boot.
$g->touch('/.autorelabel');
}
@@ -689,8 +792,8 @@ sub _discover_modpath
my $modpath;
- # Note that we're checking in ascending order of preference so that the
last
- # discovered method will be chosen
+ # Note that we're checking in ascending order of preference so that the
+ # last discovered method will be chosen
foreach my $file ('/etc/conf.modules', '/etc/modules.conf') {
if($g->exists($file)) {
@@ -759,7 +862,8 @@ sub _configure_kernel_modules
my @xen_modules = qw(xennet xen-vnif xenblk xen-vbd);
my $query = '('.join('|', @xen_modules).')';
- foreach my $path (_aug_modprobe($g, "modulename =~
regexp('$query')")) {
+ foreach my $path (_aug_modprobe($g, "modulename =~
regexp('$query')"))
+ {
my $device = $g->aug_get($path);
my $module = $g->aug_get($path.'/modulename');
@@ -783,13 +887,13 @@ sub _configure_kernel_modules
augeas_error($g, $@) if $@;
}
-# We configure a console on ttyS0. Make sure existing console references use
it.
+# Configure a console on ttyS0. Make sure existing console references use it.
# N.B. Note that the RHEL 6 xen guest kernel presents a console device called
-# /dev/hvc0, whereas previous xen guest kernels presented /dev/xvc0. The
regular
-# kernel running under KVM also presents a virtio console device called
-# /dev/hvc0, so ideally we would just leave it alone. However, RHEL 6 libvirt
-# doesn't yet support this device so we can't attach to it. We therefore use
-# /dev/ttyS0 for RHEL 6 anyway.
+# /dev/hvc0, whereas previous xen guest kernels presented /dev/xvc0. The
+# regular kernel running under KVM also presents a virtio console device
+# called /dev/hvc0, so ideally we would just leave it alone. However, RHEL 6
+# libvirt doesn't yet support this device so we can't attach to it. We
+# therefore use /dev/ttyS0 for RHEL 6 anyway.
#
# If the target doesn't support a serial console, we want to remove all
# references to it instead.
@@ -842,7 +946,7 @@ sub _configure_console
sub _configure_display_driver
{
- my ($g, $root, $config, $meta, $grub) = @_;
+ my ($g, $root, $config, $meta, $grub, $driver) = @_;
# Update the display driver if it exists
my $updated = 0;
@@ -866,7 +970,7 @@ sub _configure_display_driver
}
foreach my $path
($g->aug_match('/files'.$xorg.'/Device/Driver')) {
- $g->aug_set($path, 'qxl');
+ $g->aug_set($path, $driver);
$updated = 1;
}
@@ -884,20 +988,21 @@ sub _configure_display_driver
# Propagate augeas errors
augeas_error($g, $@) if ($@);
- # If we updated the X driver, check if X itself is actually installed. If
it
- # is, ensure the qxl driver is installed.
+ # If we updated the X driver, check if X itself is actually installed. If
+ # it is, ensure the specified driver is installed.
if ($updated &&
($g->exists('/usr/bin/X') || $g->exists('/usr/bin/X11/X'))
&&
- !_install_capability('qxl', $g, $root, $config, $meta, $grub))
+ !_install_capability($driver, $g, $root, $config, $meta, $grub))
{
- logmsg WARN, __('Display driver was updated to qxl, but unable to '.
- 'install qxl driver. X may not function correctly');
+ logmsg WARN, __x('Display driver was updated to {driver}, but unable
'.
+ 'to install {driver} driver. X may not function '.
+ 'correctly', driver => $driver);
}
}
# If the guest was shutdown uncleanly, it's possible that transient state was
-# left lying around in the rpm database. Given we know that nothing is using
the
-# rpmdb at this point, it's safe to delete these files.
+# left lying around in the rpm database. Given we know that nothing is using
+# the rpmdb at this point, it's safe to delete these files.
sub _clean_rpmdb
{
my $g = shift;
@@ -925,20 +1030,46 @@ sub _inspect_linux_kernel
# If this is a packaged kernel, try to work out the name of the package
# which installed it. This lets us know what to install to replace it
with,
# e.g. kernel, kernel-smp, kernel-hugemem, kernel-PAE
- my $package = eval { $g->command(['rpm', '-qf', '--qf',
- '%{NAME}', $path]) };
- $kernel{package} = $package if defined($package);;
+ #
+ # Due to the inclusion of a build number in SUSE packages, the version
+ # found through file and the kernel filename does not always match the
+ # version required for installation later. Get the full version-release
+ # here and track it through $kernel{fullversion}.
+ my $package;
+ my $flavor;
+ my $rpminfo = eval { $g->command(['rpm', '-qf', '--qf',
+ '%{NAME} %{VERSION}-%{RELEASE}', $path])
};
+ if (defined($rpminfo)) {
+ $rpminfo =~ /(\S+)\s(\S+)/;
+ $package = $1;
+ my $fullversion = $2;
+
+ # Some SUSE kernels are from a -base package, but it's more correct
to
+ # use the non -base package name.
+ $package =~ s/-base$//;
+ $kernel{package} = $package;
+
+ # fullversion must include the flavor (xen, smp, default, etc.) of the
+ # kernel as well (if one exists)
+ ($flavor = $package) =~ s/^kernel//;
+ $fullversion = $fullversion.$flavor if defined($flavor);
+ $kernel{fullversion} = $fullversion;
+ }
# Try to get the kernel version by running file against it
my $version;
my $filedesc = $g->file($path);
- if($filedesc =~ /^$path: Linux kernel .*\bversion\s+(\S+)\b/) {
+ if($filedesc =~ /Linux.* [kK]ernel.*\b[vV]ersion\s+(\S+)\b/) {
$version = $1;
- }
-
- # Sometimes file can't work out the kernel version, for example because
it's
- # a Xen PV kernel. In this case try to guess the version from the filename
- else {
+ # SUSE kernel version strings do not include the flavor
+ $version = $version.$flavor if defined($flavor);
+ # If $version is not correct here, default to the filename method
+ undef $version if(!$g->is_dir("/lib/modules/$version"));
+ }
+ # Sometimes file can't work out the kernel version, for example
+ # because it's a Xen PV kernel. In this case try to guess the version
+ # from the filename
+ if (!defined($version)) {
if($path =~ m{/boot/vmlinuz-(.*)}) {
$version = $1;
@@ -988,6 +1119,7 @@ sub _configure_kernel
# Pick first appropriate kernel returned by list_kernels
my $boot_kernel;
+ my $backup_ver;
foreach my $path ($grub->list_kernels()) {
my $kernel = _inspect_linux_kernel($g, $path);
my $version = $kernel->{version};
@@ -998,11 +1130,21 @@ sub _configure_kernel
# If we're configuring virtio, check this kernel supports it
next if ($virtio && !_supports_virtio($version, $g));
- $boot_kernel = $version;
+
+ # SUSE kernel installations require the version string which includes
+ # the build number. Change it here, but backup the original version
as
+ # it must be restored later.
+ if (_is_suse_family($g, $root)) {
+ $boot_kernel = $kernel->{fullversion};
+ $backup_ver = $version;
+ } else {
+ $boot_kernel = $version;
+ }
last;
}
- # There should be an installed virtio capable kernel if virtio was
installed
+ # There should be an installed virtio capable kernel if virtio was
+ # installed
die("virtio configured, but no virtio kernel found")
if ($virtio && !defined($boot_kernel));
@@ -1013,7 +1155,7 @@ sub _configure_kernel
# If the guest is using a Xen PV kernel, choose an appropriate
# normal kernel replacement
- if ($kernel_pkg eq "kernel-xen" || $kernel_pkg eq
"kernel-xenU") {
+ if ($kernel_pkg =~ /^kernel-xen/) {
$kernel_pkg = _get_replacement_kernel_name($g, $root,
$kernel_arch, $meta);
@@ -1055,7 +1197,7 @@ sub _configure_kernel
unless defined($boot_kernel);
} else {
v2vdie __x('Failed to find a {name} package to install',
- name => "kernel_pkg.$kernel_arch");
+ name => "$kernel_pkg.$kernel_arch");
}
}
}
@@ -1084,6 +1226,9 @@ sub _configure_kernel
augeas_error($g, $@) if ($@);
}
+ # If the kernel version was backed up previously (SUSE environments),
+ # restore the original value before returning it.
+ $boot_kernel = $backup_ver if defined($backup_ver);
return $boot_kernel;
}
@@ -1097,8 +1242,8 @@ sub _configure_boot
# reason is that the probing order determines the major number of vdX
# block devices. If we change it, RHEL 3 KVM guests won't boot.
_prepare_bootable($g, $root, $grub, $kernel, "virtio",
"virtio_ring",
- "virtio_blk",
"virtio_net",
- "virtio_pci");
+ "virtio_blk",
"virtio_net",
+ "virtio_pci");
} else {
_prepare_bootable($g, $root, $grub, $kernel, "sym53c8xx");
}
@@ -1121,8 +1266,8 @@ sub _get_os_arch
# Default to x86_64 if we still didn't find an architecture
return 'x86_64' unless defined($arch);
- # We want an i686 guest for i[345]86
- return 'i686' if($arch =~ /^i[345]86$/);
+ # Change i386 to i[56]86
+ $arch = _set_32bit_arch($g, $root, $arch);
return $arch;
}
@@ -1168,7 +1313,7 @@ sub _unconfigure_hv
my @apps = $g->inspect_list_applications($root);
- _unconfigure_xen($g, \@apps);
+ _unconfigure_xen($g, $root, \@apps);
_unconfigure_vbox($g, \@apps);
_unconfigure_vmware($g, \@apps);
_unconfigure_citrix($g, \@apps);
@@ -1177,7 +1322,7 @@ sub _unconfigure_hv
# Unconfigure Xen specific guest modifications
sub _unconfigure_xen
{
- my ($g, $apps) = @_;
+ my ($g, $root, $apps) = @_;
# Look for kmod-xenpv-*, which can be found on RHEL 3 machines
my @remove;
@@ -1230,6 +1375,27 @@ sub _unconfigure_xen
$g->write_file('/etc/rc.local', join("\n",
@rc_local)."\n",
$size);
}
}
+
+ if (_is_suse_family($g, $root)) {
+ # Remove xen modules from INITRD_MODULES and DOMU_INITRD_MODULES
+ my $sysconfig = '/etc/sysconfig/kernel';
+ my @variables = qw(INITRD_MODULES DOMU_INITRD_MODULES);
+ my @xen_modules = qw(xennet xen-vnif xenblk xen-vbd);
+ my $modified;
+
+ foreach my $var (@variables) {
+ foreach my $xen_mod (@xen_modules) {
+ foreach my $entry
+ ($g->aug_match("/files$sysconfig/$var/'.
+ 'value[. = '$xen_mod']"))
+ {
+ $g->aug_rm($entry);
+ $modified = 1;
+ }
+ }
+ }
+ $g->aug_save if (defined($modified));
+ }
}
# Unconfigure VirtualBox specific guest modifications
@@ -1313,8 +1479,8 @@ sub _unconfigure_vmware
# VMware tools includes 'libraries' packages which provide custom
versions
# of core functionality. We need to install non-custom versions of
- # everything provided by these packages before attempting to uninstall
them,
- # or we'll hit dependency issues
+ # everything provided by these packages before attempting to uninstall
+ # them, or we'll hit dependency issues
if (@libraries > 0) {
# We only support removal of these libraries packages on systems
which
# use yum.
@@ -1338,7 +1504,7 @@ sub _unconfigure_vmware
# of required dependencies out of our control.
my %alts;
foreach my $alt ($g->command_lines
- (['yum', '-q',
'resolvedep',
@provides]))
+ (['yum', '-q', 'resolvedep',
@provides]))
{
$alts{$alt} = 1;
}
@@ -1404,8 +1570,8 @@ sub _unconfigure_citrix
# The entries in question are named 1-6, and will normally be
# active in runlevels 2-5. They will be gettys. We could be
- # extremely prescriptive here, but allow for a reasonable
amount
- # of variation just in case.
+ # extremely prescriptive here, but allow for a reasonable
+ # amount of variation just in case.
next unless $comment =~ /^([1-6]):([2-5]+):respawn:(.*)/;
my $name = $1;
@@ -1483,8 +1649,8 @@ sub _install_capability
my ($kernel_pkg, $kernel_arch, $kernel_rpmver) =
_discover_kernel($g, $root, $grub);
- # If we didn't establish a kernel version, assume we have to
upgrade
- # it.
+ # If we didn't establish a kernel version, assume we have to
+ # upgrade it.
if (!defined($kernel_rpmver)) {
$kernel = [$kernel_pkg, $kernel_arch];
}
@@ -1506,13 +1672,13 @@ sub _install_capability
# If the guest is using a Xen PV kernel, choose an
appropriate
# normal kernel replacement
- if ($kernel_pkg eq "kernel-xen" || $kernel_pkg eq
"kernel-
xenU")
+ if ($kernel_pkg =~ /^kernel-xen/)
{
$kernel_pkg =
_get_replacement_kernel_name($g, $root, $kernel_arch,
$meta);
- # Check if we've got already got an appropriate kernel
+ # Check if we've already got an appropriate kernel
my ($inst) =
_get_installed("$kernel_pkg.$kernel_arch", $g);
@@ -1523,7 +1689,7 @@ sub _install_capability
{
# filter out xen/xenU from release field
if (defined($kernel_release) &&
- $kernel_release =~ /^(\S+?)(xen)?(U)?$/)
+ $kernel_release =~ /^(\S+?)(-xen)?(U)?$/)
{
$kernel_release = $1;
}
@@ -1574,7 +1740,8 @@ sub _install_capability
my ($epoch, $version, $release) = @$app;
if (_evr_cmp($app->[0], $app->[1], $app->[2],
- $min_epoch, $min_version, $min_release) >=
0) {
+ $min_epoch, $min_version, $min_release) >=
0)
+ {
$found = 1;
last;
}
@@ -1631,14 +1798,22 @@ sub _install_any
# If we're installing a kernel, check which kernels are there first
my @k_before = $g->glob_expand('/boot/vmlinuz-*') if defined($kernel);
+ # Workaround for SUSE bnc#836521
+ my $pbl_fix = _modify_perlBootloader($g) if (defined($kernel) &&
+ (_is_suse_family($g, $root)));
+
my $success = 0;
_net_run($g, sub {
eval {
# Try to fetch these dependencies using the guest's native update
# tool
- $success = _install_up2date($kernel, $install, $upgrade, $g);
- $success = _install_yum($kernel, $install, $upgrade, $g)
- unless ($success);
+ if (_is_suse_family($g, $root)) {
+ $success = _install_zypper($kernel, $install, $upgrade, $g);
+ } else {
+ $success = _install_up2date($kernel, $install, $upgrade, $g);
+ $success = _install_yum($kernel, $install, $upgrade, $g)
+ unless ($success);
+ }
# Fall back to local config if the above didn't work
$success = _install_config($kernel, $install, $upgrade,
@@ -1648,6 +1823,9 @@ sub _install_any
warn($@) if $@;
});
+ # Undo the previous workaround for SUSE bnc#836521
+ _restore_perlBootloader($g) if ($pbl_fix == 1);
+
# Make augeas reload to pick up any altered configuration
eval { $g->aug_load() };
augeas_error($g, $@) if ($@);
@@ -1657,7 +1835,7 @@ sub _install_any
if (defined($kernel)) {
foreach my $k ($g->glob_expand('/boot/vmlinuz-*')) {
if (!grep(/^$k$/, @k_before)) {
- $grub->check($k);
+ $grub->check($k, $root);
last;
}
}
@@ -1767,8 +1945,8 @@ sub _install_yum
}
foreach my $line (@output) {
- # Yum probably just isn't configured. Don't bother with an
error
- # message
+ # Yum probably just isn't configured. Don't bother with an
+ # error message
if ($line =~ /$failure/) {
$success = 0;
last YUM;
@@ -1780,6 +1958,90 @@ sub _install_yum
return $success;
}
+sub _install_zypper
+{
+ my ($kernel, $install, $update, $g) = @_;
+
+ # Check this system has zypper
+ return 0 unless ($g->exists('/usr/bin/zypper'));
+
+ # Install or update the kernel?
+ # If it isn't installed (because we're replacing a PV kernel), we need to
+ # install
+ # If we're installing a specific version, we need to install
+ # If the kernel package we're installing is already installed and we're
+ # just upgrading to the latest version, we need to update
+ if (defined($kernel)) {
+ my @installed = _get_installed($kernel->[0], $g);
+
+ # Don't modify the contents of $install and $update in case we fall
+ # through and they're reused in another function
+ if (@installed == 0 || defined($kernel->[2])) {
+ my @tmp = defined($install) ? @$install : ();
+ push(@tmp, $kernel);
+ $install = \@tmp;
+ } else {
+ my @tmp = defined($update) ? @$update : ();
+ push(@tmp, $kernel);
+ $update = \@tmp;
+ }
+ }
+
+ my $success = 1;
+ # Error when installing: "No provider of 'pkg' found."
+ # (Not an) Error when updating: "Package 'pkg' is not available in your
+ # repositories. Cannot reinstall, upgrade, or downgrade."
+ ZYPPER: foreach my $task (
+ [ "install", $install, qr/(^No package|already installed)/ ],
+ [ "update", $update, qr/(^No Packages|not available)/ ]
+ ) {
+ my ($action, $list, $failure) = @$task;
+
+ # Build a list of packages to install
+ my @pkgs;
+ foreach my $entry (@$list) {
+ next unless (defined($entry));
+
+ # zypper doesn't need arch or epoch
+ my ($name, undef, undef, $version, $release) = @$entry;
+
+ # Construct n-v-r
+ my $pkg = $name;
+ $pkg .= "-$version" if (defined($version));
+ $pkg .= "-$release" if (defined($release));
+
+
+ push(@pkgs, "$pkg");
+ }
+
+ if (@pkgs) {
+ my @output =
+ eval { $g->command(['/usr/bin/zypper', '-n', $action,
+ @pkgs]) };
+ if ($@) {
+ # Ignore 'No provider' errors as an install from the virt-v2v
+ # repo will be attempted next.
+ if ($@ !~ /No provider/) {
+ logmsg WARN, __x('Failed to install packages. '.
+ 'Error was: {error}', error => $@);
+ }
+ $success = 0;
+ last ZYPPER;
+ }
+ foreach my $line (@output) {
+ # Don't report an error or results if package is already
+ # installed or not found in a repo
+ if ($line =~ /$failure/) {
+ $success = 0;
+ last ZYPPER;
+ }
+ }
+ }
+ }
+
+ return $success;
+}
+
sub _install_config
{
my ($kernel_naevr, $install, $upgrade, $g, $root, $config) = @_;
@@ -1806,19 +2068,42 @@ sub _install_config
}
}
+
my @user_paths = _get_deppaths($g, $root, $config,
- \@missing, $g->inspect_get_arch($root),
@$user);
+ \@missing, $g->inspect_get_arch($root),
@$user);
# We can't proceed if there are any files missing
v2vdie __x('Installation failed because the following '.
'files referenced in the configuration file are '.
'required, but missing: {list}',
list => join(' ', @missing)) if scalar(@missing) > 0;
- # Install any non-kernel requirements
- _install_rpms($g, $config, 1, @user_paths);
- if (defined($kernel)) {
- _install_rpms($g, $config, 0, ($kernel));
+ # If a SUSE kernel is being added, a -base kernel could have been added
to
+ # to @user_paths (as a dep app). If so, move it to a new list containing
+ # both kernel and kernel-base packages to satisfy dependencies, and
+ # 'install' instead of 'upgrade' the packages.
+ if (_is_suse_family($g, $root) && (defined($kernel))) {
+ my @kernel_paths;
+ push(@kernel_paths, $kernel);
+ if (@user_paths) {
+ for my $index (reverse 0 .. scalar(@user_paths-1)) {
+ if ($user_paths[$index] =~ /(.*\/)kernel/) {
+ push(@kernel_paths, $user_paths[$index]);
+ splice(@user_paths, $index, 1);
+ }
+ }
+ # Install any non-kernel requirements
+ _install_rpms($g, $config, 1, @user_paths);
+ }
+ # Install kernel packages
+ _install_rpms($g, $config, 0, @kernel_paths);
+ } else {
+ # Install any non-kernel requirements
+ _install_rpms($g, $config, 1, @user_paths);
+
+ if (defined($kernel)) {
+ _install_rpms($g, $config, 0, ($kernel));
+ }
}
return 1;
@@ -1872,8 +2157,8 @@ sub _get_deppaths
}
}
- # For x86_64, also check if there is any i386 or i686 version
installed.
- # If there is, check if it needs to be upgraded.
+ # For x86_64, also check if there is any i386 or i686 version
+ # installed. If there is, check if it needs to be upgraded.
if ($arch eq 'x86_64') {
$path = undef;
$deps = undef;
@@ -1889,7 +2174,7 @@ sub _get_deppaths
push(@$missing, $path);
foreach my $deppath (_get_deppaths($g, $root, $config,
- $missing, 'i386',
@$deps))
+ $missing, 'i386',
@$deps))
{
$required{$deppath} = 1;
}
@@ -1963,7 +2248,12 @@ sub _discover_kernel
$kernel_pkg = $kernel->{package};
# Get the kernel package version
- $kernel_ver = $kernel->{version};
+ # SUSE requires the fullversion string
+ if (_is_suse_family($g, $root)) {
+ $kernel_ver = $kernel->{fullversion};
+ } else {
+ $kernel_ver = $kernel->{version};
+ }
last;
}
@@ -1971,13 +2261,12 @@ sub _discover_kernel
# Default to 'kernel' if package name wasn't discovered
$kernel_pkg = "kernel" if (!defined($kernel_pkg));
- # Default the kernel architecture to the userspace architecture if it
wasn't
- # directly detected
+ # Default the kernel architecture to the userspace architecture if it
+ # wasn't directly detected
$kernel_arch = $g->inspect_get_arch($root) unless defined($kernel_arch);
- # We haven't supported anything other than i686 for the kernel on 32 bit
for
- # a very long time.
- $kernel_arch = 'i686' if ('i386' eq $kernel_arch);
+ # Change i386 to i[56]86
+ $kernel_arch = _set_32bit_arch($g, $root, $kernel_arch);
return ($kernel_pkg, $kernel_arch, $kernel_ver);
}
@@ -1989,57 +2278,115 @@ sub _get_replacement_kernel_name
# Make an informed choice about a replacement kernel for distros we know
# about
- # RHEL 5
- if (_is_rhel_family($g, $root) && $g->inspect_get_major_version($root) eq
'5') {
- if ($arch eq 'i686') {
- # XXX: This assumes that PAE will be available in the hypervisor.
- # While this is almost certainly true, it's theoretically
possible
- # that it isn't. The information we need is available in the
- # capabilities XML. If PAE isn't available, we should choose
- # 'kernel'.
- return 'kernel-PAE';
+ # RedHat kernels
+ if (_is_rhel_family($g, $root)) {
+ # RHEL 5
+ if ($g->inspect_get_major_version($root) eq '5') {
+ if ($arch eq 'i686') {
+ # XXX: This assumes that PAE will be available in the
+ # hypervisor. While this is almost certainly true, it's
+ # theoretically possible that it isn't. The information we
+ # need is available in the capabilities XML. If PAE isn't
+ # available, we should choose 'kernel'.
+ return 'kernel-PAE';
+ }
+
+ # There's only 1 kernel package on RHEL 5 x86_64
+ else {
+ return 'kernel';
+ }
}
- # There's only 1 kernel package on RHEL 5 x86_64
- else {
- return 'kernel';
+ # RHEL 4
+ elsif ($g->inspect_get_major_version($root) eq '4') {
+ if ($arch eq 'i686') {
+ # If the guest has > 10G RAM, give it a hugemem kernel
+ if ($meta->{memory} > 10 * 1024 * 1024 * 1024) {
+ return 'kernel-hugemem';
+ }
+
+ # SMP kernel for guests with >1 CPU
+ elsif ($meta->{cpus} > 1) {
+ return 'kernel-smp';
+ }
+
+ else {
+ return 'kernel';
+ }
+ }
+
+ else {
+ if ($meta->{cpus} > 8) {
+ return 'kernel-largesmp';
+ }
+
+ elsif ($meta->{cpus} > 1) {
+ return 'kernel-smp';
+ }
+ else {
+ return 'kernel';
+ }
+ }
}
+
+ # RHEL 3 didn't have a xen kernel
}
- # RHEL 4
- elsif (_is_rhel_family($g, $root) && $g->inspect_get_major_version($root)
eq '4') {
- if ($arch eq 'i686') {
- # If the guest has > 10G RAM, give it a hugemem kernel
- if ($meta->{memory} > 10 * 1024 * 1024 * 1024) {
- return 'kernel-hugemem';
- }
+ # SUSE kernels
+ elsif (_is_suse_family($g, $root)) {
+ # openSUSE should always use kernel-default
+ if ($g->inspect_get_distro($root) eq 'opensuse') {
+ return 'kernel-default';
+ }
+ # SLES 11+
+ elsif ($g->inspect_get_major_version($root) ge '11') {
+ if ($arch eq 'i586') {
+ # If the guest has > 10G RAM, give it a pae kernel
+ if ($meta->{memory} > 10 * 1024 * 1024 * 1024) {
+ return 'kernel-pae';
+ }
- # SMP kernel for guests with >1 CPU
- elsif ($meta->{cpus} > 1) {
- return 'kernel-smp';
+ else {
+ return 'kernel-default';
+ }
}
+ # There is only 1 kernel which should be used on SLES 11 x86_64
else {
- return 'kernel';
+ return 'kernel-default';
}
}
- else {
- if ($meta->{cpus} > 8) {
- return 'kernel-largesmp';
- }
+ # SLES 10
+ elsif ($g->inspect_get_major_version($root) eq '10') {
+ if ($arch eq 'i586') {
+ # If the guest has > 10G RAM, give it a bigsmp kernel
+ if ($meta->{memory} > 10 * 1024 * 1024 * 1024) {
+ return 'kernel-bigsmp';
+ }
+
+ # SMP kernel for guests with >1 CPU
+ elsif ($meta->{cpus} > 1) {
+ return 'kernel-smp';
+ }
- elsif ($meta->{cpus} > 1) {
- return 'kernel-smp';
+ else {
+ return 'kernel-default';
+ }
}
+
else {
- return 'kernel';
+ if ($meta->{cpus} > 1) {
+ return 'kernel-smp';
+ }
+
+ else {
+ return 'kernel-default';
+ }
}
}
}
- # RHEL 3 didn't have a xen kernel
-
# XXX: Could do with a history of Fedora kernels in here
# For other distros, be conservative and just return 'kernel'
@@ -2060,8 +2407,8 @@ sub _get_installed
# Unfortunately, rpm sent its error to stdout instead of stderr, and
# command_lines only gives us stderr in $@. To get round this we'll
# execute the command again, sending all output to stdout and
ignoring
- # failure. If the output contains 'not installed', we'll assume
it's
not
- # a real error.
+ # failure. If the output contains 'not installed', we'll assume
it's
+ # not a real error.
my $error = $g->sh("LANG=C '".join("' '",
@$rpmcmd)."' 2>&1 ||:");
return () if ($error =~ /not installed/);
@@ -2076,7 +2423,7 @@ sub _get_installed
or die("Unexpected return from rpm command: $installed");
my ($epoch, $version, $release) = ($1, $2, $3);
- # Ensure iepoch is always numeric
+ # Ensure epoch is always numeric
$epoch = 0 if('(none)' eq $epoch);
push(@installed, [$epoch, $version, $release]);
@@ -2151,7 +2498,7 @@ sub _rpmvercmp
# of $a.
@$l = split(/(?<=[[:digit:]])(?=[[:alpha:]]) | # digit<>alpha
(?<=[[:alpha:]])(?=[[:digit:]]) | # alpha<>digit
- [^[:alnum:]]+ # sequence of non-
alphanumeric
+ [^[:alnum:]]+ # sequence of non-
alphanumeric
/x, $s);
}
@@ -2189,8 +2536,8 @@ sub _rpmvercmp
return 1 if($acmp gt $bcmp);
}
- # We got here because all the parts compared so far have been equal, and
one
- # or both have run out of parts.
+ # We got here because all the parts compared so far have been equal, and
+ # one or both have run out of parts.
# Whichever has the greatest number of parts is the largest
return -1 if(scalar(@aparts) < scalar(@bparts));
@@ -2203,7 +2550,7 @@ sub _rpmvercmp
sub _remap_block_devices
{
- my ($meta, $virtio, $g, $root) = @_;
+ my ($meta, $virtio, $g, $root, $grub) = @_;
my @devices = map { $_->{device} } @{$meta->{disks}};
@devices = sort { scsi_first_cmp($a, $b) } @devices;
@@ -2214,8 +2561,8 @@ sub _remap_block_devices
# libguestfs, which means their device name in the appliance can be
# inferred.
- # If the guest is using libata, IDE drives could have different names in
the
- # guest from their libvirt device names.
+ # If the guest is using libata, IDE drives could have different names in
+ # the guest from their libvirt device names.
# Modern distros use libata, and IDE devices are presented as sdX
my $libata = 1;
@@ -2235,6 +2582,12 @@ sub _remap_block_devices
# Fedora has used libata since FC7, which is long out of support. We
assume
# that all Fedora distributions in use use libata.
+ # SUSE uses libata, but IDE devices can be presented as hdX in some
+ # environments (such as fully virtual machines).
+ if (_is_suse_family($g, $root)) {
+ $libata = 0;
+ }
+
if ($libata) {
# If there are any IDE devices, the guest will have named these sdX
# after any SCSI devices. i.e. If we have disks hda, hdb, sda and
sdb,
@@ -2280,8 +2633,8 @@ sub _remap_block_devices
# these as xvd devices. i.e. hdX and xvdX both exist and are the same
# device.
# This mapping is also useful for P2V conversion of Citrix Xenserver
- # guests done in HVM mode. Disks are detected as sdX, although the
guest
- # uses xvdX natively.
+ # guests done in HVM mode. Disks are detected as sdX, although the
+ # guest uses xvdX natively.
if ($device =~ /^(?:h|s)d([a-z]+)/) {
$map{'xvd'.$1} = $mapped;
}
@@ -2290,13 +2643,46 @@ sub _remap_block_devices
}
eval {
- # Update bare device references in fstab and grub's device.map
- foreach my $spec ($g->aug_match('/files/etc/fstab/*/spec'),
- $g->aug_match('/files/boot/grub/device.map/*'.
- '[label() !=
"#comment"]'))
+ my @checklist;
+ my @matchlist;
+ my $grub2_remap;
+
+ # Add standard configuration files to the checklist
+ push (@checklist, '/files/etc/fstab/*/spec');
+
+ # Add grub or grub2 files to the checklist
+ if (defined($grub->{grub_conf})) {
+ push (@checklist, "/files$grub->{grub_conf}*/kernel/root");
+ push (@checklist, "/files$grub->{grub_conf}*/kernel/resume");
+ push (@checklist, '/files/boot/grub/device.map/*'.
+ '[label() != "#comment"]');
+ }
+ elsif (defined($grub->{cfg})) {
+ push (@checklist, '/files/etc/sysconfig/grub/GRUB_CMDLINE_LINUX');
+ push (@checklist, '/files/etc/default/grub/'.
+ 'GRUB_CMDLINE_LINUX_DEFAULT');
+ }
+
+ # Search through all checklist entries and add matches to a matchlist
+ foreach my $entry (@checklist) {
+ push (@matchlist, $g->aug_match($entry));
+ }
+
+ # Update device references for every entry in the matchlist
+ foreach my $spec (@matchlist)
{
my $device = $g->aug_get($spec);
+ # If this is a grub2 environment, isolate 'resume=' value
+ my $grub2_start;
+ my $grub2_end;
+ if (($spec =~ /.*GRUB_CMDLINE.*/) &&
+ ($device =~ /(.*resume=)(\S+)(\s.*)/)) {
+ $grub2_start = $1;
+ $device = $2;
+ $grub2_end = $3;
+ }
+
# Match device names and partition numbers
my $name; my $part;
foreach my $r (qr{^/dev/(cciss/c\d+d\d+)(?:p(\d+))?$},
@@ -2318,7 +2704,9 @@ sub _remap_block_devices
# about. The user will have to fix this post-conversion.
if (!exists($map{$name})) {
my $warned = 0;
- for my $file ('/etc/fstab', '/boot/grub/device.map') {
+ for my $file ('/etc/fstab', '/boot/grub/device.map',
+ '/boot/grub/menu.lst',
'/etc/sysconfig/grub',
+ '/etc/default/grub') {
if ($spec =~ m{^/files$file}) {
logmsg WARN, __x('{file} references unknown device '.
'{device}. This entry must be '.
@@ -2341,10 +2729,22 @@ sub _remap_block_devices
my $mapped = '/dev/'.$map{$name};
$mapped .= $part if defined($part);
+
+ # If this is a grub2 entry, rebuild the entire entry
+ if ($spec =~ /.*GRUB_CMDLINE.*/) {
+ $mapped = $grub2_start.$mapped.$grub2_end;
+ $grub2_remap = 1;
+ }
+
$g->aug_set($spec, $mapped);
}
$g->aug_save();
+
+ # Re-generate the grub2 config if grub2 files were changed
+ if (defined($grub2_remap)) {
+ $g->command(['grub2-mkconfig', '-o', $grub->{cfg}]);
+ }
};
augeas_error($g, $@) if ($@);
@@ -2372,6 +2772,12 @@ sub _prepare_bootable
$grub_initrd, $version]);
}
+ elsif (_is_suse_family($g, $root) &&
($g->exists('/sbin/mkinitrd'))) {
+ $g->sh('/sbin/mkinitrd -m "'.join(' ',
@modules).'" '.
+ ' -i '.$grub_initrd.' -k /boot/vmlinuz-'.$version);
+ }
+
+ # Default to original mkinitrd, if not SUSE and dracut does not exist
elsif ($g->exists('/sbin/mkinitrd')) {
# Create a new initrd which probes the required kernel modules
my @module_args = ();
@@ -2431,8 +2837,8 @@ sub _supports_acpi
# Blacklist configurations which are known to fail
# RHEL 3, x86_64
- if (_is_rhel_family($g, $root) && $g->inspect_get_major_version($root) ==
3 &&
- $arch eq 'x86_64') {
+ if (_is_rhel_family($g, $root) && $g->inspect_get_major_version($root) ==
3
+ && $arch eq 'x86_64') {
return 0;
}
@@ -2467,6 +2873,67 @@ sub _supports_virtio
return 1;
}
+sub _get_display_driver
+{
+ my ($g, $root) = @_;
+
+ if (_is_suse_family($g, $root)) {
+ return 'cirrus';
+ } else {
+ return 'qxl';
+ }
+}
+
+# RedHat and SUSE use different 32bit architectures (i686 -vs- i586)
+sub _set_32bit_arch
+{
+ my ($g, $root, $arch) = @_;
+
+ # We want an i586 or i686 guest for i[345]86
+ if ($arch =~ /^i[345]86$/) {
+ if (_is_sles_family($g, $root)) {
+ $arch = 'i586';
+ } else {
+ $arch = 'i686';
+ }
+ }
+
+ return $arch;
+}
+
+# The next two functions are a SUSE-specific temporary workaround to
+# bnc#836521. This is required to prevent root being set to (hd*) instead
+# of the correct (hd*,*). The actual fix is in a new perl-Bootloader, which
+# will likely not be on most guests.
+sub _modify_perlBootloader
+{
+ my ($g) = @_;
+ my $module = $g->sh('rpm -ql perl-Bootloader | grep GRUB.pm');
+ chomp($module);
+ my $module_bak = "$module.v2vtmp";
+
+ if ($g->grep('/dev/(?:vx', "$module")) {
+ $g->mv($module, $module_bak);
+ $g->sh("/usr/bin/sed -e's/vx/xv/' $module_bak >
$module");
+
+ return 1;
+ }
+
+ return 0;
+}
+
+sub _restore_perlBootloader
+{
+ my ($g) = @_;
+ my $module = $g->sh('rpm -ql perl-Bootloader | grep GRUB.pm');
+ chomp($module);
+ my $module_bak = "$module.v2vtmp";
+
+ if ($g->exists($module_bak)) {
+ $g->mv($module_bak, $module);
+ }
+}
+
=back
=head1 COPYRIGHT
--
1.8.1.4