(2.10) Fix bitarray ops wrt PCI slots
authorDimitris Aragiorgis <dimara@grnet.gr>
Mon, 17 Mar 2014 12:00:18 +0000 (14:00 +0200)
committerDimitris Aragiorgis <dimara@grnet.gr>
Thu, 27 Mar 2014 08:01:21 +0000 (10:01 +0200)
Introduce new method `_GetFreeSlot()` responsible only for bitarray
operations. It fixes search in case of bitarray is either '0000..'
or '1111..'.

Use it instead of `_UpdatePCISlots()` and in `_GetFreePCISlot()`.

Signed-off-by: Dimitris Aragiorgis <dimara@grnet.gr>
Reviewed-by: Jose A. Lopes <jabolopes@google.com>

lib/hypervisor/hv_kvm.py

index 1cc9938..1b15e17 100644 (file)
@@ -143,29 +143,36 @@ def _GenerateDeviceKVMId(dev_type, dev, idx=None):
                             " without UUID or PCI info")
 
 
-def _UpdatePCISlots(dev, pci_reservations):
-  """Update pci configuration for a stopped instance
+def _GetFreeSlot(slots, slot=None, reserve=False):
+  """Helper method to get first available slot in a bitarray
+
+  @type slots: bitarray
+  @param slots: the bitarray to operate on
+  @type slot: integer
+  @param slot: if given we check whether the slot is free
+  @type reserve: boolean
+  @param reserve: whether to reserve the first available slot or not
+  @return: the idx of the (first) available slot
+  @raise errors.HotplugError: If all slots in a bitarray are occupied
+    or the given slot is not free.
 
-  If dev has a pci slot then reserve it, else find first available
-  in pci_reservations bitarray. It acts on the same objects passed
-  as params so there is no need to return anything.
+  """
+  if slot is not None:
+    assert slot < len(slots)
+    if slots[slot]:
+      raise errors.HypervisorError("Slots %d occupied" % slot)
 
-  @type dev: L{objects.Disk} or L{objects.NIC}
-  @param dev: the device object for which we update its pci slot
-  @type pci_reservations: bitarray
-  @param pci_reservations: existing pci reservations for an instance
-  @raise errors.HotplugError: in case an instance has all its slot occupied
+  else:
+    avail = slots.search(_AVAILABLE_PCI_SLOT, 1)
+    if not avail:
+      raise errors.HypervisorError("All slots occupied")
 
-  """
-  if dev.pci:
-    free = dev.pci
-  else: # pylint: disable=E1103
-    [free] = pci_reservations.search(_AVAILABLE_PCI_SLOT, 1)
-    if not free:
-      raise errors.HypervisorError("All PCI slots occupied")
-    dev.pci = int(free)
+    slot = int(avail[0])
+
+  if reserve:
+    slots[slot] = True
 
-  pci_reservations[free] = True
+  return slot
 
 
 def _GetExistingDeviceInfo(dev_type, device, runtime):
@@ -1740,12 +1747,12 @@ class KVMHypervisor(hv_base.BaseHypervisor):
     pci_reservations = bitarray(self._DEFAULT_PCI_RESERVATIONS)
     kvm_disks = []
     for disk, link_name in block_devices:
-      _UpdatePCISlots(disk, pci_reservations)
+      disk.pci = _GetFreeSlot(pci_reservations, disk.pci, True)
       kvm_disks.append((disk, link_name))
 
     kvm_nics = []
     for nic in instance.nics:
-      _UpdatePCISlots(nic, pci_reservations)
+      nic.pci = _GetFreeSlot(pci_reservations, nic.pci, True)
       kvm_nics.append(nic)
 
     hvparams = hvp
@@ -2103,11 +2110,7 @@ class KVMHypervisor(hv_base.BaseHypervisor):
         slot = int(match.group(1))
         slots[slot] = True
 
-    [free] = slots.search(_AVAILABLE_PCI_SLOT, 1) # pylint: disable=E1101
-    if not free:
-      raise errors.HypervisorError("All PCI slots occupied")
-
-    dev.pci = int(free)
+    dev.pci = _GetFreeSlot(slots)
 
   def VerifyHotplugSupport(self, instance, action, dev_type):
     """Verifies that hotplug is supported.