Ejemplo n.º 1
0
    def update_migrated_volume(self, ctxt, volume, new_volume,
                               original_volume_status):
        new_name = huawei_utils.encode_name(volume.id)
        org_metadata = huawei_utils.get_volume_private_data(volume)
        new_metadata = huawei_utils.get_volume_private_data(new_volume)

        try:
            if org_metadata.get('huawei_sn') == new_metadata.get('huawei_sn'):
                self.local_cli.rename_lun(org_metadata['huawei_lun_id'],
                                          new_name[:-4] + '-org')
            self.local_cli.rename_lun(new_metadata['huawei_lun_id'],
                                      new_name,
                                      description=volume.name)
        except Exception:
            LOG.exception('Unable to rename lun %(id)s to %(name)s.', {
                'id': new_metadata['huawei_lun_id'],
                'name': new_name
            })
            name_id = new_volume.name_id
        else:
            LOG.info("Successfully rename lun %(id)s to %(name)s.", {
                'id': new_metadata['huawei_lun_id'],
                'name': new_name
            })
            name_id = None

        return {
            '_name_id': name_id,
            'provider_location': huawei_utils.to_string(**new_metadata),
        }
Ejemplo n.º 2
0
    def terminate_connection(self, volume, connector, **kwargs):
        LOG.info(
            'Terminate FC connection for volume %(id)s, '
            'connector info %(conn)s.', {
                'id': volume.id,
                'conn': connector
            })
        if self._is_volume_multi_attach_to_same_host(volume, connector):
            return

        metadata = huawei_utils.get_volume_private_data(volume)
        if metadata.get('hypermetro'):
            hypermetro = huawei_utils.get_hypermetro(self.local_cli, volume)
            if hypermetro:
                rmt_ini_tgt_map = huawei_flow.terminate_remote_fc_connection(
                    hypermetro['ID'], connector, self.fc_san,
                    self.hypermetro_rmt_cli)

        loc_ini_tgt_map = huawei_flow.terminate_fc_connection(
            volume, constants.LUN_TYPE, connector, self.fc_san, self.local_cli)
        if metadata.get('hypermetro'):
            self._merge_ini_tgt_map(loc_ini_tgt_map, rmt_ini_tgt_map)

        conn = {
            'driver_volume_type': 'fibre_channel',
            'data': {
                'initiator_target_map': loc_ini_tgt_map
            },
        }
        LOG.info('Terminate FC connection successfully: %s.', conn)
        zm_utils.remove_fc_zone(conn)
        return conn
Ejemplo n.º 3
0
    def failback(self, volumes):
        """Failover volumes back to primary backend.

        The main steps:
        1. Switch the role of replication pairs.
        2. Copy the second LUN data back to primary LUN.
        3. Split replication pairs.
        4. Switch the role of replication pairs.
        5. Enable replications.
        """
        volumes_update = []
        for v in volumes:
            v_update = {}
            v_update['volume_id'] = v.id
            drv_data = get_replication_driver_data(v)
            pair_id = drv_data.get('pair_id')
            if not pair_id:
                LOG.warning("No pair id in volume %s.", v.id)
                v_update['updates'] = {'replication_status': 'error'}
                volumes_update.append(v_update)
                continue

            rmt_lun_id = drv_data.get('rmt_lun_id')
            if not rmt_lun_id:
                LOG.warning("No remote lun id in volume %s.", v.id)
                v_update['updates'] = {'replication_status': 'error'}
                volumes_update.append(v_update)
                continue

            # Switch replication pair role, and start synchronize.
            self.local_driver.enable(pair_id)

            # Wait for synchronize complete.
            self.local_driver.wait_replica_ready(pair_id)

            # Split replication pair again
            self.rmt_driver.failover(pair_id)

            # Switch replication pair role, and start synchronize.
            self.rmt_driver.enable(pair_id)

            local_metadata = huawei_utils.get_volume_private_data(v)
            new_drv_data = to_string(
                {'pair_id': pair_id,
                 'rmt_lun_id': local_metadata.get('huawei_lun_id'),
                 'rmt_lun_wwn': local_metadata.get('huawei_lun_wwn')})
            location = huawei_utils.to_string(
                huawei_lun_id=rmt_lun_id,
                huawei_lun_wwn=drv_data.get('rmt_lun_wwn'))

            v_update['updates'] = {'provider_location': location,
                                   'replication_status': 'available',
                                   'replication_driver_data': new_drv_data}
            volumes_update.append(v_update)

        return volumes_update
Ejemplo n.º 4
0
    def _remove_volume_from_metrogroup(self, volumes, metrogroup_id):
        metro_ids = []
        for volume in volumes:
            metadata = huawei_utils.get_volume_private_data(volume)
            metro_id = metadata.get('hypermetro_id')
            if not metro_id:
                LOG.warning("Volume %s doesn't have hypermetro.", volume.id)
                continue

            self.local_cli.remove_metro_from_metrogroup(
                metrogroup_id, metro_id)
            metro_ids.append(metro_id)

        self._ensure_hypermetro_not_in_group(metrogroup_id, metro_ids)
Ejemplo n.º 5
0
    def initialize_connection(self, volume, connector):
        LOG.info(
            'Initialize FC connection for volume %(id)s, '
            'connector info %(conn)s.', {
                'id': volume.id,
                'conn': connector
            })

        metadata = huawei_utils.get_volume_private_data(volume)
        if metadata.get('hypermetro'):
            if (not connector.get('multipath')
                    and self.configuration.enforce_multipath_for_hypermetro):
                msg = _("Mapping hypermetro volume must use multipath.")
                LOG.error(msg)
                raise exception.VolumeBackendAPIException(data=msg)
            elif (not connector.get('multipath')
                  and not self.configuration.enforce_multipath_for_hypermetro):
                LOG.warning("Mapping hypermetro volume not use multipath,"
                            " so just mapping the local lun.")
            if not self.hypermetro_rmt_cli:
                msg = _("Mapping hypermetro volume requires remote.")
                LOG.error(msg)
                raise exception.VolumeBackendAPIException(data=msg)

        local_mapping = huawei_flow.initialize_fc_connection(
            volume, constants.LUN_TYPE, connector, self.fc_san, self.local_cli,
            self.configuration)
        if metadata.get('hypermetro') and connector.get('multipath'):
            hypermetro = huawei_utils.get_hypermetro(self.local_cli, volume)
            if not hypermetro:
                msg = _("Mapping hypermetro remote volume error.")
                LOG.error(msg)
                raise exception.VolumeBackendAPIException(data=msg)

            remote_mapping = huawei_flow.initialize_remote_fc_connection(
                hypermetro['ID'], connector, self.fc_san,
                self.hypermetro_rmt_cli, self.configuration)
            same_host_lun_id = self._change_same_host_lun_id(
                local_mapping, remote_mapping)
            mapping_info = self._merge_fc_mapping(local_mapping,
                                                  remote_mapping,
                                                  same_host_lun_id)
        else:
            mapping_info = local_mapping

        mapping_info.pop('aval_host_lun_ids', None)
        conn = {'driver_volume_type': 'fibre_channel', 'data': mapping_info}
        LOG.info('Initialize FC connection successfully: %s.', conn)
        zm_utils.add_fc_zone(conn)
        return conn
Ejemplo n.º 6
0
    def terminate_connection(self, volume, connector, **kwargs):
        LOG.info(
            'Terminate iscsi connection for volume %(id)s, '
            'connector info %(conn)s.', {
                'id': volume.id,
                'conn': connector
            })
        metadata = huawei_utils.get_volume_private_data(volume)
        if metadata.get('hypermetro_id'):
            huawei_flow.terminate_remote_iscsi_connection(
                metadata['hypermetro_id'], connector, self.hypermetro_rmt_cli)

        huawei_flow.terminate_iscsi_connection(volume, constants.LUN_TYPE,
                                               connector, self.local_cli)
        LOG.info('Terminate iscsi connection successfully.')
Ejemplo n.º 7
0
    def delete_hypermetro(self, volume):
        """Delete hypermetro."""
        metadata = huawei_utils.get_volume_private_data(volume)
        metro_id = metadata['hypermetro_id']
        remote_lun_id = metadata['remote_lun_id']

        if metro_id:
            self.check_metro_need_to_stop(volume)

            # Delete hypermetro
            self.client.delete_hypermetro(metro_id)

        # Delete remote lun.
        if remote_lun_id and self.rmt_client.check_lun_exist(remote_lun_id):
            self.rmt_client.delete_lun(remote_lun_id)
Ejemplo n.º 8
0
    def delete_hypermetro(self, volume):
        """Delete hypermetro."""
        metadata = huawei_utils.get_volume_private_data(volume)
        metro_id = metadata['hypermetro_id']
        remote_lun_id = metadata['remote_lun_id']

        if metro_id:
            self.check_metro_need_to_stop(volume)

            # Delete hypermetro
            self.client.delete_hypermetro(metro_id)

        # Delete remote lun.
        if remote_lun_id and self.rmt_client.check_lun_exist(remote_lun_id):
            self.rmt_client.delete_lun(remote_lun_id)
Ejemplo n.º 9
0
    def check_metro_need_to_stop(self, volume):
        metadata = huawei_utils.get_volume_private_data(volume)
        metro_id = metadata['hypermetro_id']
        metro_existed = self.client.check_hypermetro_exist(metro_id)

        if metro_existed:
            metro_info = self.client.get_hypermetro_by_id(metro_id)
            metro_health_status = metro_info['HEALTHSTATUS']
            metro_running_status = metro_info['RUNNINGSTATUS']

            if (metro_health_status == constants.HEALTH_NORMAL and
                (metro_running_status == constants.RUNNING_NORMAL or
                    metro_running_status == constants.RUNNING_SYNC)):
                self.client.stop_hypermetro(metro_id)

        return metro_id
Ejemplo n.º 10
0
    def check_metro_need_to_stop(self, volume):
        metadata = huawei_utils.get_volume_private_data(volume)
        metro_id = metadata['hypermetro_id']
        metro_existed = self.client.check_hypermetro_exist(metro_id)

        if metro_existed:
            metro_info = self.client.get_hypermetro_by_id(metro_id)
            metro_health_status = metro_info['HEALTHSTATUS']
            metro_running_status = metro_info['RUNNINGSTATUS']

            if (metro_health_status == constants.HEALTH_NORMAL
                    and (metro_running_status == constants.RUNNING_NORMAL
                         or metro_running_status == constants.RUNNING_SYNC)):
                self.client.stop_hypermetro(metro_id)

        return metro_id
Ejemplo n.º 11
0
    def failover(self, volumes):
        """Failover volumes back to secondary array.

        Split the replication pairs and make the secondary LUNs R&W.
        """
        volumes_update = []
        for v in volumes:
            v_update = {}
            v_update['volume_id'] = v.id
            drv_data = get_replication_driver_data(v)
            pair_id = drv_data.get('pair_id')
            if not pair_id:
                LOG.warning("No pair id in volume %s.", v.id)
                v_update['updates'] = {'replication_status': 'error'}
                volumes_update.append(v_update)
                continue

            rmt_lun_id = drv_data.get('rmt_lun_id')
            if not rmt_lun_id:
                LOG.warning("No remote lun id in volume %s.", v.id)
                v_update['updates'] = {'replication_status': 'error'}
                volumes_update.append(v_update)
                continue

            self.rmt_driver.failover(pair_id)

            local_metadata = huawei_utils.get_volume_private_data(v)
            new_drv_data = to_string({
                'pair_id':
                pair_id,
                'rmt_lun_id':
                local_metadata.get('huawei_lun_id'),
                'rmt_lun_wwn':
                local_metadata.get('huawei_lun_wwn')
            })
            location = huawei_utils.to_string(
                huawei_lun_id=rmt_lun_id,
                huawei_lun_wwn=drv_data.get('rmt_lun_wwn'))

            v_update['updates'] = {
                'provider_location': location,
                'replication_status': 'failed-over',
                'replication_driver_data': new_drv_data
            }
            volumes_update.append(v_update)

        return volumes_update
Ejemplo n.º 12
0
    def _terminate_connection_locked(self, host, volume, connector):
        LOG.info('Terminate iscsi connection for volume %(id)s, '
                 'connector info %(conn)s.',
                 {'id': volume.id, 'conn': connector})
        if self._is_volume_multi_attach_to_same_host(volume, connector):
            return

        metadata = huawei_utils.get_volume_private_data(volume)
        if metadata.get('hypermetro'):
            hypermetro = huawei_utils.get_hypermetro(self.local_cli, volume)
            if hypermetro:
                huawei_flow.terminate_remote_iscsi_connection(
                    hypermetro['ID'], connector, self.hypermetro_rmt_cli,
                    self.configuration)

        huawei_flow.terminate_iscsi_connection(
            volume, constants.LUN_TYPE, connector, self.local_cli,
            self.configuration)
        LOG.info('Terminate iscsi connection successfully.')
Ejemplo n.º 13
0
    def _add_volume_to_metrogroup(self, volumes, metrogroup_id):
        metro_ids = []
        for volume in volumes:
            metadata = huawei_utils.get_volume_private_data(volume)
            if not metadata.get('hypermetro'):
                LOG.warning("Volume %s doesn't have hypermetro.", volume.id)
                continue

            hypermetro = huawei_utils.get_hypermetro(self.local_cli, volume)
            if not hypermetro:
                LOG.warning("Volume %s doesn't have hypermetro on the array.",
                            volume.id)
                continue

            metro_id = hypermetro['ID']
            self._stop_hypermetro_if_need(metro_id)
            self.local_cli.add_metro_to_metrogroup(metrogroup_id, metro_id)
            metro_ids.append(metro_id)

        self._ensure_hypermetro_in_group(metrogroup_id, metro_ids)
Ejemplo n.º 14
0
    def failover(self, volumes):
        """Failover volumes back to secondary array.

        Split the replication pairs and make the secondary LUNs R&W.
        """
        volumes_update = []
        for v in volumes:
            v_update = {}
            v_update['volume_id'] = v.id
            drv_data = get_replication_driver_data(v)
            pair_id = drv_data.get('pair_id')
            if not pair_id:
                LOG.warning("No pair id in volume %s.", v.id)
                v_update['updates'] = {'replication_status': 'error'}
                volumes_update.append(v_update)
                continue

            rmt_lun_id = drv_data.get('rmt_lun_id')
            if not rmt_lun_id:
                LOG.warning("No remote lun id in volume %s.", v.id)
                v_update['updates'] = {'replication_status': 'error'}
                volumes_update.append(v_update)
                continue

            self.rmt_driver.failover(pair_id)

            local_metadata = huawei_utils.get_volume_private_data(v)
            new_drv_data = to_string(
                {'pair_id': pair_id,
                 'rmt_lun_id': local_metadata.get('huawei_lun_id'),
                 'rmt_lun_wwn': local_metadata.get('huawei_lun_wwn')})
            location = huawei_utils.to_string(
                huawei_lun_id=rmt_lun_id,
                huawei_lun_wwn=drv_data.get('rmt_lun_wwn'))

            v_update['updates'] = {'provider_location': location,
                                   'replication_status': 'failed-over',
                                   'replication_driver_data': new_drv_data}
            volumes_update.append(v_update)

        return volumes_update
Ejemplo n.º 15
0
    def initialize_connection(self, volume, connector):
        LOG.info(
            'Initialize iscsi connection for volume %(id)s, '
            'connector info %(conn)s.', {
                'id': volume.id,
                'conn': connector
            })
        metadata = huawei_utils.get_volume_private_data(volume)
        if metadata.get('hypermetro_id'):
            if not connector.get('multipath'):
                msg = _("Mapping hypermetro volume must use multipath.")
                LOG.error(msg)
                raise exception.VolumeBackendAPIException(data=msg)
            if not self.hypermetro_rmt_cli:
                msg = _("Mapping hypermetro volume requires remote.")
                LOG.error(msg)
                raise exception.VolumeBackendAPIException(data=msg)

        local_mapping = huawei_flow.initialize_iscsi_connection(
            volume, constants.LUN_TYPE, connector, self.local_cli,
            self.configuration)
        if metadata.get('hypermetro_id'):
            remote_mapping = huawei_flow.initialize_remote_iscsi_connection(
                metadata['hypermetro_id'], connector, self.hypermetro_rmt_cli,
                self.configuration)

            same_host_lun_id = self._change_same_host_lun_id(
                local_mapping, remote_mapping)
            mapping_info = self._merge_iscsi_mapping(local_mapping,
                                                     remote_mapping,
                                                     same_host_lun_id)
        else:
            mapping_info = local_mapping

        mapping_info.pop('aval_host_lun_ids', None)
        conn = {'driver_volume_type': 'iscsi', 'data': mapping_info}
        LOG.info('Initialize iscsi connection successfully: %s.', conn)
        return conn
Ejemplo n.º 16
0
    def failback(self, volumes):
        """Failover volumes back to primary backend.

        The main steps:
        1. Switch the role of replication pairs.
        2. Copy the second LUN data back to primary LUN.
        3. Split replication pairs.
        4. Switch the role of replication pairs.
        5. Enable replications.
        """
        volumes_update = []
        for v in volumes:
            v_update = {}
            v_update['volume_id'] = v.id
            drv_data = get_replication_driver_data(v)
            pair_id = drv_data.get('pair_id')
            if not pair_id:
                LOG.warning("No pair id in volume %s.", v.id)
                v_update['updates'] = {'replication_status': 'error'}
                volumes_update.append(v_update)
                continue

            rmt_lun_id = drv_data.get('rmt_lun_id')
            if not rmt_lun_id:
                LOG.warning("No remote lun id in volume %s.", v.id)
                v_update['updates'] = {'replication_status': 'error'}
                volumes_update.append(v_update)
                continue

            # Switch replication pair role, and start synchronize.
            self.local_driver.enable(pair_id)

            # Wait for synchronize complete.
            self.local_driver.wait_replica_ready(pair_id)

            # Split replication pair again
            self.rmt_driver.failover(pair_id)

            # Switch replication pair role, and start synchronize.
            self.rmt_driver.enable(pair_id)

            local_metadata = huawei_utils.get_volume_private_data(v)
            new_drv_data = to_string({
                'pair_id':
                pair_id,
                'rmt_lun_id':
                local_metadata.get('huawei_lun_id'),
                'rmt_lun_wwn':
                local_metadata.get('huawei_lun_wwn')
            })
            location = huawei_utils.to_string(
                huawei_lun_id=rmt_lun_id,
                huawei_lun_wwn=drv_data.get('rmt_lun_wwn'))

            v_update['updates'] = {
                'provider_location': location,
                'replication_status': 'available',
                'replication_driver_data': new_drv_data
            }
            volumes_update.append(v_update)

        return volumes_update
Ejemplo n.º 17
0
    def connect_volume_fc(self, volume, connector):
        """Create map between a volume and a host for FC."""
        wwns = connector['wwpns']
        LOG.info(
            'initialize_connection_fc, initiator: %(wwpns)s, '
            'volume id: %(id)s.',
            {'wwpns': wwns,
             'id': volume.id})

        metadata = huawei_utils.get_volume_private_data(volume)
        lun_id = metadata.get('remote_lun_id')
        if lun_id is None:
            msg = _("Can't get volume id. Volume name: %s.") % volume.id
            LOG.error(msg)
            raise exception.VolumeBackendAPIException(data=msg)

        original_host_name = connector['host']
        host_id = self.client.add_host_with_check(original_host_name)

        # Create hostgroup if not exist.
        host_id = self.rmt_client.add_host_with_check(original_host_name)

        online_wwns_in_host = (
            self.rmt_client.get_host_online_fc_initiators(host_id))
        online_free_wwns = self.rmt_client.get_online_free_wwns()
        fc_initiators_on_array = self.rmt_client.get_fc_initiator_on_array()
        wwns = [i for i in wwns if i in fc_initiators_on_array]

        for wwn in wwns:
            if (wwn not in online_wwns_in_host
                    and wwn not in online_free_wwns):
                wwns_in_host = (
                    self.rmt_client.get_host_fc_initiators(host_id))
                iqns_in_host = (
                    self.rmt_client.get_host_iscsi_initiators(host_id))
                if not (wwns_in_host or iqns_in_host):
                    self.rmt_client.remove_host(host_id)

                msg = _('Can not add FC port to host.')
                LOG.error(msg)
                raise exception.VolumeBackendAPIException(data=msg)

        for wwn in wwns:
            if wwn in online_free_wwns:
                self.rmt_client.add_fc_port_to_host(host_id, wwn)

        (tgt_port_wwns, init_targ_map) = (
            self.rmt_client.get_init_targ_map(wwns))

        # Add host into hostgroup.
        hostgroup_id = self.rmt_client.add_host_to_hostgroup(host_id)
        map_info = self.rmt_client.do_mapping(lun_id, hostgroup_id, host_id,
                                              hypermetro_lun=True)
        if not map_info:
            msg = _('Map info is None due to array version '
                    'not supporting hypermetro.')
            LOG.error(msg)
            raise exception.VolumeBackendAPIException(data=msg)

        host_lun_id = self.rmt_client.get_host_lun_id(host_id, lun_id)

        # Return FC properties.
        fc_info = {'driver_volume_type': 'fibre_channel',
                   'data': {'target_lun': int(host_lun_id),
                            'target_discovered': True,
                            'target_wwn': tgt_port_wwns,
                            'volume_id': volume.id,
                            'initiator_target_map': init_targ_map,
                            'map_info': map_info},
                   }

        LOG.info('Remote return FC info is: %s.', fc_info)

        return fc_info
Ejemplo n.º 18
0
    def disconnect_volume_fc(self, volume, connector):
        """Delete map between a volume and a host for FC."""
        wwns = connector['wwpns']
        metadata = huawei_utils.get_volume_private_data(volume)
        lun_id = metadata.get('remote_lun_id')
        host_name = connector['host']
        left_lunnum = -1
        lungroup_id = None
        view_id = None

        LOG.info(
            'terminate_connection_fc: volume: %(id)s, '
            'wwpns: %(wwns)s, '
            'lun_id: %(lunid)s.',
            {
                'id': volume.id,
                'wwns': wwns,
                'lunid': lun_id
            },
        )

        hostid = huawei_utils.get_host_id(self.rmt_client, host_name)
        if hostid:
            mapping_view_name = constants.MAPPING_VIEW_PREFIX + hostid
            view_id = self.rmt_client.find_mapping_view(mapping_view_name)
            if view_id:
                lungroup_id = self.rmt_client.find_lungroup_from_map(view_id)

        if lun_id and self.rmt_client.check_lun_exist(lun_id):
            if lungroup_id:
                lungroup_ids = self.rmt_client.get_lungroupids_by_lunid(lun_id)
                if lungroup_id in lungroup_ids:
                    self.rmt_client.remove_lun_from_lungroup(
                        lungroup_id, lun_id)
                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
                        })

        (tgt_port_wwns,
         init_targ_map) = (self.rmt_client.get_init_targ_map(wwns))

        hostid = huawei_utils.get_host_id(self.rmt_client, host_name)
        if hostid:
            mapping_view_name = constants.MAPPING_VIEW_PREFIX + hostid
            view_id = self.rmt_client.find_mapping_view(mapping_view_name)
            if view_id:
                lungroup_id = self.rmt_client.find_lungroup_from_map(view_id)
        if lungroup_id:
            left_lunnum = self.rmt_client.get_obj_count_from_lungroup(
                lungroup_id)

        if int(left_lunnum) > 0:
            info = {'driver_volume_type': 'fibre_channel', 'data': {}}
        else:
            info = {
                'driver_volume_type': 'fibre_channel',
                'data': {
                    'target_wwn': tgt_port_wwns,
                    'initiator_target_map': init_targ_map
                },
            }

        return info
Ejemplo n.º 19
0
    def connect_volume_fc(self, volume, connector):
        """Create map between a volume and a host for FC."""
        wwns = connector['wwpns']
        LOG.info(
            'initialize_connection_fc, initiator: %(wwpns)s, '
            'volume id: %(id)s.', {
                'wwpns': wwns,
                'id': volume.id
            })

        metadata = huawei_utils.get_volume_private_data(volume)
        lun_id = metadata.get('remote_lun_id')
        if lun_id is None:
            msg = _("Can't get volume id. Volume name: %s.") % volume.id
            LOG.error(msg)
            raise exception.VolumeBackendAPIException(data=msg)

        original_host_name = connector['host']
        host_id = self.client.add_host_with_check(original_host_name)

        # Create hostgroup if not exist.
        host_id = self.rmt_client.add_host_with_check(original_host_name)

        online_wwns_in_host = (
            self.rmt_client.get_host_online_fc_initiators(host_id))
        online_free_wwns = self.rmt_client.get_online_free_wwns()
        fc_initiators_on_array = self.rmt_client.get_fc_initiator_on_array()
        wwns = [i for i in wwns if i in fc_initiators_on_array]

        for wwn in wwns:
            if (wwn not in online_wwns_in_host
                    and wwn not in online_free_wwns):
                wwns_in_host = (
                    self.rmt_client.get_host_fc_initiators(host_id))
                iqns_in_host = (
                    self.rmt_client.get_host_iscsi_initiators(host_id))
                if not (wwns_in_host or iqns_in_host):
                    self.rmt_client.remove_host(host_id)

                msg = _('Can not add FC port to host.')
                LOG.error(msg)
                raise exception.VolumeBackendAPIException(data=msg)

        for wwn in wwns:
            if wwn in online_free_wwns:
                self.rmt_client.add_fc_port_to_host(host_id, wwn)

        (tgt_port_wwns,
         init_targ_map) = (self.rmt_client.get_init_targ_map(wwns))

        # Add host into hostgroup.
        hostgroup_id = self.rmt_client.add_host_to_hostgroup(host_id)
        map_info = self.rmt_client.do_mapping(lun_id,
                                              hostgroup_id,
                                              host_id,
                                              hypermetro_lun=True)
        if not map_info:
            msg = _('Map info is None due to array version '
                    'not supporting hypermetro.')
            LOG.error(msg)
            raise exception.VolumeBackendAPIException(data=msg)

        host_lun_id = self.rmt_client.get_host_lun_id(host_id, lun_id)

        # Return FC properties.
        fc_info = {
            'driver_volume_type': 'fibre_channel',
            'data': {
                'target_lun': int(host_lun_id),
                'target_discovered': True,
                'target_wwn': tgt_port_wwns,
                'volume_id': volume.id,
                'initiator_target_map': init_targ_map,
                'map_info': map_info
            },
        }

        LOG.info('Remote return FC info is: %s.', fc_info)

        return fc_info
Ejemplo n.º 20
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
Ejemplo n.º 21
0
    def initialize_connection(self, volume, connector):
        lun_id, lun_type = self.get_lun_id_and_type(volume)
        wwns = connector['wwpns']
        LOG.info(
            'initialize_connection, initiator: %(wwpns)s,'
            ' LUN ID: %(lun_id)s.',
            {'wwpns': wwns,
             'lun_id': lun_id},)

        portg_id = None
        host_id = self.client.add_host_with_check(connector['host'])

        if not self.fcsan:
            self.fcsan = fczm_utils.create_lookup_service()

        if self.fcsan:
            # Use FC switch.
            zone_helper = fc_zone_helper.FCZoneHelper(self.fcsan, self.client)
            try:
                (tgt_port_wwns, portg_id, init_targ_map) = (
                    zone_helper.build_ini_targ_map(wwns, host_id, lun_id,
                                                   lun_type))
            except Exception as err:
                self.remove_host_with_check(host_id)
                msg = _('build_ini_targ_map fails. %s') % err
                raise exception.VolumeBackendAPIException(data=msg)

            for ini in init_targ_map:
                self.client.ensure_fc_initiator_added(ini, host_id)
        else:
            # Not use FC switch.
            online_wwns_in_host = (
                self.client.get_host_online_fc_initiators(host_id))
            online_free_wwns = self.client.get_online_free_wwns()
            fc_initiators_on_array = self.client.get_fc_initiator_on_array()
            wwns = [i for i in wwns if i in fc_initiators_on_array]

            for wwn in wwns:
                if (wwn not in online_wwns_in_host
                        and wwn not in online_free_wwns):
                    wwns_in_host = (
                        self.client.get_host_fc_initiators(host_id))
                    iqns_in_host = (
                        self.client.get_host_iscsi_initiators(host_id))
                    if not (wwns_in_host or iqns_in_host or
                       self.client.is_host_associated_to_hostgroup(host_id)):
                        self.client.remove_host(host_id)

                    msg = _('No FC initiator can be added to host.')
                    LOG.error(msg)
                    raise exception.VolumeBackendAPIException(data=msg)

            for wwn in wwns:
                if wwn in online_free_wwns:
                    self.client.add_fc_port_to_host(host_id, wwn)

            (tgt_port_wwns, init_targ_map) = (
                self.client.get_init_targ_map(wwns))

        # Add host into hostgroup.
        hostgroup_id = self.client.add_host_to_hostgroup(host_id)

        metadata = huawei_utils.get_volume_private_data(volume)
        LOG.info("initialize_connection, metadata is: %s.", metadata)
        hypermetro_lun = metadata.get('hypermetro_id') is not None

        map_info = self.client.do_mapping(lun_id, hostgroup_id,
                                          host_id, portg_id,
                                          lun_type, hypermetro_lun)
        host_lun_id = self.client.get_host_lun_id(host_id, lun_id,
                                                  lun_type)

        # Return FC properties.
        fc_info = {'driver_volume_type': 'fibre_channel',
                   'data': {'target_lun': int(host_lun_id),
                            'target_discovered': True,
                            'target_wwn': tgt_port_wwns,
                            'volume_id': volume.id,
                            'initiator_target_map': init_targ_map,
                            'map_info': map_info}, }

        # Deal with hypermetro connection.
        if hypermetro_lun:
            loc_tgt_wwn = fc_info['data']['target_wwn']
            local_ini_tgt_map = fc_info['data']['initiator_target_map']
            hyperm = hypermetro.HuaweiHyperMetro(self.client,
                                                 self.rmt_client,
                                                 self.configuration)
            rmt_fc_info = hyperm.connect_volume_fc(volume, connector)

            rmt_tgt_wwn = rmt_fc_info['data']['target_wwn']
            rmt_ini_tgt_map = rmt_fc_info['data']['initiator_target_map']
            fc_info['data']['target_wwn'] = (loc_tgt_wwn + rmt_tgt_wwn)
            wwns = connector['wwpns']
            for wwn in wwns:
                if (wwn in local_ini_tgt_map
                        and wwn in rmt_ini_tgt_map):
                    fc_info['data']['initiator_target_map'][wwn].extend(
                        rmt_ini_tgt_map[wwn])

                elif (wwn not in local_ini_tgt_map
                        and wwn in rmt_ini_tgt_map):
                    fc_info['data']['initiator_target_map'][wwn] = (
                        rmt_ini_tgt_map[wwn])
                # else, do nothing

            loc_map_info = fc_info['data']['map_info']
            rmt_map_info = rmt_fc_info['data']['map_info']
            same_host_id = self._get_same_hostid(loc_map_info,
                                                 rmt_map_info)

            self.client.change_hostlun_id(loc_map_info, same_host_id)
            hyperm.rmt_client.change_hostlun_id(rmt_map_info, same_host_id)

            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
Ejemplo n.º 22
0
    def disconnect_volume_fc(self, volume, connector):
        """Delete map between a volume and a host for FC."""
        wwns = connector['wwpns']
        metadata = huawei_utils.get_volume_private_data(volume)
        lun_id = metadata.get('remote_lun_id')
        host_name = connector['host']
        left_lunnum = -1
        lungroup_id = None
        view_id = None

        LOG.info('terminate_connection_fc: volume: %(id)s, '
                 'wwpns: %(wwns)s, '
                 'lun_id: %(lunid)s.',
                 {'id': volume.id,
                  'wwns': wwns,
                  'lunid': lun_id},)

        hostid = huawei_utils.get_host_id(self.rmt_client, host_name)
        if hostid:
            mapping_view_name = constants.MAPPING_VIEW_PREFIX + hostid
            view_id = self.rmt_client.find_mapping_view(
                mapping_view_name)
            if view_id:
                lungroup_id = self.rmt_client.find_lungroup_from_map(
                    view_id)

        if lun_id and self.rmt_client.check_lun_exist(lun_id):
            if lungroup_id:
                lungroup_ids = self.rmt_client.get_lungroupids_by_lunid(
                    lun_id)
                if lungroup_id in lungroup_ids:
                    self.rmt_client.remove_lun_from_lungroup(
                        lungroup_id, lun_id)
                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})

        (tgt_port_wwns, init_targ_map) = (
            self.rmt_client.get_init_targ_map(wwns))

        hostid = huawei_utils.get_host_id(self.rmt_client, host_name)
        if hostid:
            mapping_view_name = constants.MAPPING_VIEW_PREFIX + hostid
            view_id = self.rmt_client.find_mapping_view(
                mapping_view_name)
            if view_id:
                lungroup_id = self.rmt_client.find_lungroup_from_map(
                    view_id)
        if lungroup_id:
            left_lunnum = self.rmt_client.get_obj_count_from_lungroup(
                lungroup_id)

        if int(left_lunnum) > 0:
            info = {'driver_volume_type': 'fibre_channel',
                    'data': {}}
        else:
            info = {'driver_volume_type': 'fibre_channel',
                    'data': {'target_wwn': tgt_port_wwns,
                             'initiator_target_map': init_targ_map}, }

        return info