Merge "Vmware:Find a SCSI adapter type for attaching iSCSI disk"
This commit is contained in:
@@ -370,6 +370,7 @@ class VirtualLsiLogicController(DataObject):
|
||||
def __init__(self, key=0, scsiCtlrUnitNumber=0):
|
||||
self.key = key
|
||||
self.scsiCtlrUnitNumber = scsiCtlrUnitNumber
|
||||
self.device = []
|
||||
|
||||
|
||||
class VirtualLsiLogicSASController(DataObject):
|
||||
|
@@ -28,6 +28,7 @@ from nova import test
|
||||
from nova.tests.unit import fake_instance
|
||||
from nova.tests.unit.virt.vmwareapi import fake
|
||||
from nova.tests.unit.virt.vmwareapi import stubs
|
||||
from nova.virt.vmwareapi import constants
|
||||
from nova.virt.vmwareapi import driver
|
||||
from nova.virt.vmwareapi import ds_util
|
||||
from nova.virt.vmwareapi import vm_util
|
||||
@@ -283,6 +284,36 @@ class VMwareVMUtilTestCase(test.NoDBTestCase):
|
||||
vmdk_adapter_type = vm_util.get_vmdk_adapter_type("dummyAdapter")
|
||||
self.assertEqual("dummyAdapter", vmdk_adapter_type)
|
||||
|
||||
def test_get_scsi_adapter_type(self):
|
||||
vm = fake.VirtualMachine()
|
||||
devices = vm.get("config.hardware.device").VirtualDevice
|
||||
scsi_controller = fake.VirtualLsiLogicController()
|
||||
ide_controller = fake.VirtualIDEController()
|
||||
devices.append(scsi_controller)
|
||||
devices.append(ide_controller)
|
||||
fake._update_object("VirtualMachine", vm)
|
||||
# return the scsi type, not ide
|
||||
hardware_device = vm.get("config.hardware.device")
|
||||
self.assertEqual(constants.DEFAULT_ADAPTER_TYPE,
|
||||
vm_util.get_scsi_adapter_type(hardware_device))
|
||||
|
||||
def test_get_scsi_adapter_type_with_error(self):
|
||||
vm = fake.VirtualMachine()
|
||||
devices = vm.get("config.hardware.device").VirtualDevice
|
||||
scsi_controller = fake.VirtualLsiLogicController()
|
||||
ide_controller = fake.VirtualIDEController()
|
||||
devices.append(scsi_controller)
|
||||
devices.append(ide_controller)
|
||||
fake._update_object("VirtualMachine", vm)
|
||||
# the controller is not suitable since the device under this controller
|
||||
# has exceeded SCSI_MAX_CONNECT_NUMBER
|
||||
for i in range(0, constants.SCSI_MAX_CONNECT_NUMBER):
|
||||
scsi_controller.device.append('device' + str(i))
|
||||
hardware_device = vm.get("config.hardware.device")
|
||||
self.assertRaises(exception.StorageError,
|
||||
vm_util.get_scsi_adapter_type,
|
||||
hardware_device)
|
||||
|
||||
def test_find_allocated_slots(self):
|
||||
disk1 = fake.VirtualDisk(200, 0)
|
||||
disk2 = fake.VirtualDisk(200, 1)
|
||||
|
@@ -216,9 +216,6 @@ class VMwareVolumeOpsTestCase(test.NoDBTestCase):
|
||||
'volume_id': 'volume-fake-id'}}
|
||||
vm_ref = 'fake-vm-ref'
|
||||
default_adapter_type = constants.DEFAULT_ADAPTER_TYPE
|
||||
vmdk_info = vm_util.VmdkInfo('fake-path', default_adapter_type,
|
||||
constants.DISK_TYPE_PREALLOCATED, 1024,
|
||||
'fake-device')
|
||||
adapter_type = adapter_type or default_adapter_type
|
||||
|
||||
with contextlib.nested(
|
||||
@@ -226,10 +223,10 @@ class VMwareVolumeOpsTestCase(test.NoDBTestCase):
|
||||
mock.patch.object(self._volumeops, '_iscsi_discover_target',
|
||||
return_value=(mock.sentinel.device_name,
|
||||
mock.sentinel.uuid)),
|
||||
mock.patch.object(vm_util, 'get_vmdk_info',
|
||||
return_value=vmdk_info),
|
||||
mock.patch.object(vm_util, 'get_scsi_adapter_type',
|
||||
return_value=adapter_type),
|
||||
mock.patch.object(self._volumeops, 'attach_disk_to_vm')
|
||||
) as (get_vm_ref, iscsi_discover_target, get_vmdk_info,
|
||||
) as (get_vm_ref, iscsi_discover_target, get_scsi_adapter_type,
|
||||
attach_disk_to_vm):
|
||||
self._volumeops.attach_volume(connection_info, self._instance,
|
||||
adapter_type)
|
||||
@@ -238,7 +235,8 @@ class VMwareVolumeOpsTestCase(test.NoDBTestCase):
|
||||
self._instance)
|
||||
iscsi_discover_target.assert_called_once_with(
|
||||
connection_info['data'])
|
||||
self.assertTrue(get_vmdk_info.called)
|
||||
if adapter_type is None:
|
||||
self.assertTrue(get_scsi_adapter_type.called)
|
||||
attach_disk_to_vm.assert_called_once_with(vm_ref,
|
||||
self._instance, adapter_type, 'rdmp',
|
||||
device_name=mock.sentinel.device_name)
|
||||
|
@@ -56,6 +56,10 @@ SUPPORTED_FLAT_VARIANTS = ["thin", "preallocated", "thick", "eagerZeroedThick"]
|
||||
EXTENSION_KEY = 'org.openstack.compute'
|
||||
EXTENSION_TYPE_INSTANCE = 'instance'
|
||||
|
||||
# The max number of devices that can be connnected to one adapter
|
||||
# One adapter has 16 slots but one reserved for controller
|
||||
SCSI_MAX_CONNECT_NUMBER = 15
|
||||
|
||||
# This list was extracted from the installation iso image for ESX 5.5 Update 1.
|
||||
# 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
|
||||
|
@@ -554,6 +554,31 @@ def get_vmdk_info(session, vm_ref, uuid=None):
|
||||
capacity_in_bytes, vmdk_device)
|
||||
|
||||
|
||||
scsi_controller_classes = {
|
||||
'ParaVirtualSCSIController': constants.ADAPTER_TYPE_PARAVIRTUAL,
|
||||
'VirtualLsiLogicController': constants.DEFAULT_ADAPTER_TYPE,
|
||||
'VirtualLsiLogicSASController': constants.ADAPTER_TYPE_LSILOGICSAS,
|
||||
'VirtualBusLogicController': constants.ADAPTER_TYPE_PARAVIRTUAL,
|
||||
}
|
||||
|
||||
|
||||
def get_scsi_adapter_type(hardware_devices):
|
||||
"""Selects a proper iscsi adapter type from the existing
|
||||
hardware devices
|
||||
"""
|
||||
if hardware_devices.__class__.__name__ == "ArrayOfVirtualDevice":
|
||||
hardware_devices = hardware_devices.VirtualDevice
|
||||
|
||||
for device in hardware_devices:
|
||||
if device.__class__.__name__ in scsi_controller_classes:
|
||||
# find the controllers which still have available slots
|
||||
if len(device.device) < constants.SCSI_MAX_CONNECT_NUMBER:
|
||||
# return the first match one
|
||||
return scsi_controller_classes[device.__class__.__name__]
|
||||
raise exception.StorageError(
|
||||
reason=_("Unable to find iSCSI Target"))
|
||||
|
||||
|
||||
def _find_controller_slot(controller_keys, taken, max_unit_number):
|
||||
for controller_key in controller_keys:
|
||||
for unit_number in range(max_unit_number):
|
||||
|
@@ -350,9 +350,12 @@ class VMwareVolumeOps(object):
|
||||
if device_name is None:
|
||||
raise exception.StorageError(
|
||||
reason=_("Unable to find iSCSI Target"))
|
||||
|
||||
vmdk = vm_util.get_vmdk_info(self._session, vm_ref)
|
||||
adapter_type = adapter_type or vmdk.adapter_type
|
||||
if adapter_type is None:
|
||||
# Get the vmdk file name that the VM is pointing to
|
||||
hardware_devices = self._session._call_method(
|
||||
vim_util, "get_dynamic_property", vm_ref,
|
||||
"VirtualMachine", "config.hardware.device")
|
||||
adapter_type = vm_util.get_scsi_adapter_type(hardware_devices)
|
||||
|
||||
self.attach_disk_to_vm(vm_ref, instance,
|
||||
adapter_type, 'rdmp',
|
||||
|
Reference in New Issue
Block a user