Merge "Vmware:Find a SCSI adapter type for attaching iSCSI disk"

This commit is contained in:
Jenkins
2015-03-31 18:58:23 +00:00
committed by Gerrit Code Review
6 changed files with 72 additions and 10 deletions

View File

@@ -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):

View File

@@ -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)

View File

@@ -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)

View File

@@ -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

View File

@@ -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):

View File

@@ -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',