def update_consistencygroup(self, context, group, add_volumes, remove_volumes): LOG.info(_LI("Update Consistency Group: %(group)s. " "This adds or removes volumes from a CG."), {'group': group['id']}) metrogroup_id = self.check_consistencygroup_need_to_stop(group) if not metrogroup_id: msg = _("The CG does not exist on array.") LOG.error(msg) raise exception.VolumeBackendAPIException(data=msg) # Deal with add volumes to CG for volume in add_volumes: metadata = huawei_utils.get_lun_metadata(volume) if not metadata.get('hypermetro'): err_msg = _("Volume %s is not in hypermetro pair.") % volume.id LOG.error(err_msg) raise exception.VolumeBackendAPIException(data=err_msg) lun_name = huawei_utils.encode_name(volume.id) hypermetro = self.client.get_hypermetro_by_lun_name(lun_name) if not hypermetro: err_msg = _("Volume %s is not in hypermetro pair.") % volume.id LOG.error(err_msg) raise exception.VolumeBackendAPIException(data=err_msg) metro_id = hypermetro['ID'] if not self._check_metro_in_cg(metro_id, metrogroup_id): self.check_metro_need_to_stop(metro_id) self.client.add_metro_to_metrogroup(metrogroup_id, metro_id) self._ensure_hypermetro_added_to_cg( metro_id, metrogroup_id) # Deal with remove volumes from CG for volume in remove_volumes: metadata = huawei_utils.get_lun_metadata(volume) if not metadata.get('hypermetro'): continue lun_name = huawei_utils.encode_name(volume.id) hypermetro = self.client.get_hypermetro_by_lun_name(lun_name) if not hypermetro: continue metro_id = hypermetro['ID'] if self._check_metro_in_cg(metro_id, metrogroup_id): self.check_metro_need_to_stop(metro_id) self.client.remove_metro_from_metrogroup(metrogroup_id, metro_id) self._ensure_hypermetro_removed_from_cg( metro_id, metrogroup_id) self.client.sync_hypermetro(metro_id) new_group_info = self.client.get_metrogroup_by_id(metrogroup_id) is_empty = new_group_info["ISEMPTY"] if is_empty == 'false': self.client.sync_metrogroup(metrogroup_id)
def update_consistencygroup(self, context, group, add_volumes, remove_volumes): LOG.info( _LI("Update Consistency Group: %(group)s. " "This adds or removes volumes from a CG."), {'group': group['id']}) model_update = {} model_update['status'] = group['status'] metrogroup_id = self.check_consistencygroup_need_to_stop(group) if metrogroup_id: # Deal with add volumes to CG for volume in add_volumes: metadata = huawei_utils.get_lun_metadata(volume) metro_id = metadata.get('hypermetro_id') if metro_id and self.client.check_hypermetro_exist(metro_id): if not self._check_metro_in_cg(metro_id, metrogroup_id): self.check_metro_need_to_stop(metro_id) self.client.add_metro_to_metrogroup( metrogroup_id, metro_id) self._ensure_hypermetro_added_to_cg( metro_id, metrogroup_id) else: err_msg = _("Hypermetro pair doesn't exist on array.") LOG.error(err_msg) raise exception.VolumeBackendAPIException(data=err_msg) # Deal with remove volumes from CG for volume in remove_volumes: metadata = huawei_utils.get_lun_metadata(volume) metro_id = metadata.get('hypermetro_id') if metro_id and self.client.check_hypermetro_exist(metro_id): if self._check_metro_in_cg(metro_id, metrogroup_id): self.check_metro_need_to_stop(metro_id) self.client.remove_metro_from_metrogroup( metrogroup_id, metro_id) self._ensure_hypermetro_removed_from_cg( metro_id, metrogroup_id) self.client.sync_hypermetro(metro_id) else: err_msg = _("Hypermetro pair doesn't exist on array.") LOG.error(err_msg) raise exception.VolumeBackendAPIException(data=err_msg) new_group_info = self.client.get_metrogroup_by_id(metrogroup_id) is_empty = new_group_info["ISEMPTY"] if is_empty == 'false': self.client.sync_metrogroup(metrogroup_id) # if CG not exist on array else: msg = _("The CG does not exist on array.") LOG.error(msg) raise exception.VolumeBackendAPIException(data=msg)
def delete_consistencygroup(self, context, group, volumes): LOG.info(_LI("Delete Consistency Group: %(group)s."), {'group': group['id']}) metrogroup_id = self.check_consistencygroup_need_to_stop(group) if not metrogroup_id: return # Remove pair from metrogroup. for volume in volumes: metadata = huawei_utils.get_lun_metadata(volume) if not metadata.get('hypermetro'): continue lun_name = huawei_utils.encode_name(volume.id) hypermetro = self.client.get_hypermetro_by_lun_name(lun_name) if not hypermetro: continue metro_id = hypermetro['ID'] if self._check_metro_in_cg(metro_id, metrogroup_id): self.client.remove_metro_from_metrogroup( metrogroup_id, metro_id) # Delete metrogroup. self.client.delete_metrogroup(metrogroup_id)
def failover(self, volumes): """Failover volumes back to secondary array. Split the replication pairs and make the secondary LUNs R&W. """ volumes_update = [] cgid_list = set() replicacg = ReplicaCG(self.local_client, self.rmt_client, self.conf) 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(_LW("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(_LW("No remote lun id in volume %s."), v.id) v_update['updates'] = {'replication_status': 'error'} volumes_update.append(v_update) continue replica_info = self.rmt_op.get_replica_info(pair_id) consisgroup_id = replica_info.get('CGID') if consisgroup_id: if consisgroup_id not in cgid_list: replicacg.failover(consisgroup_id) cgid_list.add(consisgroup_id) else: self.rmt_driver.failover(pair_id) local_metadata = huawei_utils.get_lun_metadata(v) new_drv_data = to_string({ 'pair_id': pair_id, 'huawei_sn': local_metadata.get('huawei_sn'), '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_sn=drv_data.get('huawei_sn'), 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 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_lun_metadata(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 delete_hypermetro(self, volume): """Delete hypermetro.""" metadata = huawei_utils.get_lun_metadata(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 delete_hypermetro(self, volume): """Delete hypermetro.""" metadata = huawei_utils.get_lun_metadata(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_lun_metadata(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 delete_hypermetro(self, volume, metadata=None): """Delete hypermetro.""" if not metadata: metadata = huawei_utils.get_lun_metadata(volume) metro_id = metadata.get('hypermetro_id') remote_lun_id = metadata.get('remote_lun_id') # Delete hypermetro. if metro_id and self.client.check_hypermetro_exist(metro_id): self.check_metro_need_to_stop(metro_id) 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_lun_metadata(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_lun_metadata(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 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_lun_metadata(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 disconnect_volume_fc(self, volume, connector): """Delete map between a volume and a host for FC.""" wwns = connector['wwpns'] metadata = huawei_utils.get_lun_metadata(volume) lun_id = metadata.get('remote_lun_id') host_name = connector['host'] lungroup_id = None LOG.info( _LI('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( _LW("Lun is not in lungroup. " "Lun id: %(lun_id)s, " "lungroup id: %(lungroup_id)s"), { "lun_id": lun_id, "lungroup_id": lungroup_id })
def delete_consistencygroup(self, context, group, volumes): LOG.info("Delete Consistency Group: %(group)s.", {'group': group['id']}) metrogroup_id = self.check_consistencygroup_need_to_stop(group) if metrogroup_id: # Remove pair from metrogroup. for volume in volumes: metadata = huawei_utils.get_lun_metadata(volume) metro_id = metadata.get('hypermetro_id') if metro_id and self.client.check_hypermetro_exist(metro_id): if self._check_metro_in_cg(metro_id, metrogroup_id): self.client.remove_metro_from_metrogroup( metrogroup_id, metro_id) else: err = ( _("Hypermetro pair %(id)s doesn't exist on array.") % { 'id': metro_id }) LOG.warning(err) # Delete metrogroup. self.client.delete_metrogroup(metrogroup_id)
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_lun_metadata(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_lun_metadata(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() 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_lun_metadata(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 disconnect_volume_fc(self, volume, connector): """Delete map between a volume and a host for FC.""" wwns = connector['wwpns'] metadata = huawei_utils.get_lun_metadata(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_lun_metadata(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: self.rmt_client.ensure_fc_initiator_added(wwn, host_id) (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 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. """ running_status_set = (constants.REPLICA_RUNNING_STATUS_NORMAL, constants.REPLICA_RUNNING_STATUS_SPLIT, constants.REPLICA_RUNNING_STATUS_ERRUPTED) volumes_update = [] cgid_list = set() replicacg = ReplicaCG(self.local_client, self.rmt_client, self.conf) for v in volumes: drv_data = get_replication_driver_data(v) pair_id = drv_data.get('pair_id') if not pair_id: self._pre_fail_check(v, running_status_set) 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: # Failback check running status only. 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 replica_info = self.local_op.get_replica_info(pair_id) consisgroup_id = replica_info.get('CGID') if consisgroup_id: if consisgroup_id not in cgid_list: replicacg.failback(consisgroup_id) cgid_list.add(consisgroup_id) else: # 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_lun_metadata(v) new_drv_data = to_string({ 'pair_id': pair_id, 'huawei_sn': local_metadata.get('huawei_sn'), '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_sn=drv_data.get('huawei_sn'), 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 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_lun_metadata(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_lun_metadata(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