def terminate_connection(self, volume, connector, **kwargs): if connector is None: host_name, init_pwwn = self.get_hostname_initiator_pwwn(volume) else: host_name = self.get_initiator_host_name(connector) # To support replication failback temp_client = None if (hasattr(volume, 'replication_status') and volume.replication_status == K2_REP_FAILED_OVER): temp_client = self.client self.client = self.target super(KaminarioFCDriver, self).terminate_connection(volume, connector) properties = {"driver_volume_type": "fibre_channel", "data": {}} host_rs = self.client.search("hosts", name=host_name) # In terminate_connection, host_entry is deleted if host # is not attached to any volume if host_rs.total == 0: # Get target wwpns. target_wwpns = self.get_target_info(volume) if connector is None: connector = {'wwpns': init_pwwn} target_wwpns, init_target_map = self._build_initiator_target_map( 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 return properties
def terminate_connection(self, volume, connector, **kwargs): """Disallow connection from connector.""" """ connector = {'ip': CONF.my_ip, 'host': CONF.host, 'initiator': self._initiator, 'wwnns': self._fc_wwnns, 'wwpns': self._fc_wwpns} """ lstargetWwpns = [] lsTargets = [] szwwpns = [] ret = 0 info = {'driver_volume_type': 'fibre_channel', 'data': {}} LOG.info('terminate_connection volume: %(volume)s, ' 'connector: %(con)s', {'volume': volume, 'con': connector}) # Query targetwwpns. # Get all target list of volume. for dwwpn in connector['wwpns']: szwwpn = self._convertHex2String(dwwpn) if len(szwwpn) == 0: msg = _('Invalid wwpns format %(wwpns)s') % \ {'wwpns': connector['wwpns']} raise exception.VolumeBackendAPIException(data=msg) szwwpns.append(szwwpn) if len(szwwpns) == 0: ret = errno.EFAULT msg = _('Invalid wwpns format %(wwpns)s') % \ {'wwpns': connector['wwpns']} raise exception.VolumeBackendAPIException(data=msg) else: for szwwpn in szwwpns: lstargetWwpns = self._get_targetwpns( self._conver_uuid2hex(volume['id']), szwwpn) lsTargets = list(set(lsTargets + lstargetWwpns)) # Remove all export target try: for ptarget in lsTargets: ret = self._delete_export_fc(volume['id'], ptarget, szwwpns) if ret: break except Exception: ret = errno.EFAULT finally: if ret: msg = _('Faield to unassign %(volume)s') % (volume['id']) raise exception.VolumeBackendAPIException(data=msg) # Failed to delete export with fibre channel if ret: init_targ_map = self._build_initiator_target_map(connector, lsTargets) info['data'] = {'target_wwn': lsTargets, 'initiator_target_map': init_targ_map} fczm_utils.remove_fc_zone(info) return info
def terminate_connection_with_empty_map(self, volume, connector, **kwargs): conn_info = { 'driver_volume_type': 'fibre_channel', 'data': { 'initiator_target_map': {}, }} fczm_utils.remove_fc_zone(conn_info) return conn_info
def no_zone_terminate_connection(self, volume, connector, **kwargs): conn_info = { 'driver_volume_type': 'bogus', 'data': { 'initiator_target_map': {'fake_wwn': ['fake_wwn2']}, }} fczm_utils.remove_fc_zone(conn_info) return conn_info
def _do_terminate_connection(self, volume, connector, **kwargs): """Cleanup after an FC connection has been terminated. When we clean up a terminated connection between a given connector and volume, we: 1. Translate the given connector to a host name 2. Remove the volume-to-host mapping if it exists 3. Delete the host if it has no more mappings (hosts are created automatically by this driver when mappings are created) """ vol_name = self._get_target_vol(volume) info = {} if connector is not None and 'host' in connector: # get host according to FC protocol connector = connector.copy() connector.pop('initiator', None) info = {'driver_volume_type': 'fibre_channel', 'data': {}} host_name = self._assistant.get_host_from_connector( connector, volume_name=vol_name) if host_name is None: msg = (_('terminate_connection: Failed to get host name from' ' connector.')) LOG.error(msg) raise exception.VolumeDriverException(message=msg) else: host_name = None # Unmap volumes, if hostname is None, need to get value from vdiskmap host_name = self._assistant.unmap_vol_from_host(vol_name, host_name) # Host_name could be none if host_name: resp = self._assistant.check_host_mapped_vols(host_name) if not len(resp): LOG.info("Need to remove FC Zone, building initiator " "target map.") # Build info data structure for zone removing if connector is not None and 'wwpns' in connector: target_wwpns = [] # Returning all target_wwpns in storage_nodes, since # we cannot determine which wwpns are logged in during # a VM deletion. for node in self._state['storage_nodes'].values(): target_wwpns.extend(node['WWPN']) init_targ_map = (utils.make_initiator_target_all2all_map (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) return info
def terminate_connection(self, volume, connector, **kwargs): """Disallow connection from connector.""" LOG.debug("Entering terminate_connection" " - connector: %(connector)s.", {'connector': connector}) conn_info = self.adapter.terminate_connection(volume, connector) 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 terminate_connection(self, volume, connector, **kwargs): info = {'driver_volume_type': 'fibre_channel', 'data': {}} try: self.common.unmap_volume(volume, connector, 'wwpns') if not self.common.client.list_luns_for_host( connector['wwpns'][0]): 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
def terminate_connection(self, volume, connector, **kwargs): """Disallow connection from connector.""" LOG.debug( "Entering terminate_connection" " - connector: %(connector)s.", {'connector': connector}) conn_info = self.adapter.terminate_connection(volume, connector) 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 terminate_connection(self, volume, connector): """Terminate connection between the server and the volume.""" conn_info = super(HBSDRESTFC, self).terminate_connection(volume, connector) if self.conf.hitachi_zoning_request: if conn_info and conn_info['data']['target_wwn']: init_targ_map = utils.build_initiator_target_map( connector, conn_info['data']['target_wwn'], self._lookup_service) if init_targ_map: conn_info['data']['initiator_target_map'] = init_targ_map fczm_utils.remove_fc_zone(conn_info) return conn_info
def _terminate_connection_snapshot_locked(self, host, snapshot, connector): LOG.info('Terminate FC connection for snapshot %(id)s, ' 'connector info %(conn)s.', {'id': snapshot.id, 'conn': connector}) ini_tgt_map = huawei_flow.terminate_fc_connection( snapshot, constants.SNAPSHOT_TYPE, connector, self.fc_san, self.local_cli, self.configuration) conn = {'driver_volume_type': 'fibre_channel', 'data': {'initiator_target_map': ini_tgt_map}, } LOG.info('Terminate FC connection successfully: %s.', conn) zm_utils.remove_fc_zone(conn) return conn
def terminate_connection(self, volume, connector, **kwargs): info = {'driver_volume_type': 'fibre_channel', 'data': {}} try: self.common.unmap_volume(volume, connector, 'wwpns') if not self.common.client.list_luns_for_host( connector['wwpns'][0]): 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
def terminate_connection(self, volume, connector, **kwargs): """Driver entry point to detach a volume from an instance.""" array_id = self.get_volume_replication_driver_data(volume) common = self._login(array_id=array_id) try: is_force_detach = connector is None if is_force_detach: common.terminate_connection(volume, None, None) # TODO(sonivi): remove zones, if not required # for now, do not remove zones zone_remove = False else: hostname = common._safe_hostname(connector['host']) common.terminate_connection(volume, hostname, wwn=connector['wwpns']) zone_remove = True try: vluns = common.client.getHostVLUNs(hostname) except hpeexceptions.HTTPNotFound: # No more exports for this host. pass else: # Vlun exists, so check for wwpn entry. for wwpn in connector.get('wwpns'): for vlun in vluns: if (vlun.get('active') and vlun.get('remoteName') == wwpn.upper()): zone_remove = False break info = {'driver_volume_type': 'fibre_channel', 'data': {}} if zone_remove: LOG.info("Need to remove FC Zone, building initiator " "target map") target_wwns, init_targ_map, _numPaths = \ self._build_initiator_target_map(common, connector) info['data'] = { 'target_wwn': target_wwns, 'initiator_target_map': init_targ_map } fczm_utils.remove_fc_zone(info) return info finally: self._logout(common)
def terminate_connection(self, volume, connector, **kwargs): info = {'driver_volume_type': 'fibre_channel', 'data': {}} try: if not self.common.client.list_luns_for_host( connector['wwpns'][0]): ports, init_targ_map = self.get_init_targ_map(connector) info['data'] = {'target_wwn': ports, 'initiator_target_map': init_targ_map} # multiattach volumes cannot be unmapped here, but will # be implicity unmapped when the volume is deleted. if not volume.get('multiattach'): self.common.unmap_volume(volume, connector, 'wwpns') fczm_utils.remove_fc_zone(info) finally: return info
def terminate_connection(self, volume, connector, **kwargs): """Cleanup after connection has been terminated. When we clean up a terminated connection between a given connector and volume, we: 1. Translate the given connector to a host name 2. Remove the volume-to-host mapping if it exists 3. Delete the host if it has no more mappings (hosts are created automatically by this driver when mappings are created) """ LOG.debug( 'enter: terminate_connection: volume %(vol)s with ' 'connector %(conn)s.', { 'vol': volume, 'conn': connector }) return_data = { 'driver_volume_type': 'fibre_channel', 'data': {}, } vdisk_name = volume['name'] self._wait_vdisk_copy_completed(vdisk_name) self._unmap_vdisk_from_host(vdisk_name, connector) host_name = self._get_host_from_connector(connector) if not host_name: properties = {} conn_wwpns = self._get_conn_fc_wwpns() properties['target_wwn'] = conn_wwpns properties['initiator_target_map'] = ( 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 ' 'connector %(conn)s.', { 'vol': volume, 'conn': connector }) return return_data
def terminate_connection(self, volume, connector, **kwargs): LOG.debug( 'enter: terminate_connection: volume ' '%(vol)s with connector %(conn)s', { 'vol': volume.id, 'conn': connector }) volume_name = self._convert_name(volume.name) properties = {'driver_volume_type': 'fibre_channel', 'data': {}} initiator_wwpns = [] target_wwpns = [] if connector and 'wwpns' in connector: initiator_wwpns = connector['wwpns'] target_wwpns = self._get_connected_wwpns() if len(target_wwpns) == 0: target_wwpns = [] LOG.warning( 'terminate_connection: Did not find ' 'available fc wwpns when volume %s ' 'delete lun map.', volume.id) initiator_target = {} for i_wwpn in initiator_wwpns: initiator_target[str(i_wwpn)] = target_wwpns properties['data'] = {'initiator_target_map': initiator_target} if self._check_multi_attached(volume, connector) < 2: if not initiator_wwpns: # -1 means all lun maps of this volume initiator_wwpns = -1 self._cmd.delete_lun_map(volume_name, self.protocol, initiator_wwpns) else: LOG.warning( 'volume %s has been mapped to multi VMs, and these ' 'VMs belong to the same host. The mapping ' 'cancellation request is aborted.', volume.id) zone_utils.remove_fc_zone(properties) LOG.debug( 'leave: terminate_connection: volume ' '%(vol)s with connector %(conn)s', { 'vol': volume.id, 'conn': connector }) return properties
def terminate_connection(self, volume, connector, **kwargs): """Cleanup after connection has been terminated. When we clean up a terminated connection between a given connector and volume, we: 1. Translate the given connector to a host name 2. Remove the volume-to-host mapping if it exists 3. Delete the host if it has no more mappings (hosts are created automatically by this driver when mappings are created) """ LOG.debug( 'enter: terminate_connection: volume %(vol)s with ' 'connector %(conn)s.', {'vol': volume, 'conn': connector}) return_data = { 'driver_volume_type': 'fibre_channel', 'data': {}, } vdisk_name = volume['name'] self._wait_vdisk_copy_completed(vdisk_name) self._unmap_vdisk_from_host(vdisk_name, connector) host_name = self._get_host_from_connector(connector) if not host_name: properties = {} conn_wwpns = self._get_conn_fc_wwpns() properties['target_wwn'] = conn_wwpns properties['initiator_target_map'] = ( 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 ' 'connector %(conn)s.', {'vol': volume, 'conn': connector}) return return_data
def terminate_connection(self, volume, connector, **kwargs): """Disallow connection from connector. Return empty data if other volumes are in the same zone. The FibreChannel ZoneManager doesn't remove zones if there isn't an initiator_target_map in the return of terminate_connection. :param volume: the volume object :param connector: the connector object :returns: dict -- the target_wwns and initiator_target_map if the zone is to be removed, otherwise empty """ data = {'driver_volume_type': 'fibre_channel', 'data': {}} zoning_mappings = {} if connector: zoning_mappings = self._get_zoning_mappings(volume, connector) if zoning_mappings: self.common.terminate_connection(volume, connector) data = self._cleanup_zones(zoning_mappings) fczm_utils.remove_fc_zone(data) return data
def terminate_connection(self, volume, connector, **kwargs): """Disallow connection from connector. Return empty data if other volumes are in the same zone. The FibreChannel ZoneManager doesn't remove zones if there isn't an initiator_target_map in the return of terminate_connection. :param volume: the volume object :param connector: the connector object :returns: dict -- the target_wwns and initiator_target_map if the zone is to be removed, otherwise empty """ data = {'driver_volume_type': 'fibre_channel', 'data': {}} zoning_mappings = {} if connector: zoning_mappings = self._get_zoning_mappings(volume, connector) if zoning_mappings: self.common.terminate_connection(volume, connector) data = self._cleanup_zones(zoning_mappings) fczm_utils.remove_fc_zone(data) return data
def terminate_connection(self, volume, connector, **kwargs): """Unmap an InfiniBox volume from the host""" infinidat_volume = self._get_infinidat_volume(volume) if self._protocol == 'FC': volume_type = 'fibre_channel' else: volume_type = 'iscsi' result_data = dict() ports = self._get_ports_from_connector(infinidat_volume, connector) for port in ports: host_name = self._make_host_name(port) host = self._system.hosts.safe_get(name=host_name) if host is None: # not found. ignore. continue # unmap try: host.unmap_volume(infinidat_volume) except KeyError: continue # volume mapping not found # check if the host now doesn't have mappings if host is not None and len(host.get_luns()) == 0: host.safe_delete() if self._protocol == 'FC' and connector is not None: # Create initiator-target mapping to delete host entry # this is only relevant for regular (specific host) detach target_wwpns = list(self._get_online_fc_ports()) target_wwpns, target_map = ( self._build_initiator_target_map(connector, target_wwpns)) result_data = dict(target_wwn=target_wwpns, initiator_target_map=target_map) 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
def terminate_connection(self, volume, connector, **kwargs): """Unmap an InfiniBox volume from the host""" infinidat_volume = self._get_infinidat_volume(volume) if self._protocol == 'FC': volume_type = 'fibre_channel' else: volume_type = 'iscsi' result_data = dict() ports = self._get_ports_from_connector(infinidat_volume, connector) for port in ports: host_name = self._make_host_name(port) host = self._system.hosts.safe_get(name=host_name) if host is None: # not found. ignore. continue # unmap try: host.unmap_volume(infinidat_volume) except KeyError: continue # volume mapping not found # check if the host now doesn't have mappings if host is not None and len(host.get_luns()) == 0: host.safe_delete() if self._protocol == 'FC' and connector is not None: # Create initiator-target mapping to delete host entry # this is only relevant for regular (specific host) detach target_wwpns = list(self._get_online_fc_ports()) target_wwpns, target_map = ( self._build_initiator_target_map(connector, target_wwpns)) result_data = dict(target_wwn=target_wwpns, initiator_target_map=target_map) 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
def terminate_connection(self, volume, connector, **kwargs): """Terminate a connection to a volume.""" conn_info = self.proxy.terminate_connection(volume, connector) fczm_utils.remove_fc_zone(conn_info) return conn_info
def terminate_connection(self, volume, connector, **kwargs): """Disallow connection from connector.""" conn_info = self.adapter.terminate_connection(volume, connector) zm_utils.remove_fc_zone(conn_info) return conn_info
def terminate_connection(self, volume, connector, force=False, **kwargs): # Special case if connector is None: return self.force_detach(volume) # Grab some quick info. volume_name = volume.get('id') provider_id = volume.get('provider_id') LOG.debug('Terminate connection: %s', volume_name) LOG.debug('Volume details %s', volume) # None `connector` indicates force detach, then detach all even if the # volume is multi-attached. is_multiattached = (hasattr(volume, 'volume_attachment') and self.is_multiattach_to_host( volume.get('volume_attachment'), connector['host'])) if is_multiattached: LOG.info('Cannot terminate connection: ' '%(vol)s is multiattached.', {'vol': volume_name}) return True with self._client.open_connection() as api: try: wwpns = [] if not connector else connector.get('wwpns', []) # Find the volume on the storage center. islivevol = self._is_live_vol(volume) scvolume = api.find_volume(volume_name, provider_id, islivevol) if scvolume: # Get the SSN it is on. ssn = scvolume['instanceId'].split('.')[0] # Will be None if we have no wwpns. scserver = self._find_server(api, wwpns, ssn) # Get our target map so we can return it to free up a zone. lun, targets, init_targ_map = api.find_wwns(scvolume, scserver) # Do we have extra live volume work? if islivevol: # Get our live volume. sclivevolume = api.get_live_volume(provider_id) # Do not map to a failed over volume. if (sclivevolume and not api.is_failed_over(provider_id, sclivevolume)): lvlun, lvtargets, lvinit_targ_map = ( self.terminate_secondary( api, sclivevolume, wwpns)) # Add to our return. if lvlun: targets += lvtargets init_targ_map.update(lvinit_targ_map) if (wwpns and scserver and api.unmap_volume(scvolume, scserver) is True): LOG.debug('Connection terminated') elif not wwpns and api.unmap_all(scvolume): LOG.debug('All connections terminated') else: raise exception.VolumeBackendAPIException( data=_('Terminate connection failed')) info = {'driver_volume_type': 'fibre_channel', 'data': {}} # if not then we return the target map so that # the zone can be freed up. 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: with excutils.save_and_reraise_exception(): LOG.error('Failed to terminate connection') raise exception.VolumeBackendAPIException( data=_('Terminate connection unable to connect to backend.'))
def _do_terminate_connection_locked(system_id, host): conn_info = self._do_terminate_connection(volume, connector, **kwargs) fczm_utils.remove_fc_zone(conn_info) return conn_info
def terminate_connection(self, volume, connector, **kwargs): """Terminate a connection to a volume.""" conn_info = self.proxy.terminate_connection(volume, connector) fczm_utils.remove_fc_zone(conn_info) return conn_info
def terminate_connection(self, volume, connector, **kwargs): conn_info = self.fc_terminate_connection(volume, connector) fczm_utils.remove_fc_zone(conn_info) return conn_info
def terminate_connection(self, volume, connector, **kwargs): """Delete map between a volume and a host.""" lun_id, lun_type = self.get_lun_id_and_type(volume) wwns = connector['wwpns'] host_name = connector['host'] left_lunnum = -1 lungroup_id = None view_id = None LOG.info('terminate_connection: wwpns: %(wwns)s, ' 'LUN ID: %(lun_id)s.', {'wwns': wwns, 'lun_id': lun_id}) host_id = huawei_utils.get_host_id(self.client, host_name) if host_id: mapping_view_name = constants.MAPPING_VIEW_PREFIX + host_id view_id = self.client.find_mapping_view(mapping_view_name) if view_id: lungroup_id = self.client.find_lungroup_from_map(view_id) if lun_id and lungroup_id: lungroup_ids = self.client.get_lungroupids_by_lunid(lun_id, lun_type) if lungroup_id in lungroup_ids: self.client.remove_lun_from_lungroup(lungroup_id, lun_id, lun_type) else: LOG.warning("LUN is not in lungroup. " "LUN ID: %(lun_id)s. " "Lungroup id: %(lungroup_id)s.", {"lun_id": lun_id, "lungroup_id": lungroup_id}) else: LOG.warning("Can't find lun on the array.") if lungroup_id: left_lunnum = self.client.get_obj_count_from_lungroup(lungroup_id) if int(left_lunnum) > 0: fc_info = {'driver_volume_type': 'fibre_channel', 'data': {}} else: fc_info, portg_id = self._delete_zone_and_remove_fc_initiators( wwns, host_id) if lungroup_id: if view_id and self.client.lungroup_associated( view_id, lungroup_id): self.client.delete_lungroup_mapping_view(view_id, lungroup_id) self.client.delete_lungroup(lungroup_id) if portg_id: if view_id and self.client.is_portgroup_associated_to_view( view_id, portg_id): self.client.delete_portgroup_mapping_view(view_id, portg_id) self.client.delete_portgroup(portg_id) if host_id: hostgroup_name = constants.HOSTGROUP_PREFIX + host_id hostgroup_id = self.client.find_hostgroup(hostgroup_name) if hostgroup_id: if view_id and self.client.hostgroup_associated( view_id, hostgroup_id): self.client.delete_hostgoup_mapping_view( view_id, hostgroup_id) self.client.remove_host_from_hostgroup( hostgroup_id, host_id) self.client.delete_hostgroup(hostgroup_id) if not self.client.check_fc_initiators_exist_in_host( host_id): self.client.remove_host(host_id) if view_id: self.client.delete_mapping_view(view_id) # Deal with hypermetro connection. metadata = huawei_utils.get_volume_private_data(volume) LOG.info("Detach Volume, metadata is: %s.", metadata) if metadata.get('hypermetro_id'): hyperm = hypermetro.HuaweiHyperMetro(self.client, self.rmt_client, self.configuration) hyperm.disconnect_volume_fc(volume, connector) 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 terminate_connection(self, volume, connector, **kwargs): """Disallow connection from connector.""" """ connector = {'ip': CONF.my_ip, 'host': CONF.host, 'initiator': self._initiator, 'wwnns': self._fc_wwnns, 'wwpns': self._fc_wwpns} """ lstargetWwpns = [] lsTargets = [] szwwpns = [] ret = 0 info = {'driver_volume_type': 'fibre_channel', 'data': {}} LOG.info( 'terminate_connection volume: %(volume)s, ' 'connector: %(con)s', { 'volume': volume, 'con': connector }) # Query targetwwpns. # Get all target list of volume. for dwwpn in connector['wwpns']: szwwpn = self._convertHex2String(dwwpn) if len(szwwpn) == 0: msg = _('Invalid wwpns format %(wwpns)s') % \ {'wwpns': connector['wwpns']} raise exception.VolumeBackendAPIException(data=msg) szwwpns.append(szwwpn) if len(szwwpns) == 0: ret = errno.EFAULT msg = _('Invalid wwpns format %(wwpns)s') % \ {'wwpns': connector['wwpns']} raise exception.VolumeBackendAPIException(data=msg) else: for szwwpn in szwwpns: lstargetWwpns = self._get_targetwpns( self._conver_uuid2hex(volume['id']), szwwpn) lsTargets = list(set(lsTargets + lstargetWwpns)) # Remove all export target try: for ptarget in lsTargets: ret = self._delete_export_fc(volume['id'], ptarget, szwwpns) if ret: break except Exception: ret = errno.EFAULT finally: if ret: msg = _('Faield to unassign %(volume)s') % (volume['id']) raise exception.VolumeBackendAPIException(data=msg) # Failed to delete export with fibre channel if ret: init_targ_map = self._build_initiator_target_map( connector, lsTargets) info['data'] = { 'target_wwn': lsTargets, 'initiator_target_map': init_targ_map } fczm_utils.remove_fc_zone(info) return info
def terminate_connection(self, volume, connector, **kwargs): """Disallow connection from connector.""" conn_info = self.adapter.terminate_connection(volume, connector) zm_utils.remove_fc_zone(conn_info) return conn_info
def terminate_connection(self, volume, connector, **kwargs): """Driver entry point to detach a volume from an instance.""" array_id = self.get_volume_replication_driver_data(volume) common = self._login(array_id=array_id) try: is_force_detach = connector is None remote_client = None multipath = False if connector: multipath = connector.get('multipath') LOG.debug("multipath: %(multipath)s", {'multipath': multipath}) if multipath: if volume.get('replication_status') == 'enabled': LOG.debug('This is a replication setup') remote_target = common._replication_targets[0] replication_mode = remote_target['replication_mode'] quorum_witness_ip = ( remote_target.get('quorum_witness_ip')) if replication_mode == 1: LOG.debug('replication_mode is sync') if quorum_witness_ip: LOG.debug('quorum_witness_ip is present') LOG.debug('Peer Persistence has been configured') else: LOG.debug('Since quorum_witness_ip is absent, ' 'considering this as Active/Passive ' 'replication') else: LOG.debug('Active/Passive replication has been ' 'configured') if replication_mode == 1 and quorum_witness_ip: remote_client = ( common._create_replication_client(remote_target)) if is_force_detach: common.terminate_connection(volume, None, None) # TODO(sonivi): remove zones, if not required # for now, do not remove zones zone_remove = False else: hostname = common._safe_hostname(connector['host'], connector) common.terminate_connection(volume, hostname, wwn=connector['wwpns'], remote_client=remote_client) zone_remove = True try: vluns = common.client.getHostVLUNs(hostname) except hpeexceptions.HTTPNotFound: # No more exports for this host. pass else: # Vlun exists, so check for wwpn entry. for wwpn in connector.get('wwpns'): for vlun in vluns: if (vlun.get('active') and vlun.get('remoteName') == wwpn.upper()): zone_remove = False break info = {'driver_volume_type': 'fibre_channel', 'data': {}} if zone_remove: LOG.info("Need to remove FC Zone, building initiator " "target map") target_wwns, init_targ_map, _numPaths = ( self._build_initiator_target_map(common, connector)) info['data'] = { 'target_wwn': target_wwns, 'initiator_target_map': init_targ_map } fczm_utils.remove_fc_zone(info) if remote_client: if zone_remove: try: vluns = remote_client.getHostVLUNs(hostname) except hpeexceptions.HTTPNotFound: # No more exports for this host. pass else: # Vlun exists, so check for wwpn entry. for wwpn in connector.get('wwpns'): for vlun in vluns: if (vlun.get('active') and vlun.get('remoteName') == wwpn.upper()): zone_remove = False break info_peer = {'driver_volume_type': 'fibre_channel', 'data': {}} if zone_remove: LOG.info("Need to remove FC Zone, building initiator " "target map") target_wwns, init_targ_map, _numPaths = ( self._build_initiator_target_map( common, connector, remote_client)) info_peer['data'] = { 'target_wwn': target_wwns, 'initiator_target_map': init_targ_map } fczm_utils.remove_fc_zone(info_peer) info = ({ 'driver_volume_type': 'fibre_channel', 'data': { 'target_wwn': info['data']['target_wwn'] + info_peer['data']['target_wwn'], 'initiator_target_map': self.merge_dicts( info['data']['initiator_target_map'], info_peer['data']['initiator_target_map']) } }) return info finally: self._logout(common)