def delete_snapshot(self, snapshot): snapshotname = huawei_utils.encode_name(snapshot['id']) volume_name = huawei_utils.encode_name(snapshot['volume_id']) LOG.info(_LI( 'stop_snapshot: snapshot name: %(snapshot)s, ' 'volume name: %(volume)s.'), {'snapshot': snapshotname, 'volume': volume_name},) snapshot_id = snapshot.get('provider_location', None) if snapshot_id is None: snapshot_id = self.restclient.get_snapshotid_by_name(snapshotname) if snapshot_id is not None: if self.restclient.check_snapshot_exist(snapshot_id): self.restclient.stop_snapshot(snapshot_id) self.restclient.delete_snapshot(snapshot_id) else: LOG.warning(_LW("Can't find snapshot on the array.")) else: LOG.warning(_LW("Can't find snapshot on the array.")) return False return True
def update_migrated_volume(self, ctxt, volume, new_volume, original_volume_status=None): original_name = huawei_utils.encode_name(volume['id']) current_name = huawei_utils.encode_name(new_volume['id']) lun_id = self.restclient.get_volume_by_name(current_name) try: self.restclient.rename_lun(lun_id, original_name) except exception.VolumeBackendAPIException: LOG.error(_LE('Unable to rename lun %s on array.'), current_name) return {'_name_id': new_volume['_name_id'] or new_volume['id']} LOG.debug( "Rename lun from %(current_name)s to %(original_name)s " "successfully.", { 'current_name': current_name, 'original_name': original_name }) model_update = {'_name_id': None} return model_update
def delete_snapshot(self, snapshot): snapshotname = huawei_utils.encode_name(snapshot['id']) volume_name = huawei_utils.encode_name(snapshot['volume_id']) LOG.info( _LI('stop_snapshot: snapshot name: %(snapshot)s, ' 'volume name: %(volume)s.'), { 'snapshot': snapshotname, 'volume': volume_name }, ) snapshot_id = snapshot.get('provider_location') if snapshot_id is None: snapshot_id = self.restclient.get_snapshotid_by_name(snapshotname) if snapshot_id is not None: if self.restclient.check_snapshot_exist(snapshot_id): self.restclient.stop_snapshot(snapshot_id) self.restclient.delete_snapshot(snapshot_id) else: LOG.warning(_LW("Can't find snapshot on the array.")) else: LOG.warning(_LW("Can't find snapshot on the array.")) return False return True
def create_snapshot(self, snapshot): snapshot_name = huawei_utils.encode_name(snapshot['id']) snapshot_description = snapshot['id'] volume_name = huawei_utils.encode_name(snapshot['volume_id']) LOG.info(_LI( 'create_snapshot:snapshot name: %(snapshot)s, ' 'volume name: %(volume)s.'), {'snapshot': snapshot_name, 'volume': volume_name}) lun_id = self.get_volume_by_name(volume_name) if lun_id is None: msg = (_("Can't find lun info on the array, " "lun name is: %(name)s.") % {'name': volume_name}) LOG.error(msg) raise exception.VolumeBackendAPIException(data=msg) url = self.url + "/snapshot" data = json.dumps({"TYPE": "27", "NAME": snapshot_name, "PARENTTYPE": "11", "DESCRIPTION": snapshot_description, "PARENTID": lun_id}) result = self.call(url, data) msg = 'Create snapshot error.' self._assert_rest_result(result, msg) self._assert_data_in_result(result, msg) return result['data']
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 create_volume_from_snapshot(self, volume, snapshot): """Create a volume from a snapshot. We use LUNcopy to copy a new volume from snapshot. The time needed increases as volume size does. """ snapshotname = huawei_utils.encode_name(snapshot['id']) snapshot_id = snapshot.get('provider_location', None) if snapshot_id is None: snapshot_id = self.restclient.get_snapshotid_by_name(snapshotname) if snapshot_id is None: err_msg = (_( 'create_volume_from_snapshot: Snapshot %(name)s ' 'does not exist.') % {'name': snapshotname}) LOG.error(err_msg) raise exception.VolumeBackendAPIException(data=err_msg) lun_info = self.create_volume(volume) tgt_lun_id = lun_info['ID'] luncopy_name = huawei_utils.encode_name(volume['id']) LOG.info(_LI( 'create_volume_from_snapshot: src_lun_id: %(src_lun_id)s, ' 'tgt_lun_id: %(tgt_lun_id)s, copy_name: %(copy_name)s.'), {'src_lun_id': snapshot_id, 'tgt_lun_id': tgt_lun_id, 'copy_name': luncopy_name}) event_type = 'LUNReadyWaitInterval' wait_interval = huawei_utils.get_wait_interval(self.xml_file_path, event_type) def _volume_ready(): result = self.restclient.get_lun_info(tgt_lun_id) if (result['HEALTHSTATUS'] == constants.STATUS_HEALTH and result['RUNNINGSTATUS'] == constants.STATUS_VOLUME_READY): return True return False huawei_utils.wait_for_condition(self.xml_file_path, _volume_ready, wait_interval, wait_interval * 10) self._copy_volume(volume, luncopy_name, snapshot_id, tgt_lun_id) return {'ID': lun_info['ID'], 'lun_info': lun_info}
def create_volume_from_snapshot(self, volume, snapshot): """Create a volume from a snapshot. We use LUNcopy to copy a new volume from snapshot. The time needed increases as volume size does. """ snapshotname = huawei_utils.encode_name(snapshot["id"]) snapshot_id = snapshot.get("provider_location", None) if snapshot_id is None: snapshot_id = self.restclient.get_snapshotid_by_name(snapshotname) if snapshot_id is None: err_msg = _("create_volume_from_snapshot: Snapshot %(name)s " "does not exist.") % { "name": snapshotname } LOG.error(err_msg) raise exception.VolumeBackendAPIException(data=err_msg) lun_info = self.create_volume(volume) tgt_lun_id = lun_info["ID"] luncopy_name = huawei_utils.encode_name(volume["id"]) LOG.info( _LI( "create_volume_from_snapshot: src_lun_id: %(src_lun_id)s, " "tgt_lun_id: %(tgt_lun_id)s, copy_name: %(copy_name)s." ), {"src_lun_id": snapshot_id, "tgt_lun_id": tgt_lun_id, "copy_name": luncopy_name}, ) event_type = "LUNReadyWaitInterval" wait_interval = huawei_utils.get_wait_interval(self.xml_file_path, event_type) def _volume_ready(): result = self.restclient.get_lun_info(tgt_lun_id) if ( result["HEALTHSTATUS"] == constants.STATUS_HEALTH and result["RUNNINGSTATUS"] == constants.STATUS_VOLUME_READY ): return True return False huawei_utils.wait_for_condition(self.xml_file_path, _volume_ready, wait_interval, wait_interval * 10) self._copy_volume(volume, luncopy_name, snapshot_id, tgt_lun_id) return {"ID": lun_info["ID"], "lun_info": lun_info}
def delete_volume(self, volume): """Delete a volume. Three steps: Firstly, remove associate from lungroup. Secondly, remove associate from QoS policy. Thirdly, remove the lun. """ name = huawei_utils.encode_name(volume['id']) lun_id = volume.get('provider_location') LOG.info( _LI('Delete volume: %(name)s, array lun id: %(lun_id)s.'), { 'name': name, 'lun_id': lun_id }, ) if lun_id: if self.restclient.check_lun_exist(lun_id): qos_id = self.restclient.get_qosid_by_lunid(lun_id) if qos_id: self.remove_qos_lun(lun_id, qos_id) self.restclient.delete_lun(lun_id) else: LOG.warning(_LW("Can't find lun %s on the array."), lun_id) return False return True
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 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 extend_volume(self, volume, new_size): """Extend a volume.""" volume_size = huawei_utils.get_volume_size(volume) new_volume_size = int(new_size) * units.Gi / 512 volume_name = huawei_utils.encode_name(volume['id']) LOG.info( _LI('Extend volume: %(volumename)s, oldsize:' ' %(oldsize)s newsize: %(newsize)s.'), { 'volumename': volume_name, 'oldsize': volume_size, 'newsize': new_volume_size }, ) lun_id = self.restclient.get_volume_by_name(volume_name) if lun_id is None: msg = ( _("Can't find lun info on the array, lun name is: %(name)s.") % { 'name': volume_name }) LOG.error(msg) raise exception.VolumeBackendAPIException(data=msg) luninfo = self.restclient.extend_volume(lun_id, new_volume_size) return {'provider_location': luninfo['ID'], 'lun_info': luninfo}
def create_volume(self, volume): """Create a volume.""" pool_info = self.restclient.find_pool_info() volume_name = huawei_utils.encode_name(volume['id']) volume_description = volume['name'] volume_size = huawei_utils.get_volume_size(volume) LOG.info(_LI( 'Create volume: %(volume)s, size: %(size)s.'), {'volume': volume_name, 'size': volume_size}) params = huawei_utils.get_lun_conf_params(self.xml_file_path) params['pool_id'] = pool_info['ID'] params['volume_size'] = volume_size params['volume_description'] = volume_description # Prepare LUN parameters. lun_param = huawei_utils.init_lun_parameters(volume_name, params) # Create LUN on the array. lun_info = self.restclient.create_volume(lun_param) lun_id = lun_info['ID'] return {'provider_location': lun_info['ID'], 'ID': lun_id, 'lun_info': lun_info}
def _get_group_info_by_name(self, group_id): group_name = huawei_utils.encode_name(group_id) group_info = self.local_cgop.get_replicg_by_name(group_name) if not group_info: group_name = huawei_utils.old_encode_name(group_id) group_info = self.local_cgop.get_replicg_by_name(group_name) return group_info
def create(self, group, replica_model): group_id = group.get('id') LOG.info("Create Consistency Group: %(group)s.", {'group': group_id}) group_name = huawei_utils.encode_name(group_id) self.local_cgop.create(group_name, group_id, replica_model, self.conf.replica_sync_speed)
def extend_volume(self, volume, new_size): """Extend a volume.""" volume_size = huawei_utils.get_volume_size(volume) new_volume_size = int(new_size) * units.Gi / 512 volume_name = huawei_utils.encode_name(volume['id']) LOG.info(_LI( 'Extend volume: %(volumename)s, oldsize:' ' %(oldsize)s newsize: %(newsize)s.'), {'volumename': volume_name, 'oldsize': volume_size, 'newsize': new_volume_size},) lun_id = self.restclient.get_volume_by_name(volume_name) if lun_id is None: msg = (_( "Can't find lun info on the array, lun name is: %(name)s.") % {'name': volume_name}) LOG.error(msg) raise exception.VolumeBackendAPIException(data=msg) luninfo = self.restclient.extend_volume(lun_id, new_volume_size) return {'provider_location': luninfo['ID'], 'lun_info': luninfo}
def create_volume(self, volume): """Create a volume.""" pool_name = volume_utils.extract_host(volume['host'], level='pool') pools = self.restclient.find_all_pools() pool_info = self.restclient.find_pool_info(pool_name, pools) if not pool_info: msg = (_('Error in getting pool information for the pool: %s.') % pool_name) LOG.error(msg) raise exception.VolumeBackendAPIException(data=msg) volume_name = huawei_utils.encode_name(volume['id']) volume_description = volume['name'] volume_size = huawei_utils.get_volume_size(volume) LOG.info(_LI( 'Create volume: %(volume)s, size: %(size)s.'), {'volume': volume_name, 'size': volume_size}) params = huawei_utils.get_lun_conf_params(self.xml_file_path) params['pool_id'] = pool_info['ID'] params['volume_size'] = volume_size params['volume_description'] = volume_description # Prepare LUN parameters. lun_param = huawei_utils.init_lun_parameters(volume_name, params) # Create LUN on the array. lun_info = self.restclient.create_volume(lun_param) lun_id = lun_info['ID'] return {'provider_location': lun_info['ID'], 'ID': lun_id, 'lun_info': lun_info}
def _migrate_volume(self, volume, host, new_type=None): if not self._check_migration_valid(host, volume): return (False, None) type_id = volume['volume_type_id'] volume_type = None if type_id: volume_type = volume_types.get_volume_type(None, type_id) pool_name = host['capabilities']['pool_name'] pools = self.restclient.find_all_pools() pool_info = self.restclient.find_pool_info(pool_name, pools) src_volume_name = huawei_utils.encode_name(volume['id']) dst_volume_name = six.text_type(hash(src_volume_name)) src_id = volume.get('provider_location', None) src_lun_params = self.restclient.get_lun_info(src_id) opts = None qos = None if new_type: # If new type exists, use new type. opts = huawei_utils._get_extra_spec_value( new_type['extra_specs']) opts = smartx.SmartX().get_smartx_specs_opts(opts) if 'LUNType' not in opts: opts['LUNType'] = huawei_utils.find_luntype_in_xml( self.xml_file_path) qos = huawei_utils.get_qos_by_volume_type(new_type) elif volume_type: qos = huawei_utils.get_qos_by_volume_type(volume_type) if not opts: opts = huawei_utils.get_volume_params(volume) opts = smartx.SmartX().get_smartx_specs_opts(opts) lun_info = self._create_lun_with_extra_feature(pool_info, dst_volume_name, src_lun_params, opts) lun_id = lun_info['ID'] if qos: LOG.info(_LI('QoS: %s.'), qos) SmartQos = smartx.SmartQos(self.restclient) SmartQos.create_qos(qos, lun_id) if opts: smartpartition = smartx.SmartPartition(self.restclient) smartpartition.add(opts, lun_id) smartcache = smartx.SmartCache(self.restclient) smartcache.add(opts, lun_id) dst_id = lun_info['ID'] self._wait_volume_ready(dst_id) moved = self._migrate_lun(src_id, dst_id) return moved, {}
def initialize_connection_iscsi(self, volume, connector): """Map a volume to a host and return target iSCSI information.""" LOG.info(_LI('Enter initialize_connection_iscsi.')) initiator_name = connector['initiator'] volume_name = huawei_utils.encode_name(volume['id']) LOG.info(_LI( 'initiator name: %(initiator_name)s, ' 'volume name: %(volume)s.'), {'initiator_name': initiator_name, 'volume': volume_name}) (iscsi_iqn, target_ip, portgroup_id) = self.restclient.get_iscsi_params(self.xml_file_path, connector) LOG.info(_LI('initialize_connection_iscsi, iscsi_iqn: %(iscsi_iqn)s, ' 'target_ip: %(target_ip)s, ' 'TargetPortGroup: %(portgroup_id)s.'), {'iscsi_iqn': iscsi_iqn, 'target_ip': target_ip, 'portgroup_id': portgroup_id},) # Create hostgroup if not exist. host_name = connector['host'] host_name_before_hash = None if host_name and (len(host_name) > constants.MAX_HOSTNAME_LENTH): host_name_before_hash = host_name host_name = str(hash(host_name)) host_id = self.restclient.add_host_with_check(host_name, host_name_before_hash) # Add initiator to the host. self.restclient.ensure_initiator_added(initiator_name, host_id) hostgroup_id = self.restclient.add_host_into_hostgroup(host_id) # Mapping lungroup and hostgroup to view. lun_id = self.restclient.mapping_hostgroup_and_lungroup(volume_name, hostgroup_id, host_id, portgroup_id) hostlun_id = self.restclient.find_host_lun_id(host_id, lun_id) LOG.info(_LI("initialize_connection_iscsi, host lun id is: %s."), hostlun_id) # Return iSCSI properties. properties = {} properties['target_discovered'] = False properties['target_portal'] = ('%s:%s' % (target_ip, '3260')) properties['target_iqn'] = iscsi_iqn properties['target_lun'] = int(hostlun_id) properties['volume_id'] = volume['id'] LOG.info(_LI("initialize_connection_iscsi success. Return data: %s."), properties) return {'driver_volume_type': 'iscsi', 'data': properties}
def terminate_connection_fc(self, volume, connector): """Delete map between a volume and a host.""" wwns = connector['wwpns'] volume_name = huawei_utils.encode_name(volume['id']) lun_id = volume.get('provider_location', None) host_name = connector['host'] left_lunnum = -1 LOG.info( _LI('terminate_connection_fc: volume name: %(volume)s, ' 'wwpns: %(wwns)s, ' 'lun_id: %(lunid)s.'), { 'volume': volume_name, 'wwns': wwns, 'lunid': lun_id }, ) if lun_id: if self.restclient.check_lun_exist(lun_id): # Get lungroup id by lun id. lungroup_id = self.restclient.get_lungroupid_by_lunid(lun_id) if not lungroup_id: LOG.info(_LI("Can't find lun in lungroup.")) else: self.restclient.remove_lun_from_lungroup( lungroup_id, lun_id) else: LOG.warning(_LW("Can't find lun on the array.")) tgt_port_wwns = [] for wwn in wwns: tgtwwpns = self.restclient.get_fc_target_wwpns(wwn) if tgtwwpns: tgt_port_wwns.append(tgtwwpns) init_targ_map = {} for initiator in wwns: init_targ_map[initiator] = tgt_port_wwns host_id = self.restclient.find_host(host_name) if host_id: mapping_view_name = constants.MAPPING_VIEW_PREFIX + host_id view_id = self.restclient.find_mapping_view(mapping_view_name) if view_id: lungroup_id = self.restclient.find_lungroup_from_map(view_id) if lungroup_id: left_lunnum = self.restclient.get_lunnum_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 create_volume(self, volume): """Create a volume.""" opts = huawei_utils.get_volume_params(volume) smartx_opts = smartx.SmartX().get_smartx_specs_opts(opts) params = huawei_utils.get_lun_params(self.xml_file_path, smartx_opts) pool_name = volume_utils.extract_host(volume['host'], level='pool') pools = self.restclient.find_all_pools() pool_info = self.restclient.find_pool_info(pool_name, pools) if not pool_info: # The following code is to keep compatibility with old version of # Huawei driver. pool_names = huawei_utils.get_pools(self.xml_file_path) for pool_name in pool_names.split(";"): pool_info = self.restclient.find_pool_info(pool_name, pools) if pool_info: break volume_name = huawei_utils.encode_name(volume['id']) volume_description = volume['name'] volume_size = huawei_utils.get_volume_size(volume) LOG.info(_LI( 'Create volume: %(volume)s, size: %(size)s.'), {'volume': volume_name, 'size': volume_size}) params['pool_id'] = pool_info['ID'] params['volume_size'] = volume_size params['volume_description'] = volume_description # Prepare LUN parameters. lun_param = huawei_utils.init_lun_parameters(volume_name, params) # Create LUN on the array. lun_info = self.restclient.create_volume(lun_param) lun_id = lun_info['ID'] try: qos = huawei_utils.get_volume_qos(volume) if qos: smart_qos = smartx.SmartQos(self.restclient) smart_qos.create_qos(qos, lun_id) smartpartition = smartx.SmartPartition(self.restclient) smartpartition.add(opts, lun_id) smartcache = smartx.SmartCache(self.restclient) smartcache.add(opts, lun_id) except Exception as err: self._delete_lun_with_check(lun_id) raise exception.InvalidInput( reason=_('Create volume error. Because %s.') % err) return {'provider_location': lun_info['ID'], 'ID': lun_id, 'lun_info': lun_info}
def _get_metro_group_id(self, id): group_name = huawei_utils.encode_name(id) metrogroup_id = self.client.get_metrogroup_by_name(group_name) if not metrogroup_id: group_name = huawei_utils.old_encode_name(id) metrogroup_id = self.client.get_metrogroup_by_name(group_name) return metrogroup_id
def initialize_connection_fc(self, volume, connector): wwns = connector['wwpns'] volume_name = huawei_utils.encode_name(volume['id']) LOG.info(_LI( 'initialize_connection_fc, initiator: %(wwpns)s,' ' volume name: %(volume)s.'), {'wwpns': wwns, 'volume': volume_name},) host_name_before_hash = None host_name = connector['host'] if host_name and (len(host_name) > constants.MAX_HOSTNAME_LENGTH): host_name_before_hash = host_name host_name = six.text_type(hash(host_name)) # Create hostgroup if not exist. host_id = self.restclient.add_host_with_check(host_name, host_name_before_hash) # Add host into hostgroup. hostgroup_id = self.restclient.add_host_into_hostgroup(host_id) free_wwns = self.restclient.get_connected_free_wwns() LOG.info(_LI("initialize_connection_fc, the array has free wwns: %s."), free_wwns) for wwn in wwns: if wwn in free_wwns: self.restclient.add_fc_port_to_host(host_id, wwn) lun_id = self.restclient.mapping_hostgroup_and_lungroup(volume_name, hostgroup_id, host_id) host_lun_id = self.restclient.find_host_lun_id(host_id, lun_id) tgt_port_wwns = [] for wwn in wwns: tgtwwpns = self.restclient.get_fc_target_wwpns(wwn) if tgtwwpns: tgt_port_wwns.append(tgtwwpns) init_targ_map = {} for initiator in wwns: init_targ_map[initiator] = tgt_port_wwns # Return FC properties. 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}, } LOG.info(_LI("initialize_connection_fc, return data is: %s."), info) return info
def create_volume(self, volume): """Create a volume.""" opts = huawei_utils.get_volume_params(volume) smartx_opts = smartx.SmartX().get_smartx_specs_opts(opts) params = huawei_utils.get_lun_params(self.xml_file_path, smartx_opts) pool_name = volume_utils.extract_host(volume['host'], level='pool') pools = self.restclient.find_all_pools() pool_info = self.restclient.find_pool_info(pool_name, pools) if not pool_info: # The following code is to keep compatibility with old version of # Huawei driver. pool_names = huawei_utils.get_pools(self.xml_file_path) for pool_name in pool_names.split(";"): pool_info = self.restclient.find_pool_info(pool_name, pools) if pool_info: break volume_name = huawei_utils.encode_name(volume['id']) volume_description = volume['name'] volume_size = huawei_utils.get_volume_size(volume) LOG.info(_LI('Create volume: %(volume)s, size: %(size)s.'), { 'volume': volume_name, 'size': volume_size }) params['pool_id'] = pool_info['ID'] params['volume_size'] = volume_size params['volume_description'] = volume_description # Prepare LUN parameters. lun_param = huawei_utils.init_lun_parameters(volume_name, params) # Create LUN on the array. lun_info = self.restclient.create_volume(lun_param) lun_id = lun_info['ID'] try: qos = huawei_utils.get_volume_qos(volume) if qos: smart_qos = smartx.SmartQos(self.restclient) smart_qos.create_qos(qos, lun_id) smartpartition = smartx.SmartPartition(self.restclient) smartpartition.add(opts, lun_id) smartcache = smartx.SmartCache(self.restclient) smartcache.add(opts, lun_id) except Exception as err: self._delete_lun_with_check(lun_id) raise exception.InvalidInput( reason=_('Create volume error. Because %s.') % err) return { 'provider_location': lun_info['ID'], 'ID': lun_id, 'lun_info': lun_info }
def update_migrated_volume(self, ctxt, volume, new_volume, original_volume_status=None): original_name = huawei_utils.encode_name(volume["id"]) current_name = huawei_utils.encode_name(new_volume["id"]) lun_id = self.restclient.get_volume_by_name(current_name) try: self.restclient.rename_lun(lun_id, original_name) except exception.VolumeBackendAPIException: LOG.error(_LE("Unable to rename lun %s on array."), current_name) return {"_name_id": new_volume["_name_id"] or new_volume["id"]} LOG.debug( "Rename lun from %(current_name)s to %(original_name)s " "successfully.", {"current_name": current_name, "original_name": original_name}, ) model_update = {"_name_id": None} return model_update
def create_volume(self, volume): """Create a volume.""" opts = huawei_utils.get_volume_params(volume) smartx_opts = smartx.SmartX().get_smartx_specs_opts(opts) params = huawei_utils.get_lun_params(self.xml_file_path, smartx_opts) pool_name = volume_utils.extract_host(volume['host'], level='pool') pools = self.restclient.find_all_pools() pool_info = self.restclient.find_pool_info(pool_name, pools) if not pool_info: msg = (_('Error in getting pool information for the pool: %s.') % pool_name) LOG.error(msg) raise exception.VolumeBackendAPIException(data=msg) volume_name = huawei_utils.encode_name(volume['id']) volume_description = volume['name'] volume_size = huawei_utils.get_volume_size(volume) LOG.info(_LI( 'Create volume: %(volume)s, size: %(size)s.'), {'volume': volume_name, 'size': volume_size}) params['pool_id'] = pool_info['ID'] params['volume_size'] = volume_size params['volume_description'] = volume_description # Prepare LUN parameters. lun_param = huawei_utils.init_lun_parameters(volume_name, params) # Create LUN on the array. lun_info = self.restclient.create_volume(lun_param) lun_id = lun_info['ID'] try: qos = huawei_utils.get_volume_qos(volume) if qos: smart_qos = smartx.SmartQos(self.restclient) smart_qos.create_qos(qos, lun_id) smartpartition = smartx.SmartPartition(self.restclient) smartpartition.add(opts, lun_id) smartcache = smartx.SmartCache(self.restclient) smartcache.add(opts, lun_id) except Exception as err: if lun_id: self._delete_lun_with_check(lun_id) raise exception.InvalidInput( reason=_('Create volume error. Because %s.') % err) return {'provider_location': lun_info['ID'], 'ID': lun_id, 'lun_info': lun_info}
def update_migrated_volume(self, ctxt, volume, new_volume, original_volume_status): original_name = huawei_utils.encode_name(volume['id']) current_name = huawei_utils.encode_name(new_volume['id']) lun_id = self.restclient.get_volume_by_name(current_name) try: self.restclient.rename_lun(lun_id, original_name) except exception.VolumeBackendAPIException: LOG.error(_LE('Unable to rename lun %s on array.'), current_name) return {'_name_id': new_volume['_name_id'] or new_volume['id']} LOG.debug("Rename lun from %(current_name)s to %(original_name)s " "successfully.", {'current_name': current_name, 'original_name': original_name}) model_update = {'_name_id': None} return model_update
def create_consistencygroup(self, group): LOG.info("Create Consistency Group: %(group)s.", {'group': group.id}) group_name = huawei_utils.encode_name(group.id) domain_name = self.configuration.metro_domain_name domain_id = self.client.get_hyper_domain_id(domain_name) if not domain_name or not domain_id: msg = _("The domain_name config in cinder.conf is wrong.") LOG.error(msg) raise exception.VolumeBackendAPIException(data=msg) self.client.create_metrogroup(group_name, group.id, domain_id)
def create_consistencygroup(self, group): LOG.info(_LI("Create Consistency Group: %(group)s."), {'group': group.id}) group_name = huawei_utils.encode_name(group.id) domain_name = self.configuration.metro_domain_name domain_id = self.client.get_hyper_domain_id(domain_name) if not domain_name or not domain_id: msg = _("The domain_name config in cinder.conf is wrong.") LOG.error(msg) raise exception.VolumeBackendAPIException(data=msg) self.client.create_metrogroup(group_name, group.id, domain_id)
def terminate_connection_fc(self, volume, connector): """Delete map between a volume and a host.""" wwns = connector['wwpns'] volume_name = huawei_utils.encode_name(volume['id']) lun_id = volume.get('provider_location', None) host_name = connector['host'] left_lunnum = -1 LOG.info(_LI('terminate_connection_fc: volume name: %(volume)s, ' 'wwpns: %(wwns)s, ' 'lun_id: %(lunid)s.'), {'volume': volume_name, 'wwns': wwns, 'lunid': lun_id},) if lun_id: if self.restclient.check_lun_exist(lun_id): # Get lungroup id by lun id. lungroup_id = self.restclient.get_lungroupid_by_lunid(lun_id) if not lungroup_id: LOG.info(_LI("Can't find lun in lungroup.")) else: self.restclient.remove_lun_from_lungroup(lungroup_id, lun_id) else: LOG.warning(_LW("Can't find lun on the array.")) tgt_port_wwns = [] for wwn in wwns: tgtwwpns = self.restclient.get_fc_target_wwpns(wwn) if tgtwwpns: tgt_port_wwns.append(tgtwwpns) init_targ_map = {} for initiator in wwns: init_targ_map[initiator] = tgt_port_wwns host_id = self.restclient.find_host(host_name) if host_id: mapping_view_name = constants.MAPPING_VIEW_PREFIX + host_id view_id = self.restclient.find_mapping_view(mapping_view_name) if view_id: lungroup_id = self.restclient.find_lungroup_from_map(view_id) if lungroup_id: left_lunnum = self.restclient.get_lunnum_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 delete_hypermetro(self, hypermetro_id, volume): hypermetro = self.local_cli.get_hypermetro_by_id(hypermetro_id) if hypermetro: if (hypermetro['RUNNINGSTATUS'] in (constants.METRO_RUNNING_NORMAL, constants.METRO_RUNNING_SYNC)): self.local_cli.stop_hypermetro(hypermetro_id) self.local_cli.delete_hypermetro(hypermetro_id) self.remote_cli.delete_lun(hypermetro['REMOTEOBJID']) else: name = huawei_utils.encode_name(volume.id) remote_lun_info = self.remote_cli.get_lun_info_by_name(name) if remote_lun_info: self.remote_cli.delete_lun(remote_lun_info['ID'])
def delete_hypermetro(self, volume): """Delete hypermetro.""" lun_name = huawei_utils.encode_name(volume.id) hypermetro = self.client.get_hypermetro_by_lun_name(lun_name) if not hypermetro: return metro_id = hypermetro['ID'] remote_lun_id = hypermetro['REMOTEOBJID'] # Delete hypermetro and remote lun. self.check_metro_need_to_stop(metro_id, hypermetro) self.client.delete_hypermetro(metro_id) self.rmt_client.delete_lun(remote_lun_id)
def check_consistencygroup_need_to_stop(self, group): group_name = huawei_utils.encode_name(group.id) metrogroup_id = self.client.get_metrogroup_by_name(group_name) if metrogroup_id: metrogroup_info = self.client.get_metrogroup_by_id(metrogroup_id) health_status = metrogroup_info['HEALTHSTATUS'] running_status = metrogroup_info['RUNNINGSTATUS'] if (health_status == constants.HEALTH_NORMAL and (running_status == constants.RUNNING_NORMAL or running_status == constants.RUNNING_SYNC)): self.client.stop_metrogroup(metrogroup_id) return metrogroup_id
def delete_snapshot(self, snapshot): snapshotname = huawei_utils.encode_name(snapshot["id"]) volume_name = huawei_utils.encode_name(snapshot["volume_id"]) LOG.info( _LI("stop_snapshot: snapshot name: %(snapshot)s, " "volume name: %(volume)s."), {"snapshot": snapshotname, "volume": volume_name}, ) snapshot_id = snapshot.get("provider_location", None) if snapshot_id is None: snapshot_id = self.restclient.get_snapshotid_by_name(snapshotname) if snapshot_id is not None: if self.restclient.check_snapshot_exist(snapshot_id): self.restclient.stop_snapshot(snapshot_id) self.restclient.delete_snapshot(snapshot_id) else: LOG.warning(_LW("Can't find snapshot on the array.")) else: LOG.warning(_LW("Can't find snapshot on the array.")) return False return True
def create_group(self, group_id, replica_model): LOG.info("Create replication group %s.", group_id) group_name = huawei_utils.encode_name(group_id) params = {'NAME': group_name, 'DESCRIPTION': group_id, 'RECOVERYPOLICY': '1', 'REPLICATIONMODEL': replica_model, 'SPEED': constants.REPLICA_SPEED} if replica_model == constants.REPLICA_ASYNC_MODEL: params['SYNCHRONIZETYPE'] = '2' params['TIMINGVAL'] = constants.REPLICA_CG_PERIOD group = self.group_op.create(params) return group['ID']
def create_consistencygroup(self, group_id): LOG.info("Create hypermetro consistency group %s.", group_id) domain_name = self.configs['metro_domain'] domain_id = self.local_cli.get_hypermetro_domain_id(domain_name) if not domain_id: msg = _("Hypermetro domain %s doesn't exist.") % domain_name LOG.error(msg) raise exception.VolumeBackendAPIException(data=msg) params = {"NAME": huawei_utils.encode_name(group_id), "DESCRIPTION": group_id, "RECOVERYPOLICY": "1", "SPEED": self.configs['sync_speed'], "DOMAINID": domain_id} self.local_cli.create_metrogroup(params)
def delete_hypermetro(self, volume): lun_name = huawei_utils.encode_name(volume.id) hypermetro = self.local_cli.get_hypermetro_by_lun_name(lun_name) if hypermetro: huawei_utils.remove_lun_from_lungroup(self.remote_cli, hypermetro['REMOTEOBJID']) if (hypermetro['RUNNINGSTATUS'] in (constants.METRO_RUNNING_NORMAL, constants.METRO_RUNNING_SYNC)): self.local_cli.stop_hypermetro(hypermetro['ID']) self.local_cli.delete_hypermetro(hypermetro['ID']) self.remote_cli.delete_lun(hypermetro['REMOTEOBJID']) else: remote_lun_info = self.remote_cli.get_lun_info_by_name(lun_name) if remote_lun_info: self.remote_cli.delete_lun(remote_lun_info['ID'])
def extend_volume(self, volume, new_size): """Extend a volume.""" volume_size = huawei_utils.get_volume_size(volume) new_volume_size = int(new_size) * units.Gi / 512 volume_name = huawei_utils.encode_name(volume['id']) LOG.info(_LI( 'Extend volume: %(volumename)s, oldsize:' ' %(oldsize)s newsize: %(newsize)s.'), {'volumename': volume_name, 'oldsize': volume_size, 'newsize': new_volume_size},) lun_id = self.restclient.get_lunid(volume, volume_name) luninfo = self.restclient.extend_volume(lun_id, new_volume_size) return {'provider_location': luninfo['ID'], 'lun_info': luninfo}
def create_volume(self, volume): """Create a volume.""" opts = huawei_utils.get_volume_params(volume) smartx_opts = smartx.SmartX().get_smartx_specs_opts(opts) params = huawei_utils.get_lun_params(self.xml_file_path, smartx_opts) pool_name = volume_utils.extract_host(volume["host"], level="pool") pools = self.restclient.find_all_pools() pool_info = self.restclient.find_pool_info(pool_name, pools) if not pool_info: msg = _("Error in getting pool information for the pool: %s.") % pool_name LOG.error(msg) raise exception.VolumeBackendAPIException(data=msg) volume_name = huawei_utils.encode_name(volume["id"]) volume_description = volume["name"] volume_size = huawei_utils.get_volume_size(volume) LOG.info(_LI("Create volume: %(volume)s, size: %(size)s."), {"volume": volume_name, "size": volume_size}) params["pool_id"] = pool_info["ID"] params["volume_size"] = volume_size params["volume_description"] = volume_description # Prepare LUN parameters. lun_param = huawei_utils.init_lun_parameters(volume_name, params) # Create LUN on the array. lun_info = self.restclient.create_volume(lun_param) lun_id = lun_info["ID"] try: qos = huawei_utils.get_volume_qos(volume) if qos: smart_qos = smartx.SmartQos(self.restclient) smart_qos.create_qos(qos, lun_id) smartpartition = smartx.SmartPartition(self.restclient) smartpartition.add(opts, lun_id) smartcache = smartx.SmartCache(self.restclient) smartcache.add(opts, lun_id) except Exception as err: self._delete_lun_with_check(lun_id) raise exception.InvalidInput(reason=_("Create volume error. Because %s.") % err) return {"provider_location": lun_info["ID"], "ID": lun_id, "lun_info": lun_info}
def delete_volume(self, volume): """Delete a volume. Three steps: Firstly, remove associate from lungroup. Secondly, remove associate from QoS policy. Thirdly, remove the lun. """ name = huawei_utils.encode_name(volume['id']) lun_id = volume.get('provider_location', None) LOG.info(_LI('Delete volume: %(name)s, array lun id: %(lun_id)s.'), {'name': name, 'lun_id': lun_id},) if lun_id: if self.restclient.check_lun_exist(lun_id): self.restclient.delete_lun(lun_id) else: LOG.warning(_LW("Can't find %s on the array."), lun_id) return False return True
def extend_volume(self, volume, new_size): """Extend a volume.""" volume_size = huawei_utils.get_volume_size(volume) new_volume_size = int(new_size) * units.Gi / 512 volume_name = huawei_utils.encode_name(volume['id']) LOG.info( _LI('Extend volume: %(volumename)s, oldsize:' ' %(oldsize)s newsize: %(newsize)s.'), { 'volumename': volume_name, 'oldsize': volume_size, 'newsize': new_volume_size }, ) lun_id = self.restclient.get_lunid(volume, volume_name) luninfo = self.restclient.extend_volume(lun_id, new_volume_size) return {'provider_location': luninfo['ID'], 'lun_info': luninfo}
def _pre_fail_check(self, vol, running_status_set, data_status_set=None): # check the replica_pair status vol_name = huawei_utils.encode_name(vol.id) vol_id = self.local_client.get_lun_id_by_name(vol_name) pair_info = self.local_client.get_pair_info_by_lun_id(vol_id) if pair_info: running_status = self.local_op.is_running_status( running_status_set, pair_info) data_status = self.local_op.is_data_status( data_status_set, pair_info) if data_status_set else True if not (running_status and data_status): msg = _('Replication pair %(id)s is not at the status ' 'failover/failback available, RUNNINGSTATUS: ' '%(run)s, SECRESDATASTATUS: %(sec)s.') % { 'id': pair_info['ID'], 'run': pair_info['RUNNINGSTATUS'], 'sec': pair_info['SECRESDATASTATUS'] } LOG.error(msg) raise exception.InvalidReplicationTarget(reason=msg)
def extend_volume(self, volume, new_size): """Extend a volume.""" volume_size = huawei_utils.get_volume_size(volume) new_volume_size = int(new_size) * units.Gi / 512 volume_name = huawei_utils.encode_name(volume["id"]) LOG.info( _LI("Extend volume: %(volumename)s, oldsize:" " %(oldsize)s newsize: %(newsize)s."), {"volumename": volume_name, "oldsize": volume_size, "newsize": new_volume_size}, ) lun_id = self.restclient.get_volume_by_name(volume_name) if lun_id is None: msg = _("Can't find lun info on the array, lun name is: %(name)s.") % {"name": volume_name} LOG.error(msg) raise exception.VolumeBackendAPIException(data=msg) luninfo = self.restclient.extend_volume(lun_id, new_volume_size) return {"provider_location": luninfo["ID"], "lun_info": luninfo}
def delete_volume(self, volume): """Delete a volume. Three steps: Firstly, remove associate from lungroup. Secondly, remove associate from QoS policy. Thirdly, remove the lun. """ name = huawei_utils.encode_name(volume["id"]) lun_id = volume.get("provider_location", None) LOG.info(_LI("Delete volume: %(name)s, array lun id: %(lun_id)s."), {"name": name, "lun_id": lun_id}) if lun_id: if self.restclient.check_lun_exist(lun_id): qos_id = self.restclient.get_qosid_by_lunid(lun_id) if qos_id: self.remove_qos_lun(lun_id, qos_id) self.restclient.delete_lun(lun_id) else: LOG.warning(_LW("Can't find lun %s on the array."), lun_id) return False return True
def create_volume(self, volume): """Create a volume.""" pool_name = volume_utils.extract_host(volume['host'], level='pool') pools = self.restclient.find_all_pools() pool_info = self.restclient.find_pool_info(pool_name, pools) if not pool_info: msg = (_('Error in getting pool information for the pool: %s.') % pool_name) LOG.error(msg) raise exception.VolumeBackendAPIException(data=msg) volume_name = huawei_utils.encode_name(volume['id']) volume_description = volume['name'] volume_size = huawei_utils.get_volume_size(volume) LOG.info(_LI('Create volume: %(volume)s, size: %(size)s.'), { 'volume': volume_name, 'size': volume_size }) params = huawei_utils.get_lun_conf_params(self.xml_file_path) params['pool_id'] = pool_info['ID'] params['volume_size'] = volume_size params['volume_description'] = volume_description # Prepare LUN parameters. lun_param = huawei_utils.init_lun_parameters(volume_name, params) # Create LUN on the array. lun_info = self.restclient.create_volume(lun_param) lun_id = lun_info['ID'] return { 'provider_location': lun_info['ID'], 'ID': lun_id, 'lun_info': lun_info }
def create_consistencygroup(self, group): LOG.info(_LI("Create Consistency Group: %(group)s."), {'group': group['id']}) group_name = huawei_utils.encode_name(group['id']) domain_id = self._valid_rmt_metro_domain() self.client.create_metrogroup(group_name, group['id'], domain_id)
def terminate_connection(self, volume, connector, **kwargs): """Delete map between a volume and a host.""" initiator_name = connector['initiator'] volume_name = huawei_utils.encode_name(volume['id']) lun_id = volume.get('provider_location') host_name = connector['host'] lungroup_id = None LOG.info( _LI('terminate_connection: volume name: %(volume)s, ' 'initiator name: %(ini)s, ' 'lun_id: %(lunid)s.'), { 'volume': volume_name, 'ini': initiator_name, 'lunid': lun_id }, ) iscsi_conf = huawei_utils.get_iscsi_conf(self.xml_file_path) portgroup = None portgroup_id = None view_id = None left_lunnum = -1 for ini in iscsi_conf['Initiator']: if ini['Name'] == initiator_name: for key in ini: if key == 'TargetPortGroup': portgroup = ini['TargetPortGroup'] break if portgroup: portgroup_id = self.restclient.find_tgt_port_group(portgroup) if host_name and (len(host_name) > constants.MAX_HOSTNAME_LENGTH): host_name = six.text_type(hash(host_name)) host_id = self.restclient.find_host(host_name) if host_id: mapping_view_name = constants.MAPPING_VIEW_PREFIX + host_id view_id = self.restclient.find_mapping_view(mapping_view_name) if view_id: lungroup_id = self.restclient.find_lungroup_from_map(view_id) # Remove lun from lungroup. if lun_id and self.restclient.check_lun_exist(lun_id): if lungroup_id: lungroup_ids = self.restclient.get_lungroupids_by_lunid(lun_id) if lungroup_id in lungroup_ids: self.restclient.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 }) else: LOG.warning(_LW("Can't find lun on the array.")) # Remove portgroup from mapping view if no lun left in lungroup. if lungroup_id: left_lunnum = self.restclient.get_lunnum_from_lungroup(lungroup_id) if portgroup_id and view_id and (int(left_lunnum) <= 0): if self.restclient.is_portgroup_associated_to_view( view_id, portgroup_id): self.restclient.delete_portgroup_mapping_view( view_id, portgroup_id) if view_id and (int(left_lunnum) <= 0): self.restclient.remove_chap(initiator_name) if self.restclient.lungroup_associated(view_id, lungroup_id): self.restclient.delete_lungroup_mapping_view( view_id, lungroup_id) self.restclient.delete_lungroup(lungroup_id) if self.restclient.is_initiator_associated_to_host(initiator_name): self.restclient.remove_iscsi_from_host(initiator_name) hostgroup_name = constants.HOSTGROUP_PREFIX + host_id hostgroup_id = self.restclient.find_hostgroup(hostgroup_name) if hostgroup_id: if self.restclient.hostgroup_associated(view_id, hostgroup_id): self.restclient.delete_hostgoup_mapping_view( view_id, hostgroup_id) self.restclient.remove_host_from_hostgroup( hostgroup_id, host_id) self.restclient.delete_hostgroup(hostgroup_id) self.restclient.remove_host(host_id) self.restclient.delete_mapping_view(view_id)
def initialize_connection(self, volume, connector): """Map a volume to a host and return target iSCSI information.""" LOG.info(_LI('Enter initialize_connection.')) initiator_name = connector['initiator'] volume_name = huawei_utils.encode_name(volume['id']) LOG.info( _LI('initiator name: %(initiator_name)s, ' 'volume name: %(volume)s.'), { 'initiator_name': initiator_name, 'volume': volume_name }) (iscsi_iqns, target_ips, portgroup_id) = self.restclient.get_iscsi_params( self.xml_file_path, connector) LOG.info( _LI('initialize_connection, iscsi_iqn: %(iscsi_iqn)s, ' 'target_ip: %(target_ip)s, ' 'portgroup_id: %(portgroup_id)s.'), { 'iscsi_iqn': iscsi_iqns, 'target_ip': target_ips, 'portgroup_id': portgroup_id }, ) # Create hostgroup if not exist. host_name = connector['host'] host_name_before_hash = None if host_name and (len(host_name) > constants.MAX_HOSTNAME_LENGTH): host_name_before_hash = host_name host_name = six.text_type(hash(host_name)) host_id = self.restclient.add_host_with_check(host_name, host_name_before_hash) # Add initiator to the host. self.restclient.ensure_initiator_added(self.xml_file_path, initiator_name, host_id) hostgroup_id = self.restclient.add_host_into_hostgroup(host_id) lun_id = self.restclient.get_lunid(volume, volume_name) # Mapping lungroup and hostgroup to view. self.restclient.do_mapping(lun_id, hostgroup_id, host_id, portgroup_id) hostlun_id = self.restclient.find_host_lun_id(host_id, lun_id) LOG.info(_LI("initialize_connection, host lun id is: %s."), hostlun_id) iscsi_conf = huawei_utils.get_iscsi_conf(self.xml_file_path) chapinfo = self.restclient.find_chap_info(iscsi_conf, initiator_name) # Return iSCSI properties. properties = {} properties['target_discovered'] = False properties['volume_id'] = volume['id'] multipath = connector.get('multipath', False) hostlun_id = int(hostlun_id) if not multipath: properties['target_portal'] = ('%s:3260' % target_ips[0]) properties['target_iqn'] = iscsi_iqns[0] properties['target_lun'] = hostlun_id else: properties['target_iqns'] = [iqn for iqn in iscsi_iqns] properties['target_portals'] = [ '%s:3260' % ip for ip in target_ips ] properties['target_luns'] = [hostlun_id] * len(target_ips) # If use CHAP, return CHAP info. if chapinfo: chap_username, chap_password = chapinfo.split(';') properties['auth_method'] = 'CHAP' properties['auth_username'] = chap_username properties['auth_password'] = chap_password LOG.info(_LI("initialize_connection success. Return data: %s."), properties) return {'driver_volume_type': 'iscsi', 'data': properties}
def connect_volume_fc(self, volume, connector): """Create map between a volume and a host for FC.""" wwns = connector['wwpns'] volume_name = huawei_utils.encode_name(volume.id) LOG.info(_LI( 'initialize_connection_fc, initiator: %(wwpns)s,' ' volume name: %(volume)s.'), {'wwpns': wwns, 'volume': volume_name}) metadata = huawei_utils.get_volume_metadata(volume) lun_id = metadata['remote_lun_id'] if lun_id is None: lun_id = self.rmt_client.get_lun_id_by_name(volume_name) if lun_id is None: msg = _("Can't get volume id. Volume name: %s.") % volume_name LOG.error(msg) raise exception.VolumeBackendAPIException(data=msg) original_host_name = connector['host'] host_name = huawei_utils.encode_host_name(original_host_name) host_id = self.client.add_host_with_check(host_name, original_host_name) # Create hostgroup if not exist. host_id = self.rmt_client.add_host_with_check( host_name, 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) 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(_LI('Remote return FC info is: %s.'), fc_info) return fc_info
def initialize_connection_iscsi(self, volume, connector): """Map a volume to a host and return target iSCSI information.""" LOG.info(_LI('Enter initialize_connection_iscsi.')) initiator_name = connector['initiator'] volume_name = huawei_utils.encode_name(volume['id']) LOG.info(_LI( 'initiator name: %(initiator_name)s, ' 'volume name: %(volume)s.'), {'initiator_name': initiator_name, 'volume': volume_name}) (iscsi_iqns, target_ips, portgroup_id) = self.restclient.get_iscsi_params(self.xml_file_path, connector) LOG.info(_LI('initialize_connection_iscsi, iscsi_iqn: %(iscsi_iqn)s, ' 'target_ip: %(target_ip)s, ' 'portgroup_id: %(portgroup_id)s.'), {'iscsi_iqn': iscsi_iqns, 'target_ip': target_ips, 'portgroup_id': portgroup_id},) # Create hostgroup if not exist. host_name = connector['host'] host_name_before_hash = None if host_name and (len(host_name) > constants.MAX_HOSTNAME_LENGTH): host_name_before_hash = host_name host_name = six.text_type(hash(host_name)) host_id = self.restclient.add_host_with_check(host_name, host_name_before_hash) # Add initiator to the host. self.restclient.ensure_initiator_added(self.xml_file_path, initiator_name, host_id) hostgroup_id = self.restclient.add_host_into_hostgroup(host_id) # Mapping lungroup and hostgroup to view. lun_id = self.restclient.mapping_hostgroup_and_lungroup(volume_name, hostgroup_id, host_id, portgroup_id) hostlun_id = self.restclient.find_host_lun_id(host_id, lun_id) LOG.info(_LI("initialize_connection_iscsi, host lun id is: %s."), hostlun_id) iscsi_conf = huawei_utils.get_iscsi_conf(self.xml_file_path) chapinfo = self.restclient.find_chap_info(iscsi_conf, initiator_name) # Return iSCSI properties. properties = {} properties['target_discovered'] = False properties['volume_id'] = volume['id'] multipath = connector.get('multipath', False) hostlun_id = int(hostlun_id) if not multipath: properties['target_portal'] = ('%s:3260' % target_ips[0]) properties['target_iqn'] = iscsi_iqns[0] properties['target_lun'] = hostlun_id else: properties['target_iqns'] = [iqn for iqn in iscsi_iqns] properties['target_portals'] = [ '%s:3260' % ip for ip in target_ips] properties['target_luns'] = [hostlun_id] * len(target_ips) # If use CHAP, return CHAP info. if chapinfo: chap_username, chap_password = chapinfo.split(';') properties['auth_method'] = 'CHAP' properties['auth_username'] = chap_username properties['auth_password'] = chap_password LOG.info(_LI("initialize_connection_iscsi success. Return data: %s."), properties) return {'driver_volume_type': 'iscsi', 'data': properties}
def terminate_connection(self, volume, connector, **kwargs): """Delete map between a volume and a host.""" wwns = connector['wwpns'] volume_name = huawei_utils.encode_name(volume['id']) lun_id = volume.get('provider_location') host_name = connector['host'] left_lunnum = -1 lungroup_id = None view_id = None LOG.info( _LI('terminate_connection: volume name: %(volume)s, ' 'wwpns: %(wwns)s, ' 'lun_id: %(lunid)s.'), { 'volume': volume_name, 'wwns': wwns, 'lunid': lun_id }, ) if host_name and len(host_name) > constants.MAX_HOSTNAME_LENGTH: host_name = six.text_type(hash(host_name)) host_id = self.restclient.find_host(host_name) if host_id: mapping_view_name = constants.MAPPING_VIEW_PREFIX + host_id view_id = self.restclient.find_mapping_view(mapping_view_name) if view_id: lungroup_id = self.restclient.find_lungroup_from_map(view_id) if lun_id and self.restclient.check_lun_exist(lun_id): if lungroup_id: lungroup_ids = self.restclient.get_lungroupids_by_lunid(lun_id) if lungroup_id in lungroup_ids: self.restclient.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 }) else: LOG.warning(_LW("Can't find lun on the array.")) if lungroup_id: left_lunnum = self.restclient.get_lunnum_from_lungroup(lungroup_id) if int(left_lunnum) > 0: info = {'driver_volume_type': 'fibre_channel', 'data': {}} else: if not self.fcsan_lookup_service: self.fcsan_lookup_service = fczm_utils.create_lookup_service() if self.fcsan_lookup_service: zone_helper = fc_zone_helper.FCZoneHelper( self.fcsan_lookup_service, self.restclient) (tgt_port_wwns, init_targ_map) = (zone_helper.build_ini_targ_map(wwns)) else: (tgt_port_wwns, init_targ_map) = (self.restclient.get_init_targ_map(wwns)) for wwn in wwns: if self.restclient.is_fc_initiator_associated_to_host(wwn): self.restclient.remove_fc_from_host(wwn) if lungroup_id: if view_id and self.restclient.lungroup_associated( view_id, lungroup_id): self.restclient.delete_lungroup_mapping_view( view_id, lungroup_id) self.restclient.delete_lungroup(lungroup_id) if host_id: hostgroup_name = constants.HOSTGROUP_PREFIX + host_id hostgroup_id = self.restclient.find_hostgroup(hostgroup_name) if hostgroup_id: if view_id and self.restclient.hostgroup_associated( view_id, hostgroup_id): self.restclient.delete_hostgoup_mapping_view( view_id, hostgroup_id) self.restclient.remove_host_from_hostgroup( hostgroup_id, host_id) self.restclient.delete_hostgroup(hostgroup_id) if not self.restclient.check_fc_initiators_exist_in_host( host_id): self.restclient.remove_host(host_id) if view_id: self.restclient.delete_mapping_view(view_id) info = { 'driver_volume_type': 'fibre_channel', 'data': { 'target_wwn': tgt_port_wwns, 'initiator_target_map': init_targ_map } } LOG.info(_LI("terminate_connection, return data is: %s."), info) return info
def terminate_connection_iscsi(self, volume, connector): """Delete map between a volume and a host.""" initiator_name = connector['initiator'] volume_name = huawei_utils.encode_name(volume['id']) lun_id = volume.get('provider_location', None) host_name = connector['host'] LOG.info(_LI( 'terminate_connection_iscsi: volume name: %(volume)s, ' 'initiator name: %(ini)s, ' 'lun_id: %(lunid)s.'), {'volume': volume_name, 'ini': initiator_name, 'lunid': lun_id},) iscsi_conf = huawei_utils.get_iscsi_conf(self.xml_file_path) portgroup = None portgroup_id = None left_lunnum = -1 for ini in iscsi_conf['Initiator']: if ini['Name'] == initiator_name: for key in ini: if key == 'TargetPortGroup': portgroup = ini['TargetPortGroup'] break # Remove lun from lungroup. if lun_id: if self.restclient.check_lun_exist(lun_id): # Get lungroup id by lun id. lungroup_id = self.restclient.get_lungroupid_by_lunid(lun_id) if lungroup_id: self.restclient.remove_lun_from_lungroup(lungroup_id, lun_id) else: LOG.warning(_LW("Can't find lun on the array.")) # Remove portgroup from mapping view if no lun left in lungroup. if portgroup: portgroup_id = self.restclient.find_tgt_port_group(portgroup) host_id = self.restclient.find_host(host_name) if host_id: mapping_view_name = constants.MAPPING_VIEW_PREFIX + host_id view_id = self.restclient.find_mapping_view(mapping_view_name) if view_id: lungroup_id = self.restclient.find_lungroup_from_map(view_id) if lungroup_id: left_lunnum = self.restclient.get_lunnum_from_lungroup(lungroup_id) if portgroup_id and view_id and (int(left_lunnum) <= 0): if self.restclient.is_portgroup_associated_to_view(view_id, portgroup_id): self.restclient.delete_portgroup_mapping_view(view_id, portgroup_id) if view_id and (int(left_lunnum) <= 0): self.restclient.remove_chap(initiator_name) if self.restclient.lungroup_associated(view_id, lungroup_id): self.restclient.delete_lungroup_mapping_view(view_id, lungroup_id) self.restclient.delete_lungroup(lungroup_id) if self.restclient.is_initiator_associated_to_host(initiator_name): self.restclient.remove_iscsi_from_host(initiator_name) hostgroup_name = constants.HOSTGROUP_PREFIX + host_id hostgroup_id = self.restclient.find_hostgroup(hostgroup_name) if hostgroup_id: if self.restclient.hostgroup_associated(view_id, hostgroup_id): self.restclient.delete_hostgoup_mapping_view(view_id, hostgroup_id) self.restclient.remove_host_from_hostgroup(hostgroup_id, host_id) self.restclient.delete_hostgroup(hostgroup_id) self.restclient.remove_host(host_id) self.restclient.delete_mapping_view(view_id)
def initialize_connection(self, volume, connector): wwns = connector['wwpns'] volume_name = huawei_utils.encode_name(volume['id']) LOG.info(_LI( 'initialize_connection, initiator: %(wwpns)s,' ' volume name: %(volume)s.'), {'wwpns': wwns, 'volume': volume_name},) host_name_before_hash = None host_name = connector['host'] if host_name and (len(host_name) > constants.MAX_HOSTNAME_LENGTH): host_name_before_hash = host_name host_name = six.text_type(hash(host_name)) if not self.fcsan_lookup_service: self.fcsan_lookup_service = fczm_utils.create_lookup_service() if self.fcsan_lookup_service: # Use FC switch. host_id = self.restclient.add_host_with_check( host_name, host_name_before_hash) zone_helper = fc_zone_helper.FCZoneHelper( self.fcsan_lookup_service, self.restclient) (tgt_port_wwns, init_targ_map) = ( zone_helper.build_ini_targ_map(wwns)) for ini in init_targ_map: self.restclient.ensure_fc_initiator_added(ini, host_id) else: # Not use FC switch. host_id = self.restclient.add_host_with_check( host_name, host_name_before_hash) online_wwns_in_host = ( self.restclient.get_host_online_fc_initiators(host_id)) online_free_wwns = self.restclient.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.restclient.get_host_fc_initiators(host_id)) iqns_in_host = ( self.restclient.get_host_iscsi_initiators(host_id)) if not wwns_in_host and not iqns_in_host: self.restclient.remove_host(host_id) msg = (_('Can not add FC initiator to host.')) LOG.error(msg) raise exception.VolumeBackendAPIException(data=msg) for wwn in wwns: if wwn in online_free_wwns: self.restclient.add_fc_port_to_host(host_id, wwn) (tgt_port_wwns, init_targ_map) = ( self.restclient.get_init_targ_map(wwns)) # Add host into hostgroup. hostgroup_id = self.restclient.add_host_into_hostgroup(host_id) lun_id = self.restclient.mapping_hostgroup_and_lungroup(volume_name, hostgroup_id, host_id) host_lun_id = self.restclient.find_host_lun_id(host_id, lun_id) # Return FC properties. 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}, } LOG.info(_LI("initialize_connection, return data is: %s."), info) return info
def terminate_connection(self, volume, connector, **kwargs): """Delete map between a volume and a host.""" wwns = connector['wwpns'] volume_name = huawei_utils.encode_name(volume['id']) lun_id = volume.get('provider_location', None) host_name = connector['host'] left_lunnum = -1 lungroup_id = None view_id = None LOG.info(_LI('terminate_connection: volume name: %(volume)s, ' 'wwpns: %(wwns)s, ' 'lun_id: %(lunid)s.'), {'volume': volume_name, 'wwns': wwns, 'lunid': lun_id},) if host_name and len(host_name) > constants.MAX_HOSTNAME_LENGTH: host_name = six.text_type(hash(host_name)) host_id = self.restclient.find_host(host_name) if host_id: mapping_view_name = constants.MAPPING_VIEW_PREFIX + host_id view_id = self.restclient.find_mapping_view(mapping_view_name) if view_id: lungroup_id = self.restclient.find_lungroup_from_map(view_id) if lun_id and self.restclient.check_lun_exist(lun_id): if lungroup_id: lungroup_ids = self.restclient.get_lungroupids_by_lunid(lun_id) if lungroup_id in lungroup_ids: self.restclient.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}) else: LOG.warning(_LW("Can't find lun on the array.")) if lungroup_id: left_lunnum = self.restclient.get_lunnum_from_lungroup(lungroup_id) if int(left_lunnum) > 0: info = {'driver_volume_type': 'fibre_channel', 'data': {}} else: if not self.fcsan_lookup_service: self.fcsan_lookup_service = fczm_utils.create_lookup_service() if self.fcsan_lookup_service: zone_helper = fc_zone_helper.FCZoneHelper( self.fcsan_lookup_service, self.restclient) (tgt_port_wwns, init_targ_map) = ( zone_helper.build_ini_targ_map(wwns)) else: (tgt_port_wwns, init_targ_map) = ( self.restclient.get_init_targ_map(wwns)) for wwn in wwns: if self.restclient.is_fc_initiator_associated_to_host(wwn): self.restclient.remove_fc_from_host(wwn) if lungroup_id: if view_id and self.restclient.lungroup_associated( view_id, lungroup_id): self.restclient.delete_lungroup_mapping_view(view_id, lungroup_id) self.restclient.delete_lungroup(lungroup_id) if host_id: hostgroup_name = constants.HOSTGROUP_PREFIX + host_id hostgroup_id = self.restclient.find_hostgroup(hostgroup_name) if hostgroup_id: if view_id and self.restclient.hostgroup_associated( view_id, hostgroup_id): self.restclient.delete_hostgoup_mapping_view( view_id, hostgroup_id) self.restclient.remove_host_from_hostgroup( hostgroup_id, host_id) self.restclient.delete_hostgroup(hostgroup_id) if not self.restclient.check_fc_initiators_exist_in_host( host_id): self.restclient.remove_host(host_id) if view_id: self.restclient.delete_mapping_view(view_id) info = {'driver_volume_type': 'fibre_channel', 'data': {'target_wwn': tgt_port_wwns, 'initiator_target_map': init_targ_map}} LOG.info(_LI("terminate_connection, return data is: %s."), info) return info
def disconnect_volume_fc(self, volume, connector): """Delete map between a volume and a host for FC.""" wwns = connector['wwpns'] volume_name = huawei_utils.encode_name(volume.id) metadata = huawei_utils.get_volume_metadata(volume) lun_id = metadata['remote_lun_id'] host_name = connector['host'] left_lunnum = -1 lungroup_id = None view_id = None LOG.info(_LI('terminate_connection_fc: volume name: %(volume)s, ' 'wwpns: %(wwns)s, ' 'lun_id: %(lunid)s.'), {'volume': volume_name, 'wwns': wwns, 'lunid': lun_id},) host_name = huawei_utils.encode_host_name(host_name) hostid = self.rmt_client.get_host_id_by_name(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}) (tgt_port_wwns, init_targ_map) = ( self.rmt_client.get_init_targ_map(wwns)) hostid = self.rmt_client.get_host_id_by_name(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_lunnum_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