Blob Blame History Raw
From a3c763361d39daa2b724a97c9ac672dfe45287c7 Mon Sep 17 00:00:00 2001
From: Martin Kletzander <mkletzan@redhat.com>
Date: Thu, 27 Feb 2014 13:57:37 +0100
Subject: [PATCH 3/3] addhardware: Rework the addition of controllers for
 virtio-scsi disks

https://bugzilla.redhat.com/show_bug.cgi?id=1036716

After this patch the virtio-scsi controller should be added only if
needed and its index used for the target generation of the added disk.

RHEL-only; upstream counterpart of this work was done in commits
a9c791b5, 078e1a4d, bc5d84b0, 4aec369e, 7c437f6a, 466c2bcf and 0dceb24b.

Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
---
 virtManager/addhardware.py | 57 ++++++++++++++++++++++++++++++++++------------
 1 file changed, 43 insertions(+), 14 deletions(-)

diff --git a/virtManager/addhardware.py b/virtManager/addhardware.py
index b2f5526..51a01da 100644
--- a/virtManager/addhardware.py
+++ b/virtManager/addhardware.py
@@ -20,6 +20,7 @@
 
 import logging
 import traceback
+import collections
 
 # pylint: disable=E0611
 from gi.repository import Gtk
@@ -1467,27 +1468,55 @@ class vmmAddHardware(vmmGObjectUI):
         disks = (self.vm.get_disk_devices() +
                  self.vm.get_disk_devices(inactive=True))
         for d in disks:
-            used.append(d.target)
+            if d.target not in used:
+                used.append(d.target)
 
         # Add a SCSI controller with model virtio-scsi if needed
         disk.vmm_controller = None
         if (controller_model == "virtio-scsi") and (bus == "scsi"):
+            # Get SCSI controllers
             controllers = self.vm.get_controller_devices()
-            controller = VirtualControllerSCSI(conn=self.conn.vmm)
-            controller.set_model(controller_model)
-            disk.vmm_controller = controller
-            for d in controllers:
-                if controller.type == d.type:
-                    controller.index += 1
-                if controller_model == d.model:
-                    disk.vmm_controller = None
-                    controller = d
+            ctrls_scsi = [x for x in controllers if
+                          (x.type == VirtualControllerSCSI.CONTROLLER_TYPE_SCSI)]
+
+            # Create possible new controller
+            controller = VirtualControllerSCSI(conn=self.conn.vmm,
+                                               model=controller_model)
+
+            # And set its index
+            controller.index = 0
+            if ctrls_scsi:
+                controller.index = max([int(x.index) for x in ctrls_scsi]) + 1
+
+            # Take only virtio-scsi ones
+            ctrls_scsi = [x for x in ctrls_scsi if
+                          (x.model == controller_model)]
+
+            # Save occupied places per controller
+            occupied = collections.defaultdict(int)
+            for d in disks:
+                if d.get_target_prefix() == disk.get_target_prefix():
+                    num = 0
+                    k = 0
+                    tgt = d.target
+                    if tgt[0] == 'x':
+                        # This case is here for 'xvda'
+                        tgt = tgt[1:]
+                    for i, c in enumerate(reversed(tgt[2:])):
+                        if i != 0:
+                            k = 1
+                        num += (ord(c) - ord('a') + k) * (26 ** i)
+                    occupied[num / 7] += 1
+            for c in ctrls_scsi:
+                if occupied[int(c.index)] < 7:
+                    controller = c
                     break
+            else:
+                disk.vmm_controller = controller
 
-            disk.address.type = disk.address.ADDRESS_TYPE_DRIVE
-            disk.address.controller = controller.index
-
-        disk.generate_target(used)
+            disk.generate_target(used, int(controller.index))
+        else:
+            disk.generate_target(used)
 
         isfatal, errmsg = disk.is_size_conflict()
         if not isfatal and errmsg:
-- 
1.8.5.3