From 3b28cb2a10f7746a32cb7f7b62b6fc92ebcfb1e5 Mon Sep 17 00:00:00 2001 From: "Walter A. Boring IV" Date: Fri, 9 Jun 2017 22:40:38 +0000 Subject: [PATCH] FC: refactor fczm utils decorators to functions This patch changes the Fibre Channel Zone Manager utility decorators to functions. Those functions now have to be called manually. The intention of this is to unify how the FC drivers are to be declared and used vs. the iSCSI. No more magic decorators for FC drivers only. Change-Id: I8e6e964e3694654b8ba93fe432a0dd49fa5e1df0 --- cinder/tests/fake_driver.py | 20 +++++--- cinder/volume/drivers/coprhd/fc.py | 7 +-- .../drivers/dell_emc/sc/storagecenter_fc.py | 12 ++++- .../volume/drivers/dell_emc/unity/driver.py | 10 ++-- cinder/volume/drivers/dell_emc/vmax/fc.py | 7 +-- cinder/volume/drivers/dell_emc/vnx/driver.py | 4 +- cinder/volume/drivers/dell_emc/xtremio.py | 22 ++++---- cinder/volume/drivers/dothill/dothill_fc.py | 4 +- .../volume/drivers/fujitsu/eternus_dx_fc.py | 4 +- cinder/volume/drivers/hpe/hpe_3par_fc.py | 5 +- cinder/volume/drivers/huawei/huawei_driver.py | 6 ++- cinder/volume/drivers/ibm/flashsystem_fc.py | 4 +- .../drivers/ibm/ibm_storage/ibm_storage.py | 10 ++-- .../ibm/storwize_svc/storwize_svc_fc.py | 12 +++-- cinder/volume/drivers/infinidat.py | 21 ++++---- .../drivers/inspur/instorage/instorage_fc.py | 8 +-- .../volume/drivers/kaminario/kaminario_fc.py | 16 +++--- cinder/volume/drivers/nec/volume.py | 10 ++-- .../drivers/netapp/dataontap/fc_cmode.py | 12 +++-- .../drivers/netapp/eseries/fc_driver.py | 12 +++-- cinder/volume/drivers/nimble.py | 8 +-- cinder/volume/drivers/prophetstor/dpl_fc.py | 9 ++-- cinder/volume/drivers/pure.py | 4 +- cinder/zonemanager/utils.py | 50 ++++++------------- 24 files changed, 147 insertions(+), 130 deletions(-) diff --git a/cinder/tests/fake_driver.py b/cinder/tests/fake_driver.py index 1defb353cfa..e372ad2f71e 100644 --- a/cinder/tests/fake_driver.py +++ b/cinder/tests/fake_driver.py @@ -240,38 +240,42 @@ class FakeISERDriver(FakeLoggingVolumeDriver): class FakeFibreChannelDriver(driver.FibreChannelDriver): - @fczm_utils.add_fc_zone def initialize_connection(self, volume, connector): - return { + conn_info = { 'driver_volume_type': 'fibre_channel', 'data': { 'initiator_target_map': {'fake_wwn': ['fake_wwn2']}, }} + fczm_utils.add_fc_zone(conn_info) + return conn_info - @fczm_utils.add_fc_zone def no_zone_initialize_connection(self, volume, connector): """This shouldn't call the ZM.""" - return { + conn_info = { 'driver_volume_type': 'bogus', 'data': { 'initiator_target_map': {'fake_wwn': ['fake_wwn2']}, }} + fczm_utils.add_fc_zone(conn_info) + return conn_info - @fczm_utils.remove_fc_zone def terminate_connection(self, volume, connector, **kwargs): - return { + conn_info = { 'driver_volume_type': 'fibre_channel', 'data': { 'initiator_target_map': {'fake_wwn': ['fake_wwn2']}, }} + fczm_utils.remove_fc_zone(conn_info) + return conn_info - @fczm_utils.remove_fc_zone def no_zone_terminate_connection(self, volume, connector, **kwargs): - return { + conn_info = { 'driver_volume_type': 'bogus', 'data': { 'initiator_target_map': {'fake_wwn': ['fake_wwn2']}, }} + fczm_utils.remove_fc_zone(conn_info) + return conn_info class FakeGateDriver(lvm.LVMVolumeDriver): diff --git a/cinder/volume/drivers/coprhd/fc.py b/cinder/volume/drivers/coprhd/fc.py index 3018e068566..d437f376cdb 100644 --- a/cinder/volume/drivers/coprhd/fc.py +++ b/cinder/volume/drivers/coprhd/fc.py @@ -159,7 +159,6 @@ class EMCCoprHDFCDriver(driver.FibreChannelDriver): """Make sure volume is exported.""" pass - @fczm_utils.add_fc_zone def initialize_connection(self, volume, connector): """Initializes the connection and returns connection info.""" @@ -196,12 +195,13 @@ class EMCCoprHDFCDriver(driver.FibreChannelDriver): properties['auth_password'] = auth_secret LOG.debug('FC properties: %s', properties) - return { + conn_info = { 'driver_volume_type': 'fibre_channel', 'data': properties, } + fczm_utils.add_fc_zone(conn_info) + return conn_info - @fczm_utils.remove_fc_zone def terminate_connection(self, volume, connector, **kwargs): """Driver entry point to detach a volume from an instance.""" @@ -221,6 +221,7 @@ class EMCCoprHDFCDriver(driver.FibreChannelDriver): 'data': { 'target_wwn': target_wwns, 'initiator_target_map': initiator_target_map}} + fczm_utils.remove_fc_zone(data) LOG.debug('Return FC data: %s', data) return data diff --git a/cinder/volume/drivers/dell_emc/sc/storagecenter_fc.py b/cinder/volume/drivers/dell_emc/sc/storagecenter_fc.py index 8dbfe3df2e9..ad9f1f84b8d 100644 --- a/cinder/volume/drivers/dell_emc/sc/storagecenter_fc.py +++ b/cinder/volume/drivers/dell_emc/sc/storagecenter_fc.py @@ -76,7 +76,14 @@ class SCFCDriver(storagecenter_common.SCCommonDriver, self.configuration.safe_get('volume_backend_name') or 'Dell-FC' self.storage_protocol = 'FC' - @fczm_utils.add_fc_zone + def validate_connector(self, connector): + """Fail if connector doesn't contain all the data needed by driver. + + Do a check on the connector and ensure that it has wwnns, wwpns. + """ + self.validate_connector_has_setting(connector, 'wwpns') + self.validate_connector_has_setting(connector, 'wwnns') + def initialize_connection(self, volume, connector): """Initializes the connection and returns connection info. @@ -148,6 +155,7 @@ class SCFCDriver(storagecenter_common.SCCommonDriver, init_targ_map, 'discard': True}} LOG.debug('Return FC data: %s', data) + fczm_utils.add_fc_zone(data) return data LOG.error('Lun mapping returned null!') @@ -231,7 +239,6 @@ class SCFCDriver(storagecenter_common.SCCommonDriver, 'data': {}} return info - @fczm_utils.remove_fc_zone def terminate_connection(self, volume, connector, force=False, **kwargs): # Special case if connector is None: @@ -293,6 +300,7 @@ class SCFCDriver(storagecenter_common.SCCommonDriver, if scserver and api.get_volume_count(scserver) == 0: info['data'] = {'target_wwn': targets, 'initiator_target_map': init_targ_map} + fczm_utils.remove_fc_zone(info) return info except Exception: diff --git a/cinder/volume/drivers/dell_emc/unity/driver.py b/cinder/volume/drivers/dell_emc/unity/driver.py index 80c91c4b51a..6783b862541 100644 --- a/cinder/volume/drivers/dell_emc/unity/driver.py +++ b/cinder/volume/drivers/dell_emc/unity/driver.py @@ -122,7 +122,6 @@ class UnityDriver(driver.ManageableVD, """Make sure volume is exported.""" pass - @zm_utils.add_fc_zone def initialize_connection(self, volume, connector): """Initializes the connection and returns connection info. @@ -168,12 +167,15 @@ class UnityDriver(driver.ManageableVD, } """ - return self.adapter.initialize_connection(volume, connector) + conn_info = self.adapter.initialize_connection(volume, connector) + zm_utils.add_fc_zone(conn_info) + return conn_info - @zm_utils.remove_fc_zone def terminate_connection(self, volume, connector, **kwargs): """Disallow connection from connector.""" - return self.adapter.terminate_connection(volume, connector) + conn_info = self.adapter.terminate_connection(volume, connector) + zm_utils.remove_fc_zone(conn_info) + return conn_info def get_volume_stats(self, refresh=False): """Get volume stats. diff --git a/cinder/volume/drivers/dell_emc/vmax/fc.py b/cinder/volume/drivers/dell_emc/vmax/fc.py index d201bf60e8a..13b06278129 100644 --- a/cinder/volume/drivers/dell_emc/vmax/fc.py +++ b/cinder/volume/drivers/dell_emc/vmax/fc.py @@ -198,7 +198,6 @@ class VMAXFCDriver(san.SanDriver, driver.FibreChannelDriver): """ pass - @fczm_utils.add_fc_zone def initialize_connection(self, volume, connector): """Initializes the connection and returns connection info. @@ -239,7 +238,9 @@ class VMAXFCDriver(san.SanDriver, driver.FibreChannelDriver): device_info = self.common.initialize_connection( volume, connector) if device_info: - return self.populate_data(device_info, volume, connector) + conn_info = self.populate_data(device_info, volume, connector) + fczm_utils.add_fc_zone(conn_info) + return conn_info else: return {} @@ -268,7 +269,6 @@ class VMAXFCDriver(san.SanDriver, driver.FibreChannelDriver): return data - @fczm_utils.remove_fc_zone def terminate_connection(self, volume, connector, **kwargs): """Disallow connection from connector. @@ -290,6 +290,7 @@ class VMAXFCDriver(san.SanDriver, driver.FibreChannelDriver): if zoning_mappings: self.common.terminate_connection(volume, connector) data = self._cleanup_zones(zoning_mappings) + fczm_utils.remove_fc_zone(data) return data def _get_zoning_mappings(self, volume, connector): diff --git a/cinder/volume/drivers/dell_emc/vnx/driver.py b/cinder/volume/drivers/dell_emc/vnx/driver.py index f97c764e461..4f70cd749f7 100644 --- a/cinder/volume/drivers/dell_emc/vnx/driver.py +++ b/cinder/volume/drivers/dell_emc/vnx/driver.py @@ -165,7 +165,6 @@ class VNXDriver(driver.ManageableVD, """Make sure volume is exported.""" pass - @zm_utils.add_fc_zone def initialize_connection(self, volume, connector): """Initializes the connection and returns connection info. @@ -219,9 +218,9 @@ class VNXDriver(driver.ManageableVD, LOG.debug("Exit initialize_connection" " - Returning connection info: %(conn_info)s.", {'conn_info': conn_info}) + zm_utils.add_fc_zone(conn_info) return conn_info - @zm_utils.remove_fc_zone def terminate_connection(self, volume, connector, **kwargs): """Disallow connection from connector.""" LOG.debug("Entering terminate_connection" @@ -231,6 +230,7 @@ class VNXDriver(driver.ManageableVD, LOG.debug("Exit terminate_connection" " - Returning connection info: %(conn_info)s.", {'conn_info': conn_info}) + zm_utils.remove_fc_zone(conn_info) return conn_info def get_volume_stats(self, refresh=False): diff --git a/cinder/volume/drivers/dell_emc/xtremio.py b/cinder/volume/drivers/dell_emc/xtremio.py index 92e53a6b8df..1de14af0301 100644 --- a/cinder/volume/drivers/dell_emc/xtremio.py +++ b/cinder/volume/drivers/dell_emc/xtremio.py @@ -1206,7 +1206,6 @@ class XtremIOFCDriver(XtremIOVolumeDriver, seq = range(len(uniq_luns) + 1) return min(set(seq) - uniq_luns) - @fczm_utils.add_fc_zone def initialize_connection(self, volume, connector): wwpns = self._get_initiator_names(connector) ig_name = self._get_ig_name(connector) @@ -1240,14 +1239,15 @@ class XtremIOFCDriver(XtremIOVolumeDriver, for ig in igs: lunmap = self.create_lun_map(volume, ig, lun_num) lun_num = lunmap['lun'] - return {'driver_volume_type': 'fibre_channel', - 'data': { - 'target_discovered': False, - 'target_lun': lun_num, - 'target_wwn': self.get_targets(), - 'initiator_target_map': i_t_map}} + conn_info = {'driver_volume_type': 'fibre_channel', + 'data': { + 'target_discovered': False, + 'target_lun': lun_num, + 'target_wwn': self.get_targets(), + 'initiator_target_map': i_t_map}} + fczm_utils.add_fc_zone(conn_info) + return conn_info - @fczm_utils.remove_fc_zone def terminate_connection(self, volume, connector, **kwargs): (super(XtremIOFCDriver, self) .terminate_connection(volume, connector, **kwargs)) @@ -1264,8 +1264,10 @@ class XtremIOFCDriver(XtremIOVolumeDriver, data = {'target_wwn': self.get_targets(), 'initiator_target_map': i_t_map} - return {'driver_volume_type': 'fibre_channel', - 'data': data} + conn_info = {'driver_volume_type': 'fibre_channel', + 'data': data} + fczm_utils.remove_fc_zone(conn_info) + return conn_info def _get_initiator_names(self, connector): return [wwpn if ':' in wwpn else diff --git a/cinder/volume/drivers/dothill/dothill_fc.py b/cinder/volume/drivers/dothill/dothill_fc.py index 5a45d77d4d3..0dad05616ad 100644 --- a/cinder/volume/drivers/dothill/dothill_fc.py +++ b/cinder/volume/drivers/dothill/dothill_fc.py @@ -83,7 +83,6 @@ class DotHillFCDriver(cinder.volume.driver.FibreChannelDriver): def delete_volume(self, volume): self.common.delete_volume(volume) - @fczm_utils.add_fc_zone def initialize_connection(self, volume, connector): self.common.client_login() try: @@ -98,11 +97,11 @@ class DotHillFCDriver(cinder.volume.driver.FibreChannelDriver): data['initiator_target_map'] = init_targ_map info = {'driver_volume_type': 'fibre_channel', 'data': data} + fczm_utils.add_fc_zone(info) return info finally: self.common.client_logout() - @fczm_utils.remove_fc_zone def terminate_connection(self, volume, connector, **kwargs): info = {'driver_volume_type': 'fibre_channel', 'data': {}} try: @@ -112,6 +111,7 @@ class DotHillFCDriver(cinder.volume.driver.FibreChannelDriver): ports, init_targ_map = self.get_init_targ_map(connector) info['data'] = {'target_wwn': ports, 'initiator_target_map': init_targ_map} + fczm_utils.remove_fc_zone(info) finally: return info diff --git a/cinder/volume/drivers/fujitsu/eternus_dx_fc.py b/cinder/volume/drivers/fujitsu/eternus_dx_fc.py index 74fcd5ad2c0..d01a1b7fc8d 100644 --- a/cinder/volume/drivers/fujitsu/eternus_dx_fc.py +++ b/cinder/volume/drivers/fujitsu/eternus_dx_fc.py @@ -146,7 +146,6 @@ class FJDXFCDriver(driver.FibreChannelDriver): """Driver entry point to remove an export for a volume.""" return - @fczm_utils.add_fc_zone def initialize_connection(self, volume, connector): """Allow connection to connector and return connection info.""" LOG.debug('initialize_connection, volume id: %(vid)s, ' @@ -163,9 +162,9 @@ class FJDXFCDriver(driver.FibreChannelDriver): info['data'] = data LOG.debug('initialize_connection, ' 'info: %s, exit method.', info) + fczm_utils.add_fc_zone(info) return info - @fczm_utils.remove_fc_zone def terminate_connection(self, volume, connector, **kwargs): """Disallow connection from connector.""" wwpns = connector.get('wwpns') if connector else None @@ -185,6 +184,7 @@ class FJDXFCDriver(driver.FibreChannelDriver): # No more volumes attached to the host init_tgt_map = self.common.build_fc_init_tgt_map(connector) info['data'] = {'initiator_target_map': init_tgt_map} + fczm_utils.remove_fc_zone(info) LOG.debug('terminate_connection, unmap: %(unmap)s, ' 'connection info: %(info)s, exit method', diff --git a/cinder/volume/drivers/hpe/hpe_3par_fc.py b/cinder/volume/drivers/hpe/hpe_3par_fc.py index a032e0a5d6e..e5aa9b37620 100644 --- a/cinder/volume/drivers/hpe/hpe_3par_fc.py +++ b/cinder/volume/drivers/hpe/hpe_3par_fc.py @@ -123,7 +123,6 @@ class HPE3PARFCDriver(hpebasedriver.HPE3PARDriverBase): self.protocol = 'FC' @utils.trace - @fczm_utils.add_fc_zone def initialize_connection(self, volume, connector): """Assigns the volume to a server. @@ -200,12 +199,12 @@ class HPE3PARFCDriver(hpebasedriver.HPE3PARDriverBase): encryption_key_id = volume.get('encryption_key_id', None) info['data']['encrypted'] = encryption_key_id is not None + fczm_utils.add_fc_zone(info) return info finally: self._logout(common) @utils.trace - @fczm_utils.remove_fc_zone def terminate_connection(self, volume, connector, **kwargs): """Driver entry point to unattach a volume from an instance.""" common = self._login() @@ -247,7 +246,7 @@ class HPE3PARFCDriver(hpebasedriver.HPE3PARDriverBase): info['data'] = {'target_wwn': target_wwns, 'initiator_target_map': init_targ_map} - + fczm_utils.remove_fc_zone(info) return info finally: diff --git a/cinder/volume/drivers/huawei/huawei_driver.py b/cinder/volume/drivers/huawei/huawei_driver.py index 1638fe460bf..ddc33f7d906 100644 --- a/cinder/volume/drivers/huawei/huawei_driver.py +++ b/cinder/volume/drivers/huawei/huawei_driver.py @@ -2113,7 +2113,6 @@ class HuaweiFCDriver(HuaweiBaseDriver, driver.FibreChannelDriver): data['vendor_name'] = 'Huawei' return data - @fczm_utils.add_fc_zone @coordination.synchronized('huawei-mapping-{connector[host]}') def initialize_connection(self, volume, connector): lun_id, lun_type = self.get_lun_id_and_type(volume) @@ -2232,6 +2231,7 @@ class HuaweiFCDriver(HuaweiBaseDriver, driver.FibreChannelDriver): fc_info['data']['target_lun'] = same_host_id hyperm.rmt_client.logout() + fczm_utils.add_fc_zone(fc_info) LOG.info("Return FC info is: %s.", fc_info) return fc_info @@ -2256,7 +2256,6 @@ class HuaweiFCDriver(HuaweiBaseDriver, driver.FibreChannelDriver): return same_host_id - @fczm_utils.remove_fc_zone @coordination.synchronized('huawei-mapping-{connector[host]}') def terminate_connection(self, volume, connector, **kwargs): """Delete map between a volume and a host.""" @@ -2346,6 +2345,9 @@ class HuaweiFCDriver(HuaweiBaseDriver, driver.FibreChannelDriver): LOG.info("terminate_connection, return data is: %s.", fc_info) + # This only does something if and only if the initiator_target_map + # exists in fc_info + fczm_utils.remove_fc_zone(fc_info) return fc_info def _delete_zone_and_remove_fc_initiators(self, wwns, host_id): diff --git a/cinder/volume/drivers/ibm/flashsystem_fc.py b/cinder/volume/drivers/ibm/flashsystem_fc.py index 9a242a1d4bf..e1027c38c1e 100644 --- a/cinder/volume/drivers/ibm/flashsystem_fc.py +++ b/cinder/volume/drivers/ibm/flashsystem_fc.py @@ -259,7 +259,6 @@ class FlashSystemFCDriver(fscommon.FlashSystemDriver): return {'driver_volume_type': type_str, 'data': properties} - @fczm_utils.add_fc_zone @utils.synchronized('flashsystem-init-conn', external=True) def initialize_connection(self, volume, connector): """Perform work so that an FC connection can be made. @@ -316,9 +315,9 @@ class FlashSystemFCDriver(fscommon.FlashSystemDriver): 'conn': connector, 'prop': properties}) + fczm_utils.add_fc_zone(properties) return properties - @fczm_utils.remove_fc_zone @utils.synchronized('flashsystem-term-conn', external=True) def terminate_connection(self, volume, connector, **kwargs): """Cleanup after connection has been terminated. @@ -353,6 +352,7 @@ class FlashSystemFCDriver(fscommon.FlashSystemDriver): self._build_initiator_target_map( connector['wwpns'], conn_wwpns)) return_data['data'] = properties + fczm_utils.remove_fc_zone(return_data) LOG.debug( 'leave: terminate_connection: volume %(vol)s with ' diff --git a/cinder/volume/drivers/ibm/ibm_storage/ibm_storage.py b/cinder/volume/drivers/ibm/ibm_storage/ibm_storage.py index 9095e3ab4ee..b526577eef0 100644 --- a/cinder/volume/drivers/ibm/ibm_storage/ibm_storage.py +++ b/cinder/volume/drivers/ibm/ibm_storage/ibm_storage.py @@ -144,17 +144,19 @@ class IBMStorageDriver(san.SanDriver, return self.proxy.remove_export(context, volume) - @fczm_utils.add_fc_zone def initialize_connection(self, volume, connector): """Map the created volume.""" - return self.proxy.initialize_connection(volume, connector) + conn_info = self.proxy.initialize_connection(volume, connector) + fczm_utils.add_fc_zone(conn_info) + return conn_info - @fczm_utils.remove_fc_zone def terminate_connection(self, volume, connector, **kwargs): """Terminate a connection to a volume.""" - return self.proxy.terminate_connection(volume, connector) + conn_info = self.proxy.terminate_connection(volume, connector) + fczm_utils.remove_fc_zone(conn_info) + return conn_info def create_volume_from_snapshot(self, volume, snapshot): """Create a volume from a snapshot.""" diff --git a/cinder/volume/drivers/ibm/storwize_svc/storwize_svc_fc.py b/cinder/volume/drivers/ibm/storwize_svc/storwize_svc_fc.py index 6e0ff48dee2..660a26d9c2f 100644 --- a/cinder/volume/drivers/ibm/storwize_svc/storwize_svc_fc.py +++ b/cinder/volume/drivers/ibm/storwize_svc/storwize_svc_fc.py @@ -133,12 +133,13 @@ class StorwizeSVCFCDriver(storwize_common.StorwizeSVCCommonDriver): return self.initialize_connection(volume, connector) - @fczm_utils.add_fc_zone def initialize_connection(self, volume, connector): """Perform necessary work to make a FC connection.""" @coordination.synchronized('storwize-host-{system_id}-{host}') def _do_initialize_connection_locked(system_id, host): - return self._do_initialize_connection(volume, connector) + conn_info = self._do_initialize_connection(volume, connector) + fczm_utils.add_fc_zone(conn_info) + return conn_info return _do_initialize_connection_locked(self._state['system_id'], connector['host']) @@ -297,7 +298,6 @@ class StorwizeSVCFCDriver(storwize_common.StorwizeSVCCommonDriver): return self.terminate_connection(volume, connector, **kwargs) - @fczm_utils.remove_fc_zone def terminate_connection(self, volume, connector, **kwargs): """Cleanup after an FC connection has been terminated.""" # If a fake connector is generated by nova when the host @@ -308,8 +308,10 @@ class StorwizeSVCFCDriver(storwize_common.StorwizeSVCCommonDriver): @coordination.synchronized('storwize-host-{system_id}-{host}') def _do_terminate_connection_locked(system_id, host): - return self._do_terminate_connection(volume, connector, - **kwargs) + conn_info = self._do_terminate_connection(volume, connector, + **kwargs) + fczm_utils.remove_fc_zone(conn_info) + return conn_info return _do_terminate_connection_locked(self._state['system_id'], host) def _do_terminate_connection(self, volume, connector, **kwargs): diff --git a/cinder/volume/drivers/infinidat.py b/cinder/volume/drivers/infinidat.py index 61c5e857869..0b2c0e99a87 100644 --- a/cinder/volume/drivers/infinidat.py +++ b/cinder/volume/drivers/infinidat.py @@ -330,11 +330,13 @@ class InfiniboxVolumeDriver(san.SanISCSIDriver): target_wwpns = list(self._get_online_fc_ports()) target_wwpns, init_target_map = self._build_initiator_target_map( connector, target_wwpns) - return dict(driver_volume_type='fibre_channel', - data=dict(target_discovered=False, - target_wwn=target_wwpns, - target_lun=lun, - initiator_target_map=init_target_map)) + conn_info = dict(driver_volume_type='fibre_channel', + data=dict(target_discovered=False, + target_wwn=target_wwpns, + target_lun=lun, + initiator_target_map=init_target_map)) + fczm_utils.add_fc_zone(conn_info) + return conn_info def _get_iscsi_network_space(self, netspace_name): netspace = self._system.network_spaces.safe_get( @@ -417,7 +419,6 @@ class InfiniboxVolumeDriver(san.SanISCSIDriver): ports = [iqn.IQN(connector['initiator'])] return ports - @fczm_utils.add_fc_zone @infinisdk_to_cinder_exceptions @coordination.synchronized('infinidat-{self.management_address}-lock') def initialize_connection(self, volume, connector): @@ -427,7 +428,6 @@ class InfiniboxVolumeDriver(san.SanISCSIDriver): else: return self._initialize_connection_iscsi(volume, connector) - @fczm_utils.remove_fc_zone @infinisdk_to_cinder_exceptions @coordination.synchronized('infinidat-{self.management_address}-lock') def terminate_connection(self, volume, connector, **kwargs): @@ -462,8 +462,11 @@ class InfiniboxVolumeDriver(san.SanISCSIDriver): target_wwpns)) result_data = dict(target_wwn=target_wwpns, initiator_target_map=target_map) - return dict(driver_volume_type=volume_type, - data=result_data) + conn_info = dict(driver_volume_type=volume_type, + data=result_data) + if self._protocol == 'FC': + fczm_utils.remove_fc_zone(conn_info) + return conn_info @infinisdk_to_cinder_exceptions def get_volume_stats(self, refresh=False): diff --git a/cinder/volume/drivers/inspur/instorage/instorage_fc.py b/cinder/volume/drivers/inspur/instorage/instorage_fc.py index 2a7102693e4..ec290b0656d 100644 --- a/cinder/volume/drivers/inspur/instorage/instorage_fc.py +++ b/cinder/volume/drivers/inspur/instorage/instorage_fc.py @@ -58,7 +58,6 @@ class InStorageMCSFCDriver(instorage_common.InStorageMCSCommonDriver, self.protocol = 'FC' @cinder_utils.trace - @fczm_utils.add_fc_zone @coordination.synchronized('instorage-host' '{self._state[system_id]}' '{connector[host]}') @@ -155,9 +154,10 @@ class InStorageMCSFCDriver(instorage_common.InStorageMCSCommonDriver, '%(conn)s.\n', {'vol': volume, 'conn': connector}) - return {'driver_volume_type': 'fibre_channel', 'data': properties, } + info = {'driver_volume_type': 'fibre_channel', 'data': properties, } + fczm_utils.add_fc_zone(info) + return info - @fczm_utils.remove_fc_zone def terminate_connection(self, volume, connector, **kwargs): """Cleanup after an FC connection has been terminated.""" # If a fake connector is generated by nova when the host @@ -227,6 +227,8 @@ class InStorageMCSFCDriver(instorage_common.InStorageMCSCommonDriver, (connector['wwpns'], target_wwpns)) info['data'] = {'initiator_target_map': init_targ_map} + # Only remove the zone if it's the last volume removed + fczm_utils.remove_fc_zone(info) # No volume mapped to the host, delete host from array self._assistant.delete_host(host_name) diff --git a/cinder/volume/drivers/kaminario/kaminario_fc.py b/cinder/volume/drivers/kaminario/kaminario_fc.py index 8179adc78fb..83cfdd5f5c2 100644 --- a/cinder/volume/drivers/kaminario/kaminario_fc.py +++ b/cinder/volume/drivers/kaminario/kaminario_fc.py @@ -49,7 +49,6 @@ class KaminarioFCDriver(common.KaminarioCinderDriver): self._protocol = 'FC' self.lookup_service = fczm_utils.create_lookup_service() - @fczm_utils.add_fc_zone @utils.trace @coordination.synchronized('{self.k2_lock_name}') def initialize_connection(self, volume, connector): @@ -76,13 +75,14 @@ class KaminarioFCDriver(common.KaminarioCinderDriver): if temp_client: self.client = temp_client # Return target volume information. - return {'driver_volume_type': 'fibre_channel', - 'data': {"target_discovered": True, - "target_lun": lun, - "target_wwn": target_wwpns, - "initiator_target_map": init_target_map}} + conn_info = {'driver_volume_type': 'fibre_channel', + 'data': {"target_discovered": True, + "target_lun": lun, + "target_wwn": target_wwpns, + "initiator_target_map": init_target_map}} + fczm_utils.add_fc_zone(conn_info) + return conn_info - @fczm_utils.remove_fc_zone @utils.trace @coordination.synchronized('{self.k2_lock_name}') def terminate_connection(self, volume, connector, **kwargs): @@ -105,6 +105,8 @@ class KaminarioFCDriver(common.KaminarioCinderDriver): connector, target_wwpns) properties["data"] = {"target_wwn": target_wwpns, "initiator_target_map": init_target_map} + fczm_utils.remove_fc_zone(properties) + # To support replication failback if temp_client: self.client = temp_client diff --git a/cinder/volume/drivers/nec/volume.py b/cinder/volume/drivers/nec/volume.py index 78135c08cb1..9456d06a5e3 100644 --- a/cinder/volume/drivers/nec/volume.py +++ b/cinder/volume/drivers/nec/volume.py @@ -80,13 +80,15 @@ class MStorageFCDriver(volume_helper.MStorageDSVDriver, def get_volume_stats(self, refresh=False): return self.fc_get_volume_stats(refresh) - @fczm_utils.add_fc_zone def initialize_connection(self, volume, connector): - return self.fc_initialize_connection(volume, connector) + conn_info = self.fc_initialize_connection(volume, connector) + fczm_utils.add_fc_zone(conn_info) + return conn_info - @fczm_utils.remove_fc_zone def terminate_connection(self, volume, connector, **kwargs): - return self.fc_terminate_connection(volume, connector) + conn_info = self.fc_terminate_connection(volume, connector) + fczm_utils.remove_fc_zone(conn_info) + return conn_info def create_export_snapshot(self, context, snapshot, connector): return self.fc_do_export_snapshot(context, snapshot, connector) diff --git a/cinder/volume/drivers/netapp/dataontap/fc_cmode.py b/cinder/volume/drivers/netapp/dataontap/fc_cmode.py index b8548a0b861..adc6e3f448d 100644 --- a/cinder/volume/drivers/netapp/dataontap/fc_cmode.py +++ b/cinder/volume/drivers/netapp/dataontap/fc_cmode.py @@ -94,14 +94,16 @@ class NetAppCmodeFibreChannelDriver(driver.BaseVD, def unmanage(self, volume): return self.library.unmanage(volume) - @fczm_utils.add_fc_zone def initialize_connection(self, volume, connector): - return self.library.initialize_connection_fc(volume, connector) + conn_info = self.library.initialize_connection_fc(volume, connector) + fczm_utils.add_fc_zone(conn_info) + return conn_info - @fczm_utils.remove_fc_zone def terminate_connection(self, volume, connector, **kwargs): - return self.library.terminate_connection_fc(volume, connector, - **kwargs) + conn_info = self.library.terminate_connection_fc(volume, connector, + **kwargs) + fczm_utils.remove_fc_zone(conn_info) + return conn_info def get_pool(self, volume): return self.library.get_pool(volume) diff --git a/cinder/volume/drivers/netapp/eseries/fc_driver.py b/cinder/volume/drivers/netapp/eseries/fc_driver.py index 93bf500eea1..87da283ece0 100644 --- a/cinder/volume/drivers/netapp/eseries/fc_driver.py +++ b/cinder/volume/drivers/netapp/eseries/fc_driver.py @@ -88,14 +88,16 @@ class NetAppEseriesFibreChannelDriver(driver.BaseVD, def unmanage(self, volume): return self.library.unmanage(volume) - @fczm_utils.add_fc_zone def initialize_connection(self, volume, connector, **kwargs): - return self.library.initialize_connection_fc(volume, connector) + conn_info = self.library.initialize_connection_fc(volume, connector) + fczm_utils.add_fc_zone(conn_info) + return conn_info - @fczm_utils.remove_fc_zone def terminate_connection(self, volume, connector, **kwargs): - return self.library.terminate_connection_fc(volume, connector, - **kwargs) + conn_info = self.library.terminate_connection_fc(volume, connector, + **kwargs) + fczm_utils.remove_fc_zone(conn_info) + return conn_info def get_pool(self, volume): return self.library.get_pool(volume) diff --git a/cinder/volume/drivers/nimble.py b/cinder/volume/drivers/nimble.py index 710ce388f15..527fdacc51f 100644 --- a/cinder/volume/drivers/nimble.py +++ b/cinder/volume/drivers/nimble.py @@ -860,7 +860,6 @@ class NimbleFCDriver(NimbleBaseVolumeDriver, driver.FibreChannelDriver): return init_targ_map - @fczm_utils.add_fc_zone def initialize_connection(self, volume, connector): """Driver entry point to attach a volume to an instance.""" LOG.info('Entering initialize_connection volume=%(vol)s' @@ -899,10 +898,9 @@ class NimbleFCDriver(NimbleBaseVolumeDriver, driver.FibreChannelDriver): LOG.info("Return FC data for zone addition: %(data)s.", {'data': data}) - + fczm_utils.add_fc_zone(data) return data - @fczm_utils.remove_fc_zone def terminate_connection(self, volume, connector, **kwargs): """Driver entry point to unattach a volume from an instance.""" LOG.info('Entering terminate_connection volume=%(vol)s' @@ -934,6 +932,10 @@ class NimbleFCDriver(NimbleBaseVolumeDriver, driver.FibreChannelDriver): data = {'driver_volume_type': 'fibre_channel', 'data': {'target_wwn': target_wwns}} + # FIXME: need to optionally add the initiator_target_map here when + # there are no more volumes exported to the initiator / target pair + # otherwise the zone will never get removed. + fczm_utils.remove_fc_zone(data) return data def get_wwpns_from_array(self, array_name): diff --git a/cinder/volume/drivers/prophetstor/dpl_fc.py b/cinder/volume/drivers/prophetstor/dpl_fc.py index ca9450be341..2e6c74ba286 100644 --- a/cinder/volume/drivers/prophetstor/dpl_fc.py +++ b/cinder/volume/drivers/prophetstor/dpl_fc.py @@ -218,7 +218,6 @@ class DPLFCDriver(dplcommon.DPLCOMMONDriver, return init_targ_map - @fczm_utils.add_fc_zone def initialize_connection(self, volume, connector): """Allow connection to connector and return connection info.""" """ @@ -336,10 +335,11 @@ class DPLFCDriver(dplcommon.DPLCOMMONDriver, LOG.info('Connect initialization info: ' '{driver_volume_type: fibre_channel, ' 'data: %(properties)s', {'properties': properties}) - return {'driver_volume_type': 'fibre_channel', - 'data': properties} + conn_info = {'driver_volume_type': 'fibre_channel', + 'data': properties} + fczm_utils.add_fc_zone(conn_info) + return conn_info - @fczm_utils.remove_fc_zone def terminate_connection(self, volume, connector, **kwargs): """Disallow connection from connector.""" """ @@ -397,6 +397,7 @@ class DPLFCDriver(dplcommon.DPLCOMMONDriver, lsTargets) info['data'] = {'target_wwn': lsTargets, 'initiator_target_map': init_targ_map} + fczm_utils.remove_fc_zone(info) return info diff --git a/cinder/volume/drivers/pure.py b/cinder/volume/drivers/pure.py index a8fc248df2a..1c6e85b1b8b 100644 --- a/cinder/volume/drivers/pure.py +++ b/cinder/volume/drivers/pure.py @@ -1932,7 +1932,6 @@ class PureFCDriver(PureBaseVolumeDriver, driver.FibreChannelDriver): ports = array.list_ports() return [port["wwn"] for port in ports if port["wwn"]] - @fczm_utils.add_fc_zone @pure_driver_debug_trace def initialize_connection(self, volume, connector): """Allow connection to connector and return connection info.""" @@ -1952,6 +1951,7 @@ class PureFCDriver(PureBaseVolumeDriver, driver.FibreChannelDriver): } } + fczm_utils.add_fc_zone(properties) return properties @utils.retry(exception.PureRetryableException, @@ -2009,7 +2009,6 @@ class PureFCDriver(PureBaseVolumeDriver, driver.FibreChannelDriver): return init_targ_map - @fczm_utils.remove_fc_zone @pure_driver_debug_trace def terminate_connection(self, volume, connector, **kwargs): """Terminate connection.""" @@ -2027,4 +2026,5 @@ class PureFCDriver(PureBaseVolumeDriver, driver.FibreChannelDriver): properties["data"] = {"target_wwn": target_wwns, "initiator_target_map": init_targ_map} + fczm_utils.remove_fc_zone(properties) return properties diff --git a/cinder/zonemanager/utils.py b/cinder/zonemanager/utils.py index 7628491bcdf..9c524d92dac 100644 --- a/cinder/zonemanager/utils.py +++ b/cinder/zonemanager/utils.py @@ -73,49 +73,27 @@ def get_formatted_wwn(wwn_str): for i in range(0, len(wwn_str), 2)])).lower() -def add_fc_zone(initialize_connection): - """Decorator to add a FC Zone.""" - - def decorator(self, *args, **kwargs): - conn_info = initialize_connection(self, *args, **kwargs) - if not conn_info: - LOG.warning("Driver didn't return connection info, " - "can't add zone.") - return None - - vol_type = conn_info.get('driver_volume_type', None) +def add_fc_zone(connection_info): + """Utility function to add a FC Zone.""" + if connection_info: + vol_type = connection_info.get('driver_volume_type', None) if vol_type == 'fibre_channel': - if 'initiator_target_map' in conn_info['data']: + if 'initiator_target_map' in connection_info['data']: zm = create_zone_manager() if zm: LOG.debug("add_fc_zone connection info: %(conninfo)s.", - {'conninfo': conn_info}) - zm.add_connection(conn_info) - - return conn_info - - return decorator + {'conninfo': connection_info}) + zm.add_connection(connection_info) -def remove_fc_zone(terminate_connection): - """Decorator for FC drivers to remove zone.""" - - def decorator(self, *args, **kwargs): - conn_info = terminate_connection(self, *args, **kwargs) - if not conn_info: - LOG.warning("Driver didn't return connection info from " - "terminate_connection call.") - return None - - vol_type = conn_info.get('driver_volume_type', None) +def remove_fc_zone(connection_info): + """Utility function for FC drivers to remove zone.""" + if connection_info: + vol_type = connection_info.get('driver_volume_type', None) if vol_type == 'fibre_channel': - if 'initiator_target_map' in conn_info['data']: + if 'initiator_target_map' in connection_info['data']: zm = create_zone_manager() if zm: LOG.debug("remove_fc_zone connection info: %(conninfo)s.", - {'conninfo': conn_info}) - zm.delete_connection(conn_info) - - return conn_info - - return decorator + {'conninfo': connection_info}) + zm.delete_connection(connection_info)