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

Mike Latimer mlatimer at suse.com
Thu Oct 31 20:14:05 UTC 2013


---
 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




More information about the Libguestfs mailing list