Beispiel #1
0
    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
Beispiel #2
0
    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
Beispiel #3
0
 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
Beispiel #4
0
 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
Beispiel #5
0
    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
Beispiel #6
0
 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
Beispiel #7
0
 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
Beispiel #8
0
 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
Beispiel #9
0
 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
Beispiel #10
0
    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
Beispiel #11
0
 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
Beispiel #12
0
    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)
Beispiel #13
0
 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
Beispiel #14
0
    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
Beispiel #15
0
    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
Beispiel #16
0
    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
Beispiel #17
0
    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
Beispiel #18
0
    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
Beispiel #19
0
 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
Beispiel #20
0
 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
Beispiel #21
0
    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
Beispiel #22
0
 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
Beispiel #23
0
    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.'))
Beispiel #24
0
 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
Beispiel #25
0
    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
Beispiel #26
0
 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
Beispiel #27
0
    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
Beispiel #28
0
    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
Beispiel #29
0
 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
Beispiel #30
0
    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)