From 66f2db53460520019c6845be7f2997d6769dfe0d Mon Sep 17 00:00:00 2001 From: Sabari Kumar Murugesan Date: Thu, 3 Oct 2013 23:50:05 -0700 Subject: [PATCH] VMware: fix regression attaching iscsi cinder volumes VMware drivers fail to attach a iSCSI backed cinder volume with an error 'unable to find iscsi targets' because the underlying retrieval api was updated to a newer version but not it's usage in volume_util (see commit e331287cdd1300878bfb9bbb3630889370e5fa72). This is a regression over Grizzly release. Fixes: bug #1193980 (cherry picked from commit e70211ff89785fed6a868eaab723847833590502) Change-Id: I14fe62ad98fd9161df3ce6c06160b2759a9e38b2 --- nova/tests/virt/vmwareapi/test_vmwareapi.py | 8 +++ nova/virt/vmwareapi/fake.py | 72 ++++++++++++++++++--- nova/virt/vmwareapi/volume_util.py | 17 ++--- 3 files changed, 77 insertions(+), 20 deletions(-) diff --git a/nova/tests/virt/vmwareapi/test_vmwareapi.py b/nova/tests/virt/vmwareapi/test_vmwareapi.py index aacd26b9e801..9c11f0701211 100644 --- a/nova/tests/virt/vmwareapi/test_vmwareapi.py +++ b/nova/tests/virt/vmwareapi/test_vmwareapi.py @@ -914,6 +914,14 @@ class VMwareAPIVMTestCase(test.NoDBTestCase): self.conn.attach_volume(None, connection_info, self.instance, mount_point) + def test_find_st(self): + data = {'target_portal': 'fake_target_host:port', + 'target_iqn': 'fake_target_iqn'} + host = vmwareapi_fake._get_objects('HostSystem').objects[0] + host._add_iscsi_target(data) + result = volume_util.find_st(self.conn._session, data) + self.assertEquals(('fake-device', 'fake-uuid'), result) + def test_detach_iscsi_disk_from_vm(self): self._create_vm() connection_info = self._test_vmdk_connection_info('iscsi') diff --git a/nova/virt/vmwareapi/fake.py b/nova/virt/vmwareapi/fake.py index a3e1db59c098..c89d5f1d1d27 100644 --- a/nova/virt/vmwareapi/fake.py +++ b/nova/virt/vmwareapi/fake.py @@ -33,7 +33,7 @@ from nova.virt.vmwareapi import error_util _CLASSES = ['Datacenter', 'Datastore', 'ResourcePool', 'VirtualMachine', 'Network', 'HostSystem', 'HostNetworkSystem', 'Task', 'session', - 'files', 'ClusterComputeResource'] + 'files', 'ClusterComputeResource', 'HostStorageSystem'] _FAKE_FILE_SIZE = 1024 @@ -59,6 +59,7 @@ def reset(): _db_content[c] = {} create_network() create_host_network_system() + create_host_storage_system() create_host() create_host() create_datacenter() @@ -241,8 +242,15 @@ class DataObject(object): return str(self.__dict__) -class HostInternetScsiHba(): - pass +class HostInternetScsiHba(DataObject): + """ + iSCSI Host Bus Adapter + """ + + def __init__(self): + super(HostInternetScsiHba, self).__init__() + self.device = 'vmhba33' + self.key = 'key-vmhba33' class VirtualDisk(DataObject): @@ -502,6 +510,13 @@ class HostNetworkSystem(ManagedObject): self.set("networkInfo.pnic", net_info_pnic) +class HostStorageSystem(ManagedObject): + """HostStorageSystem class.""" + + def __init__(self): + super(HostStorageSystem, self).__init__("storageSystem") + + class HostSystem(ManagedObject): """Host System class.""" @@ -510,9 +525,13 @@ class HostSystem(ManagedObject): self.set("name", name) if _db_content.get("HostNetworkSystem", None) is None: create_host_network_system() + if not _get_object_refs('HostStorageSystem'): + create_host_storage_system() host_net_key = _db_content["HostNetworkSystem"].keys()[0] host_net_sys = _db_content["HostNetworkSystem"][host_net_key].obj self.set("configManager.networkSystem", host_net_sys) + host_storage_sys_key = _get_object_refs('HostStorageSystem')[0] + self.set("configManager.storageSystem", host_storage_sys_key) summary = DataObject() hardware = DataObject() @@ -581,13 +600,43 @@ class HostSystem(ManagedObject): config = DataObject() storageDevice = DataObject() - hostBusAdapter = HostInternetScsiHba() - hostBusAdapter.HostHostBusAdapter = [hostBusAdapter] - hostBusAdapter.iScsiName = "iscsi-name" - storageDevice.hostBusAdapter = hostBusAdapter + iscsi_hba = HostInternetScsiHba() + iscsi_hba.iScsiName = "iscsi-name" + host_bus_adapter_array = DataObject() + host_bus_adapter_array.HostHostBusAdapter = [iscsi_hba] + storageDevice.hostBusAdapter = host_bus_adapter_array config.storageDevice = storageDevice - self.set("config.storageDevice.hostBusAdapter", - config.storageDevice.hostBusAdapter) + self.set("config.storageDevice.hostBusAdapter", host_bus_adapter_array) + + # Set the same on the storage system managed object + host_storage_sys = _get_object(host_storage_sys_key) + host_storage_sys.set('storageDeviceInfo.hostBusAdapter', + host_bus_adapter_array) + + def _add_iscsi_target(self, data): + default_lun = DataObject() + default_lun.scsiLun = 'key-vim.host.ScsiDisk-010' + default_lun.key = 'key-vim.host.ScsiDisk-010' + default_lun.deviceName = 'fake-device' + default_lun.uuid = 'fake-uuid' + scsi_lun_array = DataObject() + scsi_lun_array.ScsiLun = [default_lun] + self.set("config.storageDevice.scsiLun", scsi_lun_array) + + transport = DataObject() + transport.address = [data['target_portal']] + transport.iScsiName = data['target_iqn'] + default_target = DataObject() + default_target.lun = [default_lun] + default_target.transport = transport + + iscsi_adapter = DataObject() + iscsi_adapter.adapter = 'key-vmhba33' + iscsi_adapter.transport = transport + iscsi_adapter.target = [default_target] + iscsi_topology = DataObject() + iscsi_topology.adapter = [iscsi_adapter] + self.set("config.storageDevice.scsiTopology", iscsi_topology) def _add_port_group(self, spec): """Adds a port group to the host system object in the db.""" @@ -647,6 +696,11 @@ def create_host_network_system(): _create_object("HostNetworkSystem", host_net_system) +def create_host_storage_system(): + host_storage_system = HostStorageSystem() + _create_object("HostStorageSystem", host_storage_system) + + def create_host(): host_system = HostSystem() _create_object('HostSystem', host_system) diff --git a/nova/virt/vmwareapi/volume_util.py b/nova/virt/vmwareapi/volume_util.py index 11dfce9403c0..85ce0f573212 100644 --- a/nova/virt/vmwareapi/volume_util.py +++ b/nova/virt/vmwareapi/volume_util.py @@ -68,21 +68,16 @@ def find_st(session, data, cluster=None): lst_properties = ["config.storageDevice.hostBusAdapter", "config.storageDevice.scsiTopology", "config.storageDevice.scsiLun"] - props = session._call_method(vim_util, "get_object_properties", - None, host_mor, "HostSystem", - lst_properties) + prop_dict = session._call_method(vim_util, "get_dynamic_properties", + host_mor, "HostSystem", lst_properties) result = (None, None) hbas_ret = None scsi_topology = None scsi_lun_ret = None - for elem in props: - for prop in elem.propSet: - if prop.name == "config.storageDevice.hostBusAdapter": - hbas_ret = prop.val - elif prop.name == "config.storageDevice.scsiTopology": - scsi_topology = prop.val - elif prop.name == "config.storageDevice.scsiLun": - scsi_lun_ret = prop.val + if prop_dict: + hbas_ret = prop_dict.get('config.storageDevice.hostBusAdapter') + scsi_topology = prop_dict.get('config.storageDevice.scsiTopology') + scsi_lun_ret = prop_dict.get('config.storageDevice.scsiLun') # Meaning there are no host bus adapters on the host if hbas_ret is None: