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)