summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2016-05-11 20:15:50 +0000
committerGerrit Code Review <review@openstack.org>2016-05-11 20:15:51 +0000
commitbc5577b64928172651aa59898ea875e04235050a (patch)
treea04b285a35fcb4d46a2190144cd64d21a0ce85b6
parent87f47a84adbe4637aa8666d920e418d43f03e8af (diff)
parentf593d90f7d0c02726fdfce24b29e163f1f55b707 (diff)
downloadnova-bc5577b64928172651aa59898ea875e04235050a.tar.gz
Merge "<VMWare> Allocate free bus for new SCSI controller" into stable/liberty
-rw-r--r--nova/tests/unit/virt/vmwareapi/fake.py3
-rw-r--r--nova/tests/unit/virt/vmwareapi/test_vm_util.py45
-rw-r--r--nova/virt/vmwareapi/constants.py6
-rw-r--r--nova/virt/vmwareapi/vm_util.py31
4 files changed, 77 insertions, 8 deletions
diff --git a/nova/tests/unit/virt/vmwareapi/fake.py b/nova/tests/unit/virt/vmwareapi/fake.py
index 72ecd1cec4..ad375f65ba 100644
--- a/nova/tests/unit/virt/vmwareapi/fake.py
+++ b/nova/tests/unit/virt/vmwareapi/fake.py
@@ -370,8 +370,9 @@ class VirtualIDEController(DataObject):
class VirtualLsiLogicController(DataObject):
"""VirtualLsiLogicController class."""
- def __init__(self, key=0, scsiCtlrUnitNumber=0):
+ def __init__(self, key=0, scsiCtlrUnitNumber=0, busNumber=0):
self.key = key
+ self.busNumber = busNumber
self.scsiCtlrUnitNumber = scsiCtlrUnitNumber
self.device = []
diff --git a/nova/tests/unit/virt/vmwareapi/test_vm_util.py b/nova/tests/unit/virt/vmwareapi/test_vm_util.py
index d4930965c2..c20fa6de9d 100644
--- a/nova/tests/unit/virt/vmwareapi/test_vm_util.py
+++ b/nova/tests/unit/virt/vmwareapi/test_vm_util.py
@@ -214,6 +214,13 @@ class VMwareVMUtilTestCase(test.NoDBTestCase):
self.assertEqual("ns0:ParaVirtualSCSIController",
config_spec.device.obj_name)
+ def test_create_controller_spec_with_specfic_bus_number(self):
+ # Test controller spec with specifc bus number rather default 0
+ config_spec = vm_util.create_controller_spec(fake.FakeFactory(), -101,
+ adapter_type=constants.ADAPTER_TYPE_LSILOGICSAS,
+ bus_number=1)
+ self.assertEqual(1, config_spec.device.busNumber)
+
def _vmdk_path_and_adapter_type_devices(self, filename, parent=None):
# Test the adapter_type returned for a lsiLogic sas controller
controller_key = 1000
@@ -332,6 +339,27 @@ class VMwareVMUtilTestCase(test.NoDBTestCase):
self.assertEqual([1], taken[201])
self.assertEqual([7], taken[1000])
+ def test_get_bus_number_for_scsi_controller(self):
+ devices = [fake.VirtualLsiLogicController(1000, scsiCtlrUnitNumber=7,
+ busNumber=0),
+ fake.VirtualLsiLogicController(1002, scsiCtlrUnitNumber=7,
+ busNumber=2)]
+ bus_number = vm_util._get_bus_number_for_scsi_controller(devices)
+ self.assertEqual(1, bus_number)
+
+ def test_get_bus_number_for_scsi_controller_buses_used_up(self):
+ devices = [fake.VirtualLsiLogicController(1000, scsiCtlrUnitNumber=7,
+ busNumber=0),
+ fake.VirtualLsiLogicController(1001, scsiCtlrUnitNumber=7,
+ busNumber=1),
+ fake.VirtualLsiLogicController(1002, scsiCtlrUnitNumber=7,
+ busNumber=2),
+ fake.VirtualLsiLogicController(1003, scsiCtlrUnitNumber=7,
+ busNumber=3)]
+ self.assertRaises(vexc.VMwareDriverException,
+ vm_util._get_bus_number_for_scsi_controller,
+ devices)
+
def test_allocate_controller_key_and_unit_number_ide_default(self):
# Test that default IDE controllers are used when there is a free slot
# on them
@@ -386,6 +414,23 @@ class VMwareVMUtilTestCase(test.NoDBTestCase):
self.assertEqual(8, unit_number)
self.assertIsNone(controller_spec)
+ def test_allocate_controller_key_and_unit_number_scsi_new_controller(self):
+ # Test that we allocate on existing SCSI controller if there is a free
+ # slot on it
+ devices = [fake.VirtualLsiLogicController(1000, scsiCtlrUnitNumber=15)]
+ for unit_number in range(15):
+ disk = fake.VirtualDisk(1000, unit_number)
+ devices.append(disk)
+ factory = fake.FakeFactory()
+ (controller_key, unit_number,
+ controller_spec) = vm_util.allocate_controller_key_and_unit_number(
+ factory,
+ devices,
+ constants.DEFAULT_ADAPTER_TYPE)
+ self.assertEqual(-101, controller_key)
+ self.assertEqual(0, unit_number)
+ self.assertEqual(1, controller_spec.device.busNumber)
+
def test_get_vnc_config_spec(self):
fake_factory = fake.FakeFactory()
result = vm_util.get_vnc_config_spec(fake_factory,
diff --git a/nova/virt/vmwareapi/constants.py b/nova/virt/vmwareapi/constants.py
index 7842b17d9e..5d76ba61b1 100644
--- a/nova/virt/vmwareapi/constants.py
+++ b/nova/virt/vmwareapi/constants.py
@@ -54,6 +54,9 @@ ADAPTER_TYPE_IDE = "ide"
ADAPTER_TYPE_LSILOGICSAS = "lsiLogicsas"
ADAPTER_TYPE_PARAVIRTUAL = "paraVirtual"
+SCSI_ADAPTER_TYPES = [DEFAULT_ADAPTER_TYPE, ADAPTER_TYPE_LSILOGICSAS,
+ ADAPTER_TYPE_BUSLOGIC, ADAPTER_TYPE_PARAVIRTUAL]
+
SUPPORTED_FLAT_VARIANTS = ["thin", "preallocated", "thick", "eagerZeroedThick"]
EXTENSION_KEY = 'org.openstack.compute'
@@ -63,6 +66,9 @@ EXTENSION_TYPE_INSTANCE = 'instance'
# One adapter has 16 slots but one reserved for controller
SCSI_MAX_CONNECT_NUMBER = 15
+# The max number of SCSI adaptors that could be created on one instance.
+SCSI_MAX_CONTROLLER_NUMBER = 4
+
# This list was extracted from the installation iso image for ESX 6.0.
# It is contained in s.v00, which is gzipped. The list was obtained by
# searching for the string 'otherGuest' in the uncompressed contents of that
diff --git a/nova/virt/vmwareapi/vm_util.py b/nova/virt/vmwareapi/vm_util.py
index 5e19cb0a97..bf0782fd23 100644
--- a/nova/virt/vmwareapi/vm_util.py
+++ b/nova/virt/vmwareapi/vm_util.py
@@ -355,7 +355,8 @@ def get_vm_resize_spec(client_factory, vcpus, memory_mb, extra_specs,
def create_controller_spec(client_factory, key,
- adapter_type=constants.DEFAULT_ADAPTER_TYPE):
+ adapter_type=constants.DEFAULT_ADAPTER_TYPE,
+ bus_number=0):
"""Builds a Config Spec for the LSI or Bus Logic Controller's addition
which acts as the controller for the virtual hard disk to be attached
to the VM.
@@ -377,7 +378,7 @@ def create_controller_spec(client_factory, key,
virtual_controller = client_factory.create(
'ns0:VirtualLsiLogicController')
virtual_controller.key = key
- virtual_controller.busNumber = 0
+ virtual_controller.busNumber = bus_number
virtual_controller.sharedBus = "noSharing"
virtual_device_config.device = virtual_controller
return virtual_device_config
@@ -713,6 +714,19 @@ def _find_allocated_slots(devices):
return taken
+def _get_bus_number_for_scsi_controller(devices):
+ """Return usable bus number when create new SCSI controller."""
+ # Every SCSI controller will take a unique bus number
+ taken = [dev.busNumber for dev in devices if _is_scsi_controller(dev)]
+ # The max bus number for SCSI controllers is 3
+ for i in range(constants.SCSI_MAX_CONTROLLER_NUMBER):
+ if i not in taken:
+ return i
+ msg = _('Only %d SCSI controllers are allowed to be '
+ 'created on this instance.') % constants.SCSI_MAX_CONTROLLER_NUMBER
+ raise vexc.VMwareDriverException(msg)
+
+
def allocate_controller_key_and_unit_number(client_factory, devices,
adapter_type):
"""This function inspects the current set of hardware devices and returns
@@ -728,10 +742,7 @@ def allocate_controller_key_and_unit_number(client_factory, devices,
if adapter_type == constants.ADAPTER_TYPE_IDE:
ide_keys = [dev.key for dev in devices if _is_ide_controller(dev)]
ret = _find_controller_slot(ide_keys, taken, 2)
- elif adapter_type in [constants.DEFAULT_ADAPTER_TYPE,
- constants.ADAPTER_TYPE_LSILOGICSAS,
- constants.ADAPTER_TYPE_BUSLOGIC,
- constants.ADAPTER_TYPE_PARAVIRTUAL]:
+ elif adapter_type in constants.SCSI_ADAPTER_TYPES:
scsi_keys = [dev.key for dev in devices if _is_scsi_controller(dev)]
ret = _find_controller_slot(scsi_keys, taken, 16)
if ret:
@@ -739,8 +750,14 @@ def allocate_controller_key_and_unit_number(client_factory, devices,
# create new controller with the specified type and return its spec
controller_key = -101
+
+ # Get free bus number for new SCSI controller.
+ bus_number = 0
+ if adapter_type in constants.SCSI_ADAPTER_TYPES:
+ bus_number = _get_bus_number_for_scsi_controller(devices)
+
controller_spec = create_controller_spec(client_factory, controller_key,
- adapter_type)
+ adapter_type, bus_number)
return controller_key, 0, controller_spec