[Libguestfs] [PATCH 2/4] Make Linux.pm more generic

Mike Latimer
Thu, 31 Oct 2013 20:14:05 -0000

---
 lib/Sys/VirtConvert/Converter/Linux.pm | 125 +++++++++++++++++++++++++--------
 1 file changed, 97 insertions(+), 28 deletions(-)

diff --git a/lib/Sys/VirtConvert/Converter/Linux.pm
b/lib/Sys/VirtConvert/Converter/Linux.pm
index dd3573e..344d89b 100644
--- a/lib/Sys/VirtConvert/Converter/Linux.pm
+++ b/lib/Sys/VirtConvert/Converter/Linux.pm
@@ -31,16 +31,50 @@ 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+)/;
+        }
     }

+    # If initrd has not been found, 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']);
+    }
+
+    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]);
+    }
+}
+
 sub check_efi
 {
     my $self = shift;
@@ -237,7 +271,7 @@ sub update_console
 sub check
 {
     my $self = shift;
-    my ($path) = @_;
+    my ($path, $root) = @_;

     my $g = $self->{g};
     my $grub_conf = $self->{grub_conf};
@@ -256,11 +290,13 @@ sub check
     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)";

@@ -408,8 +444,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
@@ -431,8 +466,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) {
@@ -442,7 +484,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 ($@);
@@ -464,11 +506,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);
+        }
     }
 }

@@ -626,7 +671,8 @@ 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);
+    my $display = _get_display_driver($g, $root);
+    _configure_display_driver($g, $root, $config, $meta, $grub, $driver);
     _remap_block_devices($meta, $virtio, $g, $root);
     _configure_kernel_modules($g, $virtio);
     _configure_boot($kernel, $virtio, $g, $root, $grub);
@@ -637,6 +683,7 @@ sub convert
     $guestcaps{net}   = $virtio == 1 ? 'virtio' : 'e1000';
     $guestcaps{arch}  = _get_os_arch($g, $root, $grub);
     $guestcaps{acpi}  = _supports_acpi($g, $root, $guestcaps{arch});
+    $guestcaps{display} = $display;

     return \%guestcaps;
 }
@@ -843,7 +890,7 @@ sub _configure_console

 sub _configure_display_driver
 {
-    my ($g, $root, $config, $meta, $grub) = @_;
+    my ($g, $root, $config, $meta, $grub, $display) = @_;

     # Update the display driver if it exists
     my $updated = 0;
@@ -867,7 +914,7 @@ sub _configure_display_driver
         }

         foreach my $path
($g->aug_match('/files'.$xorg.'/Device/Driver')) {
-            $g->aug_set($path, 'qxl');
+            $g->aug_set($path, $display);
             $updated = 1;
         }

@@ -886,13 +933,14 @@ sub _configure_display_driver
     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.
+    # 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($display, $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, __('Display driver was updated to {display}, but
unable '.
+                        'to install {display} driver. X may not function
'.
+                        'correctly', display => $display);
     }
 }

@@ -1014,7 +1062,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);

@@ -1122,8 +1170,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$/);
+    # Determine the correct 32bit arch
+    $arch = _set_32bit_arch($g, $root, $arch);

     return $arch;
 }
@@ -1507,7 +1555,7 @@ 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,
@@ -1658,7 +1706,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;
             }
         }
@@ -1976,9 +2024,8 @@ sub _discover_kernel
     # 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);
+    # Determine the correct 32bit kernel_arch
+    $kernel_arch = _set_32bit_arch($g, $root, $kernel_arch);

     return ($kernel_pkg, $kernel_arch, $kernel_ver);
 }
@@ -2468,6 +2515,28 @@ sub _supports_virtio
     return 1;
 }

+# Distributions may use different display drivers.
+sub _get_display_driver
+{
+    my ($g, $root) = @_;
+
+    # RedHat uses qxl, which should be the default driver.
+    return 'qxl';
+}
+
+# Distributions may use either i586 or i686 for 32bit architectures
+sub _set_32bit_arch
+{
+    my ($g, $root, $arch) = @_;
+
+    if ($arch =~ /^i[345]86$/) {
+        # RedHat uses i686, which should be the default 32bit arch
+        $arch = 'i686';
+    }
+
+    return $arch;
+}
+
 =back

 =head1 COPYRIGHT
--
1.8.1.4