[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[Libguestfs] [PATCH] Default to IDE when VirtIO isn't available



Previously we used SCSI when VirtIO wasn't available. KVM's SCSI support is not
as mature as its IDE support, and SCSI isn't supported at all in RHEV.
---
 lib/Sys/VirtV2V/Converter.pm       |   50 +++++++++++-------
 lib/Sys/VirtV2V/Converter/Linux.pm |   19 ++++---
 lib/Sys/VirtV2V/GuestOS/RedHat.pm  |  100 ++++++++++++++++++++----------------
 3 files changed, 100 insertions(+), 69 deletions(-)

diff --git a/lib/Sys/VirtV2V/Converter.pm b/lib/Sys/VirtV2V/Converter.pm
index 71e94f7..5dc8550 100644
--- a/lib/Sys/VirtV2V/Converter.pm
+++ b/lib/Sys/VirtV2V/Converter.pm
@@ -87,7 +87,7 @@ use constant KVM_XML_NOVIRTIO => "
   </os>
   <devices>
     <disk device='disk'>
-      <target bus='scsi'/>
+      <target bus='ide'/>
     </disk>
     <interface type='network'>
       <model type='e1000'/>
@@ -268,51 +268,65 @@ sub _unconfigure_bootloaders
     }
 }
 
+sub _suffixcmp
+{
+    my ($a, $b) = @_;
+
+    return 1 if (length($a) > length($b));
+    return -1 if (length($a) < length($b));
+
+    return 1 if ($a gt $b);
+    return -1 if ($a lt $b);
+    return 0;
+}
+
 sub _configure_storage
 {
     my ($dom, $devices, $virtio) = @_;
 
-    my $prefix = $virtio ? 'vd' : 'sd';
+    my $prefix = $virtio ? 'vd' : 'hd';
+
+    my @removed = ();
 
     my $suffix = 'a';
     foreach my $device (@$devices) {
         my ($target) = $dom->findnodes("/domain/devices/disk[\ device='disk']/".
                                        "target[\ dev='$device']");
 
-        die(user_message(__x("Previously detected drive {drive} is no longer ".
-                             "present in domain XML: {xml}",
-                             drive => $device,
-                             xml => $dom->toString())))
+        die("Previously detected drive $device is no longer present in domain ".
+            "XML: ".$dom->toString())
             unless (defined($target));
 
-        $target->setAttribute('bus', $virtio ? 'virtio' : 'scsi');
-        $target->setAttribute('dev', $prefix.$suffix);
-        $suffix++; # Perl magic means 'z'++ == 'aa'
+        # Don't add more than 4 IDE disks
+        if (!$virtio && _suffixcmp($suffix, 'd') > 0) {
+            push(@removed, "$device(disk)");
+        } else {
+            $target->setAttribute('bus', $virtio ? 'virtio' : 'ide');
+            $target->setAttribute('dev', $prefix.$suffix);
+            $suffix++; # Perl magic means 'z'++ == 'aa'
+        }
     }
 
-    # Convert the first 4 CDROM drives to IDE, and remove the rest
-    $suffix = 'a';
-    my $i = 0;
-    my @removed = ();
+    # Convert CD-ROM devices to IDE.
+    $suffix = 'a' if ($virtio);
     foreach my $target
         ($dom->findnodes("/domain/devices/disk[\ device='cdrom']/target"))
     {
-        if ($i < 4) {
+        if (_suffixcmp($suffix, 'd') <= 0) {
             $target->setAttribute('bus', 'ide');
             $target->setAttribute('dev', "hd$suffix");
             $suffix++;
         } else {
-            push(@removed, $target->getAttribute('dev'));
+            push(@removed, $target->getAttribute('dev')."(cdrom)");
 
             my $disk = $target->getParentNode();
             $disk->getParentNode()->removeChild($disk);
         }
-        $i++;
     }
 
     if (@removed > 0) {
-        print user_message(__x("WARNING: Only 4 CDROM drives are supported. ".
-                               "The following CDROM drives have been removed: ".
+        print user_message(__x("WARNING: Only 4 IDE devices are supported. ".
+                               "The following drives have been removed: ".
                                "{list}",
                                list => join(' ', @removed)));
     }
diff --git a/lib/Sys/VirtV2V/Converter/Linux.pm b/lib/Sys/VirtV2V/Converter/Linux.pm
index 6f49351..3e76762 100644
--- a/lib/Sys/VirtV2V/Converter/Linux.pm
+++ b/lib/Sys/VirtV2V/Converter/Linux.pm
@@ -142,7 +142,7 @@ sub _configure_kernel_modules
 
     # Make a note of whether we've added scsi_hostadapter
     # We need this on RHEL 4/virtio because mkinitrd can't detect root on
-    # virtio. For simplicity we always ensure this is set.
+    # virtio. For simplicity we always ensure this is set for virtio disks.
     my $scsi_hostadapter = 0;
 
     foreach my $module (keys(%$modules)) {
@@ -164,17 +164,22 @@ sub _configure_kernel_modules
                 $hvs_modules{$module} = 1;
             }
 
-            $guestos->update_kernel_module($module,
-                                          $virtio ? "virtio_blk" : "sym53c8xx");
+            if ($virtio) {
+                $guestos->update_kernel_module($module, 'virtio_blk');
+                $scsi_hostadapter = 1;
+            }
 
-            $scsi_hostadapter = 1;
+            # IDE doesn't need scsi_hostadapter
+            else {
+                $guestos->disable_kernel_module($module);
+            }
         }
     }
 
     # Add an explicit scsi_hostadapter if it wasn't there before
-    $guestos->enable_kernel_module('scsi_hostadapter',
-                                $virtio ? "virtio_blk" : "sym53c8xx")
-        unless($scsi_hostadapter);
+    if ($virtio && !$scsi_hostadapter) {
+        $guestos->enable_kernel_module('scsi_hostadapter', 'virtio_blk');
+    }
 
     # Warn if any old-HV specific kernel modules weren't updated
     foreach my $module (keys(%hvs_modules)) {
diff --git a/lib/Sys/VirtV2V/GuestOS/RedHat.pm b/lib/Sys/VirtV2V/GuestOS/RedHat.pm
index 3f5d90a..8664c2d 100644
--- a/lib/Sys/VirtV2V/GuestOS/RedHat.pm
+++ b/lib/Sys/VirtV2V/GuestOS/RedHat.pm
@@ -964,54 +964,52 @@ sub remap_block_devices
     # same names as used by the guest. However, if the guest is using libata,
     # IDE drives could be renamed.
 
-    # Look for IDE and SCSI devices in fstab for the guest
-    my %guestif;
-    foreach my $spec ($g->aug_match('/files/etc/fstab/*/spec')) {
-        my $device = $g->aug_get($spec);
-
-        next unless($device =~ m{^/dev/(sd|hd)([a-z]+)});
-        $guestif{$1} ||= {};
-        $guestif{$1}->{$1.$2} = 1;
+    # Modern distros use libata, and IDE devices are presented as sdX
+    my $libata = 1;
+
+    # RHEL 2, 3 and 4 didn't use libata
+    # RHEL 5 does use libata, but udev rules call IDE devices hdX anyway
+    if ($desc->{distro} eq 'rhel') {
+        if ($desc->{major_version} eq '2' ||
+            $desc->{major_version} eq '3' ||
+            $desc->{major_version} eq '4' ||
+            $desc->{major_version} eq '5')
+        {
+            $libata = 0;
+        }
     }
+    # Fedora has used libata since FC7, which is long out of support. We assume
+    # that all Fedora distributions in use use libata.
+
+    if ($libata) {
+        # Look for IDE and SCSI devices in fstab for the guest
+        my %guestif;
+        foreach my $spec ($g->aug_match('/files/etc/fstab/*/spec')) {
+            my $device = $g->aug_get($spec);
+
+            next unless($device =~ m{^/dev/(sd|hd)([a-z]+)});
+            $guestif{$1} ||= {};
+            $guestif{$1}->{$1.$2} = 1;
+        }
 
-    # If fstab contains references to sdX, these could refer to IDE or SCSI
-    # devices. Need to look at the domain config for clues.
-    if (exists($guestif{sd})) {
-        # Look for IDE and SCSI devices from the domain definition
-        my %domainif;
-        foreach my $device (@$devices) {
-            foreach my $type ('hd', 'sd') {
-                if ($device =~ m{^$type([a-z]+)}) {
-                    $domainif{$type} ||= {};
-                    $domainif{$type}->{$device} = 1;
+        # If fstab contains references to sdX, these could refer to IDE or SCSI
+        # devices. We may need to update them.
+        if (exists($guestif{sd})) {
+            # Look for IDE and SCSI devices from the domain definition
+            my %domainif;
+            foreach my $device (@$devices) {
+                foreach my $type ('hd', 'sd') {
+                    if ($device =~ m{^$type([a-z]+)}) {
+                        $domainif{$type} ||= {};
+                        $domainif{$type}->{$device} = 1;
+                    }
                 }
             }
-        }
-
-        # If domain defines both IDE and SCSI drives, and fstab contains
-        # references on sdX, but not hdX, we don't know if the guest is using
-        # libata or not.  This means that we don't know if sdX in fstab refers
-        # to hdX or sdX in the domain. Warn and assume that libata device
-        # renaming is not in use.
-        if (exists($domainif{hd}) && exists($domainif{sd}) &&
-            !exists($guestif{hd}))
-        {
-            print STDERR user_message(__"WARNING: Unable to determine whether ".
-                                        "sdX devices in /etc/fstab refer to ".
-                                        "IDE or SCSI devices. Assuming they ".
-                                        "refer to SCSI devices. /etc/fstab ".
-                                        "may be incorrect after conversion if ".
-                                        "guest uses libata.");
-        }
 
-        # If we've got only IDE devices in the domain, and only sdX devices in
-        # fstab, the guest is renaming them.
-        elsif (exists($domainif{hd}) && !exists($domainif{sd}) &&
-               !exists($guestif{hd}))
-        {
             my %map;
 
             my $letter = 'a';
+            # IDE drives are presented first
             foreach my $old (sort { _drivecmp('hd', $a, $b) }
                                   keys(%{$domainif{hd}}))
             {
@@ -1019,10 +1017,16 @@ sub remap_block_devices
                 $letter++;
             }
 
+            # Followed by SCSI drives
+            foreach my $old (sort { _drivecmp('sd', $a, $b) }
+                                  keys(%{$domainif{sd}}))
+            {
+                $map{$old} = "sd$letter";
+                $letter++;
+            }
+
             map { $_ = $map{$_} } @$devices;
         }
-
-        # Otherwise we leave it alone
     }
 
     # We now assume that $devices contains an ordered list of device names, as
@@ -1030,8 +1034,16 @@ sub remap_block_devices
     # device names.
     my %map;
 
-    # Everything will be converted to either vdX or sdX
-    my $prefix = $virtio ? 'vd' : 'sd';
+    # Everything will be converted to either vdX, sdX or hdX
+    my $prefix;
+    if ($virtio) {
+        $prefix = 'vd';
+    } elsif ($libata) {
+        $prefix = 'sd';
+    } else {
+        $prefix = 'hd'
+    }
+
     my $letter = 'a';
     foreach my $device (@$devices) {
         $map{$device} = $prefix.$letter;
-- 
1.6.6.1


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]