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), }
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
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
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)
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
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.')
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)
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
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
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.')
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)
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
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
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
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
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
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
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 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
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