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): def __init__(self, key=0, scsiCtlrUnitNumber=0):
self.key = key self.key = key
self.scsiCtlrUnitNumber = scsiCtlrUnitNumber self.scsiCtlrUnitNumber = scsiCtlrUnitNumber
self.device = []
class VirtualLsiLogicSASController(DataObject): class VirtualLsiLogicSASController(DataObject):

View File

@@ -28,6 +28,7 @@ from nova import test
from nova.tests.unit import fake_instance from nova.tests.unit import fake_instance
from nova.tests.unit.virt.vmwareapi import fake from nova.tests.unit.virt.vmwareapi import fake
from nova.tests.unit.virt.vmwareapi import stubs 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 driver
from nova.virt.vmwareapi import ds_util from nova.virt.vmwareapi import ds_util
from nova.virt.vmwareapi import vm_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") vmdk_adapter_type = vm_util.get_vmdk_adapter_type("dummyAdapter")
self.assertEqual("dummyAdapter", vmdk_adapter_type) 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): def test_find_allocated_slots(self):
disk1 = fake.VirtualDisk(200, 0) disk1 = fake.VirtualDisk(200, 0)
disk2 = fake.VirtualDisk(200, 1) disk2 = fake.VirtualDisk(200, 1)

View File

@@ -216,9 +216,6 @@ class VMwareVolumeOpsTestCase(test.NoDBTestCase):
'volume_id': 'volume-fake-id'}} 'volume_id': 'volume-fake-id'}}
vm_ref = 'fake-vm-ref' vm_ref = 'fake-vm-ref'
default_adapter_type = constants.DEFAULT_ADAPTER_TYPE 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 adapter_type = adapter_type or default_adapter_type
with contextlib.nested( with contextlib.nested(
@@ -226,10 +223,10 @@ class VMwareVolumeOpsTestCase(test.NoDBTestCase):
mock.patch.object(self._volumeops, '_iscsi_discover_target', mock.patch.object(self._volumeops, '_iscsi_discover_target',
return_value=(mock.sentinel.device_name, return_value=(mock.sentinel.device_name,
mock.sentinel.uuid)), mock.sentinel.uuid)),
mock.patch.object(vm_util, 'get_vmdk_info', mock.patch.object(vm_util, 'get_scsi_adapter_type',
return_value=vmdk_info), return_value=adapter_type),
mock.patch.object(self._volumeops, 'attach_disk_to_vm') 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): attach_disk_to_vm):
self._volumeops.attach_volume(connection_info, self._instance, self._volumeops.attach_volume(connection_info, self._instance,
adapter_type) adapter_type)
@@ -238,7 +235,8 @@ class VMwareVolumeOpsTestCase(test.NoDBTestCase):
self._instance) self._instance)
iscsi_discover_target.assert_called_once_with( iscsi_discover_target.assert_called_once_with(
connection_info['data']) 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, attach_disk_to_vm.assert_called_once_with(vm_ref,
self._instance, adapter_type, 'rdmp', self._instance, adapter_type, 'rdmp',
device_name=mock.sentinel.device_name) 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_KEY = 'org.openstack.compute'
EXTENSION_TYPE_INSTANCE = 'instance' 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. # 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 # 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 # 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) 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): def _find_controller_slot(controller_keys, taken, max_unit_number):
for controller_key in controller_keys: for controller_key in controller_keys:
for unit_number in range(max_unit_number): for unit_number in range(max_unit_number):

View File

@@ -350,9 +350,12 @@ class VMwareVolumeOps(object):
if device_name is None: if device_name is None:
raise exception.StorageError( raise exception.StorageError(
reason=_("Unable to find iSCSI Target")) reason=_("Unable to find iSCSI Target"))
if adapter_type is None:
vmdk = vm_util.get_vmdk_info(self._session, vm_ref) # Get the vmdk file name that the VM is pointing to
adapter_type = adapter_type or vmdk.adapter_type 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, self.attach_disk_to_vm(vm_ref, instance,
adapter_type, 'rdmp', adapter_type, 'rdmp',