From 27f70cb00aee889b5f90af25a989ee0eed2c3f0d Mon Sep 17 00:00:00 2001 From: bingyanh Date: Sun, 9 Jul 2023 22:27:58 +0800 Subject: [PATCH] N~Z: 1 support volume migrate in storage. 2 support create snapshot group. 3 support full clone when clone volume. 4 fix create volume with qos error when concurrent. --- Cinder/Mitaka/dsware.py | 2 +- Cinder/Newton/constants.py | 15 + Cinder/Newton/dsware.py | 577 +++++++++++++++++- Cinder/Newton/fs_client.py | 78 ++- Cinder/Newton/fs_qos.py | 6 +- Cinder/Newton/fs_utils.py | 10 +- Cinder/Ocata/constants.py | 15 + Cinder/Ocata/dsware.py | 577 +++++++++++++++++- Cinder/Ocata/fs_client.py | 78 ++- Cinder/Ocata/fs_qos.py | 6 +- Cinder/Ocata/fs_utils.py | 10 +- Cinder/Pike/constants.py | 15 + Cinder/Pike/dsware.py | 577 +++++++++++++++++- Cinder/Pike/fs_client.py | 78 ++- Cinder/Pike/fs_qos.py | 6 +- Cinder/Pike/fs_utils.py | 10 +- Cinder/Queens/constants.py | 15 + Cinder/Queens/dsware.py | 577 +++++++++++++++++- Cinder/Queens/fs_client.py | 78 ++- Cinder/Queens/fs_qos.py | 6 +- Cinder/Queens/fs_utils.py | 10 +- Cinder/Rocky/constants.py | 15 + Cinder/Rocky/dsware.py | 577 +++++++++++++++++- Cinder/Rocky/fs_client.py | 78 ++- Cinder/Rocky/fs_qos.py | 6 +- Cinder/Rocky/fs_utils.py | 10 +- Cinder/Stein/constants.py | 15 + Cinder/Stein/dsware.py | 577 +++++++++++++++++- Cinder/Stein/fs_client.py | 78 ++- Cinder/Stein/fs_qos.py | 6 +- Cinder/Stein/fs_utils.py | 10 +- Cinder/Train/constants.py | 15 + Cinder/Train/dsware.py | 577 +++++++++++++++++- Cinder/Train/fs_client.py | 78 ++- Cinder/Train/fs_qos.py | 6 +- Cinder/Train/fs_utils.py | 10 +- Cinder/Ussuri/constants.py | 15 + Cinder/Ussuri/dsware.py | 577 +++++++++++++++++- Cinder/Ussuri/fs_client.py | 78 ++- Cinder/Ussuri/fs_qos.py | 6 +- Cinder/Ussuri/fs_utils.py | 10 +- Cinder/Victoria/constants.py | 15 + Cinder/Victoria/dsware.py | 577 +++++++++++++++++- Cinder/Victoria/fs_client.py | 78 ++- Cinder/Victoria/fs_qos.py | 6 +- Cinder/Victoria/fs_utils.py | 10 +- Cinder/Wallaby/constants.py | 15 + Cinder/Wallaby/dsware.py | 577 +++++++++++++++++- Cinder/Wallaby/fs_client.py | 78 ++- Cinder/Wallaby/fs_qos.py | 6 +- Cinder/Wallaby/fs_utils.py | 10 +- Cinder/Xena/constants.py | 15 + Cinder/Xena/dsware.py | 577 +++++++++++++++++- Cinder/Xena/fs_client.py | 78 ++- Cinder/Xena/fs_qos.py | 6 +- Cinder/Xena/fs_utils.py | 10 +- Cinder/Yoga/constants.py | 15 + Cinder/Yoga/dsware.py | 577 +++++++++++++++++- Cinder/Yoga/fs_client.py | 78 ++- Cinder/Yoga/fs_qos.py | 6 +- Cinder/Yoga/fs_utils.py | 10 +- Cinder/Zed/constants.py | 15 + Cinder/Zed/dsware.py | 577 +++++++++++++++++- Cinder/Zed/fs_client.py | 78 ++- Cinder/Zed/fs_qos.py | 6 +- Cinder/Zed/fs_utils.py | 10 +- ...e OpenStack Driver Configuration Guide.pdf | Bin 311407 -> 316296 bytes ...5\347\275\256\346\214\207\345\215\227.pdf" | Bin 380263 -> 386667 bytes 68 files changed, 8516 insertions(+), 404 deletions(-) diff --git a/Cinder/Mitaka/dsware.py b/Cinder/Mitaka/dsware.py index e151085..562e4bf 100644 --- a/Cinder/Mitaka/dsware.py +++ b/Cinder/Mitaka/dsware.py @@ -148,7 +148,7 @@ class DSWAREDriver(driver.VolumeDriver): """Huawei FusionStorage Driver.""" - VERSION = '1.0' + VERSION = "2.6.1" # ThirdPartySystems wiki page CI_WIKI_NAME = "Huawei_FusionStorage_CI" diff --git a/Cinder/Newton/constants.py b/Cinder/Newton/constants.py index 5f46ece..b4cb843 100644 --- a/Cinder/Newton/constants.py +++ b/Cinder/Newton/constants.py @@ -45,6 +45,14 @@ CONF_STORAGE_CERT_FILEPATH = "storage_cert_filepath" CONF_STORAGE_SSL_TWO_WAY_AUTH = "storage_ssl_two_way_auth" +DEFAULT_WAIT_INTERVAL = 5 +MIGRATION_COMPLETE = 76 +MIGRATION_FAULT = 74 +STATUS_HEALTH = 1 +STATUS_VOLUME_READY = 27 +MIGRATION_WAIT_INTERVAL = 5 +DEFAULT_WAIT_TIMEOUT = 3600 * 24 * 30 + QOS_MUST_SET = ["maxIOPS", "maxMBPS"] QOS_KEYS = ["maxIOPS", "maxMBPS", "total_iops_sec", "total_bytes_sec"] QOS_SCHEDULER_KEYS = ["scheduleType", "startDate", "startTime", @@ -53,6 +61,7 @@ QOS_SCHEDULER_DEFAULT_TYPE = "0" QOS_SCHEDULER_WEEK_TYPE = "3" QOS_SUPPORT_SCHEDULE_VERSION = "8.0" +QOS_MAX_INTERCEPT_LENGTH = 36 SECONDS_OF_DAY = 24 * 60 * 60 SECONDS_OF_HOUR = 60 * 60 SNAPSHOT_HEALTH_STATUS = ( @@ -80,3 +89,9 @@ HOSTGROUP_ALREADY_EXIST = 50157044 INITIATOR_ALREADY_EXIST = 50155102 INITIATOR_IN_HOST = 50157021 + +CHECK_CLONED_INTERVAL = 2 +REST_VOLUME_CREATING_STATUS = 15 +REST_VOLUME_DUPLICATE_VOLUME = 6 +REST_VOLUME_CREATE_SUCCESS_STATUS = 0 +CLONE_VOLUME_TIMEOUT = 3600 * 24 * 30 diff --git a/Cinder/Newton/dsware.py b/Cinder/Newton/dsware.py index 8c1b16e..3716749 100644 --- a/Cinder/Newton/dsware.py +++ b/Cinder/Newton/dsware.py @@ -14,16 +14,22 @@ # under the License. import json - +import time +import uuid from multiprocessing import Lock + +import six from oslo_config import cfg from oslo_log import log as logging +from oslo_utils import excutils from oslo_utils import units +from oslo_service import loopingcall from cinder import coordination from cinder import exception from cinder.i18n import _ from cinder import interface +from cinder import objects from cinder.volume import driver from cinder.volume.drivers.fusionstorage import constants from cinder.volume.drivers.fusionstorage import fs_client @@ -101,6 +107,9 @@ cfg.StrOpt('storage_key_filepath', default='', help='Client key directory.'), + cfg.BoolOpt('full_clone', + default=False, + help='Whether use full clone.'), ] CONF = cfg.CONF @@ -109,7 +118,7 @@ @interface.volumedriver class DSWAREBaseDriver(driver.VolumeDriver): - VERSION = '2.5.RC4' + VERSION = "2.6.1" CI_WIKI_NAME = 'Huawei_FusionStorage_CI' def __init__(self, *args, **kwargs): @@ -206,6 +215,7 @@ def _update_single_pool_info_status(self, pool_info): "total_capacity_gb": capacity['total_capacity_gb'], "free_capacity_gb": capacity['free_capacity_gb'], "provisioned_capacity_gb": capacity['provisioned_capacity_gb'], + "location_info": self.client.esn, "QoS_support": True, 'multiattach': True, "thin_provisioning_support": True, @@ -243,8 +253,12 @@ def _raise_exception(msg): raise exception.VolumeBackendAPIException(data=msg) def _get_pool_id(self, volume): - pool_id_list = [] pool_name = volume_utils.extract_host(volume.host, level='pool') + pool_id = self._get_pool_id_by_name(pool_name) + return pool_id + + def _get_pool_id_by_name(self, pool_name): + pool_id_list = [] all_pools = self.client.query_pool_info() for pool in all_pools: if pool_name == pool['poolName']: @@ -359,29 +373,111 @@ def _expand_volume_when_create(self, vol_name, vol_size): self.client.delete_volume(vol_name=vol_name) raise + def _check_create_cloned_volume_finish(self, new_volume_name, start_time): + LOG.debug('Loopcall: _check_create_cloned_volume_finish(), ' + 'volume-name %s', + new_volume_name) + current_volume = self.client.query_volume_by_name(new_volume_name) + + if current_volume and 'status' in current_volume: + status = int(current_volume['status']) + LOG.debug('Wait clone volume %(volume_name)s, status:%(status)s.', + {"volume_name": new_volume_name, + "status": status}) + if status in {constants.REST_VOLUME_CREATING_STATUS, + constants.REST_VOLUME_DUPLICATE_VOLUME}: + LOG.debug(_("Volume %s is cloning"), new_volume_name) + elif status == constants.REST_VOLUME_CREATE_SUCCESS_STATUS: + raise loopingcall.LoopingCallDone(retvalue=True) + else: + msg = _('Clone volume %(new_volume_name)s failed, ' + 'the status is:%(status)s.') + LOG.error(msg, {'new_volume_name': new_volume_name, + 'status': status}) + raise loopingcall.LoopingCallDone(retvalue=False) + + max_time_out = constants.CLONE_VOLUME_TIMEOUT + current_time = time.time() + if (current_time - start_time) > max_time_out: + msg = _('Dsware clone volume time out. ' + 'Volume: %(new_volume_name)s, status: %(status)s') + LOG.error(msg, {'new_volume_name': new_volume_name, + 'status': current_volume['status']}) + raise loopingcall.LoopingCallDone(retvalue=False) + else: + LOG.warning(_('Can not find volume %s'), new_volume_name) + msg = "DSWARE clone volume failed:volume can not find from dsware" + LOG.error(msg) + raise loopingcall.LoopingCallDone(retvalue=False) + + def _wait_for_create_cloned_volume_finish_timer(self, new_volume_name): + timer = loopingcall.FixedIntervalLoopingCall( + self._check_create_cloned_volume_finish, + new_volume_name, time.time()) + LOG.debug('Calling _check_create_cloned_volume_finish: volume-name %s', + new_volume_name) + ret = timer.start(interval=constants.CHECK_CLONED_INTERVAL).wait() + timer.stop() + return ret + def create_volume_from_snapshot(self, volume, snapshot): vol_name = self._get_vol_name(volume) snapshot_name = self._get_snapshot_name(snapshot) vol_size = volume.size + pool_id = self._get_pool_id(volume) if not self._check_snapshot_exist(snapshot.volume, snapshot): msg = _("Snapshot: %(name)s does not exist!" ) % {"name": snapshot_name} self._raise_exception(msg) - elif self._check_volume_exist(volume): + if self._check_volume_exist(volume): msg = _("Volume: %(vol_name)s already exists!" ) % {'vol_name': vol_name} self._raise_exception(msg) - else: - vol_size *= units.Ki + + vol_size *= units.Ki + if not self.configuration.full_clone: self.client.create_volume_from_snapshot( snapshot_name=snapshot_name, vol_name=vol_name, vol_size=vol_size) - self._add_qos_to_volume(volume, vol_name) - self._expand_volume_when_create(vol_name, vol_size) - result = self.client.query_volume_by_name(vol_name=vol_name) - return ({"metadata": {'lun_wwn': result.get('wwn')}} - if result else {}) + else: + self.client.create_volume(vol_name, vol_size, pool_id) + self.client.create_full_volume_from_snapshot(vol_name, + snapshot_name) + ret = self._wait_for_create_cloned_volume_finish_timer(vol_name) + if not ret: + msg = _('Create full volume %s from snap failed') % vol_name + self._raise_exception(msg) + self._add_qos_to_volume(volume, vol_name) + self._expand_volume_when_create(vol_name, vol_size) + result = self.client.query_volume_by_name(vol_name=vol_name) + return ({"metadata": {'lun_wwn': result.get('wwn')}} + if result else {}) + + def _create_volume_from_volume_full_clone(self, vol_name, vol_size, pool_id, + src_vol_name): + tmp_snap_name = "temp" + src_vol_name + "clone" + vol_name + + self.client.create_snapshot(tmp_snap_name, src_vol_name) + try: + self.client.create_volume(vol_name, vol_size, pool_id) + except Exception as err: + self.client.delete_snapshot(tmp_snap_name) + raise err + + try: + self.client.create_full_volume_from_snapshot( + vol_name, tmp_snap_name) + except Exception as err: + self.client.delete_snapshot(tmp_snap_name) + self.client.delete_volume(vol_name) + raise err + + ret = self._wait_for_create_cloned_volume_finish_timer(vol_name) + if not ret: + msg = _('Create full volume %s from snap failed') % vol_name + self._raise_exception(msg) + self.client.delete_snapshot(tmp_snap_name) def create_cloned_volume(self, volume, src_volume): vol_name = self._get_vol_name(volume) @@ -394,15 +490,22 @@ def create_cloned_volume(self, volume, src_volume): msg = _("Volume: %(vol_name)s does not exist!" ) % {"vol_name": src_vol_name} self._raise_exception(msg) - else: + + if not self.configuration.full_clone: self.client.create_volume_from_volume( vol_name=vol_name, vol_size=vol_size, src_vol_name=src_vol_name) - self._add_qos_to_volume(volume, vol_name) - self._expand_volume_when_create(vol_name, vol_size) - result = self.client.query_volume_by_name(vol_name=vol_name) - return ({"metadata": {'lun_wwn': result.get('wwn')}} - if result else {}) + else: + pool_id = self._get_pool_id(volume) + self._create_volume_from_volume_full_clone( + vol_name=vol_name, vol_size=vol_size, pool_id=pool_id, + src_vol_name=src_vol_name) + + self._add_qos_to_volume(volume, vol_name) + self._expand_volume_when_create(vol_name, vol_size) + result = self.client.query_volume_by_name(vol_name=vol_name) + return ({"metadata": {'lun_wwn': result.get('wwn')}} + if result else {}) def create_snapshot(self, snapshot): snapshot_name = self._get_snapshot_name(snapshot) @@ -577,12 +680,13 @@ def unmanage_snapshot(self, snapshot): def _check_need_changes_for_retype(self, volume, new_type, host, vol_name): before_change = {} after_change = {} - if volume.host != host["host"]: - msg = (_("Do not support retype between different host. Volume's " + migrate = False + if volume.host != host.get("host"): + migrate = True + msg = (_("retype support migration between different host. Volume's " "host: %(vol_host)s, host's host: %(host)s") - % {"vol_host": volume.host, "host": host['host']}) - LOG.error(msg) - raise exception.InvalidInput(msg) + % {"vol_host": volume.host, "host": host.get("host")}) + LOG.info(msg) old_opts = fs_utils.get_volume_specs(self.client, vol_name) new_opts = fs_utils.get_volume_type_params(new_type, self.client) @@ -592,7 +696,7 @@ def _check_need_changes_for_retype(self, volume, new_type, host, vol_name): change_opts = {"old_opts": before_change, "new_opts": after_change} - return change_opts + return migrate, change_opts def retype(self, context, volume, new_type, diff, host): LOG.info("Retype volume: %(vol)s, new_type: %(new_type)s, " @@ -603,13 +707,177 @@ def retype(self, context, volume, new_type, diff, host): "host": host}) vol_name = self._get_vol_name(volume) - change_opts = self._check_need_changes_for_retype( + migrate, change_opts = self._check_need_changes_for_retype( volume, new_type, host, vol_name) + if migrate: + src_lun_id = self._check_volume_exist_on_array(volume) + LOG.debug("Begin to migrate LUN(id: %(lun_id)s) with " + "change %(change_opts)s.", + {"lun_id": src_lun_id, "change_opts": change_opts}) + moved = self._migrate_volume(volume, host, src_lun_id) + if not moved: + LOG.warning("Storage-assisted migration failed during " + "retype.") + return False, None self._change_lun(vol_name, change_opts.get("new_opts"), change_opts.get("old_opts")) return True, None + def migrate_volume(self, context, volume, host): + """Migrate a volume within the same array.""" + LOG.info("Migrate Volume:%(volume)s, host:%(host)s", + {"volume": volume.id, + "host": host}) + src_lun_id = self._check_volume_exist_on_array(volume) + + moved = self._migrate_volume(volume, host, src_lun_id) + return moved, {} + + def _create_dst_volume(self, volume, host): + pool_name = host['capabilities']['pool_name'] + pool_id = self._get_pool_id_by_name(pool_name) + vol_name = fs_utils.encode_name(six.text_type(uuid.uuid4())) + vol_size = volume.size + vol_size *= units.Ki + self.client.create_volume( + pool_id=pool_id, vol_name=vol_name, vol_size=vol_size) + + result = self.client.query_volume_by_name_v2(vol_name=vol_name) + dst_lun_id = result.get('id') + self._wait_volume_ready(vol_name) + return vol_name, dst_lun_id + + def _migrate_volume(self, volume, host, src_lun_id): + """create migration task and wait for task done""" + if not self._check_migration_valid(host): + return False + + vol_name, dst_lun_id = self._create_dst_volume(volume, host) + + try: + self.client.create_lun_migration(src_lun_id, dst_lun_id) + + def _is_lun_migration_complete(): + return self._is_lun_migration_complete(src_lun_id, dst_lun_id) + + wait_interval = constants.MIGRATION_WAIT_INTERVAL + fs_utils.wait_for_condition(_is_lun_migration_complete, + wait_interval, + constants.DEFAULT_WAIT_TIMEOUT) + # Clean up if migration failed. + except Exception as ex: + raise exception.VolumeBackendAPIException(data=ex) + finally: + if self._is_lun_migration_exist(src_lun_id, dst_lun_id): + self.client.delete_lun_migration(src_lun_id) + self._delete_lun_with_check(vol_name) + + LOG.info("Migrate lun %s successfully.", src_lun_id) + return True + + def _delete_lun_with_check(self, vol_name): + if self.client.query_volume_by_name(vol_name): + # migrate_dst_lun don't have qos, so don't + # need to remove qos, Delete the LUN directly. + self.client.delete_volume(vol_name) + + def _is_lun_migration_complete(self, src_lun_id, dst_lun_id): + result = self.client.get_lun_migration_task_by_id(src_lun_id) + found_migration_task = False + if not result: + return False + + if (str(src_lun_id) == result.get('parent_id') and + str(dst_lun_id) == result.get('target_lun_id')): + found_migration_task = True + if constants.MIGRATION_COMPLETE == result.get('running_status'): + return True + if constants.MIGRATION_FAULT == result.get('running_status'): + msg = _("Lun migration error. " + "the migration task running_status is abnormal") + LOG.error(msg) + raise exception.VolumeBackendAPIException(data=msg) + + if not found_migration_task: + err_msg = _("lun migration error, Cannot find migration task.") + LOG.error(err_msg) + raise exception.VolumeBackendAPIException(data=err_msg) + + return False + + def _is_lun_migration_exist(self, src_lun_id, dst_lun_id): + try: + result = self.client.get_lun_migration_task_by_id(src_lun_id) + except Exception: + LOG.error("Get LUN migration error.") + return False + + if (str(src_lun_id) == result.get('parent_id') and + str(dst_lun_id) == result.get('target_lun_id')): + return True + return False + + def _wait_volume_ready(self, vol_name): + wait_interval = constants.DEFAULT_WAIT_INTERVAL + + def _volume_ready(): + result = self.client.query_volume_by_name_v2(vol_name) + if not result: + return False + + if (result.get('health_status') == constants.STATUS_HEALTH + and result.get('running_status') == constants.STATUS_VOLUME_READY): + return True + return False + + fs_utils.wait_for_condition(_volume_ready, + wait_interval, + wait_interval * 10) + + def _check_migration_valid(self, host): + if 'pool_name' not in host.get('capabilities', {}): + return False + + target_device = host.get('capabilities', {}).get('location_info') + + # Source and destination should be on same array. + if target_device != self.client.esn: + LOG.error("lun migration error, " + "Source and destination should be on same array") + return False + + pool_name = host.get('capabilities', {}).get('pool_name', '') + if len(pool_name) == 0: + LOG.error("lun migration error, pool_name not exists") + return False + + return True + + def _check_volume_exist_on_array(self, volume): + volume_name = self._get_vol_name(volume) + result = self._check_volume_exist(volume) + if not result: + msg = _("Volume %s does not exist on the array." + ) % volume.id + self._raise_exception(msg) + + lun_wwn = result.get('wwn') + if not lun_wwn: + LOG.debug("No LUN WWN recorded for volume %s.", volume.id) + + lun_id = result.get('volId') + if not lun_id: + msg = _("Volume %s does not exist on the array." + ) % volume.id + self._raise_exception(msg) + + if self.client.get_volume_snapshot(volume_name): + msg = _("Volume %s which have snapshot cannot do lun migration" + ) % volume.id + self._raise_exception(msg) + return lun_id + def _rollback_snapshot(self, vol_name, snap_name): def _snapshot_rollback_finish(): snapshot_info = self.client.get_snapshot_info_by_name(snap_name) @@ -665,6 +933,265 @@ def ensure_export(self, context, volume): def remove_export(self, context, volume): pass + def create_group(self, context, group): + """Creates a group. Driver only need to return state""" + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.create_consistencygroup(context, group) + + def create_consistencygroup(self, context, group): + """Creates a group. Driver only need to return state""" + LOG.info("Create group successfully") + return {'status': 'available'} + + def update_group(self, context, group, + add_volumes=None, remove_volumes=None): + """ + The volume manager will adds/removes the volume to/from the + group in the database, if need add_volumes, Driver just need + to check whether volume is in array or not + """ + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.update_consistencygroup( + context, group, add_volumes, remove_volumes) + + def update_consistencygroup(self, context, group, + add_volumes=None, remove_volumes=None): + """ + The volume manager will adds/removes the volume to/from the + group in the database, if need add_volumes, Driver just need + to check whether volume is in array or not + """ + if add_volumes is None: + add_volumes = [] + for volume in add_volumes: + try: + self._check_volume_exist_on_array(volume) + except Exception: + with excutils.save_and_reraise_exception(): + LOG.error("The add_volume %s not exist on array" % volume.id) + + model_update = {'status': 'available'} + LOG.info("Update group successfully") + return model_update, None, None + + def delete_group(self, context, group, volumes): + """delete the group, Driver need to delete relation lun on array""" + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.delete_consistencygroup(context, group, volumes) + + def delete_consistencygroup(self, context, group, volumes): + """delete the group, Driver need to delete relation lun on array""" + volumes_model_update = [] + model_update = {'status': 'deleted'} + for volume in volumes: + volume_model_update = {'id': volume.id} + try: + self.delete_volume(volume) + except Exception: + LOG.error('Delete volume %s failed.' % volume) + volume_model_update.update({'status': 'error_deleting'}) + else: + volume_model_update.update({'status': 'deleted'}) + + LOG.info('Deleted volume %s successfully' % volume) + volumes_model_update.append(volume_model_update) + + LOG.info("Delete group successfully") + return model_update, volumes_model_update + + def create_group_from_src(self, context, group, volumes, + group_snapshot=None, snapshots=None, + source_group=None, source_vols=None): + """ + create group from group or group-snapshot, + Driver need to create volume from volume or snapshot + """ + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.create_consistencygroup_from_src(context, group, volumes, + group_snapshot, snapshots, + source_group, source_vols) + + def create_consistencygroup_from_src(self, context, group, volumes, + group_snapshot=None, snapshots=None, + source_group=None, source_vols=None): + """ + create group from group or group-snapshot, + Driver need to create volume from volume or snapshot + """ + model_update = self.create_consistencygroup(context, group) + volumes_model_update = [] + delete_snapshots = False + + if not snapshots and source_vols: + snapshots = [] + for src_volume in source_vols: + volume_kwargs = { + 'id': src_volume.id, + '_name_id': None, + 'host': src_volume.host + } + snapshot_kwargs = { + 'id': six.text_type(uuid.uuid4()), + 'volume': objects.Volume(**volume_kwargs) + } + snapshots.append(objects.Snapshot(**snapshot_kwargs)) + + self._create_group_snapshot(snapshots) + delete_snapshots = True + + if snapshots: + volumes_model_update = self._create_volume_from_group_snapshot( + volumes, snapshots, delete_snapshots) + + if delete_snapshots: + self._delete_group_snapshot(snapshots) + + LOG.info("Create group from src successfully") + return model_update, volumes_model_update + + def _create_volume_from_group_snapshot(self, volumes, snapshots, delete_snapshots): + volumes_model_update = [] + added_volumes = [] + for i, volume in enumerate(volumes): + try: + vol_model_update = self.create_volume_from_snapshot( + volume, snapshots[i]) + vol_model_update.update({'id': volume.id}) + volumes_model_update.append(vol_model_update) + added_volumes.append(volume) + except Exception: + LOG.error("Create volume from snapshot error, Delete the newly created lun.") + with excutils.save_and_reraise_exception(): + self._delete_added_volume_snapshots( + added_volumes, snapshots, delete_snapshots) + + return volumes_model_update + + def _delete_added_volume_snapshots( + self, added_volumes, snapshots, delete_snapshots): + if delete_snapshots: + self._delete_group_snapshot(snapshots) + for add_volume in added_volumes: + vol_name = self._get_vol_name(add_volume) + self.fs_qos.remove(vol_name) + self.client.delete_volume(vol_name=vol_name) + LOG.info("delete storage newly added " + "volume success, volume is %s" % add_volume.id) + + def create_group_snapshot(self, context, group_snapshot, snapshots): + """Create group snapshot.""" + if not volume_utils.is_group_a_cg_snapshot_type(group_snapshot): + LOG.info("group_snapshot's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.create_cgsnapshot(context, group_snapshot, snapshots) + + def create_cgsnapshot(self, context, group_snapshot, snapshots): + """Create group snapshot.""" + LOG.info('Create group snapshot for group: %(group_snapshot)s', + {'group_snapshot': group_snapshot}) + + try: + snapshots_model_update = self._create_group_snapshot(snapshots) + except Exception as err: + msg = ("Create group snapshots failed. " + "Group snapshot id: %s. Reason is %s") % (group_snapshot.id, err) + LOG.error(msg) + raise exception.CinderException(msg) + + model_update = {'status': 'available'} + return model_update, snapshots_model_update + + def _create_group_snapshot(self, snapshots): + """Generate snapshots for all volumes in the group.""" + snapshots_model_update = [] + snapshot_group_list = [] + + for snapshot in snapshots: + snapshot_name = self._get_snapshot_name(snapshot) + vol_name = self._get_vol_name(snapshot.volume) + snapshot_group_list.append({ + 'name': snapshot_name, + 'sub_type': '0', + 'volume_name': vol_name + }) + snapshot_model_update = { + 'id': snapshot.id, + 'status': 'available', + } + snapshots_model_update.append(snapshot_model_update) + try: + self.client.create_consistent_snapshot_by_name(snapshot_group_list) + except Exception: + with excutils.save_and_reraise_exception(): + LOG.error("Create consistent snapshot failed, " + "snapshot_group_list is %s" % snapshot_group_list) + + return snapshots_model_update + + def delete_group_snapshot(self, context, group_snapshot, snapshots): + """Delete group snapshot.""" + if not volume_utils.is_group_a_cg_snapshot_type(group_snapshot): + LOG.info("group_snapshot's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.delete_cgsnapshot(context, group_snapshot, snapshots) + + def delete_cgsnapshot(self, context, group_snapshot, snapshots): + """Delete group snapshot.""" + LOG.info("Delete group_snapshot %s for " + "consistency group: %s" % (group_snapshot.id, group_snapshot)) + + try: + snapshots_model_update = self._delete_group_snapshot(snapshots) + except Exception as err: + msg = ("Delete cg snapshots failed. " + "group snapshot id: %s, reason is %s") % (group_snapshot.id, err) + LOG.error(msg) + raise exception.CinderException(msg) + + model_update = {'status': 'deleted'} + return model_update, snapshots_model_update + + def _delete_group_snapshot(self, snapshots): + """Delete all snapshots in snapshot group""" + snapshots_model_update = [] + for snapshot in snapshots: + snapshot_model_update = { + 'id': snapshot.id, + 'status': 'deleted' + } + snapshots_model_update.append(snapshot_model_update) + snapshot_name = self._get_snapshot_name(snapshot) + + if not self._check_snapshot_exist(snapshot.volume, snapshot): + LOG.info("snapshot %s not exist in array, " + "don't need to delete, try next one" % snapshot_name) + continue + self.client.delete_snapshot(snapshot_name=snapshot_name) + LOG.info("Delete snapshot successfully," + " the deleted snapshots is %s" % snapshot_name) + + return snapshots_model_update + class DSWAREDriver(DSWAREBaseDriver): def get_volume_stats(self, refresh=False): @@ -717,7 +1244,7 @@ def initialize_connection(self, volume, connector): vol_wwn = volume_info.get('wwn') by_id_path = "/dev/disk/by-id/" + "wwn-0x%s" % vol_wwn properties = {'device_path': by_id_path} - import time + LOG.info("Wait %(t)s second(s) for scanning the target device %(dev)s." % {"t": self.configuration.scan_device_timeout, "dev": by_id_path}) diff --git a/Cinder/Newton/fs_client.py b/Cinder/Newton/fs_client.py index 234d7f1..09d9581 100644 --- a/Cinder/Newton/fs_client.py +++ b/Cinder/Newton/fs_client.py @@ -14,16 +14,16 @@ # under the License. import json + import requests import six -import time +from oslo_log import log as logging from requests.adapters import HTTPAdapter from cinder import exception from cinder.i18n import _ from cinder.volume.drivers.fusionstorage import constants -from oslo_log import log as logging LOG = logging.getLogger(__name__) @@ -43,7 +43,8 @@ def __init__(self, fs_address, fs_user, fs_password, **extend_conf): self.session = None self.token = None self.version = None - mutual_authentication = extend_conf.get("mutual_authentication") + self.esn = None + mutual_authentication = extend_conf.get("mutual_authentication", {}) self.init_http_head(mutual_authentication) LOG.warning("Suppressing requests library SSL Warnings") @@ -147,6 +148,13 @@ def get_version(self): if result.get("currentVersion"): self.version = result["currentVersion"] + def get_esn(self): + url = "/cluster/sn" + result = self.call(url, "get") + self._assert_rest_result(result, _('Get cluster esn error.')) + self.esn = result.get("sn") + return self.esn + def login(self): self.get_version() url = '/sec/login' @@ -160,6 +168,7 @@ def login(self): self.session.headers.update({ "x-auth-token": self.token }) + self.get_esn() def logout(self): url = '/sec/logout' @@ -264,6 +273,15 @@ def query_volume_by_name(self, vol_name): result, _("Query volume by name session error")) return result.get('lunDetailInfo') + def query_volume_by_name_v2(self, vol_name): + url = '/api/v2/block_service/volumes?name=' + vol_name + result = self.call(url, 'GET', get_system_time=True) + if result.get('errorCode') in constants.VOLUME_NOT_EXIST: + return {} + self._assert_rest_result( + result, _("Query volume by name session error")) + return result.get('data', {}) + def query_volume_by_id(self, vol_id): url = 'v1.3/volume/queryById?volId=' + vol_id result = self.call(url, 'GET', get_version=True) @@ -746,3 +764,57 @@ def get_iscsi_links_info(self, iscsi_link_count, pool_list): return [iscsi["ip"] for iscsi in result.get("iscsiLinks", []) if iscsi.get("ip")] + + def create_lun_migration(self, src_lun_id, dst_lun_id, speed=2): + url = "/api/v2/block_service/lun_migration" + params = { + "parent_id": src_lun_id, + "target_lun_id": dst_lun_id, + "speed": speed, + "work_mode": 0 + } + result = self.call(url, "POST", params, get_system_time=True) + self._assert_rest_result(result, + _("create lun migration task error.")) + + def get_lun_migration_task_by_id(self, src_lun_id): + url = "/api/v2/block_service/lun_migration" + params = { + "id": src_lun_id + } + result = self.call(url, "GET", params, get_system_time=True) + self._assert_rest_result(result, + _("get lun migration task error.")) + return result.get('data', {}) + + def delete_lun_migration(self, src_lun_id): + url = "/api/v2/block_service/lun_migration" + params = { + 'id': src_lun_id + } + result = self.call(url, "DELETE", params, get_system_time=True) + self._assert_rest_result(result, + _("Delete lun migration task error.")) + + def get_volume_snapshot(self, volume_name): + url = "/volume/snapshot/list" + params = { + 'volName': volume_name, + 'batchNum': 1, + 'batchLimit': 10 + } + result = self.call(url, "POST", params) + return result.get('snapshotList', []) + + def create_consistent_snapshot_by_name(self, snapshot_group_list): + url = "/api/v2/block_service/consistency_snapshots" + result = self.call(url, "POST", snapshot_group_list, get_system_time=True) + self._assert_rest_result(result, _("create consistent_snapshot error.")) + return result.get('data', []) + + def create_full_volume_from_snapshot(self, vol_name, snapshot_name): + url = '/api/v2/block_service/createFullVolumeFromSnap' + params = {"snap_name_src": snapshot_name, "volume_name_dst": vol_name} + result = self.call(url, "POST", params, get_system_time=True) + self._assert_rest_result( + result, _("create full volume from snap fails")) diff --git a/Cinder/Newton/fs_qos.py b/Cinder/Newton/fs_qos.py index 731c45e..286dbc3 100644 --- a/Cinder/Newton/fs_qos.py +++ b/Cinder/Newton/fs_qos.py @@ -29,7 +29,11 @@ def __init__(self, client): def add(self, qos, vol_name): localtime = time.strftime('%Y%m%d%H%M%S', time.localtime()) - qos_name = constants.QOS_PREFIX + localtime + # QoS policy name. The value contains 1 to 63 characters. + # So we intercept volume_name Ensure that the length does not exceed 63 + vol_str = vol_name[-constants.QOS_MAX_INTERCEPT_LENGTH::] \ + if len(vol_name) >= constants.QOS_MAX_INTERCEPT_LENGTH else vol_name + qos_name = constants.QOS_PREFIX + localtime + '_' + vol_str self.client.create_qos(qos_name, qos) try: self.client.associate_qos_with_volume(vol_name, qos_name) diff --git a/Cinder/Newton/fs_utils.py b/Cinder/Newton/fs_utils.py index b89f582..f9a95d6 100644 --- a/Cinder/Newton/fs_utils.py +++ b/Cinder/Newton/fs_utils.py @@ -16,11 +16,11 @@ import datetime import hashlib import ipaddress -import pytz import random -import six import time +import pytz +import six from oslo_log import log as logging from oslo_service import loopingcall from oslo_utils import units @@ -756,3 +756,9 @@ def get_iscsi_info_from_storage(manager_ips, use_ipv6, valid_iscsi_ips, valid_node_ips): return _get_target_info(manager_ips, use_ipv6, valid_iscsi_ips, valid_node_ips) + + +def encode_name(my_uuid): + encoded_name = hashlib.md5(my_uuid.encode('utf-8')).hexdigest() + target_lun_prefix = my_uuid.split('-')[0] + '-' + return target_lun_prefix + encoded_name diff --git a/Cinder/Ocata/constants.py b/Cinder/Ocata/constants.py index 5f46ece..b4cb843 100644 --- a/Cinder/Ocata/constants.py +++ b/Cinder/Ocata/constants.py @@ -45,6 +45,14 @@ CONF_STORAGE_CERT_FILEPATH = "storage_cert_filepath" CONF_STORAGE_SSL_TWO_WAY_AUTH = "storage_ssl_two_way_auth" +DEFAULT_WAIT_INTERVAL = 5 +MIGRATION_COMPLETE = 76 +MIGRATION_FAULT = 74 +STATUS_HEALTH = 1 +STATUS_VOLUME_READY = 27 +MIGRATION_WAIT_INTERVAL = 5 +DEFAULT_WAIT_TIMEOUT = 3600 * 24 * 30 + QOS_MUST_SET = ["maxIOPS", "maxMBPS"] QOS_KEYS = ["maxIOPS", "maxMBPS", "total_iops_sec", "total_bytes_sec"] QOS_SCHEDULER_KEYS = ["scheduleType", "startDate", "startTime", @@ -53,6 +61,7 @@ QOS_SCHEDULER_DEFAULT_TYPE = "0" QOS_SCHEDULER_WEEK_TYPE = "3" QOS_SUPPORT_SCHEDULE_VERSION = "8.0" +QOS_MAX_INTERCEPT_LENGTH = 36 SECONDS_OF_DAY = 24 * 60 * 60 SECONDS_OF_HOUR = 60 * 60 SNAPSHOT_HEALTH_STATUS = ( @@ -80,3 +89,9 @@ HOSTGROUP_ALREADY_EXIST = 50157044 INITIATOR_ALREADY_EXIST = 50155102 INITIATOR_IN_HOST = 50157021 + +CHECK_CLONED_INTERVAL = 2 +REST_VOLUME_CREATING_STATUS = 15 +REST_VOLUME_DUPLICATE_VOLUME = 6 +REST_VOLUME_CREATE_SUCCESS_STATUS = 0 +CLONE_VOLUME_TIMEOUT = 3600 * 24 * 30 diff --git a/Cinder/Ocata/dsware.py b/Cinder/Ocata/dsware.py index 8c1b16e..3716749 100644 --- a/Cinder/Ocata/dsware.py +++ b/Cinder/Ocata/dsware.py @@ -14,16 +14,22 @@ # under the License. import json - +import time +import uuid from multiprocessing import Lock + +import six from oslo_config import cfg from oslo_log import log as logging +from oslo_utils import excutils from oslo_utils import units +from oslo_service import loopingcall from cinder import coordination from cinder import exception from cinder.i18n import _ from cinder import interface +from cinder import objects from cinder.volume import driver from cinder.volume.drivers.fusionstorage import constants from cinder.volume.drivers.fusionstorage import fs_client @@ -101,6 +107,9 @@ cfg.StrOpt('storage_key_filepath', default='', help='Client key directory.'), + cfg.BoolOpt('full_clone', + default=False, + help='Whether use full clone.'), ] CONF = cfg.CONF @@ -109,7 +118,7 @@ @interface.volumedriver class DSWAREBaseDriver(driver.VolumeDriver): - VERSION = '2.5.RC4' + VERSION = "2.6.1" CI_WIKI_NAME = 'Huawei_FusionStorage_CI' def __init__(self, *args, **kwargs): @@ -206,6 +215,7 @@ def _update_single_pool_info_status(self, pool_info): "total_capacity_gb": capacity['total_capacity_gb'], "free_capacity_gb": capacity['free_capacity_gb'], "provisioned_capacity_gb": capacity['provisioned_capacity_gb'], + "location_info": self.client.esn, "QoS_support": True, 'multiattach': True, "thin_provisioning_support": True, @@ -243,8 +253,12 @@ def _raise_exception(msg): raise exception.VolumeBackendAPIException(data=msg) def _get_pool_id(self, volume): - pool_id_list = [] pool_name = volume_utils.extract_host(volume.host, level='pool') + pool_id = self._get_pool_id_by_name(pool_name) + return pool_id + + def _get_pool_id_by_name(self, pool_name): + pool_id_list = [] all_pools = self.client.query_pool_info() for pool in all_pools: if pool_name == pool['poolName']: @@ -359,29 +373,111 @@ def _expand_volume_when_create(self, vol_name, vol_size): self.client.delete_volume(vol_name=vol_name) raise + def _check_create_cloned_volume_finish(self, new_volume_name, start_time): + LOG.debug('Loopcall: _check_create_cloned_volume_finish(), ' + 'volume-name %s', + new_volume_name) + current_volume = self.client.query_volume_by_name(new_volume_name) + + if current_volume and 'status' in current_volume: + status = int(current_volume['status']) + LOG.debug('Wait clone volume %(volume_name)s, status:%(status)s.', + {"volume_name": new_volume_name, + "status": status}) + if status in {constants.REST_VOLUME_CREATING_STATUS, + constants.REST_VOLUME_DUPLICATE_VOLUME}: + LOG.debug(_("Volume %s is cloning"), new_volume_name) + elif status == constants.REST_VOLUME_CREATE_SUCCESS_STATUS: + raise loopingcall.LoopingCallDone(retvalue=True) + else: + msg = _('Clone volume %(new_volume_name)s failed, ' + 'the status is:%(status)s.') + LOG.error(msg, {'new_volume_name': new_volume_name, + 'status': status}) + raise loopingcall.LoopingCallDone(retvalue=False) + + max_time_out = constants.CLONE_VOLUME_TIMEOUT + current_time = time.time() + if (current_time - start_time) > max_time_out: + msg = _('Dsware clone volume time out. ' + 'Volume: %(new_volume_name)s, status: %(status)s') + LOG.error(msg, {'new_volume_name': new_volume_name, + 'status': current_volume['status']}) + raise loopingcall.LoopingCallDone(retvalue=False) + else: + LOG.warning(_('Can not find volume %s'), new_volume_name) + msg = "DSWARE clone volume failed:volume can not find from dsware" + LOG.error(msg) + raise loopingcall.LoopingCallDone(retvalue=False) + + def _wait_for_create_cloned_volume_finish_timer(self, new_volume_name): + timer = loopingcall.FixedIntervalLoopingCall( + self._check_create_cloned_volume_finish, + new_volume_name, time.time()) + LOG.debug('Calling _check_create_cloned_volume_finish: volume-name %s', + new_volume_name) + ret = timer.start(interval=constants.CHECK_CLONED_INTERVAL).wait() + timer.stop() + return ret + def create_volume_from_snapshot(self, volume, snapshot): vol_name = self._get_vol_name(volume) snapshot_name = self._get_snapshot_name(snapshot) vol_size = volume.size + pool_id = self._get_pool_id(volume) if not self._check_snapshot_exist(snapshot.volume, snapshot): msg = _("Snapshot: %(name)s does not exist!" ) % {"name": snapshot_name} self._raise_exception(msg) - elif self._check_volume_exist(volume): + if self._check_volume_exist(volume): msg = _("Volume: %(vol_name)s already exists!" ) % {'vol_name': vol_name} self._raise_exception(msg) - else: - vol_size *= units.Ki + + vol_size *= units.Ki + if not self.configuration.full_clone: self.client.create_volume_from_snapshot( snapshot_name=snapshot_name, vol_name=vol_name, vol_size=vol_size) - self._add_qos_to_volume(volume, vol_name) - self._expand_volume_when_create(vol_name, vol_size) - result = self.client.query_volume_by_name(vol_name=vol_name) - return ({"metadata": {'lun_wwn': result.get('wwn')}} - if result else {}) + else: + self.client.create_volume(vol_name, vol_size, pool_id) + self.client.create_full_volume_from_snapshot(vol_name, + snapshot_name) + ret = self._wait_for_create_cloned_volume_finish_timer(vol_name) + if not ret: + msg = _('Create full volume %s from snap failed') % vol_name + self._raise_exception(msg) + self._add_qos_to_volume(volume, vol_name) + self._expand_volume_when_create(vol_name, vol_size) + result = self.client.query_volume_by_name(vol_name=vol_name) + return ({"metadata": {'lun_wwn': result.get('wwn')}} + if result else {}) + + def _create_volume_from_volume_full_clone(self, vol_name, vol_size, pool_id, + src_vol_name): + tmp_snap_name = "temp" + src_vol_name + "clone" + vol_name + + self.client.create_snapshot(tmp_snap_name, src_vol_name) + try: + self.client.create_volume(vol_name, vol_size, pool_id) + except Exception as err: + self.client.delete_snapshot(tmp_snap_name) + raise err + + try: + self.client.create_full_volume_from_snapshot( + vol_name, tmp_snap_name) + except Exception as err: + self.client.delete_snapshot(tmp_snap_name) + self.client.delete_volume(vol_name) + raise err + + ret = self._wait_for_create_cloned_volume_finish_timer(vol_name) + if not ret: + msg = _('Create full volume %s from snap failed') % vol_name + self._raise_exception(msg) + self.client.delete_snapshot(tmp_snap_name) def create_cloned_volume(self, volume, src_volume): vol_name = self._get_vol_name(volume) @@ -394,15 +490,22 @@ def create_cloned_volume(self, volume, src_volume): msg = _("Volume: %(vol_name)s does not exist!" ) % {"vol_name": src_vol_name} self._raise_exception(msg) - else: + + if not self.configuration.full_clone: self.client.create_volume_from_volume( vol_name=vol_name, vol_size=vol_size, src_vol_name=src_vol_name) - self._add_qos_to_volume(volume, vol_name) - self._expand_volume_when_create(vol_name, vol_size) - result = self.client.query_volume_by_name(vol_name=vol_name) - return ({"metadata": {'lun_wwn': result.get('wwn')}} - if result else {}) + else: + pool_id = self._get_pool_id(volume) + self._create_volume_from_volume_full_clone( + vol_name=vol_name, vol_size=vol_size, pool_id=pool_id, + src_vol_name=src_vol_name) + + self._add_qos_to_volume(volume, vol_name) + self._expand_volume_when_create(vol_name, vol_size) + result = self.client.query_volume_by_name(vol_name=vol_name) + return ({"metadata": {'lun_wwn': result.get('wwn')}} + if result else {}) def create_snapshot(self, snapshot): snapshot_name = self._get_snapshot_name(snapshot) @@ -577,12 +680,13 @@ def unmanage_snapshot(self, snapshot): def _check_need_changes_for_retype(self, volume, new_type, host, vol_name): before_change = {} after_change = {} - if volume.host != host["host"]: - msg = (_("Do not support retype between different host. Volume's " + migrate = False + if volume.host != host.get("host"): + migrate = True + msg = (_("retype support migration between different host. Volume's " "host: %(vol_host)s, host's host: %(host)s") - % {"vol_host": volume.host, "host": host['host']}) - LOG.error(msg) - raise exception.InvalidInput(msg) + % {"vol_host": volume.host, "host": host.get("host")}) + LOG.info(msg) old_opts = fs_utils.get_volume_specs(self.client, vol_name) new_opts = fs_utils.get_volume_type_params(new_type, self.client) @@ -592,7 +696,7 @@ def _check_need_changes_for_retype(self, volume, new_type, host, vol_name): change_opts = {"old_opts": before_change, "new_opts": after_change} - return change_opts + return migrate, change_opts def retype(self, context, volume, new_type, diff, host): LOG.info("Retype volume: %(vol)s, new_type: %(new_type)s, " @@ -603,13 +707,177 @@ def retype(self, context, volume, new_type, diff, host): "host": host}) vol_name = self._get_vol_name(volume) - change_opts = self._check_need_changes_for_retype( + migrate, change_opts = self._check_need_changes_for_retype( volume, new_type, host, vol_name) + if migrate: + src_lun_id = self._check_volume_exist_on_array(volume) + LOG.debug("Begin to migrate LUN(id: %(lun_id)s) with " + "change %(change_opts)s.", + {"lun_id": src_lun_id, "change_opts": change_opts}) + moved = self._migrate_volume(volume, host, src_lun_id) + if not moved: + LOG.warning("Storage-assisted migration failed during " + "retype.") + return False, None self._change_lun(vol_name, change_opts.get("new_opts"), change_opts.get("old_opts")) return True, None + def migrate_volume(self, context, volume, host): + """Migrate a volume within the same array.""" + LOG.info("Migrate Volume:%(volume)s, host:%(host)s", + {"volume": volume.id, + "host": host}) + src_lun_id = self._check_volume_exist_on_array(volume) + + moved = self._migrate_volume(volume, host, src_lun_id) + return moved, {} + + def _create_dst_volume(self, volume, host): + pool_name = host['capabilities']['pool_name'] + pool_id = self._get_pool_id_by_name(pool_name) + vol_name = fs_utils.encode_name(six.text_type(uuid.uuid4())) + vol_size = volume.size + vol_size *= units.Ki + self.client.create_volume( + pool_id=pool_id, vol_name=vol_name, vol_size=vol_size) + + result = self.client.query_volume_by_name_v2(vol_name=vol_name) + dst_lun_id = result.get('id') + self._wait_volume_ready(vol_name) + return vol_name, dst_lun_id + + def _migrate_volume(self, volume, host, src_lun_id): + """create migration task and wait for task done""" + if not self._check_migration_valid(host): + return False + + vol_name, dst_lun_id = self._create_dst_volume(volume, host) + + try: + self.client.create_lun_migration(src_lun_id, dst_lun_id) + + def _is_lun_migration_complete(): + return self._is_lun_migration_complete(src_lun_id, dst_lun_id) + + wait_interval = constants.MIGRATION_WAIT_INTERVAL + fs_utils.wait_for_condition(_is_lun_migration_complete, + wait_interval, + constants.DEFAULT_WAIT_TIMEOUT) + # Clean up if migration failed. + except Exception as ex: + raise exception.VolumeBackendAPIException(data=ex) + finally: + if self._is_lun_migration_exist(src_lun_id, dst_lun_id): + self.client.delete_lun_migration(src_lun_id) + self._delete_lun_with_check(vol_name) + + LOG.info("Migrate lun %s successfully.", src_lun_id) + return True + + def _delete_lun_with_check(self, vol_name): + if self.client.query_volume_by_name(vol_name): + # migrate_dst_lun don't have qos, so don't + # need to remove qos, Delete the LUN directly. + self.client.delete_volume(vol_name) + + def _is_lun_migration_complete(self, src_lun_id, dst_lun_id): + result = self.client.get_lun_migration_task_by_id(src_lun_id) + found_migration_task = False + if not result: + return False + + if (str(src_lun_id) == result.get('parent_id') and + str(dst_lun_id) == result.get('target_lun_id')): + found_migration_task = True + if constants.MIGRATION_COMPLETE == result.get('running_status'): + return True + if constants.MIGRATION_FAULT == result.get('running_status'): + msg = _("Lun migration error. " + "the migration task running_status is abnormal") + LOG.error(msg) + raise exception.VolumeBackendAPIException(data=msg) + + if not found_migration_task: + err_msg = _("lun migration error, Cannot find migration task.") + LOG.error(err_msg) + raise exception.VolumeBackendAPIException(data=err_msg) + + return False + + def _is_lun_migration_exist(self, src_lun_id, dst_lun_id): + try: + result = self.client.get_lun_migration_task_by_id(src_lun_id) + except Exception: + LOG.error("Get LUN migration error.") + return False + + if (str(src_lun_id) == result.get('parent_id') and + str(dst_lun_id) == result.get('target_lun_id')): + return True + return False + + def _wait_volume_ready(self, vol_name): + wait_interval = constants.DEFAULT_WAIT_INTERVAL + + def _volume_ready(): + result = self.client.query_volume_by_name_v2(vol_name) + if not result: + return False + + if (result.get('health_status') == constants.STATUS_HEALTH + and result.get('running_status') == constants.STATUS_VOLUME_READY): + return True + return False + + fs_utils.wait_for_condition(_volume_ready, + wait_interval, + wait_interval * 10) + + def _check_migration_valid(self, host): + if 'pool_name' not in host.get('capabilities', {}): + return False + + target_device = host.get('capabilities', {}).get('location_info') + + # Source and destination should be on same array. + if target_device != self.client.esn: + LOG.error("lun migration error, " + "Source and destination should be on same array") + return False + + pool_name = host.get('capabilities', {}).get('pool_name', '') + if len(pool_name) == 0: + LOG.error("lun migration error, pool_name not exists") + return False + + return True + + def _check_volume_exist_on_array(self, volume): + volume_name = self._get_vol_name(volume) + result = self._check_volume_exist(volume) + if not result: + msg = _("Volume %s does not exist on the array." + ) % volume.id + self._raise_exception(msg) + + lun_wwn = result.get('wwn') + if not lun_wwn: + LOG.debug("No LUN WWN recorded for volume %s.", volume.id) + + lun_id = result.get('volId') + if not lun_id: + msg = _("Volume %s does not exist on the array." + ) % volume.id + self._raise_exception(msg) + + if self.client.get_volume_snapshot(volume_name): + msg = _("Volume %s which have snapshot cannot do lun migration" + ) % volume.id + self._raise_exception(msg) + return lun_id + def _rollback_snapshot(self, vol_name, snap_name): def _snapshot_rollback_finish(): snapshot_info = self.client.get_snapshot_info_by_name(snap_name) @@ -665,6 +933,265 @@ def ensure_export(self, context, volume): def remove_export(self, context, volume): pass + def create_group(self, context, group): + """Creates a group. Driver only need to return state""" + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.create_consistencygroup(context, group) + + def create_consistencygroup(self, context, group): + """Creates a group. Driver only need to return state""" + LOG.info("Create group successfully") + return {'status': 'available'} + + def update_group(self, context, group, + add_volumes=None, remove_volumes=None): + """ + The volume manager will adds/removes the volume to/from the + group in the database, if need add_volumes, Driver just need + to check whether volume is in array or not + """ + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.update_consistencygroup( + context, group, add_volumes, remove_volumes) + + def update_consistencygroup(self, context, group, + add_volumes=None, remove_volumes=None): + """ + The volume manager will adds/removes the volume to/from the + group in the database, if need add_volumes, Driver just need + to check whether volume is in array or not + """ + if add_volumes is None: + add_volumes = [] + for volume in add_volumes: + try: + self._check_volume_exist_on_array(volume) + except Exception: + with excutils.save_and_reraise_exception(): + LOG.error("The add_volume %s not exist on array" % volume.id) + + model_update = {'status': 'available'} + LOG.info("Update group successfully") + return model_update, None, None + + def delete_group(self, context, group, volumes): + """delete the group, Driver need to delete relation lun on array""" + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.delete_consistencygroup(context, group, volumes) + + def delete_consistencygroup(self, context, group, volumes): + """delete the group, Driver need to delete relation lun on array""" + volumes_model_update = [] + model_update = {'status': 'deleted'} + for volume in volumes: + volume_model_update = {'id': volume.id} + try: + self.delete_volume(volume) + except Exception: + LOG.error('Delete volume %s failed.' % volume) + volume_model_update.update({'status': 'error_deleting'}) + else: + volume_model_update.update({'status': 'deleted'}) + + LOG.info('Deleted volume %s successfully' % volume) + volumes_model_update.append(volume_model_update) + + LOG.info("Delete group successfully") + return model_update, volumes_model_update + + def create_group_from_src(self, context, group, volumes, + group_snapshot=None, snapshots=None, + source_group=None, source_vols=None): + """ + create group from group or group-snapshot, + Driver need to create volume from volume or snapshot + """ + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.create_consistencygroup_from_src(context, group, volumes, + group_snapshot, snapshots, + source_group, source_vols) + + def create_consistencygroup_from_src(self, context, group, volumes, + group_snapshot=None, snapshots=None, + source_group=None, source_vols=None): + """ + create group from group or group-snapshot, + Driver need to create volume from volume or snapshot + """ + model_update = self.create_consistencygroup(context, group) + volumes_model_update = [] + delete_snapshots = False + + if not snapshots and source_vols: + snapshots = [] + for src_volume in source_vols: + volume_kwargs = { + 'id': src_volume.id, + '_name_id': None, + 'host': src_volume.host + } + snapshot_kwargs = { + 'id': six.text_type(uuid.uuid4()), + 'volume': objects.Volume(**volume_kwargs) + } + snapshots.append(objects.Snapshot(**snapshot_kwargs)) + + self._create_group_snapshot(snapshots) + delete_snapshots = True + + if snapshots: + volumes_model_update = self._create_volume_from_group_snapshot( + volumes, snapshots, delete_snapshots) + + if delete_snapshots: + self._delete_group_snapshot(snapshots) + + LOG.info("Create group from src successfully") + return model_update, volumes_model_update + + def _create_volume_from_group_snapshot(self, volumes, snapshots, delete_snapshots): + volumes_model_update = [] + added_volumes = [] + for i, volume in enumerate(volumes): + try: + vol_model_update = self.create_volume_from_snapshot( + volume, snapshots[i]) + vol_model_update.update({'id': volume.id}) + volumes_model_update.append(vol_model_update) + added_volumes.append(volume) + except Exception: + LOG.error("Create volume from snapshot error, Delete the newly created lun.") + with excutils.save_and_reraise_exception(): + self._delete_added_volume_snapshots( + added_volumes, snapshots, delete_snapshots) + + return volumes_model_update + + def _delete_added_volume_snapshots( + self, added_volumes, snapshots, delete_snapshots): + if delete_snapshots: + self._delete_group_snapshot(snapshots) + for add_volume in added_volumes: + vol_name = self._get_vol_name(add_volume) + self.fs_qos.remove(vol_name) + self.client.delete_volume(vol_name=vol_name) + LOG.info("delete storage newly added " + "volume success, volume is %s" % add_volume.id) + + def create_group_snapshot(self, context, group_snapshot, snapshots): + """Create group snapshot.""" + if not volume_utils.is_group_a_cg_snapshot_type(group_snapshot): + LOG.info("group_snapshot's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.create_cgsnapshot(context, group_snapshot, snapshots) + + def create_cgsnapshot(self, context, group_snapshot, snapshots): + """Create group snapshot.""" + LOG.info('Create group snapshot for group: %(group_snapshot)s', + {'group_snapshot': group_snapshot}) + + try: + snapshots_model_update = self._create_group_snapshot(snapshots) + except Exception as err: + msg = ("Create group snapshots failed. " + "Group snapshot id: %s. Reason is %s") % (group_snapshot.id, err) + LOG.error(msg) + raise exception.CinderException(msg) + + model_update = {'status': 'available'} + return model_update, snapshots_model_update + + def _create_group_snapshot(self, snapshots): + """Generate snapshots for all volumes in the group.""" + snapshots_model_update = [] + snapshot_group_list = [] + + for snapshot in snapshots: + snapshot_name = self._get_snapshot_name(snapshot) + vol_name = self._get_vol_name(snapshot.volume) + snapshot_group_list.append({ + 'name': snapshot_name, + 'sub_type': '0', + 'volume_name': vol_name + }) + snapshot_model_update = { + 'id': snapshot.id, + 'status': 'available', + } + snapshots_model_update.append(snapshot_model_update) + try: + self.client.create_consistent_snapshot_by_name(snapshot_group_list) + except Exception: + with excutils.save_and_reraise_exception(): + LOG.error("Create consistent snapshot failed, " + "snapshot_group_list is %s" % snapshot_group_list) + + return snapshots_model_update + + def delete_group_snapshot(self, context, group_snapshot, snapshots): + """Delete group snapshot.""" + if not volume_utils.is_group_a_cg_snapshot_type(group_snapshot): + LOG.info("group_snapshot's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.delete_cgsnapshot(context, group_snapshot, snapshots) + + def delete_cgsnapshot(self, context, group_snapshot, snapshots): + """Delete group snapshot.""" + LOG.info("Delete group_snapshot %s for " + "consistency group: %s" % (group_snapshot.id, group_snapshot)) + + try: + snapshots_model_update = self._delete_group_snapshot(snapshots) + except Exception as err: + msg = ("Delete cg snapshots failed. " + "group snapshot id: %s, reason is %s") % (group_snapshot.id, err) + LOG.error(msg) + raise exception.CinderException(msg) + + model_update = {'status': 'deleted'} + return model_update, snapshots_model_update + + def _delete_group_snapshot(self, snapshots): + """Delete all snapshots in snapshot group""" + snapshots_model_update = [] + for snapshot in snapshots: + snapshot_model_update = { + 'id': snapshot.id, + 'status': 'deleted' + } + snapshots_model_update.append(snapshot_model_update) + snapshot_name = self._get_snapshot_name(snapshot) + + if not self._check_snapshot_exist(snapshot.volume, snapshot): + LOG.info("snapshot %s not exist in array, " + "don't need to delete, try next one" % snapshot_name) + continue + self.client.delete_snapshot(snapshot_name=snapshot_name) + LOG.info("Delete snapshot successfully," + " the deleted snapshots is %s" % snapshot_name) + + return snapshots_model_update + class DSWAREDriver(DSWAREBaseDriver): def get_volume_stats(self, refresh=False): @@ -717,7 +1244,7 @@ def initialize_connection(self, volume, connector): vol_wwn = volume_info.get('wwn') by_id_path = "/dev/disk/by-id/" + "wwn-0x%s" % vol_wwn properties = {'device_path': by_id_path} - import time + LOG.info("Wait %(t)s second(s) for scanning the target device %(dev)s." % {"t": self.configuration.scan_device_timeout, "dev": by_id_path}) diff --git a/Cinder/Ocata/fs_client.py b/Cinder/Ocata/fs_client.py index 234d7f1..09d9581 100644 --- a/Cinder/Ocata/fs_client.py +++ b/Cinder/Ocata/fs_client.py @@ -14,16 +14,16 @@ # under the License. import json + import requests import six -import time +from oslo_log import log as logging from requests.adapters import HTTPAdapter from cinder import exception from cinder.i18n import _ from cinder.volume.drivers.fusionstorage import constants -from oslo_log import log as logging LOG = logging.getLogger(__name__) @@ -43,7 +43,8 @@ def __init__(self, fs_address, fs_user, fs_password, **extend_conf): self.session = None self.token = None self.version = None - mutual_authentication = extend_conf.get("mutual_authentication") + self.esn = None + mutual_authentication = extend_conf.get("mutual_authentication", {}) self.init_http_head(mutual_authentication) LOG.warning("Suppressing requests library SSL Warnings") @@ -147,6 +148,13 @@ def get_version(self): if result.get("currentVersion"): self.version = result["currentVersion"] + def get_esn(self): + url = "/cluster/sn" + result = self.call(url, "get") + self._assert_rest_result(result, _('Get cluster esn error.')) + self.esn = result.get("sn") + return self.esn + def login(self): self.get_version() url = '/sec/login' @@ -160,6 +168,7 @@ def login(self): self.session.headers.update({ "x-auth-token": self.token }) + self.get_esn() def logout(self): url = '/sec/logout' @@ -264,6 +273,15 @@ def query_volume_by_name(self, vol_name): result, _("Query volume by name session error")) return result.get('lunDetailInfo') + def query_volume_by_name_v2(self, vol_name): + url = '/api/v2/block_service/volumes?name=' + vol_name + result = self.call(url, 'GET', get_system_time=True) + if result.get('errorCode') in constants.VOLUME_NOT_EXIST: + return {} + self._assert_rest_result( + result, _("Query volume by name session error")) + return result.get('data', {}) + def query_volume_by_id(self, vol_id): url = 'v1.3/volume/queryById?volId=' + vol_id result = self.call(url, 'GET', get_version=True) @@ -746,3 +764,57 @@ def get_iscsi_links_info(self, iscsi_link_count, pool_list): return [iscsi["ip"] for iscsi in result.get("iscsiLinks", []) if iscsi.get("ip")] + + def create_lun_migration(self, src_lun_id, dst_lun_id, speed=2): + url = "/api/v2/block_service/lun_migration" + params = { + "parent_id": src_lun_id, + "target_lun_id": dst_lun_id, + "speed": speed, + "work_mode": 0 + } + result = self.call(url, "POST", params, get_system_time=True) + self._assert_rest_result(result, + _("create lun migration task error.")) + + def get_lun_migration_task_by_id(self, src_lun_id): + url = "/api/v2/block_service/lun_migration" + params = { + "id": src_lun_id + } + result = self.call(url, "GET", params, get_system_time=True) + self._assert_rest_result(result, + _("get lun migration task error.")) + return result.get('data', {}) + + def delete_lun_migration(self, src_lun_id): + url = "/api/v2/block_service/lun_migration" + params = { + 'id': src_lun_id + } + result = self.call(url, "DELETE", params, get_system_time=True) + self._assert_rest_result(result, + _("Delete lun migration task error.")) + + def get_volume_snapshot(self, volume_name): + url = "/volume/snapshot/list" + params = { + 'volName': volume_name, + 'batchNum': 1, + 'batchLimit': 10 + } + result = self.call(url, "POST", params) + return result.get('snapshotList', []) + + def create_consistent_snapshot_by_name(self, snapshot_group_list): + url = "/api/v2/block_service/consistency_snapshots" + result = self.call(url, "POST", snapshot_group_list, get_system_time=True) + self._assert_rest_result(result, _("create consistent_snapshot error.")) + return result.get('data', []) + + def create_full_volume_from_snapshot(self, vol_name, snapshot_name): + url = '/api/v2/block_service/createFullVolumeFromSnap' + params = {"snap_name_src": snapshot_name, "volume_name_dst": vol_name} + result = self.call(url, "POST", params, get_system_time=True) + self._assert_rest_result( + result, _("create full volume from snap fails")) diff --git a/Cinder/Ocata/fs_qos.py b/Cinder/Ocata/fs_qos.py index 731c45e..286dbc3 100644 --- a/Cinder/Ocata/fs_qos.py +++ b/Cinder/Ocata/fs_qos.py @@ -29,7 +29,11 @@ def __init__(self, client): def add(self, qos, vol_name): localtime = time.strftime('%Y%m%d%H%M%S', time.localtime()) - qos_name = constants.QOS_PREFIX + localtime + # QoS policy name. The value contains 1 to 63 characters. + # So we intercept volume_name Ensure that the length does not exceed 63 + vol_str = vol_name[-constants.QOS_MAX_INTERCEPT_LENGTH::] \ + if len(vol_name) >= constants.QOS_MAX_INTERCEPT_LENGTH else vol_name + qos_name = constants.QOS_PREFIX + localtime + '_' + vol_str self.client.create_qos(qos_name, qos) try: self.client.associate_qos_with_volume(vol_name, qos_name) diff --git a/Cinder/Ocata/fs_utils.py b/Cinder/Ocata/fs_utils.py index 8b9ae78..0856038 100644 --- a/Cinder/Ocata/fs_utils.py +++ b/Cinder/Ocata/fs_utils.py @@ -16,11 +16,11 @@ import datetime import hashlib import ipaddress -import pytz import random -import six import time +import pytz +import six from oslo_log import log as logging from oslo_service import loopingcall from oslo_utils import units @@ -758,3 +758,9 @@ def get_iscsi_info_from_storage(manager_ips, use_ipv6, valid_iscsi_ips, valid_node_ips): return _get_target_info(manager_ips, use_ipv6, valid_iscsi_ips, valid_node_ips) + + +def encode_name(my_uuid): + encoded_name = hashlib.md5(my_uuid.encode('utf-8')).hexdigest() + target_lun_prefix = my_uuid.split('-')[0] + '-' + return target_lun_prefix + encoded_name diff --git a/Cinder/Pike/constants.py b/Cinder/Pike/constants.py index 5f46ece..b4cb843 100644 --- a/Cinder/Pike/constants.py +++ b/Cinder/Pike/constants.py @@ -45,6 +45,14 @@ CONF_STORAGE_CERT_FILEPATH = "storage_cert_filepath" CONF_STORAGE_SSL_TWO_WAY_AUTH = "storage_ssl_two_way_auth" +DEFAULT_WAIT_INTERVAL = 5 +MIGRATION_COMPLETE = 76 +MIGRATION_FAULT = 74 +STATUS_HEALTH = 1 +STATUS_VOLUME_READY = 27 +MIGRATION_WAIT_INTERVAL = 5 +DEFAULT_WAIT_TIMEOUT = 3600 * 24 * 30 + QOS_MUST_SET = ["maxIOPS", "maxMBPS"] QOS_KEYS = ["maxIOPS", "maxMBPS", "total_iops_sec", "total_bytes_sec"] QOS_SCHEDULER_KEYS = ["scheduleType", "startDate", "startTime", @@ -53,6 +61,7 @@ QOS_SCHEDULER_DEFAULT_TYPE = "0" QOS_SCHEDULER_WEEK_TYPE = "3" QOS_SUPPORT_SCHEDULE_VERSION = "8.0" +QOS_MAX_INTERCEPT_LENGTH = 36 SECONDS_OF_DAY = 24 * 60 * 60 SECONDS_OF_HOUR = 60 * 60 SNAPSHOT_HEALTH_STATUS = ( @@ -80,3 +89,9 @@ HOSTGROUP_ALREADY_EXIST = 50157044 INITIATOR_ALREADY_EXIST = 50155102 INITIATOR_IN_HOST = 50157021 + +CHECK_CLONED_INTERVAL = 2 +REST_VOLUME_CREATING_STATUS = 15 +REST_VOLUME_DUPLICATE_VOLUME = 6 +REST_VOLUME_CREATE_SUCCESS_STATUS = 0 +CLONE_VOLUME_TIMEOUT = 3600 * 24 * 30 diff --git a/Cinder/Pike/dsware.py b/Cinder/Pike/dsware.py index cc3c0af..cd425cf 100644 --- a/Cinder/Pike/dsware.py +++ b/Cinder/Pike/dsware.py @@ -14,16 +14,22 @@ # under the License. import json - +import time +import uuid from multiprocessing import Lock + +import six from oslo_config import cfg from oslo_log import log as logging +from oslo_utils import excutils from oslo_utils import units +from oslo_service import loopingcall from cinder import coordination from cinder import exception from cinder.i18n import _ from cinder import interface +from cinder import objects from cinder.volume import driver from cinder.volume.drivers.fusionstorage import constants from cinder.volume.drivers.fusionstorage import fs_client @@ -105,6 +111,9 @@ cfg.StrOpt('storage_key_filepath', default='', help='Client key directory.'), + cfg.BoolOpt('full_clone', + default=False, + help='Whether use full clone.'), ] CONF = cfg.CONF @@ -113,7 +122,7 @@ @interface.volumedriver class DSWAREBaseDriver(driver.VolumeDriver): - VERSION = '2.5.RC4' + VERSION = "2.6.1" CI_WIKI_NAME = 'Huawei_FusionStorage_CI' def __init__(self, *args, **kwargs): @@ -210,6 +219,7 @@ def _update_single_pool_info_status(self, pool_info): "total_capacity_gb": capacity['total_capacity_gb'], "free_capacity_gb": capacity['free_capacity_gb'], "provisioned_capacity_gb": capacity['provisioned_capacity_gb'], + "location_info": self.client.esn, "QoS_support": True, 'multiattach': True, "thin_provisioning_support": True, @@ -247,8 +257,12 @@ def _raise_exception(msg): raise exception.VolumeBackendAPIException(data=msg) def _get_pool_id(self, volume): - pool_id_list = [] pool_name = volume_utils.extract_host(volume.host, level='pool') + pool_id = self._get_pool_id_by_name(pool_name) + return pool_id + + def _get_pool_id_by_name(self, pool_name): + pool_id_list = [] all_pools = self.client.query_pool_info() for pool in all_pools: if pool_name == pool['poolName']: @@ -363,29 +377,111 @@ def _expand_volume_when_create(self, vol_name, vol_size): self.client.delete_volume(vol_name=vol_name) raise + def _check_create_cloned_volume_finish(self, new_volume_name, start_time): + LOG.debug('Loopcall: _check_create_cloned_volume_finish(), ' + 'volume-name %s', + new_volume_name) + current_volume = self.client.query_volume_by_name(new_volume_name) + + if current_volume and 'status' in current_volume: + status = int(current_volume['status']) + LOG.debug('Wait clone volume %(volume_name)s, status:%(status)s.', + {"volume_name": new_volume_name, + "status": status}) + if status in {constants.REST_VOLUME_CREATING_STATUS, + constants.REST_VOLUME_DUPLICATE_VOLUME}: + LOG.debug(_("Volume %s is cloning"), new_volume_name) + elif status == constants.REST_VOLUME_CREATE_SUCCESS_STATUS: + raise loopingcall.LoopingCallDone(retvalue=True) + else: + msg = _('Clone volume %(new_volume_name)s failed, ' + 'the status is:%(status)s.') + LOG.error(msg, {'new_volume_name': new_volume_name, + 'status': status}) + raise loopingcall.LoopingCallDone(retvalue=False) + + max_time_out = constants.CLONE_VOLUME_TIMEOUT + current_time = time.time() + if (current_time - start_time) > max_time_out: + msg = _('Dsware clone volume time out. ' + 'Volume: %(new_volume_name)s, status: %(status)s') + LOG.error(msg, {'new_volume_name': new_volume_name, + 'status': current_volume['status']}) + raise loopingcall.LoopingCallDone(retvalue=False) + else: + LOG.warning(_('Can not find volume %s'), new_volume_name) + msg = "DSWARE clone volume failed:volume can not find from dsware" + LOG.error(msg) + raise loopingcall.LoopingCallDone(retvalue=False) + + def _wait_for_create_cloned_volume_finish_timer(self, new_volume_name): + timer = loopingcall.FixedIntervalLoopingCall( + self._check_create_cloned_volume_finish, + new_volume_name, time.time()) + LOG.debug('Calling _check_create_cloned_volume_finish: volume-name %s', + new_volume_name) + ret = timer.start(interval=constants.CHECK_CLONED_INTERVAL).wait() + timer.stop() + return ret + def create_volume_from_snapshot(self, volume, snapshot): vol_name = self._get_vol_name(volume) snapshot_name = self._get_snapshot_name(snapshot) vol_size = volume.size + pool_id = self._get_pool_id(volume) if not self._check_snapshot_exist(snapshot.volume, snapshot): msg = _("Snapshot: %(name)s does not exist!" ) % {"name": snapshot_name} self._raise_exception(msg) - elif self._check_volume_exist(volume): + if self._check_volume_exist(volume): msg = _("Volume: %(vol_name)s already exists!" ) % {'vol_name': vol_name} self._raise_exception(msg) - else: - vol_size *= units.Ki + + vol_size *= units.Ki + if not self.configuration.full_clone: self.client.create_volume_from_snapshot( snapshot_name=snapshot_name, vol_name=vol_name, vol_size=vol_size) - self._add_qos_to_volume(volume, vol_name) - self._expand_volume_when_create(vol_name, vol_size) - result = self.client.query_volume_by_name(vol_name=vol_name) - return ({"metadata": {'lun_wwn': result.get('wwn')}} - if result else {}) + else: + self.client.create_volume(vol_name, vol_size, pool_id) + self.client.create_full_volume_from_snapshot(vol_name, + snapshot_name) + ret = self._wait_for_create_cloned_volume_finish_timer(vol_name) + if not ret: + msg = _('Create full volume %s from snap failed') % vol_name + self._raise_exception(msg) + self._add_qos_to_volume(volume, vol_name) + self._expand_volume_when_create(vol_name, vol_size) + result = self.client.query_volume_by_name(vol_name=vol_name) + return ({"metadata": {'lun_wwn': result.get('wwn')}} + if result else {}) + + def _create_volume_from_volume_full_clone(self, vol_name, vol_size, pool_id, + src_vol_name): + tmp_snap_name = "temp" + src_vol_name + "clone" + vol_name + + self.client.create_snapshot(tmp_snap_name, src_vol_name) + try: + self.client.create_volume(vol_name, vol_size, pool_id) + except Exception as err: + self.client.delete_snapshot(tmp_snap_name) + raise err + + try: + self.client.create_full_volume_from_snapshot( + vol_name, tmp_snap_name) + except Exception as err: + self.client.delete_snapshot(tmp_snap_name) + self.client.delete_volume(vol_name) + raise err + + ret = self._wait_for_create_cloned_volume_finish_timer(vol_name) + if not ret: + msg = _('Create full volume %s from snap failed') % vol_name + self._raise_exception(msg) + self.client.delete_snapshot(tmp_snap_name) def create_cloned_volume(self, volume, src_volume): vol_name = self._get_vol_name(volume) @@ -398,15 +494,22 @@ def create_cloned_volume(self, volume, src_volume): msg = _("Volume: %(vol_name)s does not exist!" ) % {"vol_name": src_vol_name} self._raise_exception(msg) - else: + + if not self.configuration.full_clone: self.client.create_volume_from_volume( vol_name=vol_name, vol_size=vol_size, src_vol_name=src_vol_name) - self._add_qos_to_volume(volume, vol_name) - self._expand_volume_when_create(vol_name, vol_size) - result = self.client.query_volume_by_name(vol_name=vol_name) - return ({"metadata": {'lun_wwn': result.get('wwn')}} - if result else {}) + else: + pool_id = self._get_pool_id(volume) + self._create_volume_from_volume_full_clone( + vol_name=vol_name, vol_size=vol_size, pool_id=pool_id, + src_vol_name=src_vol_name) + + self._add_qos_to_volume(volume, vol_name) + self._expand_volume_when_create(vol_name, vol_size) + result = self.client.query_volume_by_name(vol_name=vol_name) + return ({"metadata": {'lun_wwn': result.get('wwn')}} + if result else {}) def create_snapshot(self, snapshot): snapshot_name = self._get_snapshot_name(snapshot) @@ -581,12 +684,13 @@ def unmanage_snapshot(self, snapshot): def _check_need_changes_for_retype(self, volume, new_type, host, vol_name): before_change = {} after_change = {} - if volume.host != host["host"]: - msg = (_("Do not support retype between different host. Volume's " + migrate = False + if volume.host != host.get("host"): + migrate = True + msg = (_("retype support migration between different host. Volume's " "host: %(vol_host)s, host's host: %(host)s") - % {"vol_host": volume.host, "host": host['host']}) - LOG.error(msg) - raise exception.InvalidInput(msg) + % {"vol_host": volume.host, "host": host.get("host")}) + LOG.info(msg) old_opts = fs_utils.get_volume_specs(self.client, vol_name) new_opts = fs_utils.get_volume_type_params(new_type, self.client) @@ -596,7 +700,7 @@ def _check_need_changes_for_retype(self, volume, new_type, host, vol_name): change_opts = {"old_opts": before_change, "new_opts": after_change} - return change_opts + return migrate, change_opts def retype(self, context, volume, new_type, diff, host): LOG.info("Retype volume: %(vol)s, new_type: %(new_type)s, " @@ -607,13 +711,177 @@ def retype(self, context, volume, new_type, diff, host): "host": host}) vol_name = self._get_vol_name(volume) - change_opts = self._check_need_changes_for_retype( + migrate, change_opts = self._check_need_changes_for_retype( volume, new_type, host, vol_name) + if migrate: + src_lun_id = self._check_volume_exist_on_array(volume) + LOG.debug("Begin to migrate LUN(id: %(lun_id)s) with " + "change %(change_opts)s.", + {"lun_id": src_lun_id, "change_opts": change_opts}) + moved = self._migrate_volume(volume, host, src_lun_id) + if not moved: + LOG.warning("Storage-assisted migration failed during " + "retype.") + return False, None self._change_lun(vol_name, change_opts.get("new_opts"), change_opts.get("old_opts")) return True, None + def migrate_volume(self, context, volume, host): + """Migrate a volume within the same array.""" + LOG.info("Migrate Volume:%(volume)s, host:%(host)s", + {"volume": volume.id, + "host": host}) + src_lun_id = self._check_volume_exist_on_array(volume) + + moved = self._migrate_volume(volume, host, src_lun_id) + return moved, {} + + def _create_dst_volume(self, volume, host): + pool_name = host['capabilities']['pool_name'] + pool_id = self._get_pool_id_by_name(pool_name) + vol_name = fs_utils.encode_name(six.text_type(uuid.uuid4())) + vol_size = volume.size + vol_size *= units.Ki + self.client.create_volume( + pool_id=pool_id, vol_name=vol_name, vol_size=vol_size) + + result = self.client.query_volume_by_name_v2(vol_name=vol_name) + dst_lun_id = result.get('id') + self._wait_volume_ready(vol_name) + return vol_name, dst_lun_id + + def _migrate_volume(self, volume, host, src_lun_id): + """create migration task and wait for task done""" + if not self._check_migration_valid(host): + return False + + vol_name, dst_lun_id = self._create_dst_volume(volume, host) + + try: + self.client.create_lun_migration(src_lun_id, dst_lun_id) + + def _is_lun_migration_complete(): + return self._is_lun_migration_complete(src_lun_id, dst_lun_id) + + wait_interval = constants.MIGRATION_WAIT_INTERVAL + fs_utils.wait_for_condition(_is_lun_migration_complete, + wait_interval, + constants.DEFAULT_WAIT_TIMEOUT) + # Clean up if migration failed. + except Exception as ex: + raise exception.VolumeBackendAPIException(data=ex) + finally: + if self._is_lun_migration_exist(src_lun_id, dst_lun_id): + self.client.delete_lun_migration(src_lun_id) + self._delete_lun_with_check(vol_name) + + LOG.info("Migrate lun %s successfully.", src_lun_id) + return True + + def _delete_lun_with_check(self, vol_name): + if self.client.query_volume_by_name(vol_name): + # migrate_dst_lun don't have qos, so don't + # need to remove qos, Delete the LUN directly. + self.client.delete_volume(vol_name) + + def _is_lun_migration_complete(self, src_lun_id, dst_lun_id): + result = self.client.get_lun_migration_task_by_id(src_lun_id) + found_migration_task = False + if not result: + return False + + if (str(src_lun_id) == result.get('parent_id') and + str(dst_lun_id) == result.get('target_lun_id')): + found_migration_task = True + if constants.MIGRATION_COMPLETE == result.get('running_status'): + return True + if constants.MIGRATION_FAULT == result.get('running_status'): + msg = _("Lun migration error. " + "the migration task running_status is abnormal") + LOG.error(msg) + raise exception.VolumeBackendAPIException(data=msg) + + if not found_migration_task: + err_msg = _("lun migration error, Cannot find migration task.") + LOG.error(err_msg) + raise exception.VolumeBackendAPIException(data=err_msg) + + return False + + def _is_lun_migration_exist(self, src_lun_id, dst_lun_id): + try: + result = self.client.get_lun_migration_task_by_id(src_lun_id) + except Exception: + LOG.error("Get LUN migration error.") + return False + + if (str(src_lun_id) == result.get('parent_id') and + str(dst_lun_id) == result.get('target_lun_id')): + return True + return False + + def _wait_volume_ready(self, vol_name): + wait_interval = constants.DEFAULT_WAIT_INTERVAL + + def _volume_ready(): + result = self.client.query_volume_by_name_v2(vol_name) + if not result: + return False + + if (result.get('health_status') == constants.STATUS_HEALTH + and result.get('running_status') == constants.STATUS_VOLUME_READY): + return True + return False + + fs_utils.wait_for_condition(_volume_ready, + wait_interval, + wait_interval * 10) + + def _check_migration_valid(self, host): + if 'pool_name' not in host.get('capabilities', {}): + return False + + target_device = host.get('capabilities', {}).get('location_info') + + # Source and destination should be on same array. + if target_device != self.client.esn: + LOG.error("lun migration error, " + "Source and destination should be on same array") + return False + + pool_name = host.get('capabilities', {}).get('pool_name', '') + if len(pool_name) == 0: + LOG.error("lun migration error, pool_name not exists") + return False + + return True + + def _check_volume_exist_on_array(self, volume): + volume_name = self._get_vol_name(volume) + result = self._check_volume_exist(volume) + if not result: + msg = _("Volume %s does not exist on the array." + ) % volume.id + self._raise_exception(msg) + + lun_wwn = result.get('wwn') + if not lun_wwn: + LOG.debug("No LUN WWN recorded for volume %s.", volume.id) + + lun_id = result.get('volId') + if not lun_id: + msg = _("Volume %s does not exist on the array." + ) % volume.id + self._raise_exception(msg) + + if self.client.get_volume_snapshot(volume_name): + msg = _("Volume %s which have snapshot cannot do lun migration" + ) % volume.id + self._raise_exception(msg) + return lun_id + def _rollback_snapshot(self, vol_name, snap_name): def _snapshot_rollback_finish(): snapshot_info = self.client.get_snapshot_info_by_name(snap_name) @@ -669,6 +937,265 @@ def ensure_export(self, context, volume): def remove_export(self, context, volume): pass + def create_group(self, context, group): + """Creates a group. Driver only need to return state""" + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.create_consistencygroup(context, group) + + def create_consistencygroup(self, context, group): + """Creates a group. Driver only need to return state""" + LOG.info("Create group successfully") + return {'status': 'available'} + + def update_group(self, context, group, + add_volumes=None, remove_volumes=None): + """ + The volume manager will adds/removes the volume to/from the + group in the database, if need add_volumes, Driver just need + to check whether volume is in array or not + """ + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.update_consistencygroup( + context, group, add_volumes, remove_volumes) + + def update_consistencygroup(self, context, group, + add_volumes=None, remove_volumes=None): + """ + The volume manager will adds/removes the volume to/from the + group in the database, if need add_volumes, Driver just need + to check whether volume is in array or not + """ + if add_volumes is None: + add_volumes = [] + for volume in add_volumes: + try: + self._check_volume_exist_on_array(volume) + except Exception: + with excutils.save_and_reraise_exception(): + LOG.error("The add_volume %s not exist on array" % volume.id) + + model_update = {'status': 'available'} + LOG.info("Update group successfully") + return model_update, None, None + + def delete_group(self, context, group, volumes): + """delete the group, Driver need to delete relation lun on array""" + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.delete_consistencygroup(context, group, volumes) + + def delete_consistencygroup(self, context, group, volumes): + """delete the group, Driver need to delete relation lun on array""" + volumes_model_update = [] + model_update = {'status': 'deleted'} + for volume in volumes: + volume_model_update = {'id': volume.id} + try: + self.delete_volume(volume) + except Exception: + LOG.error('Delete volume %s failed.' % volume) + volume_model_update.update({'status': 'error_deleting'}) + else: + volume_model_update.update({'status': 'deleted'}) + + LOG.info('Deleted volume %s successfully' % volume) + volumes_model_update.append(volume_model_update) + + LOG.info("Delete group successfully") + return model_update, volumes_model_update + + def create_group_from_src(self, context, group, volumes, + group_snapshot=None, snapshots=None, + source_group=None, source_vols=None): + """ + create group from group or group-snapshot, + Driver need to create volume from volume or snapshot + """ + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.create_consistencygroup_from_src(context, group, volumes, + group_snapshot, snapshots, + source_group, source_vols) + + def create_consistencygroup_from_src(self, context, group, volumes, + group_snapshot=None, snapshots=None, + source_group=None, source_vols=None): + """ + create group from group or group-snapshot, + Driver need to create volume from volume or snapshot + """ + model_update = self.create_consistencygroup(context, group) + volumes_model_update = [] + delete_snapshots = False + + if not snapshots and source_vols: + snapshots = [] + for src_volume in source_vols: + volume_kwargs = { + 'id': src_volume.id, + '_name_id': None, + 'host': src_volume.host + } + snapshot_kwargs = { + 'id': six.text_type(uuid.uuid4()), + 'volume': objects.Volume(**volume_kwargs) + } + snapshots.append(objects.Snapshot(**snapshot_kwargs)) + + self._create_group_snapshot(snapshots) + delete_snapshots = True + + if snapshots: + volumes_model_update = self._create_volume_from_group_snapshot( + volumes, snapshots, delete_snapshots) + + if delete_snapshots: + self._delete_group_snapshot(snapshots) + + LOG.info("Create group from src successfully") + return model_update, volumes_model_update + + def _create_volume_from_group_snapshot(self, volumes, snapshots, delete_snapshots): + volumes_model_update = [] + added_volumes = [] + for i, volume in enumerate(volumes): + try: + vol_model_update = self.create_volume_from_snapshot( + volume, snapshots[i]) + vol_model_update.update({'id': volume.id}) + volumes_model_update.append(vol_model_update) + added_volumes.append(volume) + except Exception: + LOG.error("Create volume from snapshot error, Delete the newly created lun.") + with excutils.save_and_reraise_exception(): + self._delete_added_volume_snapshots( + added_volumes, snapshots, delete_snapshots) + + return volumes_model_update + + def _delete_added_volume_snapshots( + self, added_volumes, snapshots, delete_snapshots): + if delete_snapshots: + self._delete_group_snapshot(snapshots) + for add_volume in added_volumes: + vol_name = self._get_vol_name(add_volume) + self.fs_qos.remove(vol_name) + self.client.delete_volume(vol_name=vol_name) + LOG.info("delete storage newly added " + "volume success, volume is %s" % add_volume.id) + + def create_group_snapshot(self, context, group_snapshot, snapshots): + """Create group snapshot.""" + if not volume_utils.is_group_a_cg_snapshot_type(group_snapshot): + LOG.info("group_snapshot's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.create_cgsnapshot(context, group_snapshot, snapshots) + + def create_cgsnapshot(self, context, group_snapshot, snapshots): + """Create group snapshot.""" + LOG.info('Create group snapshot for group: %(group_snapshot)s', + {'group_snapshot': group_snapshot}) + + try: + snapshots_model_update = self._create_group_snapshot(snapshots) + except Exception as err: + msg = ("Create group snapshots failed. " + "Group snapshot id: %s. Reason is %s") % (group_snapshot.id, err) + LOG.error(msg) + raise exception.CinderException(msg) + + model_update = {'status': 'available'} + return model_update, snapshots_model_update + + def _create_group_snapshot(self, snapshots): + """Generate snapshots for all volumes in the group.""" + snapshots_model_update = [] + snapshot_group_list = [] + + for snapshot in snapshots: + snapshot_name = self._get_snapshot_name(snapshot) + vol_name = self._get_vol_name(snapshot.volume) + snapshot_group_list.append({ + 'name': snapshot_name, + 'sub_type': '0', + 'volume_name': vol_name + }) + snapshot_model_update = { + 'id': snapshot.id, + 'status': 'available', + } + snapshots_model_update.append(snapshot_model_update) + try: + self.client.create_consistent_snapshot_by_name(snapshot_group_list) + except Exception: + with excutils.save_and_reraise_exception(): + LOG.error("Create consistent snapshot failed, " + "snapshot_group_list is %s" % snapshot_group_list) + + return snapshots_model_update + + def delete_group_snapshot(self, context, group_snapshot, snapshots): + """Delete group snapshot.""" + if not volume_utils.is_group_a_cg_snapshot_type(group_snapshot): + LOG.info("group_snapshot's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.delete_cgsnapshot(context, group_snapshot, snapshots) + + def delete_cgsnapshot(self, context, group_snapshot, snapshots): + """Delete group snapshot.""" + LOG.info("Delete group_snapshot %s for " + "consistency group: %s" % (group_snapshot.id, group_snapshot)) + + try: + snapshots_model_update = self._delete_group_snapshot(snapshots) + except Exception as err: + msg = ("Delete cg snapshots failed. " + "group snapshot id: %s, reason is %s") % (group_snapshot.id, err) + LOG.error(msg) + raise exception.CinderException(msg) + + model_update = {'status': 'deleted'} + return model_update, snapshots_model_update + + def _delete_group_snapshot(self, snapshots): + """Delete all snapshots in snapshot group""" + snapshots_model_update = [] + for snapshot in snapshots: + snapshot_model_update = { + 'id': snapshot.id, + 'status': 'deleted' + } + snapshots_model_update.append(snapshot_model_update) + snapshot_name = self._get_snapshot_name(snapshot) + + if not self._check_snapshot_exist(snapshot.volume, snapshot): + LOG.info("snapshot %s not exist in array, " + "don't need to delete, try next one" % snapshot_name) + continue + self.client.delete_snapshot(snapshot_name=snapshot_name) + LOG.info("Delete snapshot successfully," + " the deleted snapshots is %s" % snapshot_name) + + return snapshots_model_update + class DSWAREDriver(DSWAREBaseDriver): def get_volume_stats(self, refresh=False): @@ -721,7 +1248,7 @@ def initialize_connection(self, volume, connector): vol_wwn = volume_info.get('wwn') by_id_path = "/dev/disk/by-id/" + "wwn-0x%s" % vol_wwn properties = {'device_path': by_id_path} - import time + LOG.info("Wait %(t)s second(s) for scanning the target device %(dev)s." % {"t": self.configuration.scan_device_timeout, "dev": by_id_path}) diff --git a/Cinder/Pike/fs_client.py b/Cinder/Pike/fs_client.py index 234d7f1..09d9581 100644 --- a/Cinder/Pike/fs_client.py +++ b/Cinder/Pike/fs_client.py @@ -14,16 +14,16 @@ # under the License. import json + import requests import six -import time +from oslo_log import log as logging from requests.adapters import HTTPAdapter from cinder import exception from cinder.i18n import _ from cinder.volume.drivers.fusionstorage import constants -from oslo_log import log as logging LOG = logging.getLogger(__name__) @@ -43,7 +43,8 @@ def __init__(self, fs_address, fs_user, fs_password, **extend_conf): self.session = None self.token = None self.version = None - mutual_authentication = extend_conf.get("mutual_authentication") + self.esn = None + mutual_authentication = extend_conf.get("mutual_authentication", {}) self.init_http_head(mutual_authentication) LOG.warning("Suppressing requests library SSL Warnings") @@ -147,6 +148,13 @@ def get_version(self): if result.get("currentVersion"): self.version = result["currentVersion"] + def get_esn(self): + url = "/cluster/sn" + result = self.call(url, "get") + self._assert_rest_result(result, _('Get cluster esn error.')) + self.esn = result.get("sn") + return self.esn + def login(self): self.get_version() url = '/sec/login' @@ -160,6 +168,7 @@ def login(self): self.session.headers.update({ "x-auth-token": self.token }) + self.get_esn() def logout(self): url = '/sec/logout' @@ -264,6 +273,15 @@ def query_volume_by_name(self, vol_name): result, _("Query volume by name session error")) return result.get('lunDetailInfo') + def query_volume_by_name_v2(self, vol_name): + url = '/api/v2/block_service/volumes?name=' + vol_name + result = self.call(url, 'GET', get_system_time=True) + if result.get('errorCode') in constants.VOLUME_NOT_EXIST: + return {} + self._assert_rest_result( + result, _("Query volume by name session error")) + return result.get('data', {}) + def query_volume_by_id(self, vol_id): url = 'v1.3/volume/queryById?volId=' + vol_id result = self.call(url, 'GET', get_version=True) @@ -746,3 +764,57 @@ def get_iscsi_links_info(self, iscsi_link_count, pool_list): return [iscsi["ip"] for iscsi in result.get("iscsiLinks", []) if iscsi.get("ip")] + + def create_lun_migration(self, src_lun_id, dst_lun_id, speed=2): + url = "/api/v2/block_service/lun_migration" + params = { + "parent_id": src_lun_id, + "target_lun_id": dst_lun_id, + "speed": speed, + "work_mode": 0 + } + result = self.call(url, "POST", params, get_system_time=True) + self._assert_rest_result(result, + _("create lun migration task error.")) + + def get_lun_migration_task_by_id(self, src_lun_id): + url = "/api/v2/block_service/lun_migration" + params = { + "id": src_lun_id + } + result = self.call(url, "GET", params, get_system_time=True) + self._assert_rest_result(result, + _("get lun migration task error.")) + return result.get('data', {}) + + def delete_lun_migration(self, src_lun_id): + url = "/api/v2/block_service/lun_migration" + params = { + 'id': src_lun_id + } + result = self.call(url, "DELETE", params, get_system_time=True) + self._assert_rest_result(result, + _("Delete lun migration task error.")) + + def get_volume_snapshot(self, volume_name): + url = "/volume/snapshot/list" + params = { + 'volName': volume_name, + 'batchNum': 1, + 'batchLimit': 10 + } + result = self.call(url, "POST", params) + return result.get('snapshotList', []) + + def create_consistent_snapshot_by_name(self, snapshot_group_list): + url = "/api/v2/block_service/consistency_snapshots" + result = self.call(url, "POST", snapshot_group_list, get_system_time=True) + self._assert_rest_result(result, _("create consistent_snapshot error.")) + return result.get('data', []) + + def create_full_volume_from_snapshot(self, vol_name, snapshot_name): + url = '/api/v2/block_service/createFullVolumeFromSnap' + params = {"snap_name_src": snapshot_name, "volume_name_dst": vol_name} + result = self.call(url, "POST", params, get_system_time=True) + self._assert_rest_result( + result, _("create full volume from snap fails")) diff --git a/Cinder/Pike/fs_qos.py b/Cinder/Pike/fs_qos.py index 731c45e..286dbc3 100644 --- a/Cinder/Pike/fs_qos.py +++ b/Cinder/Pike/fs_qos.py @@ -29,7 +29,11 @@ def __init__(self, client): def add(self, qos, vol_name): localtime = time.strftime('%Y%m%d%H%M%S', time.localtime()) - qos_name = constants.QOS_PREFIX + localtime + # QoS policy name. The value contains 1 to 63 characters. + # So we intercept volume_name Ensure that the length does not exceed 63 + vol_str = vol_name[-constants.QOS_MAX_INTERCEPT_LENGTH::] \ + if len(vol_name) >= constants.QOS_MAX_INTERCEPT_LENGTH else vol_name + qos_name = constants.QOS_PREFIX + localtime + '_' + vol_str self.client.create_qos(qos_name, qos) try: self.client.associate_qos_with_volume(vol_name, qos_name) diff --git a/Cinder/Pike/fs_utils.py b/Cinder/Pike/fs_utils.py index 8b9ae78..0856038 100644 --- a/Cinder/Pike/fs_utils.py +++ b/Cinder/Pike/fs_utils.py @@ -16,11 +16,11 @@ import datetime import hashlib import ipaddress -import pytz import random -import six import time +import pytz +import six from oslo_log import log as logging from oslo_service import loopingcall from oslo_utils import units @@ -758,3 +758,9 @@ def get_iscsi_info_from_storage(manager_ips, use_ipv6, valid_iscsi_ips, valid_node_ips): return _get_target_info(manager_ips, use_ipv6, valid_iscsi_ips, valid_node_ips) + + +def encode_name(my_uuid): + encoded_name = hashlib.md5(my_uuid.encode('utf-8')).hexdigest() + target_lun_prefix = my_uuid.split('-')[0] + '-' + return target_lun_prefix + encoded_name diff --git a/Cinder/Queens/constants.py b/Cinder/Queens/constants.py index 5f46ece..b4cb843 100644 --- a/Cinder/Queens/constants.py +++ b/Cinder/Queens/constants.py @@ -45,6 +45,14 @@ CONF_STORAGE_CERT_FILEPATH = "storage_cert_filepath" CONF_STORAGE_SSL_TWO_WAY_AUTH = "storage_ssl_two_way_auth" +DEFAULT_WAIT_INTERVAL = 5 +MIGRATION_COMPLETE = 76 +MIGRATION_FAULT = 74 +STATUS_HEALTH = 1 +STATUS_VOLUME_READY = 27 +MIGRATION_WAIT_INTERVAL = 5 +DEFAULT_WAIT_TIMEOUT = 3600 * 24 * 30 + QOS_MUST_SET = ["maxIOPS", "maxMBPS"] QOS_KEYS = ["maxIOPS", "maxMBPS", "total_iops_sec", "total_bytes_sec"] QOS_SCHEDULER_KEYS = ["scheduleType", "startDate", "startTime", @@ -53,6 +61,7 @@ QOS_SCHEDULER_DEFAULT_TYPE = "0" QOS_SCHEDULER_WEEK_TYPE = "3" QOS_SUPPORT_SCHEDULE_VERSION = "8.0" +QOS_MAX_INTERCEPT_LENGTH = 36 SECONDS_OF_DAY = 24 * 60 * 60 SECONDS_OF_HOUR = 60 * 60 SNAPSHOT_HEALTH_STATUS = ( @@ -80,3 +89,9 @@ HOSTGROUP_ALREADY_EXIST = 50157044 INITIATOR_ALREADY_EXIST = 50155102 INITIATOR_IN_HOST = 50157021 + +CHECK_CLONED_INTERVAL = 2 +REST_VOLUME_CREATING_STATUS = 15 +REST_VOLUME_DUPLICATE_VOLUME = 6 +REST_VOLUME_CREATE_SUCCESS_STATUS = 0 +CLONE_VOLUME_TIMEOUT = 3600 * 24 * 30 diff --git a/Cinder/Queens/dsware.py b/Cinder/Queens/dsware.py index c1c15d9..38d1262 100644 --- a/Cinder/Queens/dsware.py +++ b/Cinder/Queens/dsware.py @@ -14,16 +14,22 @@ # under the License. import json - +import time +import uuid from multiprocessing import Lock + +import six from oslo_config import cfg from oslo_log import log as logging +from oslo_utils import excutils from oslo_utils import units +from oslo_service import loopingcall from cinder import coordination from cinder import exception from cinder.i18n import _ from cinder import interface +from cinder import objects from cinder.volume import driver from cinder.volume.drivers.fusionstorage import constants from cinder.volume.drivers.fusionstorage import fs_client @@ -105,6 +111,9 @@ cfg.StrOpt('storage_key_filepath', default='', help='Client key directory.'), + cfg.BoolOpt('full_clone', + default=False, + help='Whether use full clone.'), ] CONF = cfg.CONF @@ -113,7 +122,7 @@ @interface.volumedriver class DSWAREBaseDriver(driver.VolumeDriver): - VERSION = '2.5.RC4' + VERSION = "2.6.1" CI_WIKI_NAME = 'Huawei_FusionStorage_CI' def __init__(self, *args, **kwargs): @@ -210,6 +219,7 @@ def _update_single_pool_info_status(self, pool_info): "total_capacity_gb": capacity['total_capacity_gb'], "free_capacity_gb": capacity['free_capacity_gb'], "provisioned_capacity_gb": capacity['provisioned_capacity_gb'], + "location_info": self.client.esn, "QoS_support": True, 'multiattach': True, "thin_provisioning_support": True, @@ -247,8 +257,12 @@ def _raise_exception(msg): raise exception.VolumeBackendAPIException(data=msg) def _get_pool_id(self, volume): - pool_id_list = [] pool_name = volume_utils.extract_host(volume.host, level='pool') + pool_id = self._get_pool_id_by_name(pool_name) + return pool_id + + def _get_pool_id_by_name(self, pool_name): + pool_id_list = [] all_pools = self.client.query_pool_info() for pool in all_pools: if pool_name == pool['poolName']: @@ -363,29 +377,111 @@ def _expand_volume_when_create(self, vol_name, vol_size): self.client.delete_volume(vol_name=vol_name) raise + def _check_create_cloned_volume_finish(self, new_volume_name, start_time): + LOG.debug('Loopcall: _check_create_cloned_volume_finish(), ' + 'volume-name %s', + new_volume_name) + current_volume = self.client.query_volume_by_name(new_volume_name) + + if current_volume and 'status' in current_volume: + status = int(current_volume['status']) + LOG.debug('Wait clone volume %(volume_name)s, status:%(status)s.', + {"volume_name": new_volume_name, + "status": status}) + if status in {constants.REST_VOLUME_CREATING_STATUS, + constants.REST_VOLUME_DUPLICATE_VOLUME}: + LOG.debug(_("Volume %s is cloning"), new_volume_name) + elif status == constants.REST_VOLUME_CREATE_SUCCESS_STATUS: + raise loopingcall.LoopingCallDone(retvalue=True) + else: + msg = _('Clone volume %(new_volume_name)s failed, ' + 'the status is:%(status)s.') + LOG.error(msg, {'new_volume_name': new_volume_name, + 'status': status}) + raise loopingcall.LoopingCallDone(retvalue=False) + + max_time_out = constants.CLONE_VOLUME_TIMEOUT + current_time = time.time() + if (current_time - start_time) > max_time_out: + msg = _('Dsware clone volume time out. ' + 'Volume: %(new_volume_name)s, status: %(status)s') + LOG.error(msg, {'new_volume_name': new_volume_name, + 'status': current_volume['status']}) + raise loopingcall.LoopingCallDone(retvalue=False) + else: + LOG.warning(_('Can not find volume %s'), new_volume_name) + msg = "DSWARE clone volume failed:volume can not find from dsware" + LOG.error(msg) + raise loopingcall.LoopingCallDone(retvalue=False) + + def _wait_for_create_cloned_volume_finish_timer(self, new_volume_name): + timer = loopingcall.FixedIntervalLoopingCall( + self._check_create_cloned_volume_finish, + new_volume_name, time.time()) + LOG.debug('Calling _check_create_cloned_volume_finish: volume-name %s', + new_volume_name) + ret = timer.start(interval=constants.CHECK_CLONED_INTERVAL).wait() + timer.stop() + return ret + def create_volume_from_snapshot(self, volume, snapshot): vol_name = self._get_vol_name(volume) snapshot_name = self._get_snapshot_name(snapshot) vol_size = volume.size + pool_id = self._get_pool_id(volume) if not self._check_snapshot_exist(snapshot.volume, snapshot): msg = _("Snapshot: %(name)s does not exist!" ) % {"name": snapshot_name} self._raise_exception(msg) - elif self._check_volume_exist(volume): + if self._check_volume_exist(volume): msg = _("Volume: %(vol_name)s already exists!" ) % {'vol_name': vol_name} self._raise_exception(msg) - else: - vol_size *= units.Ki + + vol_size *= units.Ki + if not self.configuration.full_clone: self.client.create_volume_from_snapshot( snapshot_name=snapshot_name, vol_name=vol_name, vol_size=vol_size) - self._add_qos_to_volume(volume, vol_name) - self._expand_volume_when_create(vol_name, vol_size) - result = self.client.query_volume_by_name(vol_name=vol_name) - return ({"metadata": {'lun_wwn': result.get('wwn')}} - if result else {}) + else: + self.client.create_volume(vol_name, vol_size, pool_id) + self.client.create_full_volume_from_snapshot(vol_name, + snapshot_name) + ret = self._wait_for_create_cloned_volume_finish_timer(vol_name) + if not ret: + msg = _('Create full volume %s from snap failed') % vol_name + self._raise_exception(msg) + self._add_qos_to_volume(volume, vol_name) + self._expand_volume_when_create(vol_name, vol_size) + result = self.client.query_volume_by_name(vol_name=vol_name) + return ({"metadata": {'lun_wwn': result.get('wwn')}} + if result else {}) + + def _create_volume_from_volume_full_clone(self, vol_name, vol_size, pool_id, + src_vol_name): + tmp_snap_name = "temp" + src_vol_name + "clone" + vol_name + + self.client.create_snapshot(tmp_snap_name, src_vol_name) + try: + self.client.create_volume(vol_name, vol_size, pool_id) + except Exception as err: + self.client.delete_snapshot(tmp_snap_name) + raise err + + try: + self.client.create_full_volume_from_snapshot( + vol_name, tmp_snap_name) + except Exception as err: + self.client.delete_snapshot(tmp_snap_name) + self.client.delete_volume(vol_name) + raise err + + ret = self._wait_for_create_cloned_volume_finish_timer(vol_name) + if not ret: + msg = _('Create full volume %s from snap failed') % vol_name + self._raise_exception(msg) + self.client.delete_snapshot(tmp_snap_name) def create_cloned_volume(self, volume, src_volume): vol_name = self._get_vol_name(volume) @@ -398,15 +494,22 @@ def create_cloned_volume(self, volume, src_volume): msg = _("Volume: %(vol_name)s does not exist!" ) % {"vol_name": src_vol_name} self._raise_exception(msg) - else: + + if not self.configuration.full_clone: self.client.create_volume_from_volume( vol_name=vol_name, vol_size=vol_size, src_vol_name=src_vol_name) - self._add_qos_to_volume(volume, vol_name) - self._expand_volume_when_create(vol_name, vol_size) - result = self.client.query_volume_by_name(vol_name=vol_name) - return ({"metadata": {'lun_wwn': result.get('wwn')}} - if result else {}) + else: + pool_id = self._get_pool_id(volume) + self._create_volume_from_volume_full_clone( + vol_name=vol_name, vol_size=vol_size, pool_id=pool_id, + src_vol_name=src_vol_name) + + self._add_qos_to_volume(volume, vol_name) + self._expand_volume_when_create(vol_name, vol_size) + result = self.client.query_volume_by_name(vol_name=vol_name) + return ({"metadata": {'lun_wwn': result.get('wwn')}} + if result else {}) def create_snapshot(self, snapshot): snapshot_name = self._get_snapshot_name(snapshot) @@ -581,12 +684,13 @@ def unmanage_snapshot(self, snapshot): def _check_need_changes_for_retype(self, volume, new_type, host, vol_name): before_change = {} after_change = {} - if volume.host != host["host"]: - msg = (_("Do not support retype between different host. Volume's " + migrate = False + if volume.host != host.get("host"): + migrate = True + msg = (_("retype support migration between different host. Volume's " "host: %(vol_host)s, host's host: %(host)s") - % {"vol_host": volume.host, "host": host['host']}) - LOG.error(msg) - raise exception.InvalidInput(msg) + % {"vol_host": volume.host, "host": host.get("host")}) + LOG.info(msg) old_opts = fs_utils.get_volume_specs(self.client, vol_name) new_opts = fs_utils.get_volume_type_params(new_type, self.client) @@ -596,7 +700,7 @@ def _check_need_changes_for_retype(self, volume, new_type, host, vol_name): change_opts = {"old_opts": before_change, "new_opts": after_change} - return change_opts + return migrate, change_opts def retype(self, context, volume, new_type, diff, host): LOG.info("Retype volume: %(vol)s, new_type: %(new_type)s, " @@ -607,13 +711,177 @@ def retype(self, context, volume, new_type, diff, host): "host": host}) vol_name = self._get_vol_name(volume) - change_opts = self._check_need_changes_for_retype( + migrate, change_opts = self._check_need_changes_for_retype( volume, new_type, host, vol_name) + if migrate: + src_lun_id = self._check_volume_exist_on_array(volume) + LOG.debug("Begin to migrate LUN(id: %(lun_id)s) with " + "change %(change_opts)s.", + {"lun_id": src_lun_id, "change_opts": change_opts}) + moved = self._migrate_volume(volume, host, src_lun_id) + if not moved: + LOG.warning("Storage-assisted migration failed during " + "retype.") + return False, None self._change_lun(vol_name, change_opts.get("new_opts"), change_opts.get("old_opts")) return True, None + def migrate_volume(self, context, volume, host): + """Migrate a volume within the same array.""" + LOG.info("Migrate Volume:%(volume)s, host:%(host)s", + {"volume": volume.id, + "host": host}) + src_lun_id = self._check_volume_exist_on_array(volume) + + moved = self._migrate_volume(volume, host, src_lun_id) + return moved, {} + + def _create_dst_volume(self, volume, host): + pool_name = host['capabilities']['pool_name'] + pool_id = self._get_pool_id_by_name(pool_name) + vol_name = fs_utils.encode_name(six.text_type(uuid.uuid4())) + vol_size = volume.size + vol_size *= units.Ki + self.client.create_volume( + pool_id=pool_id, vol_name=vol_name, vol_size=vol_size) + + result = self.client.query_volume_by_name_v2(vol_name=vol_name) + dst_lun_id = result.get('id') + self._wait_volume_ready(vol_name) + return vol_name, dst_lun_id + + def _migrate_volume(self, volume, host, src_lun_id): + """create migration task and wait for task done""" + if not self._check_migration_valid(host): + return False + + vol_name, dst_lun_id = self._create_dst_volume(volume, host) + + try: + self.client.create_lun_migration(src_lun_id, dst_lun_id) + + def _is_lun_migration_complete(): + return self._is_lun_migration_complete(src_lun_id, dst_lun_id) + + wait_interval = constants.MIGRATION_WAIT_INTERVAL + fs_utils.wait_for_condition(_is_lun_migration_complete, + wait_interval, + constants.DEFAULT_WAIT_TIMEOUT) + # Clean up if migration failed. + except Exception as ex: + raise exception.VolumeBackendAPIException(data=ex) + finally: + if self._is_lun_migration_exist(src_lun_id, dst_lun_id): + self.client.delete_lun_migration(src_lun_id) + self._delete_lun_with_check(vol_name) + + LOG.info("Migrate lun %s successfully.", src_lun_id) + return True + + def _delete_lun_with_check(self, vol_name): + if self.client.query_volume_by_name(vol_name): + # migrate_dst_lun don't have qos, so don't + # need to remove qos, Delete the LUN directly. + self.client.delete_volume(vol_name) + + def _is_lun_migration_complete(self, src_lun_id, dst_lun_id): + result = self.client.get_lun_migration_task_by_id(src_lun_id) + found_migration_task = False + if not result: + return False + + if (str(src_lun_id) == result.get('parent_id') and + str(dst_lun_id) == result.get('target_lun_id')): + found_migration_task = True + if constants.MIGRATION_COMPLETE == result.get('running_status'): + return True + if constants.MIGRATION_FAULT == result.get('running_status'): + msg = _("Lun migration error. " + "the migration task running_status is abnormal") + LOG.error(msg) + raise exception.VolumeBackendAPIException(data=msg) + + if not found_migration_task: + err_msg = _("lun migration error, Cannot find migration task.") + LOG.error(err_msg) + raise exception.VolumeBackendAPIException(data=err_msg) + + return False + + def _is_lun_migration_exist(self, src_lun_id, dst_lun_id): + try: + result = self.client.get_lun_migration_task_by_id(src_lun_id) + except Exception: + LOG.error("Get LUN migration error.") + return False + + if (str(src_lun_id) == result.get('parent_id') and + str(dst_lun_id) == result.get('target_lun_id')): + return True + return False + + def _wait_volume_ready(self, vol_name): + wait_interval = constants.DEFAULT_WAIT_INTERVAL + + def _volume_ready(): + result = self.client.query_volume_by_name_v2(vol_name) + if not result: + return False + + if (result.get('health_status') == constants.STATUS_HEALTH + and result.get('running_status') == constants.STATUS_VOLUME_READY): + return True + return False + + fs_utils.wait_for_condition(_volume_ready, + wait_interval, + wait_interval * 10) + + def _check_migration_valid(self, host): + if 'pool_name' not in host.get('capabilities', {}): + return False + + target_device = host.get('capabilities', {}).get('location_info') + + # Source and destination should be on same array. + if target_device != self.client.esn: + LOG.error("lun migration error, " + "Source and destination should be on same array") + return False + + pool_name = host.get('capabilities', {}).get('pool_name', '') + if len(pool_name) == 0: + LOG.error("lun migration error, pool_name not exists") + return False + + return True + + def _check_volume_exist_on_array(self, volume): + volume_name = self._get_vol_name(volume) + result = self._check_volume_exist(volume) + if not result: + msg = _("Volume %s does not exist on the array." + ) % volume.id + self._raise_exception(msg) + + lun_wwn = result.get('wwn') + if not lun_wwn: + LOG.debug("No LUN WWN recorded for volume %s.", volume.id) + + lun_id = result.get('volId') + if not lun_id: + msg = _("Volume %s does not exist on the array." + ) % volume.id + self._raise_exception(msg) + + if self.client.get_volume_snapshot(volume_name): + msg = _("Volume %s which have snapshot cannot do lun migration" + ) % volume.id + self._raise_exception(msg) + return lun_id + def _rollback_snapshot(self, vol_name, snap_name): def _snapshot_rollback_finish(): snapshot_info = self.client.get_snapshot_info_by_name(snap_name) @@ -669,6 +937,265 @@ def ensure_export(self, context, volume): def remove_export(self, context, volume): pass + def create_group(self, context, group): + """Creates a group. Driver only need to return state""" + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.create_consistencygroup(context, group) + + def create_consistencygroup(self, context, group): + """Creates a group. Driver only need to return state""" + LOG.info("Create group successfully") + return {'status': 'available'} + + def update_group(self, context, group, + add_volumes=None, remove_volumes=None): + """ + The volume manager will adds/removes the volume to/from the + group in the database, if need add_volumes, Driver just need + to check whether volume is in array or not + """ + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.update_consistencygroup( + context, group, add_volumes, remove_volumes) + + def update_consistencygroup(self, context, group, + add_volumes=None, remove_volumes=None): + """ + The volume manager will adds/removes the volume to/from the + group in the database, if need add_volumes, Driver just need + to check whether volume is in array or not + """ + if add_volumes is None: + add_volumes = [] + for volume in add_volumes: + try: + self._check_volume_exist_on_array(volume) + except Exception: + with excutils.save_and_reraise_exception(): + LOG.error("The add_volume %s not exist on array" % volume.id) + + model_update = {'status': 'available'} + LOG.info("Update group successfully") + return model_update, None, None + + def delete_group(self, context, group, volumes): + """delete the group, Driver need to delete relation lun on array""" + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.delete_consistencygroup(context, group, volumes) + + def delete_consistencygroup(self, context, group, volumes): + """delete the group, Driver need to delete relation lun on array""" + volumes_model_update = [] + model_update = {'status': 'deleted'} + for volume in volumes: + volume_model_update = {'id': volume.id} + try: + self.delete_volume(volume) + except Exception: + LOG.error('Delete volume %s failed.' % volume) + volume_model_update.update({'status': 'error_deleting'}) + else: + volume_model_update.update({'status': 'deleted'}) + + LOG.info('Deleted volume %s successfully' % volume) + volumes_model_update.append(volume_model_update) + + LOG.info("Delete group successfully") + return model_update, volumes_model_update + + def create_group_from_src(self, context, group, volumes, + group_snapshot=None, snapshots=None, + source_group=None, source_vols=None): + """ + create group from group or group-snapshot, + Driver need to create volume from volume or snapshot + """ + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.create_consistencygroup_from_src(context, group, volumes, + group_snapshot, snapshots, + source_group, source_vols) + + def create_consistencygroup_from_src(self, context, group, volumes, + group_snapshot=None, snapshots=None, + source_group=None, source_vols=None): + """ + create group from group or group-snapshot, + Driver need to create volume from volume or snapshot + """ + model_update = self.create_consistencygroup(context, group) + volumes_model_update = [] + delete_snapshots = False + + if not snapshots and source_vols: + snapshots = [] + for src_volume in source_vols: + volume_kwargs = { + 'id': src_volume.id, + '_name_id': None, + 'host': src_volume.host + } + snapshot_kwargs = { + 'id': six.text_type(uuid.uuid4()), + 'volume': objects.Volume(**volume_kwargs) + } + snapshots.append(objects.Snapshot(**snapshot_kwargs)) + + self._create_group_snapshot(snapshots) + delete_snapshots = True + + if snapshots: + volumes_model_update = self._create_volume_from_group_snapshot( + volumes, snapshots, delete_snapshots) + + if delete_snapshots: + self._delete_group_snapshot(snapshots) + + LOG.info("Create group from src successfully") + return model_update, volumes_model_update + + def _create_volume_from_group_snapshot(self, volumes, snapshots, delete_snapshots): + volumes_model_update = [] + added_volumes = [] + for i, volume in enumerate(volumes): + try: + vol_model_update = self.create_volume_from_snapshot( + volume, snapshots[i]) + vol_model_update.update({'id': volume.id}) + volumes_model_update.append(vol_model_update) + added_volumes.append(volume) + except Exception: + LOG.error("Create volume from snapshot error, Delete the newly created lun.") + with excutils.save_and_reraise_exception(): + self._delete_added_volume_snapshots( + added_volumes, snapshots, delete_snapshots) + + return volumes_model_update + + def _delete_added_volume_snapshots( + self, added_volumes, snapshots, delete_snapshots): + if delete_snapshots: + self._delete_group_snapshot(snapshots) + for add_volume in added_volumes: + vol_name = self._get_vol_name(add_volume) + self.fs_qos.remove(vol_name) + self.client.delete_volume(vol_name=vol_name) + LOG.info("delete storage newly added " + "volume success, volume is %s" % add_volume.id) + + def create_group_snapshot(self, context, group_snapshot, snapshots): + """Create group snapshot.""" + if not volume_utils.is_group_a_cg_snapshot_type(group_snapshot): + LOG.info("group_snapshot's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.create_cgsnapshot(context, group_snapshot, snapshots) + + def create_cgsnapshot(self, context, group_snapshot, snapshots): + """Create group snapshot.""" + LOG.info('Create group snapshot for group: %(group_snapshot)s', + {'group_snapshot': group_snapshot}) + + try: + snapshots_model_update = self._create_group_snapshot(snapshots) + except Exception as err: + msg = ("Create group snapshots failed. " + "Group snapshot id: %s. Reason is %s") % (group_snapshot.id, err) + LOG.error(msg) + raise exception.CinderException(msg) + + model_update = {'status': 'available'} + return model_update, snapshots_model_update + + def _create_group_snapshot(self, snapshots): + """Generate snapshots for all volumes in the group.""" + snapshots_model_update = [] + snapshot_group_list = [] + + for snapshot in snapshots: + snapshot_name = self._get_snapshot_name(snapshot) + vol_name = self._get_vol_name(snapshot.volume) + snapshot_group_list.append({ + 'name': snapshot_name, + 'sub_type': '0', + 'volume_name': vol_name + }) + snapshot_model_update = { + 'id': snapshot.id, + 'status': 'available', + } + snapshots_model_update.append(snapshot_model_update) + try: + self.client.create_consistent_snapshot_by_name(snapshot_group_list) + except Exception: + with excutils.save_and_reraise_exception(): + LOG.error("Create consistent snapshot failed, " + "snapshot_group_list is %s" % snapshot_group_list) + + return snapshots_model_update + + def delete_group_snapshot(self, context, group_snapshot, snapshots): + """Delete group snapshot.""" + if not volume_utils.is_group_a_cg_snapshot_type(group_snapshot): + LOG.info("group_snapshot's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.delete_cgsnapshot(context, group_snapshot, snapshots) + + def delete_cgsnapshot(self, context, group_snapshot, snapshots): + """Delete group snapshot.""" + LOG.info("Delete group_snapshot %s for " + "consistency group: %s" % (group_snapshot.id, group_snapshot)) + + try: + snapshots_model_update = self._delete_group_snapshot(snapshots) + except Exception as err: + msg = ("Delete cg snapshots failed. " + "group snapshot id: %s, reason is %s") % (group_snapshot.id, err) + LOG.error(msg) + raise exception.CinderException(msg) + + model_update = {'status': 'deleted'} + return model_update, snapshots_model_update + + def _delete_group_snapshot(self, snapshots): + """Delete all snapshots in snapshot group""" + snapshots_model_update = [] + for snapshot in snapshots: + snapshot_model_update = { + 'id': snapshot.id, + 'status': 'deleted' + } + snapshots_model_update.append(snapshot_model_update) + snapshot_name = self._get_snapshot_name(snapshot) + + if not self._check_snapshot_exist(snapshot.volume, snapshot): + LOG.info("snapshot %s not exist in array, " + "don't need to delete, try next one" % snapshot_name) + continue + self.client.delete_snapshot(snapshot_name=snapshot_name) + LOG.info("Delete snapshot successfully," + " the deleted snapshots is %s" % snapshot_name) + + return snapshots_model_update + class DSWAREDriver(DSWAREBaseDriver): def get_volume_stats(self, refresh=False): @@ -721,7 +1248,7 @@ def initialize_connection(self, volume, connector): vol_wwn = volume_info.get('wwn') by_id_path = "/dev/disk/by-id/" + "wwn-0x%s" % vol_wwn properties = {'device_path': by_id_path} - import time + LOG.info("Wait %(t)s second(s) for scanning the target device %(dev)s." % {"t": self.configuration.scan_device_timeout, "dev": by_id_path}) diff --git a/Cinder/Queens/fs_client.py b/Cinder/Queens/fs_client.py index 234d7f1..09d9581 100644 --- a/Cinder/Queens/fs_client.py +++ b/Cinder/Queens/fs_client.py @@ -14,16 +14,16 @@ # under the License. import json + import requests import six -import time +from oslo_log import log as logging from requests.adapters import HTTPAdapter from cinder import exception from cinder.i18n import _ from cinder.volume.drivers.fusionstorage import constants -from oslo_log import log as logging LOG = logging.getLogger(__name__) @@ -43,7 +43,8 @@ def __init__(self, fs_address, fs_user, fs_password, **extend_conf): self.session = None self.token = None self.version = None - mutual_authentication = extend_conf.get("mutual_authentication") + self.esn = None + mutual_authentication = extend_conf.get("mutual_authentication", {}) self.init_http_head(mutual_authentication) LOG.warning("Suppressing requests library SSL Warnings") @@ -147,6 +148,13 @@ def get_version(self): if result.get("currentVersion"): self.version = result["currentVersion"] + def get_esn(self): + url = "/cluster/sn" + result = self.call(url, "get") + self._assert_rest_result(result, _('Get cluster esn error.')) + self.esn = result.get("sn") + return self.esn + def login(self): self.get_version() url = '/sec/login' @@ -160,6 +168,7 @@ def login(self): self.session.headers.update({ "x-auth-token": self.token }) + self.get_esn() def logout(self): url = '/sec/logout' @@ -264,6 +273,15 @@ def query_volume_by_name(self, vol_name): result, _("Query volume by name session error")) return result.get('lunDetailInfo') + def query_volume_by_name_v2(self, vol_name): + url = '/api/v2/block_service/volumes?name=' + vol_name + result = self.call(url, 'GET', get_system_time=True) + if result.get('errorCode') in constants.VOLUME_NOT_EXIST: + return {} + self._assert_rest_result( + result, _("Query volume by name session error")) + return result.get('data', {}) + def query_volume_by_id(self, vol_id): url = 'v1.3/volume/queryById?volId=' + vol_id result = self.call(url, 'GET', get_version=True) @@ -746,3 +764,57 @@ def get_iscsi_links_info(self, iscsi_link_count, pool_list): return [iscsi["ip"] for iscsi in result.get("iscsiLinks", []) if iscsi.get("ip")] + + def create_lun_migration(self, src_lun_id, dst_lun_id, speed=2): + url = "/api/v2/block_service/lun_migration" + params = { + "parent_id": src_lun_id, + "target_lun_id": dst_lun_id, + "speed": speed, + "work_mode": 0 + } + result = self.call(url, "POST", params, get_system_time=True) + self._assert_rest_result(result, + _("create lun migration task error.")) + + def get_lun_migration_task_by_id(self, src_lun_id): + url = "/api/v2/block_service/lun_migration" + params = { + "id": src_lun_id + } + result = self.call(url, "GET", params, get_system_time=True) + self._assert_rest_result(result, + _("get lun migration task error.")) + return result.get('data', {}) + + def delete_lun_migration(self, src_lun_id): + url = "/api/v2/block_service/lun_migration" + params = { + 'id': src_lun_id + } + result = self.call(url, "DELETE", params, get_system_time=True) + self._assert_rest_result(result, + _("Delete lun migration task error.")) + + def get_volume_snapshot(self, volume_name): + url = "/volume/snapshot/list" + params = { + 'volName': volume_name, + 'batchNum': 1, + 'batchLimit': 10 + } + result = self.call(url, "POST", params) + return result.get('snapshotList', []) + + def create_consistent_snapshot_by_name(self, snapshot_group_list): + url = "/api/v2/block_service/consistency_snapshots" + result = self.call(url, "POST", snapshot_group_list, get_system_time=True) + self._assert_rest_result(result, _("create consistent_snapshot error.")) + return result.get('data', []) + + def create_full_volume_from_snapshot(self, vol_name, snapshot_name): + url = '/api/v2/block_service/createFullVolumeFromSnap' + params = {"snap_name_src": snapshot_name, "volume_name_dst": vol_name} + result = self.call(url, "POST", params, get_system_time=True) + self._assert_rest_result( + result, _("create full volume from snap fails")) diff --git a/Cinder/Queens/fs_qos.py b/Cinder/Queens/fs_qos.py index 731c45e..286dbc3 100644 --- a/Cinder/Queens/fs_qos.py +++ b/Cinder/Queens/fs_qos.py @@ -29,7 +29,11 @@ def __init__(self, client): def add(self, qos, vol_name): localtime = time.strftime('%Y%m%d%H%M%S', time.localtime()) - qos_name = constants.QOS_PREFIX + localtime + # QoS policy name. The value contains 1 to 63 characters. + # So we intercept volume_name Ensure that the length does not exceed 63 + vol_str = vol_name[-constants.QOS_MAX_INTERCEPT_LENGTH::] \ + if len(vol_name) >= constants.QOS_MAX_INTERCEPT_LENGTH else vol_name + qos_name = constants.QOS_PREFIX + localtime + '_' + vol_str self.client.create_qos(qos_name, qos) try: self.client.associate_qos_with_volume(vol_name, qos_name) diff --git a/Cinder/Queens/fs_utils.py b/Cinder/Queens/fs_utils.py index 8b9ae78..0856038 100644 --- a/Cinder/Queens/fs_utils.py +++ b/Cinder/Queens/fs_utils.py @@ -16,11 +16,11 @@ import datetime import hashlib import ipaddress -import pytz import random -import six import time +import pytz +import six from oslo_log import log as logging from oslo_service import loopingcall from oslo_utils import units @@ -758,3 +758,9 @@ def get_iscsi_info_from_storage(manager_ips, use_ipv6, valid_iscsi_ips, valid_node_ips): return _get_target_info(manager_ips, use_ipv6, valid_iscsi_ips, valid_node_ips) + + +def encode_name(my_uuid): + encoded_name = hashlib.md5(my_uuid.encode('utf-8')).hexdigest() + target_lun_prefix = my_uuid.split('-')[0] + '-' + return target_lun_prefix + encoded_name diff --git a/Cinder/Rocky/constants.py b/Cinder/Rocky/constants.py index 5f46ece..b4cb843 100644 --- a/Cinder/Rocky/constants.py +++ b/Cinder/Rocky/constants.py @@ -45,6 +45,14 @@ CONF_STORAGE_CERT_FILEPATH = "storage_cert_filepath" CONF_STORAGE_SSL_TWO_WAY_AUTH = "storage_ssl_two_way_auth" +DEFAULT_WAIT_INTERVAL = 5 +MIGRATION_COMPLETE = 76 +MIGRATION_FAULT = 74 +STATUS_HEALTH = 1 +STATUS_VOLUME_READY = 27 +MIGRATION_WAIT_INTERVAL = 5 +DEFAULT_WAIT_TIMEOUT = 3600 * 24 * 30 + QOS_MUST_SET = ["maxIOPS", "maxMBPS"] QOS_KEYS = ["maxIOPS", "maxMBPS", "total_iops_sec", "total_bytes_sec"] QOS_SCHEDULER_KEYS = ["scheduleType", "startDate", "startTime", @@ -53,6 +61,7 @@ QOS_SCHEDULER_DEFAULT_TYPE = "0" QOS_SCHEDULER_WEEK_TYPE = "3" QOS_SUPPORT_SCHEDULE_VERSION = "8.0" +QOS_MAX_INTERCEPT_LENGTH = 36 SECONDS_OF_DAY = 24 * 60 * 60 SECONDS_OF_HOUR = 60 * 60 SNAPSHOT_HEALTH_STATUS = ( @@ -80,3 +89,9 @@ HOSTGROUP_ALREADY_EXIST = 50157044 INITIATOR_ALREADY_EXIST = 50155102 INITIATOR_IN_HOST = 50157021 + +CHECK_CLONED_INTERVAL = 2 +REST_VOLUME_CREATING_STATUS = 15 +REST_VOLUME_DUPLICATE_VOLUME = 6 +REST_VOLUME_CREATE_SUCCESS_STATUS = 0 +CLONE_VOLUME_TIMEOUT = 3600 * 24 * 30 diff --git a/Cinder/Rocky/dsware.py b/Cinder/Rocky/dsware.py index c1c15d9..38d1262 100644 --- a/Cinder/Rocky/dsware.py +++ b/Cinder/Rocky/dsware.py @@ -14,16 +14,22 @@ # under the License. import json - +import time +import uuid from multiprocessing import Lock + +import six from oslo_config import cfg from oslo_log import log as logging +from oslo_utils import excutils from oslo_utils import units +from oslo_service import loopingcall from cinder import coordination from cinder import exception from cinder.i18n import _ from cinder import interface +from cinder import objects from cinder.volume import driver from cinder.volume.drivers.fusionstorage import constants from cinder.volume.drivers.fusionstorage import fs_client @@ -105,6 +111,9 @@ cfg.StrOpt('storage_key_filepath', default='', help='Client key directory.'), + cfg.BoolOpt('full_clone', + default=False, + help='Whether use full clone.'), ] CONF = cfg.CONF @@ -113,7 +122,7 @@ @interface.volumedriver class DSWAREBaseDriver(driver.VolumeDriver): - VERSION = '2.5.RC4' + VERSION = "2.6.1" CI_WIKI_NAME = 'Huawei_FusionStorage_CI' def __init__(self, *args, **kwargs): @@ -210,6 +219,7 @@ def _update_single_pool_info_status(self, pool_info): "total_capacity_gb": capacity['total_capacity_gb'], "free_capacity_gb": capacity['free_capacity_gb'], "provisioned_capacity_gb": capacity['provisioned_capacity_gb'], + "location_info": self.client.esn, "QoS_support": True, 'multiattach': True, "thin_provisioning_support": True, @@ -247,8 +257,12 @@ def _raise_exception(msg): raise exception.VolumeBackendAPIException(data=msg) def _get_pool_id(self, volume): - pool_id_list = [] pool_name = volume_utils.extract_host(volume.host, level='pool') + pool_id = self._get_pool_id_by_name(pool_name) + return pool_id + + def _get_pool_id_by_name(self, pool_name): + pool_id_list = [] all_pools = self.client.query_pool_info() for pool in all_pools: if pool_name == pool['poolName']: @@ -363,29 +377,111 @@ def _expand_volume_when_create(self, vol_name, vol_size): self.client.delete_volume(vol_name=vol_name) raise + def _check_create_cloned_volume_finish(self, new_volume_name, start_time): + LOG.debug('Loopcall: _check_create_cloned_volume_finish(), ' + 'volume-name %s', + new_volume_name) + current_volume = self.client.query_volume_by_name(new_volume_name) + + if current_volume and 'status' in current_volume: + status = int(current_volume['status']) + LOG.debug('Wait clone volume %(volume_name)s, status:%(status)s.', + {"volume_name": new_volume_name, + "status": status}) + if status in {constants.REST_VOLUME_CREATING_STATUS, + constants.REST_VOLUME_DUPLICATE_VOLUME}: + LOG.debug(_("Volume %s is cloning"), new_volume_name) + elif status == constants.REST_VOLUME_CREATE_SUCCESS_STATUS: + raise loopingcall.LoopingCallDone(retvalue=True) + else: + msg = _('Clone volume %(new_volume_name)s failed, ' + 'the status is:%(status)s.') + LOG.error(msg, {'new_volume_name': new_volume_name, + 'status': status}) + raise loopingcall.LoopingCallDone(retvalue=False) + + max_time_out = constants.CLONE_VOLUME_TIMEOUT + current_time = time.time() + if (current_time - start_time) > max_time_out: + msg = _('Dsware clone volume time out. ' + 'Volume: %(new_volume_name)s, status: %(status)s') + LOG.error(msg, {'new_volume_name': new_volume_name, + 'status': current_volume['status']}) + raise loopingcall.LoopingCallDone(retvalue=False) + else: + LOG.warning(_('Can not find volume %s'), new_volume_name) + msg = "DSWARE clone volume failed:volume can not find from dsware" + LOG.error(msg) + raise loopingcall.LoopingCallDone(retvalue=False) + + def _wait_for_create_cloned_volume_finish_timer(self, new_volume_name): + timer = loopingcall.FixedIntervalLoopingCall( + self._check_create_cloned_volume_finish, + new_volume_name, time.time()) + LOG.debug('Calling _check_create_cloned_volume_finish: volume-name %s', + new_volume_name) + ret = timer.start(interval=constants.CHECK_CLONED_INTERVAL).wait() + timer.stop() + return ret + def create_volume_from_snapshot(self, volume, snapshot): vol_name = self._get_vol_name(volume) snapshot_name = self._get_snapshot_name(snapshot) vol_size = volume.size + pool_id = self._get_pool_id(volume) if not self._check_snapshot_exist(snapshot.volume, snapshot): msg = _("Snapshot: %(name)s does not exist!" ) % {"name": snapshot_name} self._raise_exception(msg) - elif self._check_volume_exist(volume): + if self._check_volume_exist(volume): msg = _("Volume: %(vol_name)s already exists!" ) % {'vol_name': vol_name} self._raise_exception(msg) - else: - vol_size *= units.Ki + + vol_size *= units.Ki + if not self.configuration.full_clone: self.client.create_volume_from_snapshot( snapshot_name=snapshot_name, vol_name=vol_name, vol_size=vol_size) - self._add_qos_to_volume(volume, vol_name) - self._expand_volume_when_create(vol_name, vol_size) - result = self.client.query_volume_by_name(vol_name=vol_name) - return ({"metadata": {'lun_wwn': result.get('wwn')}} - if result else {}) + else: + self.client.create_volume(vol_name, vol_size, pool_id) + self.client.create_full_volume_from_snapshot(vol_name, + snapshot_name) + ret = self._wait_for_create_cloned_volume_finish_timer(vol_name) + if not ret: + msg = _('Create full volume %s from snap failed') % vol_name + self._raise_exception(msg) + self._add_qos_to_volume(volume, vol_name) + self._expand_volume_when_create(vol_name, vol_size) + result = self.client.query_volume_by_name(vol_name=vol_name) + return ({"metadata": {'lun_wwn': result.get('wwn')}} + if result else {}) + + def _create_volume_from_volume_full_clone(self, vol_name, vol_size, pool_id, + src_vol_name): + tmp_snap_name = "temp" + src_vol_name + "clone" + vol_name + + self.client.create_snapshot(tmp_snap_name, src_vol_name) + try: + self.client.create_volume(vol_name, vol_size, pool_id) + except Exception as err: + self.client.delete_snapshot(tmp_snap_name) + raise err + + try: + self.client.create_full_volume_from_snapshot( + vol_name, tmp_snap_name) + except Exception as err: + self.client.delete_snapshot(tmp_snap_name) + self.client.delete_volume(vol_name) + raise err + + ret = self._wait_for_create_cloned_volume_finish_timer(vol_name) + if not ret: + msg = _('Create full volume %s from snap failed') % vol_name + self._raise_exception(msg) + self.client.delete_snapshot(tmp_snap_name) def create_cloned_volume(self, volume, src_volume): vol_name = self._get_vol_name(volume) @@ -398,15 +494,22 @@ def create_cloned_volume(self, volume, src_volume): msg = _("Volume: %(vol_name)s does not exist!" ) % {"vol_name": src_vol_name} self._raise_exception(msg) - else: + + if not self.configuration.full_clone: self.client.create_volume_from_volume( vol_name=vol_name, vol_size=vol_size, src_vol_name=src_vol_name) - self._add_qos_to_volume(volume, vol_name) - self._expand_volume_when_create(vol_name, vol_size) - result = self.client.query_volume_by_name(vol_name=vol_name) - return ({"metadata": {'lun_wwn': result.get('wwn')}} - if result else {}) + else: + pool_id = self._get_pool_id(volume) + self._create_volume_from_volume_full_clone( + vol_name=vol_name, vol_size=vol_size, pool_id=pool_id, + src_vol_name=src_vol_name) + + self._add_qos_to_volume(volume, vol_name) + self._expand_volume_when_create(vol_name, vol_size) + result = self.client.query_volume_by_name(vol_name=vol_name) + return ({"metadata": {'lun_wwn': result.get('wwn')}} + if result else {}) def create_snapshot(self, snapshot): snapshot_name = self._get_snapshot_name(snapshot) @@ -581,12 +684,13 @@ def unmanage_snapshot(self, snapshot): def _check_need_changes_for_retype(self, volume, new_type, host, vol_name): before_change = {} after_change = {} - if volume.host != host["host"]: - msg = (_("Do not support retype between different host. Volume's " + migrate = False + if volume.host != host.get("host"): + migrate = True + msg = (_("retype support migration between different host. Volume's " "host: %(vol_host)s, host's host: %(host)s") - % {"vol_host": volume.host, "host": host['host']}) - LOG.error(msg) - raise exception.InvalidInput(msg) + % {"vol_host": volume.host, "host": host.get("host")}) + LOG.info(msg) old_opts = fs_utils.get_volume_specs(self.client, vol_name) new_opts = fs_utils.get_volume_type_params(new_type, self.client) @@ -596,7 +700,7 @@ def _check_need_changes_for_retype(self, volume, new_type, host, vol_name): change_opts = {"old_opts": before_change, "new_opts": after_change} - return change_opts + return migrate, change_opts def retype(self, context, volume, new_type, diff, host): LOG.info("Retype volume: %(vol)s, new_type: %(new_type)s, " @@ -607,13 +711,177 @@ def retype(self, context, volume, new_type, diff, host): "host": host}) vol_name = self._get_vol_name(volume) - change_opts = self._check_need_changes_for_retype( + migrate, change_opts = self._check_need_changes_for_retype( volume, new_type, host, vol_name) + if migrate: + src_lun_id = self._check_volume_exist_on_array(volume) + LOG.debug("Begin to migrate LUN(id: %(lun_id)s) with " + "change %(change_opts)s.", + {"lun_id": src_lun_id, "change_opts": change_opts}) + moved = self._migrate_volume(volume, host, src_lun_id) + if not moved: + LOG.warning("Storage-assisted migration failed during " + "retype.") + return False, None self._change_lun(vol_name, change_opts.get("new_opts"), change_opts.get("old_opts")) return True, None + def migrate_volume(self, context, volume, host): + """Migrate a volume within the same array.""" + LOG.info("Migrate Volume:%(volume)s, host:%(host)s", + {"volume": volume.id, + "host": host}) + src_lun_id = self._check_volume_exist_on_array(volume) + + moved = self._migrate_volume(volume, host, src_lun_id) + return moved, {} + + def _create_dst_volume(self, volume, host): + pool_name = host['capabilities']['pool_name'] + pool_id = self._get_pool_id_by_name(pool_name) + vol_name = fs_utils.encode_name(six.text_type(uuid.uuid4())) + vol_size = volume.size + vol_size *= units.Ki + self.client.create_volume( + pool_id=pool_id, vol_name=vol_name, vol_size=vol_size) + + result = self.client.query_volume_by_name_v2(vol_name=vol_name) + dst_lun_id = result.get('id') + self._wait_volume_ready(vol_name) + return vol_name, dst_lun_id + + def _migrate_volume(self, volume, host, src_lun_id): + """create migration task and wait for task done""" + if not self._check_migration_valid(host): + return False + + vol_name, dst_lun_id = self._create_dst_volume(volume, host) + + try: + self.client.create_lun_migration(src_lun_id, dst_lun_id) + + def _is_lun_migration_complete(): + return self._is_lun_migration_complete(src_lun_id, dst_lun_id) + + wait_interval = constants.MIGRATION_WAIT_INTERVAL + fs_utils.wait_for_condition(_is_lun_migration_complete, + wait_interval, + constants.DEFAULT_WAIT_TIMEOUT) + # Clean up if migration failed. + except Exception as ex: + raise exception.VolumeBackendAPIException(data=ex) + finally: + if self._is_lun_migration_exist(src_lun_id, dst_lun_id): + self.client.delete_lun_migration(src_lun_id) + self._delete_lun_with_check(vol_name) + + LOG.info("Migrate lun %s successfully.", src_lun_id) + return True + + def _delete_lun_with_check(self, vol_name): + if self.client.query_volume_by_name(vol_name): + # migrate_dst_lun don't have qos, so don't + # need to remove qos, Delete the LUN directly. + self.client.delete_volume(vol_name) + + def _is_lun_migration_complete(self, src_lun_id, dst_lun_id): + result = self.client.get_lun_migration_task_by_id(src_lun_id) + found_migration_task = False + if not result: + return False + + if (str(src_lun_id) == result.get('parent_id') and + str(dst_lun_id) == result.get('target_lun_id')): + found_migration_task = True + if constants.MIGRATION_COMPLETE == result.get('running_status'): + return True + if constants.MIGRATION_FAULT == result.get('running_status'): + msg = _("Lun migration error. " + "the migration task running_status is abnormal") + LOG.error(msg) + raise exception.VolumeBackendAPIException(data=msg) + + if not found_migration_task: + err_msg = _("lun migration error, Cannot find migration task.") + LOG.error(err_msg) + raise exception.VolumeBackendAPIException(data=err_msg) + + return False + + def _is_lun_migration_exist(self, src_lun_id, dst_lun_id): + try: + result = self.client.get_lun_migration_task_by_id(src_lun_id) + except Exception: + LOG.error("Get LUN migration error.") + return False + + if (str(src_lun_id) == result.get('parent_id') and + str(dst_lun_id) == result.get('target_lun_id')): + return True + return False + + def _wait_volume_ready(self, vol_name): + wait_interval = constants.DEFAULT_WAIT_INTERVAL + + def _volume_ready(): + result = self.client.query_volume_by_name_v2(vol_name) + if not result: + return False + + if (result.get('health_status') == constants.STATUS_HEALTH + and result.get('running_status') == constants.STATUS_VOLUME_READY): + return True + return False + + fs_utils.wait_for_condition(_volume_ready, + wait_interval, + wait_interval * 10) + + def _check_migration_valid(self, host): + if 'pool_name' not in host.get('capabilities', {}): + return False + + target_device = host.get('capabilities', {}).get('location_info') + + # Source and destination should be on same array. + if target_device != self.client.esn: + LOG.error("lun migration error, " + "Source and destination should be on same array") + return False + + pool_name = host.get('capabilities', {}).get('pool_name', '') + if len(pool_name) == 0: + LOG.error("lun migration error, pool_name not exists") + return False + + return True + + def _check_volume_exist_on_array(self, volume): + volume_name = self._get_vol_name(volume) + result = self._check_volume_exist(volume) + if not result: + msg = _("Volume %s does not exist on the array." + ) % volume.id + self._raise_exception(msg) + + lun_wwn = result.get('wwn') + if not lun_wwn: + LOG.debug("No LUN WWN recorded for volume %s.", volume.id) + + lun_id = result.get('volId') + if not lun_id: + msg = _("Volume %s does not exist on the array." + ) % volume.id + self._raise_exception(msg) + + if self.client.get_volume_snapshot(volume_name): + msg = _("Volume %s which have snapshot cannot do lun migration" + ) % volume.id + self._raise_exception(msg) + return lun_id + def _rollback_snapshot(self, vol_name, snap_name): def _snapshot_rollback_finish(): snapshot_info = self.client.get_snapshot_info_by_name(snap_name) @@ -669,6 +937,265 @@ def ensure_export(self, context, volume): def remove_export(self, context, volume): pass + def create_group(self, context, group): + """Creates a group. Driver only need to return state""" + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.create_consistencygroup(context, group) + + def create_consistencygroup(self, context, group): + """Creates a group. Driver only need to return state""" + LOG.info("Create group successfully") + return {'status': 'available'} + + def update_group(self, context, group, + add_volumes=None, remove_volumes=None): + """ + The volume manager will adds/removes the volume to/from the + group in the database, if need add_volumes, Driver just need + to check whether volume is in array or not + """ + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.update_consistencygroup( + context, group, add_volumes, remove_volumes) + + def update_consistencygroup(self, context, group, + add_volumes=None, remove_volumes=None): + """ + The volume manager will adds/removes the volume to/from the + group in the database, if need add_volumes, Driver just need + to check whether volume is in array or not + """ + if add_volumes is None: + add_volumes = [] + for volume in add_volumes: + try: + self._check_volume_exist_on_array(volume) + except Exception: + with excutils.save_and_reraise_exception(): + LOG.error("The add_volume %s not exist on array" % volume.id) + + model_update = {'status': 'available'} + LOG.info("Update group successfully") + return model_update, None, None + + def delete_group(self, context, group, volumes): + """delete the group, Driver need to delete relation lun on array""" + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.delete_consistencygroup(context, group, volumes) + + def delete_consistencygroup(self, context, group, volumes): + """delete the group, Driver need to delete relation lun on array""" + volumes_model_update = [] + model_update = {'status': 'deleted'} + for volume in volumes: + volume_model_update = {'id': volume.id} + try: + self.delete_volume(volume) + except Exception: + LOG.error('Delete volume %s failed.' % volume) + volume_model_update.update({'status': 'error_deleting'}) + else: + volume_model_update.update({'status': 'deleted'}) + + LOG.info('Deleted volume %s successfully' % volume) + volumes_model_update.append(volume_model_update) + + LOG.info("Delete group successfully") + return model_update, volumes_model_update + + def create_group_from_src(self, context, group, volumes, + group_snapshot=None, snapshots=None, + source_group=None, source_vols=None): + """ + create group from group or group-snapshot, + Driver need to create volume from volume or snapshot + """ + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.create_consistencygroup_from_src(context, group, volumes, + group_snapshot, snapshots, + source_group, source_vols) + + def create_consistencygroup_from_src(self, context, group, volumes, + group_snapshot=None, snapshots=None, + source_group=None, source_vols=None): + """ + create group from group or group-snapshot, + Driver need to create volume from volume or snapshot + """ + model_update = self.create_consistencygroup(context, group) + volumes_model_update = [] + delete_snapshots = False + + if not snapshots and source_vols: + snapshots = [] + for src_volume in source_vols: + volume_kwargs = { + 'id': src_volume.id, + '_name_id': None, + 'host': src_volume.host + } + snapshot_kwargs = { + 'id': six.text_type(uuid.uuid4()), + 'volume': objects.Volume(**volume_kwargs) + } + snapshots.append(objects.Snapshot(**snapshot_kwargs)) + + self._create_group_snapshot(snapshots) + delete_snapshots = True + + if snapshots: + volumes_model_update = self._create_volume_from_group_snapshot( + volumes, snapshots, delete_snapshots) + + if delete_snapshots: + self._delete_group_snapshot(snapshots) + + LOG.info("Create group from src successfully") + return model_update, volumes_model_update + + def _create_volume_from_group_snapshot(self, volumes, snapshots, delete_snapshots): + volumes_model_update = [] + added_volumes = [] + for i, volume in enumerate(volumes): + try: + vol_model_update = self.create_volume_from_snapshot( + volume, snapshots[i]) + vol_model_update.update({'id': volume.id}) + volumes_model_update.append(vol_model_update) + added_volumes.append(volume) + except Exception: + LOG.error("Create volume from snapshot error, Delete the newly created lun.") + with excutils.save_and_reraise_exception(): + self._delete_added_volume_snapshots( + added_volumes, snapshots, delete_snapshots) + + return volumes_model_update + + def _delete_added_volume_snapshots( + self, added_volumes, snapshots, delete_snapshots): + if delete_snapshots: + self._delete_group_snapshot(snapshots) + for add_volume in added_volumes: + vol_name = self._get_vol_name(add_volume) + self.fs_qos.remove(vol_name) + self.client.delete_volume(vol_name=vol_name) + LOG.info("delete storage newly added " + "volume success, volume is %s" % add_volume.id) + + def create_group_snapshot(self, context, group_snapshot, snapshots): + """Create group snapshot.""" + if not volume_utils.is_group_a_cg_snapshot_type(group_snapshot): + LOG.info("group_snapshot's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.create_cgsnapshot(context, group_snapshot, snapshots) + + def create_cgsnapshot(self, context, group_snapshot, snapshots): + """Create group snapshot.""" + LOG.info('Create group snapshot for group: %(group_snapshot)s', + {'group_snapshot': group_snapshot}) + + try: + snapshots_model_update = self._create_group_snapshot(snapshots) + except Exception as err: + msg = ("Create group snapshots failed. " + "Group snapshot id: %s. Reason is %s") % (group_snapshot.id, err) + LOG.error(msg) + raise exception.CinderException(msg) + + model_update = {'status': 'available'} + return model_update, snapshots_model_update + + def _create_group_snapshot(self, snapshots): + """Generate snapshots for all volumes in the group.""" + snapshots_model_update = [] + snapshot_group_list = [] + + for snapshot in snapshots: + snapshot_name = self._get_snapshot_name(snapshot) + vol_name = self._get_vol_name(snapshot.volume) + snapshot_group_list.append({ + 'name': snapshot_name, + 'sub_type': '0', + 'volume_name': vol_name + }) + snapshot_model_update = { + 'id': snapshot.id, + 'status': 'available', + } + snapshots_model_update.append(snapshot_model_update) + try: + self.client.create_consistent_snapshot_by_name(snapshot_group_list) + except Exception: + with excutils.save_and_reraise_exception(): + LOG.error("Create consistent snapshot failed, " + "snapshot_group_list is %s" % snapshot_group_list) + + return snapshots_model_update + + def delete_group_snapshot(self, context, group_snapshot, snapshots): + """Delete group snapshot.""" + if not volume_utils.is_group_a_cg_snapshot_type(group_snapshot): + LOG.info("group_snapshot's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.delete_cgsnapshot(context, group_snapshot, snapshots) + + def delete_cgsnapshot(self, context, group_snapshot, snapshots): + """Delete group snapshot.""" + LOG.info("Delete group_snapshot %s for " + "consistency group: %s" % (group_snapshot.id, group_snapshot)) + + try: + snapshots_model_update = self._delete_group_snapshot(snapshots) + except Exception as err: + msg = ("Delete cg snapshots failed. " + "group snapshot id: %s, reason is %s") % (group_snapshot.id, err) + LOG.error(msg) + raise exception.CinderException(msg) + + model_update = {'status': 'deleted'} + return model_update, snapshots_model_update + + def _delete_group_snapshot(self, snapshots): + """Delete all snapshots in snapshot group""" + snapshots_model_update = [] + for snapshot in snapshots: + snapshot_model_update = { + 'id': snapshot.id, + 'status': 'deleted' + } + snapshots_model_update.append(snapshot_model_update) + snapshot_name = self._get_snapshot_name(snapshot) + + if not self._check_snapshot_exist(snapshot.volume, snapshot): + LOG.info("snapshot %s not exist in array, " + "don't need to delete, try next one" % snapshot_name) + continue + self.client.delete_snapshot(snapshot_name=snapshot_name) + LOG.info("Delete snapshot successfully," + " the deleted snapshots is %s" % snapshot_name) + + return snapshots_model_update + class DSWAREDriver(DSWAREBaseDriver): def get_volume_stats(self, refresh=False): @@ -721,7 +1248,7 @@ def initialize_connection(self, volume, connector): vol_wwn = volume_info.get('wwn') by_id_path = "/dev/disk/by-id/" + "wwn-0x%s" % vol_wwn properties = {'device_path': by_id_path} - import time + LOG.info("Wait %(t)s second(s) for scanning the target device %(dev)s." % {"t": self.configuration.scan_device_timeout, "dev": by_id_path}) diff --git a/Cinder/Rocky/fs_client.py b/Cinder/Rocky/fs_client.py index 234d7f1..09d9581 100644 --- a/Cinder/Rocky/fs_client.py +++ b/Cinder/Rocky/fs_client.py @@ -14,16 +14,16 @@ # under the License. import json + import requests import six -import time +from oslo_log import log as logging from requests.adapters import HTTPAdapter from cinder import exception from cinder.i18n import _ from cinder.volume.drivers.fusionstorage import constants -from oslo_log import log as logging LOG = logging.getLogger(__name__) @@ -43,7 +43,8 @@ def __init__(self, fs_address, fs_user, fs_password, **extend_conf): self.session = None self.token = None self.version = None - mutual_authentication = extend_conf.get("mutual_authentication") + self.esn = None + mutual_authentication = extend_conf.get("mutual_authentication", {}) self.init_http_head(mutual_authentication) LOG.warning("Suppressing requests library SSL Warnings") @@ -147,6 +148,13 @@ def get_version(self): if result.get("currentVersion"): self.version = result["currentVersion"] + def get_esn(self): + url = "/cluster/sn" + result = self.call(url, "get") + self._assert_rest_result(result, _('Get cluster esn error.')) + self.esn = result.get("sn") + return self.esn + def login(self): self.get_version() url = '/sec/login' @@ -160,6 +168,7 @@ def login(self): self.session.headers.update({ "x-auth-token": self.token }) + self.get_esn() def logout(self): url = '/sec/logout' @@ -264,6 +273,15 @@ def query_volume_by_name(self, vol_name): result, _("Query volume by name session error")) return result.get('lunDetailInfo') + def query_volume_by_name_v2(self, vol_name): + url = '/api/v2/block_service/volumes?name=' + vol_name + result = self.call(url, 'GET', get_system_time=True) + if result.get('errorCode') in constants.VOLUME_NOT_EXIST: + return {} + self._assert_rest_result( + result, _("Query volume by name session error")) + return result.get('data', {}) + def query_volume_by_id(self, vol_id): url = 'v1.3/volume/queryById?volId=' + vol_id result = self.call(url, 'GET', get_version=True) @@ -746,3 +764,57 @@ def get_iscsi_links_info(self, iscsi_link_count, pool_list): return [iscsi["ip"] for iscsi in result.get("iscsiLinks", []) if iscsi.get("ip")] + + def create_lun_migration(self, src_lun_id, dst_lun_id, speed=2): + url = "/api/v2/block_service/lun_migration" + params = { + "parent_id": src_lun_id, + "target_lun_id": dst_lun_id, + "speed": speed, + "work_mode": 0 + } + result = self.call(url, "POST", params, get_system_time=True) + self._assert_rest_result(result, + _("create lun migration task error.")) + + def get_lun_migration_task_by_id(self, src_lun_id): + url = "/api/v2/block_service/lun_migration" + params = { + "id": src_lun_id + } + result = self.call(url, "GET", params, get_system_time=True) + self._assert_rest_result(result, + _("get lun migration task error.")) + return result.get('data', {}) + + def delete_lun_migration(self, src_lun_id): + url = "/api/v2/block_service/lun_migration" + params = { + 'id': src_lun_id + } + result = self.call(url, "DELETE", params, get_system_time=True) + self._assert_rest_result(result, + _("Delete lun migration task error.")) + + def get_volume_snapshot(self, volume_name): + url = "/volume/snapshot/list" + params = { + 'volName': volume_name, + 'batchNum': 1, + 'batchLimit': 10 + } + result = self.call(url, "POST", params) + return result.get('snapshotList', []) + + def create_consistent_snapshot_by_name(self, snapshot_group_list): + url = "/api/v2/block_service/consistency_snapshots" + result = self.call(url, "POST", snapshot_group_list, get_system_time=True) + self._assert_rest_result(result, _("create consistent_snapshot error.")) + return result.get('data', []) + + def create_full_volume_from_snapshot(self, vol_name, snapshot_name): + url = '/api/v2/block_service/createFullVolumeFromSnap' + params = {"snap_name_src": snapshot_name, "volume_name_dst": vol_name} + result = self.call(url, "POST", params, get_system_time=True) + self._assert_rest_result( + result, _("create full volume from snap fails")) diff --git a/Cinder/Rocky/fs_qos.py b/Cinder/Rocky/fs_qos.py index 731c45e..286dbc3 100644 --- a/Cinder/Rocky/fs_qos.py +++ b/Cinder/Rocky/fs_qos.py @@ -29,7 +29,11 @@ def __init__(self, client): def add(self, qos, vol_name): localtime = time.strftime('%Y%m%d%H%M%S', time.localtime()) - qos_name = constants.QOS_PREFIX + localtime + # QoS policy name. The value contains 1 to 63 characters. + # So we intercept volume_name Ensure that the length does not exceed 63 + vol_str = vol_name[-constants.QOS_MAX_INTERCEPT_LENGTH::] \ + if len(vol_name) >= constants.QOS_MAX_INTERCEPT_LENGTH else vol_name + qos_name = constants.QOS_PREFIX + localtime + '_' + vol_str self.client.create_qos(qos_name, qos) try: self.client.associate_qos_with_volume(vol_name, qos_name) diff --git a/Cinder/Rocky/fs_utils.py b/Cinder/Rocky/fs_utils.py index 8b9ae78..0856038 100644 --- a/Cinder/Rocky/fs_utils.py +++ b/Cinder/Rocky/fs_utils.py @@ -16,11 +16,11 @@ import datetime import hashlib import ipaddress -import pytz import random -import six import time +import pytz +import six from oslo_log import log as logging from oslo_service import loopingcall from oslo_utils import units @@ -758,3 +758,9 @@ def get_iscsi_info_from_storage(manager_ips, use_ipv6, valid_iscsi_ips, valid_node_ips): return _get_target_info(manager_ips, use_ipv6, valid_iscsi_ips, valid_node_ips) + + +def encode_name(my_uuid): + encoded_name = hashlib.md5(my_uuid.encode('utf-8')).hexdigest() + target_lun_prefix = my_uuid.split('-')[0] + '-' + return target_lun_prefix + encoded_name diff --git a/Cinder/Stein/constants.py b/Cinder/Stein/constants.py index 5f46ece..b4cb843 100644 --- a/Cinder/Stein/constants.py +++ b/Cinder/Stein/constants.py @@ -45,6 +45,14 @@ CONF_STORAGE_CERT_FILEPATH = "storage_cert_filepath" CONF_STORAGE_SSL_TWO_WAY_AUTH = "storage_ssl_two_way_auth" +DEFAULT_WAIT_INTERVAL = 5 +MIGRATION_COMPLETE = 76 +MIGRATION_FAULT = 74 +STATUS_HEALTH = 1 +STATUS_VOLUME_READY = 27 +MIGRATION_WAIT_INTERVAL = 5 +DEFAULT_WAIT_TIMEOUT = 3600 * 24 * 30 + QOS_MUST_SET = ["maxIOPS", "maxMBPS"] QOS_KEYS = ["maxIOPS", "maxMBPS", "total_iops_sec", "total_bytes_sec"] QOS_SCHEDULER_KEYS = ["scheduleType", "startDate", "startTime", @@ -53,6 +61,7 @@ QOS_SCHEDULER_DEFAULT_TYPE = "0" QOS_SCHEDULER_WEEK_TYPE = "3" QOS_SUPPORT_SCHEDULE_VERSION = "8.0" +QOS_MAX_INTERCEPT_LENGTH = 36 SECONDS_OF_DAY = 24 * 60 * 60 SECONDS_OF_HOUR = 60 * 60 SNAPSHOT_HEALTH_STATUS = ( @@ -80,3 +89,9 @@ HOSTGROUP_ALREADY_EXIST = 50157044 INITIATOR_ALREADY_EXIST = 50155102 INITIATOR_IN_HOST = 50157021 + +CHECK_CLONED_INTERVAL = 2 +REST_VOLUME_CREATING_STATUS = 15 +REST_VOLUME_DUPLICATE_VOLUME = 6 +REST_VOLUME_CREATE_SUCCESS_STATUS = 0 +CLONE_VOLUME_TIMEOUT = 3600 * 24 * 30 diff --git a/Cinder/Stein/dsware.py b/Cinder/Stein/dsware.py index c1c15d9..38d1262 100644 --- a/Cinder/Stein/dsware.py +++ b/Cinder/Stein/dsware.py @@ -14,16 +14,22 @@ # under the License. import json - +import time +import uuid from multiprocessing import Lock + +import six from oslo_config import cfg from oslo_log import log as logging +from oslo_utils import excutils from oslo_utils import units +from oslo_service import loopingcall from cinder import coordination from cinder import exception from cinder.i18n import _ from cinder import interface +from cinder import objects from cinder.volume import driver from cinder.volume.drivers.fusionstorage import constants from cinder.volume.drivers.fusionstorage import fs_client @@ -105,6 +111,9 @@ cfg.StrOpt('storage_key_filepath', default='', help='Client key directory.'), + cfg.BoolOpt('full_clone', + default=False, + help='Whether use full clone.'), ] CONF = cfg.CONF @@ -113,7 +122,7 @@ @interface.volumedriver class DSWAREBaseDriver(driver.VolumeDriver): - VERSION = '2.5.RC4' + VERSION = "2.6.1" CI_WIKI_NAME = 'Huawei_FusionStorage_CI' def __init__(self, *args, **kwargs): @@ -210,6 +219,7 @@ def _update_single_pool_info_status(self, pool_info): "total_capacity_gb": capacity['total_capacity_gb'], "free_capacity_gb": capacity['free_capacity_gb'], "provisioned_capacity_gb": capacity['provisioned_capacity_gb'], + "location_info": self.client.esn, "QoS_support": True, 'multiattach': True, "thin_provisioning_support": True, @@ -247,8 +257,12 @@ def _raise_exception(msg): raise exception.VolumeBackendAPIException(data=msg) def _get_pool_id(self, volume): - pool_id_list = [] pool_name = volume_utils.extract_host(volume.host, level='pool') + pool_id = self._get_pool_id_by_name(pool_name) + return pool_id + + def _get_pool_id_by_name(self, pool_name): + pool_id_list = [] all_pools = self.client.query_pool_info() for pool in all_pools: if pool_name == pool['poolName']: @@ -363,29 +377,111 @@ def _expand_volume_when_create(self, vol_name, vol_size): self.client.delete_volume(vol_name=vol_name) raise + def _check_create_cloned_volume_finish(self, new_volume_name, start_time): + LOG.debug('Loopcall: _check_create_cloned_volume_finish(), ' + 'volume-name %s', + new_volume_name) + current_volume = self.client.query_volume_by_name(new_volume_name) + + if current_volume and 'status' in current_volume: + status = int(current_volume['status']) + LOG.debug('Wait clone volume %(volume_name)s, status:%(status)s.', + {"volume_name": new_volume_name, + "status": status}) + if status in {constants.REST_VOLUME_CREATING_STATUS, + constants.REST_VOLUME_DUPLICATE_VOLUME}: + LOG.debug(_("Volume %s is cloning"), new_volume_name) + elif status == constants.REST_VOLUME_CREATE_SUCCESS_STATUS: + raise loopingcall.LoopingCallDone(retvalue=True) + else: + msg = _('Clone volume %(new_volume_name)s failed, ' + 'the status is:%(status)s.') + LOG.error(msg, {'new_volume_name': new_volume_name, + 'status': status}) + raise loopingcall.LoopingCallDone(retvalue=False) + + max_time_out = constants.CLONE_VOLUME_TIMEOUT + current_time = time.time() + if (current_time - start_time) > max_time_out: + msg = _('Dsware clone volume time out. ' + 'Volume: %(new_volume_name)s, status: %(status)s') + LOG.error(msg, {'new_volume_name': new_volume_name, + 'status': current_volume['status']}) + raise loopingcall.LoopingCallDone(retvalue=False) + else: + LOG.warning(_('Can not find volume %s'), new_volume_name) + msg = "DSWARE clone volume failed:volume can not find from dsware" + LOG.error(msg) + raise loopingcall.LoopingCallDone(retvalue=False) + + def _wait_for_create_cloned_volume_finish_timer(self, new_volume_name): + timer = loopingcall.FixedIntervalLoopingCall( + self._check_create_cloned_volume_finish, + new_volume_name, time.time()) + LOG.debug('Calling _check_create_cloned_volume_finish: volume-name %s', + new_volume_name) + ret = timer.start(interval=constants.CHECK_CLONED_INTERVAL).wait() + timer.stop() + return ret + def create_volume_from_snapshot(self, volume, snapshot): vol_name = self._get_vol_name(volume) snapshot_name = self._get_snapshot_name(snapshot) vol_size = volume.size + pool_id = self._get_pool_id(volume) if not self._check_snapshot_exist(snapshot.volume, snapshot): msg = _("Snapshot: %(name)s does not exist!" ) % {"name": snapshot_name} self._raise_exception(msg) - elif self._check_volume_exist(volume): + if self._check_volume_exist(volume): msg = _("Volume: %(vol_name)s already exists!" ) % {'vol_name': vol_name} self._raise_exception(msg) - else: - vol_size *= units.Ki + + vol_size *= units.Ki + if not self.configuration.full_clone: self.client.create_volume_from_snapshot( snapshot_name=snapshot_name, vol_name=vol_name, vol_size=vol_size) - self._add_qos_to_volume(volume, vol_name) - self._expand_volume_when_create(vol_name, vol_size) - result = self.client.query_volume_by_name(vol_name=vol_name) - return ({"metadata": {'lun_wwn': result.get('wwn')}} - if result else {}) + else: + self.client.create_volume(vol_name, vol_size, pool_id) + self.client.create_full_volume_from_snapshot(vol_name, + snapshot_name) + ret = self._wait_for_create_cloned_volume_finish_timer(vol_name) + if not ret: + msg = _('Create full volume %s from snap failed') % vol_name + self._raise_exception(msg) + self._add_qos_to_volume(volume, vol_name) + self._expand_volume_when_create(vol_name, vol_size) + result = self.client.query_volume_by_name(vol_name=vol_name) + return ({"metadata": {'lun_wwn': result.get('wwn')}} + if result else {}) + + def _create_volume_from_volume_full_clone(self, vol_name, vol_size, pool_id, + src_vol_name): + tmp_snap_name = "temp" + src_vol_name + "clone" + vol_name + + self.client.create_snapshot(tmp_snap_name, src_vol_name) + try: + self.client.create_volume(vol_name, vol_size, pool_id) + except Exception as err: + self.client.delete_snapshot(tmp_snap_name) + raise err + + try: + self.client.create_full_volume_from_snapshot( + vol_name, tmp_snap_name) + except Exception as err: + self.client.delete_snapshot(tmp_snap_name) + self.client.delete_volume(vol_name) + raise err + + ret = self._wait_for_create_cloned_volume_finish_timer(vol_name) + if not ret: + msg = _('Create full volume %s from snap failed') % vol_name + self._raise_exception(msg) + self.client.delete_snapshot(tmp_snap_name) def create_cloned_volume(self, volume, src_volume): vol_name = self._get_vol_name(volume) @@ -398,15 +494,22 @@ def create_cloned_volume(self, volume, src_volume): msg = _("Volume: %(vol_name)s does not exist!" ) % {"vol_name": src_vol_name} self._raise_exception(msg) - else: + + if not self.configuration.full_clone: self.client.create_volume_from_volume( vol_name=vol_name, vol_size=vol_size, src_vol_name=src_vol_name) - self._add_qos_to_volume(volume, vol_name) - self._expand_volume_when_create(vol_name, vol_size) - result = self.client.query_volume_by_name(vol_name=vol_name) - return ({"metadata": {'lun_wwn': result.get('wwn')}} - if result else {}) + else: + pool_id = self._get_pool_id(volume) + self._create_volume_from_volume_full_clone( + vol_name=vol_name, vol_size=vol_size, pool_id=pool_id, + src_vol_name=src_vol_name) + + self._add_qos_to_volume(volume, vol_name) + self._expand_volume_when_create(vol_name, vol_size) + result = self.client.query_volume_by_name(vol_name=vol_name) + return ({"metadata": {'lun_wwn': result.get('wwn')}} + if result else {}) def create_snapshot(self, snapshot): snapshot_name = self._get_snapshot_name(snapshot) @@ -581,12 +684,13 @@ def unmanage_snapshot(self, snapshot): def _check_need_changes_for_retype(self, volume, new_type, host, vol_name): before_change = {} after_change = {} - if volume.host != host["host"]: - msg = (_("Do not support retype between different host. Volume's " + migrate = False + if volume.host != host.get("host"): + migrate = True + msg = (_("retype support migration between different host. Volume's " "host: %(vol_host)s, host's host: %(host)s") - % {"vol_host": volume.host, "host": host['host']}) - LOG.error(msg) - raise exception.InvalidInput(msg) + % {"vol_host": volume.host, "host": host.get("host")}) + LOG.info(msg) old_opts = fs_utils.get_volume_specs(self.client, vol_name) new_opts = fs_utils.get_volume_type_params(new_type, self.client) @@ -596,7 +700,7 @@ def _check_need_changes_for_retype(self, volume, new_type, host, vol_name): change_opts = {"old_opts": before_change, "new_opts": after_change} - return change_opts + return migrate, change_opts def retype(self, context, volume, new_type, diff, host): LOG.info("Retype volume: %(vol)s, new_type: %(new_type)s, " @@ -607,13 +711,177 @@ def retype(self, context, volume, new_type, diff, host): "host": host}) vol_name = self._get_vol_name(volume) - change_opts = self._check_need_changes_for_retype( + migrate, change_opts = self._check_need_changes_for_retype( volume, new_type, host, vol_name) + if migrate: + src_lun_id = self._check_volume_exist_on_array(volume) + LOG.debug("Begin to migrate LUN(id: %(lun_id)s) with " + "change %(change_opts)s.", + {"lun_id": src_lun_id, "change_opts": change_opts}) + moved = self._migrate_volume(volume, host, src_lun_id) + if not moved: + LOG.warning("Storage-assisted migration failed during " + "retype.") + return False, None self._change_lun(vol_name, change_opts.get("new_opts"), change_opts.get("old_opts")) return True, None + def migrate_volume(self, context, volume, host): + """Migrate a volume within the same array.""" + LOG.info("Migrate Volume:%(volume)s, host:%(host)s", + {"volume": volume.id, + "host": host}) + src_lun_id = self._check_volume_exist_on_array(volume) + + moved = self._migrate_volume(volume, host, src_lun_id) + return moved, {} + + def _create_dst_volume(self, volume, host): + pool_name = host['capabilities']['pool_name'] + pool_id = self._get_pool_id_by_name(pool_name) + vol_name = fs_utils.encode_name(six.text_type(uuid.uuid4())) + vol_size = volume.size + vol_size *= units.Ki + self.client.create_volume( + pool_id=pool_id, vol_name=vol_name, vol_size=vol_size) + + result = self.client.query_volume_by_name_v2(vol_name=vol_name) + dst_lun_id = result.get('id') + self._wait_volume_ready(vol_name) + return vol_name, dst_lun_id + + def _migrate_volume(self, volume, host, src_lun_id): + """create migration task and wait for task done""" + if not self._check_migration_valid(host): + return False + + vol_name, dst_lun_id = self._create_dst_volume(volume, host) + + try: + self.client.create_lun_migration(src_lun_id, dst_lun_id) + + def _is_lun_migration_complete(): + return self._is_lun_migration_complete(src_lun_id, dst_lun_id) + + wait_interval = constants.MIGRATION_WAIT_INTERVAL + fs_utils.wait_for_condition(_is_lun_migration_complete, + wait_interval, + constants.DEFAULT_WAIT_TIMEOUT) + # Clean up if migration failed. + except Exception as ex: + raise exception.VolumeBackendAPIException(data=ex) + finally: + if self._is_lun_migration_exist(src_lun_id, dst_lun_id): + self.client.delete_lun_migration(src_lun_id) + self._delete_lun_with_check(vol_name) + + LOG.info("Migrate lun %s successfully.", src_lun_id) + return True + + def _delete_lun_with_check(self, vol_name): + if self.client.query_volume_by_name(vol_name): + # migrate_dst_lun don't have qos, so don't + # need to remove qos, Delete the LUN directly. + self.client.delete_volume(vol_name) + + def _is_lun_migration_complete(self, src_lun_id, dst_lun_id): + result = self.client.get_lun_migration_task_by_id(src_lun_id) + found_migration_task = False + if not result: + return False + + if (str(src_lun_id) == result.get('parent_id') and + str(dst_lun_id) == result.get('target_lun_id')): + found_migration_task = True + if constants.MIGRATION_COMPLETE == result.get('running_status'): + return True + if constants.MIGRATION_FAULT == result.get('running_status'): + msg = _("Lun migration error. " + "the migration task running_status is abnormal") + LOG.error(msg) + raise exception.VolumeBackendAPIException(data=msg) + + if not found_migration_task: + err_msg = _("lun migration error, Cannot find migration task.") + LOG.error(err_msg) + raise exception.VolumeBackendAPIException(data=err_msg) + + return False + + def _is_lun_migration_exist(self, src_lun_id, dst_lun_id): + try: + result = self.client.get_lun_migration_task_by_id(src_lun_id) + except Exception: + LOG.error("Get LUN migration error.") + return False + + if (str(src_lun_id) == result.get('parent_id') and + str(dst_lun_id) == result.get('target_lun_id')): + return True + return False + + def _wait_volume_ready(self, vol_name): + wait_interval = constants.DEFAULT_WAIT_INTERVAL + + def _volume_ready(): + result = self.client.query_volume_by_name_v2(vol_name) + if not result: + return False + + if (result.get('health_status') == constants.STATUS_HEALTH + and result.get('running_status') == constants.STATUS_VOLUME_READY): + return True + return False + + fs_utils.wait_for_condition(_volume_ready, + wait_interval, + wait_interval * 10) + + def _check_migration_valid(self, host): + if 'pool_name' not in host.get('capabilities', {}): + return False + + target_device = host.get('capabilities', {}).get('location_info') + + # Source and destination should be on same array. + if target_device != self.client.esn: + LOG.error("lun migration error, " + "Source and destination should be on same array") + return False + + pool_name = host.get('capabilities', {}).get('pool_name', '') + if len(pool_name) == 0: + LOG.error("lun migration error, pool_name not exists") + return False + + return True + + def _check_volume_exist_on_array(self, volume): + volume_name = self._get_vol_name(volume) + result = self._check_volume_exist(volume) + if not result: + msg = _("Volume %s does not exist on the array." + ) % volume.id + self._raise_exception(msg) + + lun_wwn = result.get('wwn') + if not lun_wwn: + LOG.debug("No LUN WWN recorded for volume %s.", volume.id) + + lun_id = result.get('volId') + if not lun_id: + msg = _("Volume %s does not exist on the array." + ) % volume.id + self._raise_exception(msg) + + if self.client.get_volume_snapshot(volume_name): + msg = _("Volume %s which have snapshot cannot do lun migration" + ) % volume.id + self._raise_exception(msg) + return lun_id + def _rollback_snapshot(self, vol_name, snap_name): def _snapshot_rollback_finish(): snapshot_info = self.client.get_snapshot_info_by_name(snap_name) @@ -669,6 +937,265 @@ def ensure_export(self, context, volume): def remove_export(self, context, volume): pass + def create_group(self, context, group): + """Creates a group. Driver only need to return state""" + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.create_consistencygroup(context, group) + + def create_consistencygroup(self, context, group): + """Creates a group. Driver only need to return state""" + LOG.info("Create group successfully") + return {'status': 'available'} + + def update_group(self, context, group, + add_volumes=None, remove_volumes=None): + """ + The volume manager will adds/removes the volume to/from the + group in the database, if need add_volumes, Driver just need + to check whether volume is in array or not + """ + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.update_consistencygroup( + context, group, add_volumes, remove_volumes) + + def update_consistencygroup(self, context, group, + add_volumes=None, remove_volumes=None): + """ + The volume manager will adds/removes the volume to/from the + group in the database, if need add_volumes, Driver just need + to check whether volume is in array or not + """ + if add_volumes is None: + add_volumes = [] + for volume in add_volumes: + try: + self._check_volume_exist_on_array(volume) + except Exception: + with excutils.save_and_reraise_exception(): + LOG.error("The add_volume %s not exist on array" % volume.id) + + model_update = {'status': 'available'} + LOG.info("Update group successfully") + return model_update, None, None + + def delete_group(self, context, group, volumes): + """delete the group, Driver need to delete relation lun on array""" + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.delete_consistencygroup(context, group, volumes) + + def delete_consistencygroup(self, context, group, volumes): + """delete the group, Driver need to delete relation lun on array""" + volumes_model_update = [] + model_update = {'status': 'deleted'} + for volume in volumes: + volume_model_update = {'id': volume.id} + try: + self.delete_volume(volume) + except Exception: + LOG.error('Delete volume %s failed.' % volume) + volume_model_update.update({'status': 'error_deleting'}) + else: + volume_model_update.update({'status': 'deleted'}) + + LOG.info('Deleted volume %s successfully' % volume) + volumes_model_update.append(volume_model_update) + + LOG.info("Delete group successfully") + return model_update, volumes_model_update + + def create_group_from_src(self, context, group, volumes, + group_snapshot=None, snapshots=None, + source_group=None, source_vols=None): + """ + create group from group or group-snapshot, + Driver need to create volume from volume or snapshot + """ + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.create_consistencygroup_from_src(context, group, volumes, + group_snapshot, snapshots, + source_group, source_vols) + + def create_consistencygroup_from_src(self, context, group, volumes, + group_snapshot=None, snapshots=None, + source_group=None, source_vols=None): + """ + create group from group or group-snapshot, + Driver need to create volume from volume or snapshot + """ + model_update = self.create_consistencygroup(context, group) + volumes_model_update = [] + delete_snapshots = False + + if not snapshots and source_vols: + snapshots = [] + for src_volume in source_vols: + volume_kwargs = { + 'id': src_volume.id, + '_name_id': None, + 'host': src_volume.host + } + snapshot_kwargs = { + 'id': six.text_type(uuid.uuid4()), + 'volume': objects.Volume(**volume_kwargs) + } + snapshots.append(objects.Snapshot(**snapshot_kwargs)) + + self._create_group_snapshot(snapshots) + delete_snapshots = True + + if snapshots: + volumes_model_update = self._create_volume_from_group_snapshot( + volumes, snapshots, delete_snapshots) + + if delete_snapshots: + self._delete_group_snapshot(snapshots) + + LOG.info("Create group from src successfully") + return model_update, volumes_model_update + + def _create_volume_from_group_snapshot(self, volumes, snapshots, delete_snapshots): + volumes_model_update = [] + added_volumes = [] + for i, volume in enumerate(volumes): + try: + vol_model_update = self.create_volume_from_snapshot( + volume, snapshots[i]) + vol_model_update.update({'id': volume.id}) + volumes_model_update.append(vol_model_update) + added_volumes.append(volume) + except Exception: + LOG.error("Create volume from snapshot error, Delete the newly created lun.") + with excutils.save_and_reraise_exception(): + self._delete_added_volume_snapshots( + added_volumes, snapshots, delete_snapshots) + + return volumes_model_update + + def _delete_added_volume_snapshots( + self, added_volumes, snapshots, delete_snapshots): + if delete_snapshots: + self._delete_group_snapshot(snapshots) + for add_volume in added_volumes: + vol_name = self._get_vol_name(add_volume) + self.fs_qos.remove(vol_name) + self.client.delete_volume(vol_name=vol_name) + LOG.info("delete storage newly added " + "volume success, volume is %s" % add_volume.id) + + def create_group_snapshot(self, context, group_snapshot, snapshots): + """Create group snapshot.""" + if not volume_utils.is_group_a_cg_snapshot_type(group_snapshot): + LOG.info("group_snapshot's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.create_cgsnapshot(context, group_snapshot, snapshots) + + def create_cgsnapshot(self, context, group_snapshot, snapshots): + """Create group snapshot.""" + LOG.info('Create group snapshot for group: %(group_snapshot)s', + {'group_snapshot': group_snapshot}) + + try: + snapshots_model_update = self._create_group_snapshot(snapshots) + except Exception as err: + msg = ("Create group snapshots failed. " + "Group snapshot id: %s. Reason is %s") % (group_snapshot.id, err) + LOG.error(msg) + raise exception.CinderException(msg) + + model_update = {'status': 'available'} + return model_update, snapshots_model_update + + def _create_group_snapshot(self, snapshots): + """Generate snapshots for all volumes in the group.""" + snapshots_model_update = [] + snapshot_group_list = [] + + for snapshot in snapshots: + snapshot_name = self._get_snapshot_name(snapshot) + vol_name = self._get_vol_name(snapshot.volume) + snapshot_group_list.append({ + 'name': snapshot_name, + 'sub_type': '0', + 'volume_name': vol_name + }) + snapshot_model_update = { + 'id': snapshot.id, + 'status': 'available', + } + snapshots_model_update.append(snapshot_model_update) + try: + self.client.create_consistent_snapshot_by_name(snapshot_group_list) + except Exception: + with excutils.save_and_reraise_exception(): + LOG.error("Create consistent snapshot failed, " + "snapshot_group_list is %s" % snapshot_group_list) + + return snapshots_model_update + + def delete_group_snapshot(self, context, group_snapshot, snapshots): + """Delete group snapshot.""" + if not volume_utils.is_group_a_cg_snapshot_type(group_snapshot): + LOG.info("group_snapshot's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.delete_cgsnapshot(context, group_snapshot, snapshots) + + def delete_cgsnapshot(self, context, group_snapshot, snapshots): + """Delete group snapshot.""" + LOG.info("Delete group_snapshot %s for " + "consistency group: %s" % (group_snapshot.id, group_snapshot)) + + try: + snapshots_model_update = self._delete_group_snapshot(snapshots) + except Exception as err: + msg = ("Delete cg snapshots failed. " + "group snapshot id: %s, reason is %s") % (group_snapshot.id, err) + LOG.error(msg) + raise exception.CinderException(msg) + + model_update = {'status': 'deleted'} + return model_update, snapshots_model_update + + def _delete_group_snapshot(self, snapshots): + """Delete all snapshots in snapshot group""" + snapshots_model_update = [] + for snapshot in snapshots: + snapshot_model_update = { + 'id': snapshot.id, + 'status': 'deleted' + } + snapshots_model_update.append(snapshot_model_update) + snapshot_name = self._get_snapshot_name(snapshot) + + if not self._check_snapshot_exist(snapshot.volume, snapshot): + LOG.info("snapshot %s not exist in array, " + "don't need to delete, try next one" % snapshot_name) + continue + self.client.delete_snapshot(snapshot_name=snapshot_name) + LOG.info("Delete snapshot successfully," + " the deleted snapshots is %s" % snapshot_name) + + return snapshots_model_update + class DSWAREDriver(DSWAREBaseDriver): def get_volume_stats(self, refresh=False): @@ -721,7 +1248,7 @@ def initialize_connection(self, volume, connector): vol_wwn = volume_info.get('wwn') by_id_path = "/dev/disk/by-id/" + "wwn-0x%s" % vol_wwn properties = {'device_path': by_id_path} - import time + LOG.info("Wait %(t)s second(s) for scanning the target device %(dev)s." % {"t": self.configuration.scan_device_timeout, "dev": by_id_path}) diff --git a/Cinder/Stein/fs_client.py b/Cinder/Stein/fs_client.py index 234d7f1..09d9581 100644 --- a/Cinder/Stein/fs_client.py +++ b/Cinder/Stein/fs_client.py @@ -14,16 +14,16 @@ # under the License. import json + import requests import six -import time +from oslo_log import log as logging from requests.adapters import HTTPAdapter from cinder import exception from cinder.i18n import _ from cinder.volume.drivers.fusionstorage import constants -from oslo_log import log as logging LOG = logging.getLogger(__name__) @@ -43,7 +43,8 @@ def __init__(self, fs_address, fs_user, fs_password, **extend_conf): self.session = None self.token = None self.version = None - mutual_authentication = extend_conf.get("mutual_authentication") + self.esn = None + mutual_authentication = extend_conf.get("mutual_authentication", {}) self.init_http_head(mutual_authentication) LOG.warning("Suppressing requests library SSL Warnings") @@ -147,6 +148,13 @@ def get_version(self): if result.get("currentVersion"): self.version = result["currentVersion"] + def get_esn(self): + url = "/cluster/sn" + result = self.call(url, "get") + self._assert_rest_result(result, _('Get cluster esn error.')) + self.esn = result.get("sn") + return self.esn + def login(self): self.get_version() url = '/sec/login' @@ -160,6 +168,7 @@ def login(self): self.session.headers.update({ "x-auth-token": self.token }) + self.get_esn() def logout(self): url = '/sec/logout' @@ -264,6 +273,15 @@ def query_volume_by_name(self, vol_name): result, _("Query volume by name session error")) return result.get('lunDetailInfo') + def query_volume_by_name_v2(self, vol_name): + url = '/api/v2/block_service/volumes?name=' + vol_name + result = self.call(url, 'GET', get_system_time=True) + if result.get('errorCode') in constants.VOLUME_NOT_EXIST: + return {} + self._assert_rest_result( + result, _("Query volume by name session error")) + return result.get('data', {}) + def query_volume_by_id(self, vol_id): url = 'v1.3/volume/queryById?volId=' + vol_id result = self.call(url, 'GET', get_version=True) @@ -746,3 +764,57 @@ def get_iscsi_links_info(self, iscsi_link_count, pool_list): return [iscsi["ip"] for iscsi in result.get("iscsiLinks", []) if iscsi.get("ip")] + + def create_lun_migration(self, src_lun_id, dst_lun_id, speed=2): + url = "/api/v2/block_service/lun_migration" + params = { + "parent_id": src_lun_id, + "target_lun_id": dst_lun_id, + "speed": speed, + "work_mode": 0 + } + result = self.call(url, "POST", params, get_system_time=True) + self._assert_rest_result(result, + _("create lun migration task error.")) + + def get_lun_migration_task_by_id(self, src_lun_id): + url = "/api/v2/block_service/lun_migration" + params = { + "id": src_lun_id + } + result = self.call(url, "GET", params, get_system_time=True) + self._assert_rest_result(result, + _("get lun migration task error.")) + return result.get('data', {}) + + def delete_lun_migration(self, src_lun_id): + url = "/api/v2/block_service/lun_migration" + params = { + 'id': src_lun_id + } + result = self.call(url, "DELETE", params, get_system_time=True) + self._assert_rest_result(result, + _("Delete lun migration task error.")) + + def get_volume_snapshot(self, volume_name): + url = "/volume/snapshot/list" + params = { + 'volName': volume_name, + 'batchNum': 1, + 'batchLimit': 10 + } + result = self.call(url, "POST", params) + return result.get('snapshotList', []) + + def create_consistent_snapshot_by_name(self, snapshot_group_list): + url = "/api/v2/block_service/consistency_snapshots" + result = self.call(url, "POST", snapshot_group_list, get_system_time=True) + self._assert_rest_result(result, _("create consistent_snapshot error.")) + return result.get('data', []) + + def create_full_volume_from_snapshot(self, vol_name, snapshot_name): + url = '/api/v2/block_service/createFullVolumeFromSnap' + params = {"snap_name_src": snapshot_name, "volume_name_dst": vol_name} + result = self.call(url, "POST", params, get_system_time=True) + self._assert_rest_result( + result, _("create full volume from snap fails")) diff --git a/Cinder/Stein/fs_qos.py b/Cinder/Stein/fs_qos.py index 731c45e..286dbc3 100644 --- a/Cinder/Stein/fs_qos.py +++ b/Cinder/Stein/fs_qos.py @@ -29,7 +29,11 @@ def __init__(self, client): def add(self, qos, vol_name): localtime = time.strftime('%Y%m%d%H%M%S', time.localtime()) - qos_name = constants.QOS_PREFIX + localtime + # QoS policy name. The value contains 1 to 63 characters. + # So we intercept volume_name Ensure that the length does not exceed 63 + vol_str = vol_name[-constants.QOS_MAX_INTERCEPT_LENGTH::] \ + if len(vol_name) >= constants.QOS_MAX_INTERCEPT_LENGTH else vol_name + qos_name = constants.QOS_PREFIX + localtime + '_' + vol_str self.client.create_qos(qos_name, qos) try: self.client.associate_qos_with_volume(vol_name, qos_name) diff --git a/Cinder/Stein/fs_utils.py b/Cinder/Stein/fs_utils.py index 8b9ae78..0856038 100644 --- a/Cinder/Stein/fs_utils.py +++ b/Cinder/Stein/fs_utils.py @@ -16,11 +16,11 @@ import datetime import hashlib import ipaddress -import pytz import random -import six import time +import pytz +import six from oslo_log import log as logging from oslo_service import loopingcall from oslo_utils import units @@ -758,3 +758,9 @@ def get_iscsi_info_from_storage(manager_ips, use_ipv6, valid_iscsi_ips, valid_node_ips): return _get_target_info(manager_ips, use_ipv6, valid_iscsi_ips, valid_node_ips) + + +def encode_name(my_uuid): + encoded_name = hashlib.md5(my_uuid.encode('utf-8')).hexdigest() + target_lun_prefix = my_uuid.split('-')[0] + '-' + return target_lun_prefix + encoded_name diff --git a/Cinder/Train/constants.py b/Cinder/Train/constants.py index 5f46ece..b4cb843 100644 --- a/Cinder/Train/constants.py +++ b/Cinder/Train/constants.py @@ -45,6 +45,14 @@ CONF_STORAGE_CERT_FILEPATH = "storage_cert_filepath" CONF_STORAGE_SSL_TWO_WAY_AUTH = "storage_ssl_two_way_auth" +DEFAULT_WAIT_INTERVAL = 5 +MIGRATION_COMPLETE = 76 +MIGRATION_FAULT = 74 +STATUS_HEALTH = 1 +STATUS_VOLUME_READY = 27 +MIGRATION_WAIT_INTERVAL = 5 +DEFAULT_WAIT_TIMEOUT = 3600 * 24 * 30 + QOS_MUST_SET = ["maxIOPS", "maxMBPS"] QOS_KEYS = ["maxIOPS", "maxMBPS", "total_iops_sec", "total_bytes_sec"] QOS_SCHEDULER_KEYS = ["scheduleType", "startDate", "startTime", @@ -53,6 +61,7 @@ QOS_SCHEDULER_DEFAULT_TYPE = "0" QOS_SCHEDULER_WEEK_TYPE = "3" QOS_SUPPORT_SCHEDULE_VERSION = "8.0" +QOS_MAX_INTERCEPT_LENGTH = 36 SECONDS_OF_DAY = 24 * 60 * 60 SECONDS_OF_HOUR = 60 * 60 SNAPSHOT_HEALTH_STATUS = ( @@ -80,3 +89,9 @@ HOSTGROUP_ALREADY_EXIST = 50157044 INITIATOR_ALREADY_EXIST = 50155102 INITIATOR_IN_HOST = 50157021 + +CHECK_CLONED_INTERVAL = 2 +REST_VOLUME_CREATING_STATUS = 15 +REST_VOLUME_DUPLICATE_VOLUME = 6 +REST_VOLUME_CREATE_SUCCESS_STATUS = 0 +CLONE_VOLUME_TIMEOUT = 3600 * 24 * 30 diff --git a/Cinder/Train/dsware.py b/Cinder/Train/dsware.py index 75e1808..b03e039 100644 --- a/Cinder/Train/dsware.py +++ b/Cinder/Train/dsware.py @@ -14,16 +14,22 @@ # under the License. import json - +import time +import uuid from multiprocessing import Lock + +import six from oslo_config import cfg from oslo_log import log as logging +from oslo_utils import excutils from oslo_utils import units +from oslo_service import loopingcall from cinder import coordination from cinder import exception from cinder.i18n import _ from cinder import interface +from cinder import objects from cinder.volume import driver from cinder.volume.drivers.fusionstorage import constants from cinder.volume.drivers.fusionstorage import fs_client @@ -105,6 +111,9 @@ cfg.StrOpt('storage_key_filepath', default='', help='Client key directory.'), + cfg.BoolOpt('full_clone', + default=False, + help='Whether use full clone.'), ] CONF = cfg.CONF @@ -113,7 +122,7 @@ @interface.volumedriver class DSWAREBaseDriver(driver.VolumeDriver): - VERSION = '2.5.RC4' + VERSION = "2.6.1" CI_WIKI_NAME = 'Huawei_FusionStorage_CI' def __init__(self, *args, **kwargs): @@ -210,6 +219,7 @@ def _update_single_pool_info_status(self, pool_info): "total_capacity_gb": capacity['total_capacity_gb'], "free_capacity_gb": capacity['free_capacity_gb'], "provisioned_capacity_gb": capacity['provisioned_capacity_gb'], + "location_info": self.client.esn, "QoS_support": True, 'multiattach': True, "thin_provisioning_support": True, @@ -247,8 +257,12 @@ def _raise_exception(msg): raise exception.VolumeBackendAPIException(data=msg) def _get_pool_id(self, volume): - pool_id_list = [] pool_name = volume_utils.extract_host(volume.host, level='pool') + pool_id = self._get_pool_id_by_name(pool_name) + return pool_id + + def _get_pool_id_by_name(self, pool_name): + pool_id_list = [] all_pools = self.client.query_pool_info() for pool in all_pools: if pool_name == pool['poolName']: @@ -363,29 +377,111 @@ def _expand_volume_when_create(self, vol_name, vol_size): self.client.delete_volume(vol_name=vol_name) raise + def _check_create_cloned_volume_finish(self, new_volume_name, start_time): + LOG.debug('Loopcall: _check_create_cloned_volume_finish(), ' + 'volume-name %s', + new_volume_name) + current_volume = self.client.query_volume_by_name(new_volume_name) + + if current_volume and 'status' in current_volume: + status = int(current_volume['status']) + LOG.debug('Wait clone volume %(volume_name)s, status:%(status)s.', + {"volume_name": new_volume_name, + "status": status}) + if status in {constants.REST_VOLUME_CREATING_STATUS, + constants.REST_VOLUME_DUPLICATE_VOLUME}: + LOG.debug(_("Volume %s is cloning"), new_volume_name) + elif status == constants.REST_VOLUME_CREATE_SUCCESS_STATUS: + raise loopingcall.LoopingCallDone(retvalue=True) + else: + msg = _('Clone volume %(new_volume_name)s failed, ' + 'the status is:%(status)s.') + LOG.error(msg, {'new_volume_name': new_volume_name, + 'status': status}) + raise loopingcall.LoopingCallDone(retvalue=False) + + max_time_out = constants.CLONE_VOLUME_TIMEOUT + current_time = time.time() + if (current_time - start_time) > max_time_out: + msg = _('Dsware clone volume time out. ' + 'Volume: %(new_volume_name)s, status: %(status)s') + LOG.error(msg, {'new_volume_name': new_volume_name, + 'status': current_volume['status']}) + raise loopingcall.LoopingCallDone(retvalue=False) + else: + LOG.warning(_('Can not find volume %s'), new_volume_name) + msg = "DSWARE clone volume failed:volume can not find from dsware" + LOG.error(msg) + raise loopingcall.LoopingCallDone(retvalue=False) + + def _wait_for_create_cloned_volume_finish_timer(self, new_volume_name): + timer = loopingcall.FixedIntervalLoopingCall( + self._check_create_cloned_volume_finish, + new_volume_name, time.time()) + LOG.debug('Calling _check_create_cloned_volume_finish: volume-name %s', + new_volume_name) + ret = timer.start(interval=constants.CHECK_CLONED_INTERVAL).wait() + timer.stop() + return ret + def create_volume_from_snapshot(self, volume, snapshot): vol_name = self._get_vol_name(volume) snapshot_name = self._get_snapshot_name(snapshot) vol_size = volume.size + pool_id = self._get_pool_id(volume) if not self._check_snapshot_exist(snapshot.volume, snapshot): msg = _("Snapshot: %(name)s does not exist!" ) % {"name": snapshot_name} self._raise_exception(msg) - elif self._check_volume_exist(volume): + if self._check_volume_exist(volume): msg = _("Volume: %(vol_name)s already exists!" ) % {'vol_name': vol_name} self._raise_exception(msg) - else: - vol_size *= units.Ki + + vol_size *= units.Ki + if not self.configuration.full_clone: self.client.create_volume_from_snapshot( snapshot_name=snapshot_name, vol_name=vol_name, vol_size=vol_size) - self._add_qos_to_volume(volume, vol_name) - self._expand_volume_when_create(vol_name, vol_size) - result = self.client.query_volume_by_name(vol_name=vol_name) - return ({"metadata": {'lun_wwn': result.get('wwn')}} - if result else {}) + else: + self.client.create_volume(vol_name, vol_size, pool_id) + self.client.create_full_volume_from_snapshot(vol_name, + snapshot_name) + ret = self._wait_for_create_cloned_volume_finish_timer(vol_name) + if not ret: + msg = _('Create full volume %s from snap failed') % vol_name + self._raise_exception(msg) + self._add_qos_to_volume(volume, vol_name) + self._expand_volume_when_create(vol_name, vol_size) + result = self.client.query_volume_by_name(vol_name=vol_name) + return ({"metadata": {'lun_wwn': result.get('wwn')}} + if result else {}) + + def _create_volume_from_volume_full_clone(self, vol_name, vol_size, pool_id, + src_vol_name): + tmp_snap_name = "temp" + src_vol_name + "clone" + vol_name + + self.client.create_snapshot(tmp_snap_name, src_vol_name) + try: + self.client.create_volume(vol_name, vol_size, pool_id) + except Exception as err: + self.client.delete_snapshot(tmp_snap_name) + raise err + + try: + self.client.create_full_volume_from_snapshot( + vol_name, tmp_snap_name) + except Exception as err: + self.client.delete_snapshot(tmp_snap_name) + self.client.delete_volume(vol_name) + raise err + + ret = self._wait_for_create_cloned_volume_finish_timer(vol_name) + if not ret: + msg = _('Create full volume %s from snap failed') % vol_name + self._raise_exception(msg) + self.client.delete_snapshot(tmp_snap_name) def create_cloned_volume(self, volume, src_volume): vol_name = self._get_vol_name(volume) @@ -398,15 +494,22 @@ def create_cloned_volume(self, volume, src_volume): msg = _("Volume: %(vol_name)s does not exist!" ) % {"vol_name": src_vol_name} self._raise_exception(msg) - else: + + if not self.configuration.full_clone: self.client.create_volume_from_volume( vol_name=vol_name, vol_size=vol_size, src_vol_name=src_vol_name) - self._add_qos_to_volume(volume, vol_name) - self._expand_volume_when_create(vol_name, vol_size) - result = self.client.query_volume_by_name(vol_name=vol_name) - return ({"metadata": {'lun_wwn': result.get('wwn')}} - if result else {}) + else: + pool_id = self._get_pool_id(volume) + self._create_volume_from_volume_full_clone( + vol_name=vol_name, vol_size=vol_size, pool_id=pool_id, + src_vol_name=src_vol_name) + + self._add_qos_to_volume(volume, vol_name) + self._expand_volume_when_create(vol_name, vol_size) + result = self.client.query_volume_by_name(vol_name=vol_name) + return ({"metadata": {'lun_wwn': result.get('wwn')}} + if result else {}) def create_snapshot(self, snapshot): snapshot_name = self._get_snapshot_name(snapshot) @@ -581,12 +684,13 @@ def unmanage_snapshot(self, snapshot): def _check_need_changes_for_retype(self, volume, new_type, host, vol_name): before_change = {} after_change = {} - if volume.host != host["host"]: - msg = (_("Do not support retype between different host. Volume's " + migrate = False + if volume.host != host.get("host"): + migrate = True + msg = (_("retype support migration between different host. Volume's " "host: %(vol_host)s, host's host: %(host)s") - % {"vol_host": volume.host, "host": host['host']}) - LOG.error(msg) - raise exception.InvalidInput(msg) + % {"vol_host": volume.host, "host": host.get("host")}) + LOG.info(msg) old_opts = fs_utils.get_volume_specs(self.client, vol_name) new_opts = fs_utils.get_volume_type_params(new_type, self.client) @@ -596,7 +700,7 @@ def _check_need_changes_for_retype(self, volume, new_type, host, vol_name): change_opts = {"old_opts": before_change, "new_opts": after_change} - return change_opts + return migrate, change_opts def retype(self, context, volume, new_type, diff, host): LOG.info("Retype volume: %(vol)s, new_type: %(new_type)s, " @@ -607,13 +711,177 @@ def retype(self, context, volume, new_type, diff, host): "host": host}) vol_name = self._get_vol_name(volume) - change_opts = self._check_need_changes_for_retype( + migrate, change_opts = self._check_need_changes_for_retype( volume, new_type, host, vol_name) + if migrate: + src_lun_id = self._check_volume_exist_on_array(volume) + LOG.debug("Begin to migrate LUN(id: %(lun_id)s) with " + "change %(change_opts)s.", + {"lun_id": src_lun_id, "change_opts": change_opts}) + moved = self._migrate_volume(volume, host, src_lun_id) + if not moved: + LOG.warning("Storage-assisted migration failed during " + "retype.") + return False, None self._change_lun(vol_name, change_opts.get("new_opts"), change_opts.get("old_opts")) return True, None + def migrate_volume(self, context, volume, host): + """Migrate a volume within the same array.""" + LOG.info("Migrate Volume:%(volume)s, host:%(host)s", + {"volume": volume.id, + "host": host}) + src_lun_id = self._check_volume_exist_on_array(volume) + + moved = self._migrate_volume(volume, host, src_lun_id) + return moved, {} + + def _create_dst_volume(self, volume, host): + pool_name = host['capabilities']['pool_name'] + pool_id = self._get_pool_id_by_name(pool_name) + vol_name = fs_utils.encode_name(six.text_type(uuid.uuid4())) + vol_size = volume.size + vol_size *= units.Ki + self.client.create_volume( + pool_id=pool_id, vol_name=vol_name, vol_size=vol_size) + + result = self.client.query_volume_by_name_v2(vol_name=vol_name) + dst_lun_id = result.get('id') + self._wait_volume_ready(vol_name) + return vol_name, dst_lun_id + + def _migrate_volume(self, volume, host, src_lun_id): + """create migration task and wait for task done""" + if not self._check_migration_valid(host): + return False + + vol_name, dst_lun_id = self._create_dst_volume(volume, host) + + try: + self.client.create_lun_migration(src_lun_id, dst_lun_id) + + def _is_lun_migration_complete(): + return self._is_lun_migration_complete(src_lun_id, dst_lun_id) + + wait_interval = constants.MIGRATION_WAIT_INTERVAL + fs_utils.wait_for_condition(_is_lun_migration_complete, + wait_interval, + constants.DEFAULT_WAIT_TIMEOUT) + # Clean up if migration failed. + except Exception as ex: + raise exception.VolumeBackendAPIException(data=ex) + finally: + if self._is_lun_migration_exist(src_lun_id, dst_lun_id): + self.client.delete_lun_migration(src_lun_id) + self._delete_lun_with_check(vol_name) + + LOG.info("Migrate lun %s successfully.", src_lun_id) + return True + + def _delete_lun_with_check(self, vol_name): + if self.client.query_volume_by_name(vol_name): + # migrate_dst_lun don't have qos, so don't + # need to remove qos, Delete the LUN directly. + self.client.delete_volume(vol_name) + + def _is_lun_migration_complete(self, src_lun_id, dst_lun_id): + result = self.client.get_lun_migration_task_by_id(src_lun_id) + found_migration_task = False + if not result: + return False + + if (str(src_lun_id) == result.get('parent_id') and + str(dst_lun_id) == result.get('target_lun_id')): + found_migration_task = True + if constants.MIGRATION_COMPLETE == result.get('running_status'): + return True + if constants.MIGRATION_FAULT == result.get('running_status'): + msg = _("Lun migration error. " + "the migration task running_status is abnormal") + LOG.error(msg) + raise exception.VolumeBackendAPIException(data=msg) + + if not found_migration_task: + err_msg = _("lun migration error, Cannot find migration task.") + LOG.error(err_msg) + raise exception.VolumeBackendAPIException(data=err_msg) + + return False + + def _is_lun_migration_exist(self, src_lun_id, dst_lun_id): + try: + result = self.client.get_lun_migration_task_by_id(src_lun_id) + except Exception: + LOG.error("Get LUN migration error.") + return False + + if (str(src_lun_id) == result.get('parent_id') and + str(dst_lun_id) == result.get('target_lun_id')): + return True + return False + + def _wait_volume_ready(self, vol_name): + wait_interval = constants.DEFAULT_WAIT_INTERVAL + + def _volume_ready(): + result = self.client.query_volume_by_name_v2(vol_name) + if not result: + return False + + if (result.get('health_status') == constants.STATUS_HEALTH + and result.get('running_status') == constants.STATUS_VOLUME_READY): + return True + return False + + fs_utils.wait_for_condition(_volume_ready, + wait_interval, + wait_interval * 10) + + def _check_migration_valid(self, host): + if 'pool_name' not in host.get('capabilities', {}): + return False + + target_device = host.get('capabilities', {}).get('location_info') + + # Source and destination should be on same array. + if target_device != self.client.esn: + LOG.error("lun migration error, " + "Source and destination should be on same array") + return False + + pool_name = host.get('capabilities', {}).get('pool_name', '') + if len(pool_name) == 0: + LOG.error("lun migration error, pool_name not exists") + return False + + return True + + def _check_volume_exist_on_array(self, volume): + volume_name = self._get_vol_name(volume) + result = self._check_volume_exist(volume) + if not result: + msg = _("Volume %s does not exist on the array." + ) % volume.id + self._raise_exception(msg) + + lun_wwn = result.get('wwn') + if not lun_wwn: + LOG.debug("No LUN WWN recorded for volume %s.", volume.id) + + lun_id = result.get('volId') + if not lun_id: + msg = _("Volume %s does not exist on the array." + ) % volume.id + self._raise_exception(msg) + + if self.client.get_volume_snapshot(volume_name): + msg = _("Volume %s which have snapshot cannot do lun migration" + ) % volume.id + self._raise_exception(msg) + return lun_id + def _rollback_snapshot(self, vol_name, snap_name): def _snapshot_rollback_finish(): snapshot_info = self.client.get_snapshot_info_by_name(snap_name) @@ -669,6 +937,265 @@ def ensure_export(self, context, volume): def remove_export(self, context, volume): pass + def create_group(self, context, group): + """Creates a group. Driver only need to return state""" + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.create_consistencygroup(context, group) + + def create_consistencygroup(self, context, group): + """Creates a group. Driver only need to return state""" + LOG.info("Create group successfully") + return {'status': 'available'} + + def update_group(self, context, group, + add_volumes=None, remove_volumes=None): + """ + The volume manager will adds/removes the volume to/from the + group in the database, if need add_volumes, Driver just need + to check whether volume is in array or not + """ + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.update_consistencygroup( + context, group, add_volumes, remove_volumes) + + def update_consistencygroup(self, context, group, + add_volumes=None, remove_volumes=None): + """ + The volume manager will adds/removes the volume to/from the + group in the database, if need add_volumes, Driver just need + to check whether volume is in array or not + """ + if add_volumes is None: + add_volumes = [] + for volume in add_volumes: + try: + self._check_volume_exist_on_array(volume) + except Exception: + with excutils.save_and_reraise_exception(): + LOG.error("The add_volume %s not exist on array" % volume.id) + + model_update = {'status': 'available'} + LOG.info("Update group successfully") + return model_update, None, None + + def delete_group(self, context, group, volumes): + """delete the group, Driver need to delete relation lun on array""" + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.delete_consistencygroup(context, group, volumes) + + def delete_consistencygroup(self, context, group, volumes): + """delete the group, Driver need to delete relation lun on array""" + volumes_model_update = [] + model_update = {'status': 'deleted'} + for volume in volumes: + volume_model_update = {'id': volume.id} + try: + self.delete_volume(volume) + except Exception: + LOG.error('Delete volume %s failed.' % volume) + volume_model_update.update({'status': 'error_deleting'}) + else: + volume_model_update.update({'status': 'deleted'}) + + LOG.info('Deleted volume %s successfully' % volume) + volumes_model_update.append(volume_model_update) + + LOG.info("Delete group successfully") + return model_update, volumes_model_update + + def create_group_from_src(self, context, group, volumes, + group_snapshot=None, snapshots=None, + source_group=None, source_vols=None): + """ + create group from group or group-snapshot, + Driver need to create volume from volume or snapshot + """ + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.create_consistencygroup_from_src(context, group, volumes, + group_snapshot, snapshots, + source_group, source_vols) + + def create_consistencygroup_from_src(self, context, group, volumes, + group_snapshot=None, snapshots=None, + source_group=None, source_vols=None): + """ + create group from group or group-snapshot, + Driver need to create volume from volume or snapshot + """ + model_update = self.create_consistencygroup(context, group) + volumes_model_update = [] + delete_snapshots = False + + if not snapshots and source_vols: + snapshots = [] + for src_volume in source_vols: + volume_kwargs = { + 'id': src_volume.id, + '_name_id': None, + 'host': src_volume.host + } + snapshot_kwargs = { + 'id': six.text_type(uuid.uuid4()), + 'volume': objects.Volume(**volume_kwargs) + } + snapshots.append(objects.Snapshot(**snapshot_kwargs)) + + self._create_group_snapshot(snapshots) + delete_snapshots = True + + if snapshots: + volumes_model_update = self._create_volume_from_group_snapshot( + volumes, snapshots, delete_snapshots) + + if delete_snapshots: + self._delete_group_snapshot(snapshots) + + LOG.info("Create group from src successfully") + return model_update, volumes_model_update + + def _create_volume_from_group_snapshot(self, volumes, snapshots, delete_snapshots): + volumes_model_update = [] + added_volumes = [] + for i, volume in enumerate(volumes): + try: + vol_model_update = self.create_volume_from_snapshot( + volume, snapshots[i]) + vol_model_update.update({'id': volume.id}) + volumes_model_update.append(vol_model_update) + added_volumes.append(volume) + except Exception: + LOG.error("Create volume from snapshot error, Delete the newly created lun.") + with excutils.save_and_reraise_exception(): + self._delete_added_volume_snapshots( + added_volumes, snapshots, delete_snapshots) + + return volumes_model_update + + def _delete_added_volume_snapshots( + self, added_volumes, snapshots, delete_snapshots): + if delete_snapshots: + self._delete_group_snapshot(snapshots) + for add_volume in added_volumes: + vol_name = self._get_vol_name(add_volume) + self.fs_qos.remove(vol_name) + self.client.delete_volume(vol_name=vol_name) + LOG.info("delete storage newly added " + "volume success, volume is %s" % add_volume.id) + + def create_group_snapshot(self, context, group_snapshot, snapshots): + """Create group snapshot.""" + if not volume_utils.is_group_a_cg_snapshot_type(group_snapshot): + LOG.info("group_snapshot's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.create_cgsnapshot(context, group_snapshot, snapshots) + + def create_cgsnapshot(self, context, group_snapshot, snapshots): + """Create group snapshot.""" + LOG.info('Create group snapshot for group: %(group_snapshot)s', + {'group_snapshot': group_snapshot}) + + try: + snapshots_model_update = self._create_group_snapshot(snapshots) + except Exception as err: + msg = ("Create group snapshots failed. " + "Group snapshot id: %s. Reason is %s") % (group_snapshot.id, err) + LOG.error(msg) + raise exception.CinderException(msg) + + model_update = {'status': 'available'} + return model_update, snapshots_model_update + + def _create_group_snapshot(self, snapshots): + """Generate snapshots for all volumes in the group.""" + snapshots_model_update = [] + snapshot_group_list = [] + + for snapshot in snapshots: + snapshot_name = self._get_snapshot_name(snapshot) + vol_name = self._get_vol_name(snapshot.volume) + snapshot_group_list.append({ + 'name': snapshot_name, + 'sub_type': '0', + 'volume_name': vol_name + }) + snapshot_model_update = { + 'id': snapshot.id, + 'status': 'available', + } + snapshots_model_update.append(snapshot_model_update) + try: + self.client.create_consistent_snapshot_by_name(snapshot_group_list) + except Exception: + with excutils.save_and_reraise_exception(): + LOG.error("Create consistent snapshot failed, " + "snapshot_group_list is %s" % snapshot_group_list) + + return snapshots_model_update + + def delete_group_snapshot(self, context, group_snapshot, snapshots): + """Delete group snapshot.""" + if not volume_utils.is_group_a_cg_snapshot_type(group_snapshot): + LOG.info("group_snapshot's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.delete_cgsnapshot(context, group_snapshot, snapshots) + + def delete_cgsnapshot(self, context, group_snapshot, snapshots): + """Delete group snapshot.""" + LOG.info("Delete group_snapshot %s for " + "consistency group: %s" % (group_snapshot.id, group_snapshot)) + + try: + snapshots_model_update = self._delete_group_snapshot(snapshots) + except Exception as err: + msg = ("Delete cg snapshots failed. " + "group snapshot id: %s, reason is %s") % (group_snapshot.id, err) + LOG.error(msg) + raise exception.CinderException(msg) + + model_update = {'status': 'deleted'} + return model_update, snapshots_model_update + + def _delete_group_snapshot(self, snapshots): + """Delete all snapshots in snapshot group""" + snapshots_model_update = [] + for snapshot in snapshots: + snapshot_model_update = { + 'id': snapshot.id, + 'status': 'deleted' + } + snapshots_model_update.append(snapshot_model_update) + snapshot_name = self._get_snapshot_name(snapshot) + + if not self._check_snapshot_exist(snapshot.volume, snapshot): + LOG.info("snapshot %s not exist in array, " + "don't need to delete, try next one" % snapshot_name) + continue + self.client.delete_snapshot(snapshot_name=snapshot_name) + LOG.info("Delete snapshot successfully," + " the deleted snapshots is %s" % snapshot_name) + + return snapshots_model_update + class DSWAREDriver(DSWAREBaseDriver): def get_volume_stats(self, refresh=False): @@ -721,7 +1248,7 @@ def initialize_connection(self, volume, connector): vol_wwn = volume_info.get('wwn') by_id_path = "/dev/disk/by-id/" + "wwn-0x%s" % vol_wwn properties = {'device_path': by_id_path} - import time + LOG.info("Wait %(t)s second(s) for scanning the target device %(dev)s." % {"t": self.configuration.scan_device_timeout, "dev": by_id_path}) diff --git a/Cinder/Train/fs_client.py b/Cinder/Train/fs_client.py index 234d7f1..09d9581 100644 --- a/Cinder/Train/fs_client.py +++ b/Cinder/Train/fs_client.py @@ -14,16 +14,16 @@ # under the License. import json + import requests import six -import time +from oslo_log import log as logging from requests.adapters import HTTPAdapter from cinder import exception from cinder.i18n import _ from cinder.volume.drivers.fusionstorage import constants -from oslo_log import log as logging LOG = logging.getLogger(__name__) @@ -43,7 +43,8 @@ def __init__(self, fs_address, fs_user, fs_password, **extend_conf): self.session = None self.token = None self.version = None - mutual_authentication = extend_conf.get("mutual_authentication") + self.esn = None + mutual_authentication = extend_conf.get("mutual_authentication", {}) self.init_http_head(mutual_authentication) LOG.warning("Suppressing requests library SSL Warnings") @@ -147,6 +148,13 @@ def get_version(self): if result.get("currentVersion"): self.version = result["currentVersion"] + def get_esn(self): + url = "/cluster/sn" + result = self.call(url, "get") + self._assert_rest_result(result, _('Get cluster esn error.')) + self.esn = result.get("sn") + return self.esn + def login(self): self.get_version() url = '/sec/login' @@ -160,6 +168,7 @@ def login(self): self.session.headers.update({ "x-auth-token": self.token }) + self.get_esn() def logout(self): url = '/sec/logout' @@ -264,6 +273,15 @@ def query_volume_by_name(self, vol_name): result, _("Query volume by name session error")) return result.get('lunDetailInfo') + def query_volume_by_name_v2(self, vol_name): + url = '/api/v2/block_service/volumes?name=' + vol_name + result = self.call(url, 'GET', get_system_time=True) + if result.get('errorCode') in constants.VOLUME_NOT_EXIST: + return {} + self._assert_rest_result( + result, _("Query volume by name session error")) + return result.get('data', {}) + def query_volume_by_id(self, vol_id): url = 'v1.3/volume/queryById?volId=' + vol_id result = self.call(url, 'GET', get_version=True) @@ -746,3 +764,57 @@ def get_iscsi_links_info(self, iscsi_link_count, pool_list): return [iscsi["ip"] for iscsi in result.get("iscsiLinks", []) if iscsi.get("ip")] + + def create_lun_migration(self, src_lun_id, dst_lun_id, speed=2): + url = "/api/v2/block_service/lun_migration" + params = { + "parent_id": src_lun_id, + "target_lun_id": dst_lun_id, + "speed": speed, + "work_mode": 0 + } + result = self.call(url, "POST", params, get_system_time=True) + self._assert_rest_result(result, + _("create lun migration task error.")) + + def get_lun_migration_task_by_id(self, src_lun_id): + url = "/api/v2/block_service/lun_migration" + params = { + "id": src_lun_id + } + result = self.call(url, "GET", params, get_system_time=True) + self._assert_rest_result(result, + _("get lun migration task error.")) + return result.get('data', {}) + + def delete_lun_migration(self, src_lun_id): + url = "/api/v2/block_service/lun_migration" + params = { + 'id': src_lun_id + } + result = self.call(url, "DELETE", params, get_system_time=True) + self._assert_rest_result(result, + _("Delete lun migration task error.")) + + def get_volume_snapshot(self, volume_name): + url = "/volume/snapshot/list" + params = { + 'volName': volume_name, + 'batchNum': 1, + 'batchLimit': 10 + } + result = self.call(url, "POST", params) + return result.get('snapshotList', []) + + def create_consistent_snapshot_by_name(self, snapshot_group_list): + url = "/api/v2/block_service/consistency_snapshots" + result = self.call(url, "POST", snapshot_group_list, get_system_time=True) + self._assert_rest_result(result, _("create consistent_snapshot error.")) + return result.get('data', []) + + def create_full_volume_from_snapshot(self, vol_name, snapshot_name): + url = '/api/v2/block_service/createFullVolumeFromSnap' + params = {"snap_name_src": snapshot_name, "volume_name_dst": vol_name} + result = self.call(url, "POST", params, get_system_time=True) + self._assert_rest_result( + result, _("create full volume from snap fails")) diff --git a/Cinder/Train/fs_qos.py b/Cinder/Train/fs_qos.py index 731c45e..286dbc3 100644 --- a/Cinder/Train/fs_qos.py +++ b/Cinder/Train/fs_qos.py @@ -29,7 +29,11 @@ def __init__(self, client): def add(self, qos, vol_name): localtime = time.strftime('%Y%m%d%H%M%S', time.localtime()) - qos_name = constants.QOS_PREFIX + localtime + # QoS policy name. The value contains 1 to 63 characters. + # So we intercept volume_name Ensure that the length does not exceed 63 + vol_str = vol_name[-constants.QOS_MAX_INTERCEPT_LENGTH::] \ + if len(vol_name) >= constants.QOS_MAX_INTERCEPT_LENGTH else vol_name + qos_name = constants.QOS_PREFIX + localtime + '_' + vol_str self.client.create_qos(qos_name, qos) try: self.client.associate_qos_with_volume(vol_name, qos_name) diff --git a/Cinder/Train/fs_utils.py b/Cinder/Train/fs_utils.py index 8b9ae78..0856038 100644 --- a/Cinder/Train/fs_utils.py +++ b/Cinder/Train/fs_utils.py @@ -16,11 +16,11 @@ import datetime import hashlib import ipaddress -import pytz import random -import six import time +import pytz +import six from oslo_log import log as logging from oslo_service import loopingcall from oslo_utils import units @@ -758,3 +758,9 @@ def get_iscsi_info_from_storage(manager_ips, use_ipv6, valid_iscsi_ips, valid_node_ips): return _get_target_info(manager_ips, use_ipv6, valid_iscsi_ips, valid_node_ips) + + +def encode_name(my_uuid): + encoded_name = hashlib.md5(my_uuid.encode('utf-8')).hexdigest() + target_lun_prefix = my_uuid.split('-')[0] + '-' + return target_lun_prefix + encoded_name diff --git a/Cinder/Ussuri/constants.py b/Cinder/Ussuri/constants.py index 5f46ece..b4cb843 100644 --- a/Cinder/Ussuri/constants.py +++ b/Cinder/Ussuri/constants.py @@ -45,6 +45,14 @@ CONF_STORAGE_CERT_FILEPATH = "storage_cert_filepath" CONF_STORAGE_SSL_TWO_WAY_AUTH = "storage_ssl_two_way_auth" +DEFAULT_WAIT_INTERVAL = 5 +MIGRATION_COMPLETE = 76 +MIGRATION_FAULT = 74 +STATUS_HEALTH = 1 +STATUS_VOLUME_READY = 27 +MIGRATION_WAIT_INTERVAL = 5 +DEFAULT_WAIT_TIMEOUT = 3600 * 24 * 30 + QOS_MUST_SET = ["maxIOPS", "maxMBPS"] QOS_KEYS = ["maxIOPS", "maxMBPS", "total_iops_sec", "total_bytes_sec"] QOS_SCHEDULER_KEYS = ["scheduleType", "startDate", "startTime", @@ -53,6 +61,7 @@ QOS_SCHEDULER_DEFAULT_TYPE = "0" QOS_SCHEDULER_WEEK_TYPE = "3" QOS_SUPPORT_SCHEDULE_VERSION = "8.0" +QOS_MAX_INTERCEPT_LENGTH = 36 SECONDS_OF_DAY = 24 * 60 * 60 SECONDS_OF_HOUR = 60 * 60 SNAPSHOT_HEALTH_STATUS = ( @@ -80,3 +89,9 @@ HOSTGROUP_ALREADY_EXIST = 50157044 INITIATOR_ALREADY_EXIST = 50155102 INITIATOR_IN_HOST = 50157021 + +CHECK_CLONED_INTERVAL = 2 +REST_VOLUME_CREATING_STATUS = 15 +REST_VOLUME_DUPLICATE_VOLUME = 6 +REST_VOLUME_CREATE_SUCCESS_STATUS = 0 +CLONE_VOLUME_TIMEOUT = 3600 * 24 * 30 diff --git a/Cinder/Ussuri/dsware.py b/Cinder/Ussuri/dsware.py index 75e1808..b03e039 100644 --- a/Cinder/Ussuri/dsware.py +++ b/Cinder/Ussuri/dsware.py @@ -14,16 +14,22 @@ # under the License. import json - +import time +import uuid from multiprocessing import Lock + +import six from oslo_config import cfg from oslo_log import log as logging +from oslo_utils import excutils from oslo_utils import units +from oslo_service import loopingcall from cinder import coordination from cinder import exception from cinder.i18n import _ from cinder import interface +from cinder import objects from cinder.volume import driver from cinder.volume.drivers.fusionstorage import constants from cinder.volume.drivers.fusionstorage import fs_client @@ -105,6 +111,9 @@ cfg.StrOpt('storage_key_filepath', default='', help='Client key directory.'), + cfg.BoolOpt('full_clone', + default=False, + help='Whether use full clone.'), ] CONF = cfg.CONF @@ -113,7 +122,7 @@ @interface.volumedriver class DSWAREBaseDriver(driver.VolumeDriver): - VERSION = '2.5.RC4' + VERSION = "2.6.1" CI_WIKI_NAME = 'Huawei_FusionStorage_CI' def __init__(self, *args, **kwargs): @@ -210,6 +219,7 @@ def _update_single_pool_info_status(self, pool_info): "total_capacity_gb": capacity['total_capacity_gb'], "free_capacity_gb": capacity['free_capacity_gb'], "provisioned_capacity_gb": capacity['provisioned_capacity_gb'], + "location_info": self.client.esn, "QoS_support": True, 'multiattach': True, "thin_provisioning_support": True, @@ -247,8 +257,12 @@ def _raise_exception(msg): raise exception.VolumeBackendAPIException(data=msg) def _get_pool_id(self, volume): - pool_id_list = [] pool_name = volume_utils.extract_host(volume.host, level='pool') + pool_id = self._get_pool_id_by_name(pool_name) + return pool_id + + def _get_pool_id_by_name(self, pool_name): + pool_id_list = [] all_pools = self.client.query_pool_info() for pool in all_pools: if pool_name == pool['poolName']: @@ -363,29 +377,111 @@ def _expand_volume_when_create(self, vol_name, vol_size): self.client.delete_volume(vol_name=vol_name) raise + def _check_create_cloned_volume_finish(self, new_volume_name, start_time): + LOG.debug('Loopcall: _check_create_cloned_volume_finish(), ' + 'volume-name %s', + new_volume_name) + current_volume = self.client.query_volume_by_name(new_volume_name) + + if current_volume and 'status' in current_volume: + status = int(current_volume['status']) + LOG.debug('Wait clone volume %(volume_name)s, status:%(status)s.', + {"volume_name": new_volume_name, + "status": status}) + if status in {constants.REST_VOLUME_CREATING_STATUS, + constants.REST_VOLUME_DUPLICATE_VOLUME}: + LOG.debug(_("Volume %s is cloning"), new_volume_name) + elif status == constants.REST_VOLUME_CREATE_SUCCESS_STATUS: + raise loopingcall.LoopingCallDone(retvalue=True) + else: + msg = _('Clone volume %(new_volume_name)s failed, ' + 'the status is:%(status)s.') + LOG.error(msg, {'new_volume_name': new_volume_name, + 'status': status}) + raise loopingcall.LoopingCallDone(retvalue=False) + + max_time_out = constants.CLONE_VOLUME_TIMEOUT + current_time = time.time() + if (current_time - start_time) > max_time_out: + msg = _('Dsware clone volume time out. ' + 'Volume: %(new_volume_name)s, status: %(status)s') + LOG.error(msg, {'new_volume_name': new_volume_name, + 'status': current_volume['status']}) + raise loopingcall.LoopingCallDone(retvalue=False) + else: + LOG.warning(_('Can not find volume %s'), new_volume_name) + msg = "DSWARE clone volume failed:volume can not find from dsware" + LOG.error(msg) + raise loopingcall.LoopingCallDone(retvalue=False) + + def _wait_for_create_cloned_volume_finish_timer(self, new_volume_name): + timer = loopingcall.FixedIntervalLoopingCall( + self._check_create_cloned_volume_finish, + new_volume_name, time.time()) + LOG.debug('Calling _check_create_cloned_volume_finish: volume-name %s', + new_volume_name) + ret = timer.start(interval=constants.CHECK_CLONED_INTERVAL).wait() + timer.stop() + return ret + def create_volume_from_snapshot(self, volume, snapshot): vol_name = self._get_vol_name(volume) snapshot_name = self._get_snapshot_name(snapshot) vol_size = volume.size + pool_id = self._get_pool_id(volume) if not self._check_snapshot_exist(snapshot.volume, snapshot): msg = _("Snapshot: %(name)s does not exist!" ) % {"name": snapshot_name} self._raise_exception(msg) - elif self._check_volume_exist(volume): + if self._check_volume_exist(volume): msg = _("Volume: %(vol_name)s already exists!" ) % {'vol_name': vol_name} self._raise_exception(msg) - else: - vol_size *= units.Ki + + vol_size *= units.Ki + if not self.configuration.full_clone: self.client.create_volume_from_snapshot( snapshot_name=snapshot_name, vol_name=vol_name, vol_size=vol_size) - self._add_qos_to_volume(volume, vol_name) - self._expand_volume_when_create(vol_name, vol_size) - result = self.client.query_volume_by_name(vol_name=vol_name) - return ({"metadata": {'lun_wwn': result.get('wwn')}} - if result else {}) + else: + self.client.create_volume(vol_name, vol_size, pool_id) + self.client.create_full_volume_from_snapshot(vol_name, + snapshot_name) + ret = self._wait_for_create_cloned_volume_finish_timer(vol_name) + if not ret: + msg = _('Create full volume %s from snap failed') % vol_name + self._raise_exception(msg) + self._add_qos_to_volume(volume, vol_name) + self._expand_volume_when_create(vol_name, vol_size) + result = self.client.query_volume_by_name(vol_name=vol_name) + return ({"metadata": {'lun_wwn': result.get('wwn')}} + if result else {}) + + def _create_volume_from_volume_full_clone(self, vol_name, vol_size, pool_id, + src_vol_name): + tmp_snap_name = "temp" + src_vol_name + "clone" + vol_name + + self.client.create_snapshot(tmp_snap_name, src_vol_name) + try: + self.client.create_volume(vol_name, vol_size, pool_id) + except Exception as err: + self.client.delete_snapshot(tmp_snap_name) + raise err + + try: + self.client.create_full_volume_from_snapshot( + vol_name, tmp_snap_name) + except Exception as err: + self.client.delete_snapshot(tmp_snap_name) + self.client.delete_volume(vol_name) + raise err + + ret = self._wait_for_create_cloned_volume_finish_timer(vol_name) + if not ret: + msg = _('Create full volume %s from snap failed') % vol_name + self._raise_exception(msg) + self.client.delete_snapshot(tmp_snap_name) def create_cloned_volume(self, volume, src_volume): vol_name = self._get_vol_name(volume) @@ -398,15 +494,22 @@ def create_cloned_volume(self, volume, src_volume): msg = _("Volume: %(vol_name)s does not exist!" ) % {"vol_name": src_vol_name} self._raise_exception(msg) - else: + + if not self.configuration.full_clone: self.client.create_volume_from_volume( vol_name=vol_name, vol_size=vol_size, src_vol_name=src_vol_name) - self._add_qos_to_volume(volume, vol_name) - self._expand_volume_when_create(vol_name, vol_size) - result = self.client.query_volume_by_name(vol_name=vol_name) - return ({"metadata": {'lun_wwn': result.get('wwn')}} - if result else {}) + else: + pool_id = self._get_pool_id(volume) + self._create_volume_from_volume_full_clone( + vol_name=vol_name, vol_size=vol_size, pool_id=pool_id, + src_vol_name=src_vol_name) + + self._add_qos_to_volume(volume, vol_name) + self._expand_volume_when_create(vol_name, vol_size) + result = self.client.query_volume_by_name(vol_name=vol_name) + return ({"metadata": {'lun_wwn': result.get('wwn')}} + if result else {}) def create_snapshot(self, snapshot): snapshot_name = self._get_snapshot_name(snapshot) @@ -581,12 +684,13 @@ def unmanage_snapshot(self, snapshot): def _check_need_changes_for_retype(self, volume, new_type, host, vol_name): before_change = {} after_change = {} - if volume.host != host["host"]: - msg = (_("Do not support retype between different host. Volume's " + migrate = False + if volume.host != host.get("host"): + migrate = True + msg = (_("retype support migration between different host. Volume's " "host: %(vol_host)s, host's host: %(host)s") - % {"vol_host": volume.host, "host": host['host']}) - LOG.error(msg) - raise exception.InvalidInput(msg) + % {"vol_host": volume.host, "host": host.get("host")}) + LOG.info(msg) old_opts = fs_utils.get_volume_specs(self.client, vol_name) new_opts = fs_utils.get_volume_type_params(new_type, self.client) @@ -596,7 +700,7 @@ def _check_need_changes_for_retype(self, volume, new_type, host, vol_name): change_opts = {"old_opts": before_change, "new_opts": after_change} - return change_opts + return migrate, change_opts def retype(self, context, volume, new_type, diff, host): LOG.info("Retype volume: %(vol)s, new_type: %(new_type)s, " @@ -607,13 +711,177 @@ def retype(self, context, volume, new_type, diff, host): "host": host}) vol_name = self._get_vol_name(volume) - change_opts = self._check_need_changes_for_retype( + migrate, change_opts = self._check_need_changes_for_retype( volume, new_type, host, vol_name) + if migrate: + src_lun_id = self._check_volume_exist_on_array(volume) + LOG.debug("Begin to migrate LUN(id: %(lun_id)s) with " + "change %(change_opts)s.", + {"lun_id": src_lun_id, "change_opts": change_opts}) + moved = self._migrate_volume(volume, host, src_lun_id) + if not moved: + LOG.warning("Storage-assisted migration failed during " + "retype.") + return False, None self._change_lun(vol_name, change_opts.get("new_opts"), change_opts.get("old_opts")) return True, None + def migrate_volume(self, context, volume, host): + """Migrate a volume within the same array.""" + LOG.info("Migrate Volume:%(volume)s, host:%(host)s", + {"volume": volume.id, + "host": host}) + src_lun_id = self._check_volume_exist_on_array(volume) + + moved = self._migrate_volume(volume, host, src_lun_id) + return moved, {} + + def _create_dst_volume(self, volume, host): + pool_name = host['capabilities']['pool_name'] + pool_id = self._get_pool_id_by_name(pool_name) + vol_name = fs_utils.encode_name(six.text_type(uuid.uuid4())) + vol_size = volume.size + vol_size *= units.Ki + self.client.create_volume( + pool_id=pool_id, vol_name=vol_name, vol_size=vol_size) + + result = self.client.query_volume_by_name_v2(vol_name=vol_name) + dst_lun_id = result.get('id') + self._wait_volume_ready(vol_name) + return vol_name, dst_lun_id + + def _migrate_volume(self, volume, host, src_lun_id): + """create migration task and wait for task done""" + if not self._check_migration_valid(host): + return False + + vol_name, dst_lun_id = self._create_dst_volume(volume, host) + + try: + self.client.create_lun_migration(src_lun_id, dst_lun_id) + + def _is_lun_migration_complete(): + return self._is_lun_migration_complete(src_lun_id, dst_lun_id) + + wait_interval = constants.MIGRATION_WAIT_INTERVAL + fs_utils.wait_for_condition(_is_lun_migration_complete, + wait_interval, + constants.DEFAULT_WAIT_TIMEOUT) + # Clean up if migration failed. + except Exception as ex: + raise exception.VolumeBackendAPIException(data=ex) + finally: + if self._is_lun_migration_exist(src_lun_id, dst_lun_id): + self.client.delete_lun_migration(src_lun_id) + self._delete_lun_with_check(vol_name) + + LOG.info("Migrate lun %s successfully.", src_lun_id) + return True + + def _delete_lun_with_check(self, vol_name): + if self.client.query_volume_by_name(vol_name): + # migrate_dst_lun don't have qos, so don't + # need to remove qos, Delete the LUN directly. + self.client.delete_volume(vol_name) + + def _is_lun_migration_complete(self, src_lun_id, dst_lun_id): + result = self.client.get_lun_migration_task_by_id(src_lun_id) + found_migration_task = False + if not result: + return False + + if (str(src_lun_id) == result.get('parent_id') and + str(dst_lun_id) == result.get('target_lun_id')): + found_migration_task = True + if constants.MIGRATION_COMPLETE == result.get('running_status'): + return True + if constants.MIGRATION_FAULT == result.get('running_status'): + msg = _("Lun migration error. " + "the migration task running_status is abnormal") + LOG.error(msg) + raise exception.VolumeBackendAPIException(data=msg) + + if not found_migration_task: + err_msg = _("lun migration error, Cannot find migration task.") + LOG.error(err_msg) + raise exception.VolumeBackendAPIException(data=err_msg) + + return False + + def _is_lun_migration_exist(self, src_lun_id, dst_lun_id): + try: + result = self.client.get_lun_migration_task_by_id(src_lun_id) + except Exception: + LOG.error("Get LUN migration error.") + return False + + if (str(src_lun_id) == result.get('parent_id') and + str(dst_lun_id) == result.get('target_lun_id')): + return True + return False + + def _wait_volume_ready(self, vol_name): + wait_interval = constants.DEFAULT_WAIT_INTERVAL + + def _volume_ready(): + result = self.client.query_volume_by_name_v2(vol_name) + if not result: + return False + + if (result.get('health_status') == constants.STATUS_HEALTH + and result.get('running_status') == constants.STATUS_VOLUME_READY): + return True + return False + + fs_utils.wait_for_condition(_volume_ready, + wait_interval, + wait_interval * 10) + + def _check_migration_valid(self, host): + if 'pool_name' not in host.get('capabilities', {}): + return False + + target_device = host.get('capabilities', {}).get('location_info') + + # Source and destination should be on same array. + if target_device != self.client.esn: + LOG.error("lun migration error, " + "Source and destination should be on same array") + return False + + pool_name = host.get('capabilities', {}).get('pool_name', '') + if len(pool_name) == 0: + LOG.error("lun migration error, pool_name not exists") + return False + + return True + + def _check_volume_exist_on_array(self, volume): + volume_name = self._get_vol_name(volume) + result = self._check_volume_exist(volume) + if not result: + msg = _("Volume %s does not exist on the array." + ) % volume.id + self._raise_exception(msg) + + lun_wwn = result.get('wwn') + if not lun_wwn: + LOG.debug("No LUN WWN recorded for volume %s.", volume.id) + + lun_id = result.get('volId') + if not lun_id: + msg = _("Volume %s does not exist on the array." + ) % volume.id + self._raise_exception(msg) + + if self.client.get_volume_snapshot(volume_name): + msg = _("Volume %s which have snapshot cannot do lun migration" + ) % volume.id + self._raise_exception(msg) + return lun_id + def _rollback_snapshot(self, vol_name, snap_name): def _snapshot_rollback_finish(): snapshot_info = self.client.get_snapshot_info_by_name(snap_name) @@ -669,6 +937,265 @@ def ensure_export(self, context, volume): def remove_export(self, context, volume): pass + def create_group(self, context, group): + """Creates a group. Driver only need to return state""" + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.create_consistencygroup(context, group) + + def create_consistencygroup(self, context, group): + """Creates a group. Driver only need to return state""" + LOG.info("Create group successfully") + return {'status': 'available'} + + def update_group(self, context, group, + add_volumes=None, remove_volumes=None): + """ + The volume manager will adds/removes the volume to/from the + group in the database, if need add_volumes, Driver just need + to check whether volume is in array or not + """ + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.update_consistencygroup( + context, group, add_volumes, remove_volumes) + + def update_consistencygroup(self, context, group, + add_volumes=None, remove_volumes=None): + """ + The volume manager will adds/removes the volume to/from the + group in the database, if need add_volumes, Driver just need + to check whether volume is in array or not + """ + if add_volumes is None: + add_volumes = [] + for volume in add_volumes: + try: + self._check_volume_exist_on_array(volume) + except Exception: + with excutils.save_and_reraise_exception(): + LOG.error("The add_volume %s not exist on array" % volume.id) + + model_update = {'status': 'available'} + LOG.info("Update group successfully") + return model_update, None, None + + def delete_group(self, context, group, volumes): + """delete the group, Driver need to delete relation lun on array""" + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.delete_consistencygroup(context, group, volumes) + + def delete_consistencygroup(self, context, group, volumes): + """delete the group, Driver need to delete relation lun on array""" + volumes_model_update = [] + model_update = {'status': 'deleted'} + for volume in volumes: + volume_model_update = {'id': volume.id} + try: + self.delete_volume(volume) + except Exception: + LOG.error('Delete volume %s failed.' % volume) + volume_model_update.update({'status': 'error_deleting'}) + else: + volume_model_update.update({'status': 'deleted'}) + + LOG.info('Deleted volume %s successfully' % volume) + volumes_model_update.append(volume_model_update) + + LOG.info("Delete group successfully") + return model_update, volumes_model_update + + def create_group_from_src(self, context, group, volumes, + group_snapshot=None, snapshots=None, + source_group=None, source_vols=None): + """ + create group from group or group-snapshot, + Driver need to create volume from volume or snapshot + """ + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.create_consistencygroup_from_src(context, group, volumes, + group_snapshot, snapshots, + source_group, source_vols) + + def create_consistencygroup_from_src(self, context, group, volumes, + group_snapshot=None, snapshots=None, + source_group=None, source_vols=None): + """ + create group from group or group-snapshot, + Driver need to create volume from volume or snapshot + """ + model_update = self.create_consistencygroup(context, group) + volumes_model_update = [] + delete_snapshots = False + + if not snapshots and source_vols: + snapshots = [] + for src_volume in source_vols: + volume_kwargs = { + 'id': src_volume.id, + '_name_id': None, + 'host': src_volume.host + } + snapshot_kwargs = { + 'id': six.text_type(uuid.uuid4()), + 'volume': objects.Volume(**volume_kwargs) + } + snapshots.append(objects.Snapshot(**snapshot_kwargs)) + + self._create_group_snapshot(snapshots) + delete_snapshots = True + + if snapshots: + volumes_model_update = self._create_volume_from_group_snapshot( + volumes, snapshots, delete_snapshots) + + if delete_snapshots: + self._delete_group_snapshot(snapshots) + + LOG.info("Create group from src successfully") + return model_update, volumes_model_update + + def _create_volume_from_group_snapshot(self, volumes, snapshots, delete_snapshots): + volumes_model_update = [] + added_volumes = [] + for i, volume in enumerate(volumes): + try: + vol_model_update = self.create_volume_from_snapshot( + volume, snapshots[i]) + vol_model_update.update({'id': volume.id}) + volumes_model_update.append(vol_model_update) + added_volumes.append(volume) + except Exception: + LOG.error("Create volume from snapshot error, Delete the newly created lun.") + with excutils.save_and_reraise_exception(): + self._delete_added_volume_snapshots( + added_volumes, snapshots, delete_snapshots) + + return volumes_model_update + + def _delete_added_volume_snapshots( + self, added_volumes, snapshots, delete_snapshots): + if delete_snapshots: + self._delete_group_snapshot(snapshots) + for add_volume in added_volumes: + vol_name = self._get_vol_name(add_volume) + self.fs_qos.remove(vol_name) + self.client.delete_volume(vol_name=vol_name) + LOG.info("delete storage newly added " + "volume success, volume is %s" % add_volume.id) + + def create_group_snapshot(self, context, group_snapshot, snapshots): + """Create group snapshot.""" + if not volume_utils.is_group_a_cg_snapshot_type(group_snapshot): + LOG.info("group_snapshot's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.create_cgsnapshot(context, group_snapshot, snapshots) + + def create_cgsnapshot(self, context, group_snapshot, snapshots): + """Create group snapshot.""" + LOG.info('Create group snapshot for group: %(group_snapshot)s', + {'group_snapshot': group_snapshot}) + + try: + snapshots_model_update = self._create_group_snapshot(snapshots) + except Exception as err: + msg = ("Create group snapshots failed. " + "Group snapshot id: %s. Reason is %s") % (group_snapshot.id, err) + LOG.error(msg) + raise exception.CinderException(msg) + + model_update = {'status': 'available'} + return model_update, snapshots_model_update + + def _create_group_snapshot(self, snapshots): + """Generate snapshots for all volumes in the group.""" + snapshots_model_update = [] + snapshot_group_list = [] + + for snapshot in snapshots: + snapshot_name = self._get_snapshot_name(snapshot) + vol_name = self._get_vol_name(snapshot.volume) + snapshot_group_list.append({ + 'name': snapshot_name, + 'sub_type': '0', + 'volume_name': vol_name + }) + snapshot_model_update = { + 'id': snapshot.id, + 'status': 'available', + } + snapshots_model_update.append(snapshot_model_update) + try: + self.client.create_consistent_snapshot_by_name(snapshot_group_list) + except Exception: + with excutils.save_and_reraise_exception(): + LOG.error("Create consistent snapshot failed, " + "snapshot_group_list is %s" % snapshot_group_list) + + return snapshots_model_update + + def delete_group_snapshot(self, context, group_snapshot, snapshots): + """Delete group snapshot.""" + if not volume_utils.is_group_a_cg_snapshot_type(group_snapshot): + LOG.info("group_snapshot's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.delete_cgsnapshot(context, group_snapshot, snapshots) + + def delete_cgsnapshot(self, context, group_snapshot, snapshots): + """Delete group snapshot.""" + LOG.info("Delete group_snapshot %s for " + "consistency group: %s" % (group_snapshot.id, group_snapshot)) + + try: + snapshots_model_update = self._delete_group_snapshot(snapshots) + except Exception as err: + msg = ("Delete cg snapshots failed. " + "group snapshot id: %s, reason is %s") % (group_snapshot.id, err) + LOG.error(msg) + raise exception.CinderException(msg) + + model_update = {'status': 'deleted'} + return model_update, snapshots_model_update + + def _delete_group_snapshot(self, snapshots): + """Delete all snapshots in snapshot group""" + snapshots_model_update = [] + for snapshot in snapshots: + snapshot_model_update = { + 'id': snapshot.id, + 'status': 'deleted' + } + snapshots_model_update.append(snapshot_model_update) + snapshot_name = self._get_snapshot_name(snapshot) + + if not self._check_snapshot_exist(snapshot.volume, snapshot): + LOG.info("snapshot %s not exist in array, " + "don't need to delete, try next one" % snapshot_name) + continue + self.client.delete_snapshot(snapshot_name=snapshot_name) + LOG.info("Delete snapshot successfully," + " the deleted snapshots is %s" % snapshot_name) + + return snapshots_model_update + class DSWAREDriver(DSWAREBaseDriver): def get_volume_stats(self, refresh=False): @@ -721,7 +1248,7 @@ def initialize_connection(self, volume, connector): vol_wwn = volume_info.get('wwn') by_id_path = "/dev/disk/by-id/" + "wwn-0x%s" % vol_wwn properties = {'device_path': by_id_path} - import time + LOG.info("Wait %(t)s second(s) for scanning the target device %(dev)s." % {"t": self.configuration.scan_device_timeout, "dev": by_id_path}) diff --git a/Cinder/Ussuri/fs_client.py b/Cinder/Ussuri/fs_client.py index 234d7f1..09d9581 100644 --- a/Cinder/Ussuri/fs_client.py +++ b/Cinder/Ussuri/fs_client.py @@ -14,16 +14,16 @@ # under the License. import json + import requests import six -import time +from oslo_log import log as logging from requests.adapters import HTTPAdapter from cinder import exception from cinder.i18n import _ from cinder.volume.drivers.fusionstorage import constants -from oslo_log import log as logging LOG = logging.getLogger(__name__) @@ -43,7 +43,8 @@ def __init__(self, fs_address, fs_user, fs_password, **extend_conf): self.session = None self.token = None self.version = None - mutual_authentication = extend_conf.get("mutual_authentication") + self.esn = None + mutual_authentication = extend_conf.get("mutual_authentication", {}) self.init_http_head(mutual_authentication) LOG.warning("Suppressing requests library SSL Warnings") @@ -147,6 +148,13 @@ def get_version(self): if result.get("currentVersion"): self.version = result["currentVersion"] + def get_esn(self): + url = "/cluster/sn" + result = self.call(url, "get") + self._assert_rest_result(result, _('Get cluster esn error.')) + self.esn = result.get("sn") + return self.esn + def login(self): self.get_version() url = '/sec/login' @@ -160,6 +168,7 @@ def login(self): self.session.headers.update({ "x-auth-token": self.token }) + self.get_esn() def logout(self): url = '/sec/logout' @@ -264,6 +273,15 @@ def query_volume_by_name(self, vol_name): result, _("Query volume by name session error")) return result.get('lunDetailInfo') + def query_volume_by_name_v2(self, vol_name): + url = '/api/v2/block_service/volumes?name=' + vol_name + result = self.call(url, 'GET', get_system_time=True) + if result.get('errorCode') in constants.VOLUME_NOT_EXIST: + return {} + self._assert_rest_result( + result, _("Query volume by name session error")) + return result.get('data', {}) + def query_volume_by_id(self, vol_id): url = 'v1.3/volume/queryById?volId=' + vol_id result = self.call(url, 'GET', get_version=True) @@ -746,3 +764,57 @@ def get_iscsi_links_info(self, iscsi_link_count, pool_list): return [iscsi["ip"] for iscsi in result.get("iscsiLinks", []) if iscsi.get("ip")] + + def create_lun_migration(self, src_lun_id, dst_lun_id, speed=2): + url = "/api/v2/block_service/lun_migration" + params = { + "parent_id": src_lun_id, + "target_lun_id": dst_lun_id, + "speed": speed, + "work_mode": 0 + } + result = self.call(url, "POST", params, get_system_time=True) + self._assert_rest_result(result, + _("create lun migration task error.")) + + def get_lun_migration_task_by_id(self, src_lun_id): + url = "/api/v2/block_service/lun_migration" + params = { + "id": src_lun_id + } + result = self.call(url, "GET", params, get_system_time=True) + self._assert_rest_result(result, + _("get lun migration task error.")) + return result.get('data', {}) + + def delete_lun_migration(self, src_lun_id): + url = "/api/v2/block_service/lun_migration" + params = { + 'id': src_lun_id + } + result = self.call(url, "DELETE", params, get_system_time=True) + self._assert_rest_result(result, + _("Delete lun migration task error.")) + + def get_volume_snapshot(self, volume_name): + url = "/volume/snapshot/list" + params = { + 'volName': volume_name, + 'batchNum': 1, + 'batchLimit': 10 + } + result = self.call(url, "POST", params) + return result.get('snapshotList', []) + + def create_consistent_snapshot_by_name(self, snapshot_group_list): + url = "/api/v2/block_service/consistency_snapshots" + result = self.call(url, "POST", snapshot_group_list, get_system_time=True) + self._assert_rest_result(result, _("create consistent_snapshot error.")) + return result.get('data', []) + + def create_full_volume_from_snapshot(self, vol_name, snapshot_name): + url = '/api/v2/block_service/createFullVolumeFromSnap' + params = {"snap_name_src": snapshot_name, "volume_name_dst": vol_name} + result = self.call(url, "POST", params, get_system_time=True) + self._assert_rest_result( + result, _("create full volume from snap fails")) diff --git a/Cinder/Ussuri/fs_qos.py b/Cinder/Ussuri/fs_qos.py index 731c45e..286dbc3 100644 --- a/Cinder/Ussuri/fs_qos.py +++ b/Cinder/Ussuri/fs_qos.py @@ -29,7 +29,11 @@ def __init__(self, client): def add(self, qos, vol_name): localtime = time.strftime('%Y%m%d%H%M%S', time.localtime()) - qos_name = constants.QOS_PREFIX + localtime + # QoS policy name. The value contains 1 to 63 characters. + # So we intercept volume_name Ensure that the length does not exceed 63 + vol_str = vol_name[-constants.QOS_MAX_INTERCEPT_LENGTH::] \ + if len(vol_name) >= constants.QOS_MAX_INTERCEPT_LENGTH else vol_name + qos_name = constants.QOS_PREFIX + localtime + '_' + vol_str self.client.create_qos(qos_name, qos) try: self.client.associate_qos_with_volume(vol_name, qos_name) diff --git a/Cinder/Ussuri/fs_utils.py b/Cinder/Ussuri/fs_utils.py index 8b9ae78..0856038 100644 --- a/Cinder/Ussuri/fs_utils.py +++ b/Cinder/Ussuri/fs_utils.py @@ -16,11 +16,11 @@ import datetime import hashlib import ipaddress -import pytz import random -import six import time +import pytz +import six from oslo_log import log as logging from oslo_service import loopingcall from oslo_utils import units @@ -758,3 +758,9 @@ def get_iscsi_info_from_storage(manager_ips, use_ipv6, valid_iscsi_ips, valid_node_ips): return _get_target_info(manager_ips, use_ipv6, valid_iscsi_ips, valid_node_ips) + + +def encode_name(my_uuid): + encoded_name = hashlib.md5(my_uuid.encode('utf-8')).hexdigest() + target_lun_prefix = my_uuid.split('-')[0] + '-' + return target_lun_prefix + encoded_name diff --git a/Cinder/Victoria/constants.py b/Cinder/Victoria/constants.py index 5f46ece..b4cb843 100644 --- a/Cinder/Victoria/constants.py +++ b/Cinder/Victoria/constants.py @@ -45,6 +45,14 @@ CONF_STORAGE_CERT_FILEPATH = "storage_cert_filepath" CONF_STORAGE_SSL_TWO_WAY_AUTH = "storage_ssl_two_way_auth" +DEFAULT_WAIT_INTERVAL = 5 +MIGRATION_COMPLETE = 76 +MIGRATION_FAULT = 74 +STATUS_HEALTH = 1 +STATUS_VOLUME_READY = 27 +MIGRATION_WAIT_INTERVAL = 5 +DEFAULT_WAIT_TIMEOUT = 3600 * 24 * 30 + QOS_MUST_SET = ["maxIOPS", "maxMBPS"] QOS_KEYS = ["maxIOPS", "maxMBPS", "total_iops_sec", "total_bytes_sec"] QOS_SCHEDULER_KEYS = ["scheduleType", "startDate", "startTime", @@ -53,6 +61,7 @@ QOS_SCHEDULER_DEFAULT_TYPE = "0" QOS_SCHEDULER_WEEK_TYPE = "3" QOS_SUPPORT_SCHEDULE_VERSION = "8.0" +QOS_MAX_INTERCEPT_LENGTH = 36 SECONDS_OF_DAY = 24 * 60 * 60 SECONDS_OF_HOUR = 60 * 60 SNAPSHOT_HEALTH_STATUS = ( @@ -80,3 +89,9 @@ HOSTGROUP_ALREADY_EXIST = 50157044 INITIATOR_ALREADY_EXIST = 50155102 INITIATOR_IN_HOST = 50157021 + +CHECK_CLONED_INTERVAL = 2 +REST_VOLUME_CREATING_STATUS = 15 +REST_VOLUME_DUPLICATE_VOLUME = 6 +REST_VOLUME_CREATE_SUCCESS_STATUS = 0 +CLONE_VOLUME_TIMEOUT = 3600 * 24 * 30 diff --git a/Cinder/Victoria/dsware.py b/Cinder/Victoria/dsware.py index 75e1808..b03e039 100644 --- a/Cinder/Victoria/dsware.py +++ b/Cinder/Victoria/dsware.py @@ -14,16 +14,22 @@ # under the License. import json - +import time +import uuid from multiprocessing import Lock + +import six from oslo_config import cfg from oslo_log import log as logging +from oslo_utils import excutils from oslo_utils import units +from oslo_service import loopingcall from cinder import coordination from cinder import exception from cinder.i18n import _ from cinder import interface +from cinder import objects from cinder.volume import driver from cinder.volume.drivers.fusionstorage import constants from cinder.volume.drivers.fusionstorage import fs_client @@ -105,6 +111,9 @@ cfg.StrOpt('storage_key_filepath', default='', help='Client key directory.'), + cfg.BoolOpt('full_clone', + default=False, + help='Whether use full clone.'), ] CONF = cfg.CONF @@ -113,7 +122,7 @@ @interface.volumedriver class DSWAREBaseDriver(driver.VolumeDriver): - VERSION = '2.5.RC4' + VERSION = "2.6.1" CI_WIKI_NAME = 'Huawei_FusionStorage_CI' def __init__(self, *args, **kwargs): @@ -210,6 +219,7 @@ def _update_single_pool_info_status(self, pool_info): "total_capacity_gb": capacity['total_capacity_gb'], "free_capacity_gb": capacity['free_capacity_gb'], "provisioned_capacity_gb": capacity['provisioned_capacity_gb'], + "location_info": self.client.esn, "QoS_support": True, 'multiattach': True, "thin_provisioning_support": True, @@ -247,8 +257,12 @@ def _raise_exception(msg): raise exception.VolumeBackendAPIException(data=msg) def _get_pool_id(self, volume): - pool_id_list = [] pool_name = volume_utils.extract_host(volume.host, level='pool') + pool_id = self._get_pool_id_by_name(pool_name) + return pool_id + + def _get_pool_id_by_name(self, pool_name): + pool_id_list = [] all_pools = self.client.query_pool_info() for pool in all_pools: if pool_name == pool['poolName']: @@ -363,29 +377,111 @@ def _expand_volume_when_create(self, vol_name, vol_size): self.client.delete_volume(vol_name=vol_name) raise + def _check_create_cloned_volume_finish(self, new_volume_name, start_time): + LOG.debug('Loopcall: _check_create_cloned_volume_finish(), ' + 'volume-name %s', + new_volume_name) + current_volume = self.client.query_volume_by_name(new_volume_name) + + if current_volume and 'status' in current_volume: + status = int(current_volume['status']) + LOG.debug('Wait clone volume %(volume_name)s, status:%(status)s.', + {"volume_name": new_volume_name, + "status": status}) + if status in {constants.REST_VOLUME_CREATING_STATUS, + constants.REST_VOLUME_DUPLICATE_VOLUME}: + LOG.debug(_("Volume %s is cloning"), new_volume_name) + elif status == constants.REST_VOLUME_CREATE_SUCCESS_STATUS: + raise loopingcall.LoopingCallDone(retvalue=True) + else: + msg = _('Clone volume %(new_volume_name)s failed, ' + 'the status is:%(status)s.') + LOG.error(msg, {'new_volume_name': new_volume_name, + 'status': status}) + raise loopingcall.LoopingCallDone(retvalue=False) + + max_time_out = constants.CLONE_VOLUME_TIMEOUT + current_time = time.time() + if (current_time - start_time) > max_time_out: + msg = _('Dsware clone volume time out. ' + 'Volume: %(new_volume_name)s, status: %(status)s') + LOG.error(msg, {'new_volume_name': new_volume_name, + 'status': current_volume['status']}) + raise loopingcall.LoopingCallDone(retvalue=False) + else: + LOG.warning(_('Can not find volume %s'), new_volume_name) + msg = "DSWARE clone volume failed:volume can not find from dsware" + LOG.error(msg) + raise loopingcall.LoopingCallDone(retvalue=False) + + def _wait_for_create_cloned_volume_finish_timer(self, new_volume_name): + timer = loopingcall.FixedIntervalLoopingCall( + self._check_create_cloned_volume_finish, + new_volume_name, time.time()) + LOG.debug('Calling _check_create_cloned_volume_finish: volume-name %s', + new_volume_name) + ret = timer.start(interval=constants.CHECK_CLONED_INTERVAL).wait() + timer.stop() + return ret + def create_volume_from_snapshot(self, volume, snapshot): vol_name = self._get_vol_name(volume) snapshot_name = self._get_snapshot_name(snapshot) vol_size = volume.size + pool_id = self._get_pool_id(volume) if not self._check_snapshot_exist(snapshot.volume, snapshot): msg = _("Snapshot: %(name)s does not exist!" ) % {"name": snapshot_name} self._raise_exception(msg) - elif self._check_volume_exist(volume): + if self._check_volume_exist(volume): msg = _("Volume: %(vol_name)s already exists!" ) % {'vol_name': vol_name} self._raise_exception(msg) - else: - vol_size *= units.Ki + + vol_size *= units.Ki + if not self.configuration.full_clone: self.client.create_volume_from_snapshot( snapshot_name=snapshot_name, vol_name=vol_name, vol_size=vol_size) - self._add_qos_to_volume(volume, vol_name) - self._expand_volume_when_create(vol_name, vol_size) - result = self.client.query_volume_by_name(vol_name=vol_name) - return ({"metadata": {'lun_wwn': result.get('wwn')}} - if result else {}) + else: + self.client.create_volume(vol_name, vol_size, pool_id) + self.client.create_full_volume_from_snapshot(vol_name, + snapshot_name) + ret = self._wait_for_create_cloned_volume_finish_timer(vol_name) + if not ret: + msg = _('Create full volume %s from snap failed') % vol_name + self._raise_exception(msg) + self._add_qos_to_volume(volume, vol_name) + self._expand_volume_when_create(vol_name, vol_size) + result = self.client.query_volume_by_name(vol_name=vol_name) + return ({"metadata": {'lun_wwn': result.get('wwn')}} + if result else {}) + + def _create_volume_from_volume_full_clone(self, vol_name, vol_size, pool_id, + src_vol_name): + tmp_snap_name = "temp" + src_vol_name + "clone" + vol_name + + self.client.create_snapshot(tmp_snap_name, src_vol_name) + try: + self.client.create_volume(vol_name, vol_size, pool_id) + except Exception as err: + self.client.delete_snapshot(tmp_snap_name) + raise err + + try: + self.client.create_full_volume_from_snapshot( + vol_name, tmp_snap_name) + except Exception as err: + self.client.delete_snapshot(tmp_snap_name) + self.client.delete_volume(vol_name) + raise err + + ret = self._wait_for_create_cloned_volume_finish_timer(vol_name) + if not ret: + msg = _('Create full volume %s from snap failed') % vol_name + self._raise_exception(msg) + self.client.delete_snapshot(tmp_snap_name) def create_cloned_volume(self, volume, src_volume): vol_name = self._get_vol_name(volume) @@ -398,15 +494,22 @@ def create_cloned_volume(self, volume, src_volume): msg = _("Volume: %(vol_name)s does not exist!" ) % {"vol_name": src_vol_name} self._raise_exception(msg) - else: + + if not self.configuration.full_clone: self.client.create_volume_from_volume( vol_name=vol_name, vol_size=vol_size, src_vol_name=src_vol_name) - self._add_qos_to_volume(volume, vol_name) - self._expand_volume_when_create(vol_name, vol_size) - result = self.client.query_volume_by_name(vol_name=vol_name) - return ({"metadata": {'lun_wwn': result.get('wwn')}} - if result else {}) + else: + pool_id = self._get_pool_id(volume) + self._create_volume_from_volume_full_clone( + vol_name=vol_name, vol_size=vol_size, pool_id=pool_id, + src_vol_name=src_vol_name) + + self._add_qos_to_volume(volume, vol_name) + self._expand_volume_when_create(vol_name, vol_size) + result = self.client.query_volume_by_name(vol_name=vol_name) + return ({"metadata": {'lun_wwn': result.get('wwn')}} + if result else {}) def create_snapshot(self, snapshot): snapshot_name = self._get_snapshot_name(snapshot) @@ -581,12 +684,13 @@ def unmanage_snapshot(self, snapshot): def _check_need_changes_for_retype(self, volume, new_type, host, vol_name): before_change = {} after_change = {} - if volume.host != host["host"]: - msg = (_("Do not support retype between different host. Volume's " + migrate = False + if volume.host != host.get("host"): + migrate = True + msg = (_("retype support migration between different host. Volume's " "host: %(vol_host)s, host's host: %(host)s") - % {"vol_host": volume.host, "host": host['host']}) - LOG.error(msg) - raise exception.InvalidInput(msg) + % {"vol_host": volume.host, "host": host.get("host")}) + LOG.info(msg) old_opts = fs_utils.get_volume_specs(self.client, vol_name) new_opts = fs_utils.get_volume_type_params(new_type, self.client) @@ -596,7 +700,7 @@ def _check_need_changes_for_retype(self, volume, new_type, host, vol_name): change_opts = {"old_opts": before_change, "new_opts": after_change} - return change_opts + return migrate, change_opts def retype(self, context, volume, new_type, diff, host): LOG.info("Retype volume: %(vol)s, new_type: %(new_type)s, " @@ -607,13 +711,177 @@ def retype(self, context, volume, new_type, diff, host): "host": host}) vol_name = self._get_vol_name(volume) - change_opts = self._check_need_changes_for_retype( + migrate, change_opts = self._check_need_changes_for_retype( volume, new_type, host, vol_name) + if migrate: + src_lun_id = self._check_volume_exist_on_array(volume) + LOG.debug("Begin to migrate LUN(id: %(lun_id)s) with " + "change %(change_opts)s.", + {"lun_id": src_lun_id, "change_opts": change_opts}) + moved = self._migrate_volume(volume, host, src_lun_id) + if not moved: + LOG.warning("Storage-assisted migration failed during " + "retype.") + return False, None self._change_lun(vol_name, change_opts.get("new_opts"), change_opts.get("old_opts")) return True, None + def migrate_volume(self, context, volume, host): + """Migrate a volume within the same array.""" + LOG.info("Migrate Volume:%(volume)s, host:%(host)s", + {"volume": volume.id, + "host": host}) + src_lun_id = self._check_volume_exist_on_array(volume) + + moved = self._migrate_volume(volume, host, src_lun_id) + return moved, {} + + def _create_dst_volume(self, volume, host): + pool_name = host['capabilities']['pool_name'] + pool_id = self._get_pool_id_by_name(pool_name) + vol_name = fs_utils.encode_name(six.text_type(uuid.uuid4())) + vol_size = volume.size + vol_size *= units.Ki + self.client.create_volume( + pool_id=pool_id, vol_name=vol_name, vol_size=vol_size) + + result = self.client.query_volume_by_name_v2(vol_name=vol_name) + dst_lun_id = result.get('id') + self._wait_volume_ready(vol_name) + return vol_name, dst_lun_id + + def _migrate_volume(self, volume, host, src_lun_id): + """create migration task and wait for task done""" + if not self._check_migration_valid(host): + return False + + vol_name, dst_lun_id = self._create_dst_volume(volume, host) + + try: + self.client.create_lun_migration(src_lun_id, dst_lun_id) + + def _is_lun_migration_complete(): + return self._is_lun_migration_complete(src_lun_id, dst_lun_id) + + wait_interval = constants.MIGRATION_WAIT_INTERVAL + fs_utils.wait_for_condition(_is_lun_migration_complete, + wait_interval, + constants.DEFAULT_WAIT_TIMEOUT) + # Clean up if migration failed. + except Exception as ex: + raise exception.VolumeBackendAPIException(data=ex) + finally: + if self._is_lun_migration_exist(src_lun_id, dst_lun_id): + self.client.delete_lun_migration(src_lun_id) + self._delete_lun_with_check(vol_name) + + LOG.info("Migrate lun %s successfully.", src_lun_id) + return True + + def _delete_lun_with_check(self, vol_name): + if self.client.query_volume_by_name(vol_name): + # migrate_dst_lun don't have qos, so don't + # need to remove qos, Delete the LUN directly. + self.client.delete_volume(vol_name) + + def _is_lun_migration_complete(self, src_lun_id, dst_lun_id): + result = self.client.get_lun_migration_task_by_id(src_lun_id) + found_migration_task = False + if not result: + return False + + if (str(src_lun_id) == result.get('parent_id') and + str(dst_lun_id) == result.get('target_lun_id')): + found_migration_task = True + if constants.MIGRATION_COMPLETE == result.get('running_status'): + return True + if constants.MIGRATION_FAULT == result.get('running_status'): + msg = _("Lun migration error. " + "the migration task running_status is abnormal") + LOG.error(msg) + raise exception.VolumeBackendAPIException(data=msg) + + if not found_migration_task: + err_msg = _("lun migration error, Cannot find migration task.") + LOG.error(err_msg) + raise exception.VolumeBackendAPIException(data=err_msg) + + return False + + def _is_lun_migration_exist(self, src_lun_id, dst_lun_id): + try: + result = self.client.get_lun_migration_task_by_id(src_lun_id) + except Exception: + LOG.error("Get LUN migration error.") + return False + + if (str(src_lun_id) == result.get('parent_id') and + str(dst_lun_id) == result.get('target_lun_id')): + return True + return False + + def _wait_volume_ready(self, vol_name): + wait_interval = constants.DEFAULT_WAIT_INTERVAL + + def _volume_ready(): + result = self.client.query_volume_by_name_v2(vol_name) + if not result: + return False + + if (result.get('health_status') == constants.STATUS_HEALTH + and result.get('running_status') == constants.STATUS_VOLUME_READY): + return True + return False + + fs_utils.wait_for_condition(_volume_ready, + wait_interval, + wait_interval * 10) + + def _check_migration_valid(self, host): + if 'pool_name' not in host.get('capabilities', {}): + return False + + target_device = host.get('capabilities', {}).get('location_info') + + # Source and destination should be on same array. + if target_device != self.client.esn: + LOG.error("lun migration error, " + "Source and destination should be on same array") + return False + + pool_name = host.get('capabilities', {}).get('pool_name', '') + if len(pool_name) == 0: + LOG.error("lun migration error, pool_name not exists") + return False + + return True + + def _check_volume_exist_on_array(self, volume): + volume_name = self._get_vol_name(volume) + result = self._check_volume_exist(volume) + if not result: + msg = _("Volume %s does not exist on the array." + ) % volume.id + self._raise_exception(msg) + + lun_wwn = result.get('wwn') + if not lun_wwn: + LOG.debug("No LUN WWN recorded for volume %s.", volume.id) + + lun_id = result.get('volId') + if not lun_id: + msg = _("Volume %s does not exist on the array." + ) % volume.id + self._raise_exception(msg) + + if self.client.get_volume_snapshot(volume_name): + msg = _("Volume %s which have snapshot cannot do lun migration" + ) % volume.id + self._raise_exception(msg) + return lun_id + def _rollback_snapshot(self, vol_name, snap_name): def _snapshot_rollback_finish(): snapshot_info = self.client.get_snapshot_info_by_name(snap_name) @@ -669,6 +937,265 @@ def ensure_export(self, context, volume): def remove_export(self, context, volume): pass + def create_group(self, context, group): + """Creates a group. Driver only need to return state""" + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.create_consistencygroup(context, group) + + def create_consistencygroup(self, context, group): + """Creates a group. Driver only need to return state""" + LOG.info("Create group successfully") + return {'status': 'available'} + + def update_group(self, context, group, + add_volumes=None, remove_volumes=None): + """ + The volume manager will adds/removes the volume to/from the + group in the database, if need add_volumes, Driver just need + to check whether volume is in array or not + """ + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.update_consistencygroup( + context, group, add_volumes, remove_volumes) + + def update_consistencygroup(self, context, group, + add_volumes=None, remove_volumes=None): + """ + The volume manager will adds/removes the volume to/from the + group in the database, if need add_volumes, Driver just need + to check whether volume is in array or not + """ + if add_volumes is None: + add_volumes = [] + for volume in add_volumes: + try: + self._check_volume_exist_on_array(volume) + except Exception: + with excutils.save_and_reraise_exception(): + LOG.error("The add_volume %s not exist on array" % volume.id) + + model_update = {'status': 'available'} + LOG.info("Update group successfully") + return model_update, None, None + + def delete_group(self, context, group, volumes): + """delete the group, Driver need to delete relation lun on array""" + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.delete_consistencygroup(context, group, volumes) + + def delete_consistencygroup(self, context, group, volumes): + """delete the group, Driver need to delete relation lun on array""" + volumes_model_update = [] + model_update = {'status': 'deleted'} + for volume in volumes: + volume_model_update = {'id': volume.id} + try: + self.delete_volume(volume) + except Exception: + LOG.error('Delete volume %s failed.' % volume) + volume_model_update.update({'status': 'error_deleting'}) + else: + volume_model_update.update({'status': 'deleted'}) + + LOG.info('Deleted volume %s successfully' % volume) + volumes_model_update.append(volume_model_update) + + LOG.info("Delete group successfully") + return model_update, volumes_model_update + + def create_group_from_src(self, context, group, volumes, + group_snapshot=None, snapshots=None, + source_group=None, source_vols=None): + """ + create group from group or group-snapshot, + Driver need to create volume from volume or snapshot + """ + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.create_consistencygroup_from_src(context, group, volumes, + group_snapshot, snapshots, + source_group, source_vols) + + def create_consistencygroup_from_src(self, context, group, volumes, + group_snapshot=None, snapshots=None, + source_group=None, source_vols=None): + """ + create group from group or group-snapshot, + Driver need to create volume from volume or snapshot + """ + model_update = self.create_consistencygroup(context, group) + volumes_model_update = [] + delete_snapshots = False + + if not snapshots and source_vols: + snapshots = [] + for src_volume in source_vols: + volume_kwargs = { + 'id': src_volume.id, + '_name_id': None, + 'host': src_volume.host + } + snapshot_kwargs = { + 'id': six.text_type(uuid.uuid4()), + 'volume': objects.Volume(**volume_kwargs) + } + snapshots.append(objects.Snapshot(**snapshot_kwargs)) + + self._create_group_snapshot(snapshots) + delete_snapshots = True + + if snapshots: + volumes_model_update = self._create_volume_from_group_snapshot( + volumes, snapshots, delete_snapshots) + + if delete_snapshots: + self._delete_group_snapshot(snapshots) + + LOG.info("Create group from src successfully") + return model_update, volumes_model_update + + def _create_volume_from_group_snapshot(self, volumes, snapshots, delete_snapshots): + volumes_model_update = [] + added_volumes = [] + for i, volume in enumerate(volumes): + try: + vol_model_update = self.create_volume_from_snapshot( + volume, snapshots[i]) + vol_model_update.update({'id': volume.id}) + volumes_model_update.append(vol_model_update) + added_volumes.append(volume) + except Exception: + LOG.error("Create volume from snapshot error, Delete the newly created lun.") + with excutils.save_and_reraise_exception(): + self._delete_added_volume_snapshots( + added_volumes, snapshots, delete_snapshots) + + return volumes_model_update + + def _delete_added_volume_snapshots( + self, added_volumes, snapshots, delete_snapshots): + if delete_snapshots: + self._delete_group_snapshot(snapshots) + for add_volume in added_volumes: + vol_name = self._get_vol_name(add_volume) + self.fs_qos.remove(vol_name) + self.client.delete_volume(vol_name=vol_name) + LOG.info("delete storage newly added " + "volume success, volume is %s" % add_volume.id) + + def create_group_snapshot(self, context, group_snapshot, snapshots): + """Create group snapshot.""" + if not volume_utils.is_group_a_cg_snapshot_type(group_snapshot): + LOG.info("group_snapshot's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.create_cgsnapshot(context, group_snapshot, snapshots) + + def create_cgsnapshot(self, context, group_snapshot, snapshots): + """Create group snapshot.""" + LOG.info('Create group snapshot for group: %(group_snapshot)s', + {'group_snapshot': group_snapshot}) + + try: + snapshots_model_update = self._create_group_snapshot(snapshots) + except Exception as err: + msg = ("Create group snapshots failed. " + "Group snapshot id: %s. Reason is %s") % (group_snapshot.id, err) + LOG.error(msg) + raise exception.CinderException(msg) + + model_update = {'status': 'available'} + return model_update, snapshots_model_update + + def _create_group_snapshot(self, snapshots): + """Generate snapshots for all volumes in the group.""" + snapshots_model_update = [] + snapshot_group_list = [] + + for snapshot in snapshots: + snapshot_name = self._get_snapshot_name(snapshot) + vol_name = self._get_vol_name(snapshot.volume) + snapshot_group_list.append({ + 'name': snapshot_name, + 'sub_type': '0', + 'volume_name': vol_name + }) + snapshot_model_update = { + 'id': snapshot.id, + 'status': 'available', + } + snapshots_model_update.append(snapshot_model_update) + try: + self.client.create_consistent_snapshot_by_name(snapshot_group_list) + except Exception: + with excutils.save_and_reraise_exception(): + LOG.error("Create consistent snapshot failed, " + "snapshot_group_list is %s" % snapshot_group_list) + + return snapshots_model_update + + def delete_group_snapshot(self, context, group_snapshot, snapshots): + """Delete group snapshot.""" + if not volume_utils.is_group_a_cg_snapshot_type(group_snapshot): + LOG.info("group_snapshot's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.delete_cgsnapshot(context, group_snapshot, snapshots) + + def delete_cgsnapshot(self, context, group_snapshot, snapshots): + """Delete group snapshot.""" + LOG.info("Delete group_snapshot %s for " + "consistency group: %s" % (group_snapshot.id, group_snapshot)) + + try: + snapshots_model_update = self._delete_group_snapshot(snapshots) + except Exception as err: + msg = ("Delete cg snapshots failed. " + "group snapshot id: %s, reason is %s") % (group_snapshot.id, err) + LOG.error(msg) + raise exception.CinderException(msg) + + model_update = {'status': 'deleted'} + return model_update, snapshots_model_update + + def _delete_group_snapshot(self, snapshots): + """Delete all snapshots in snapshot group""" + snapshots_model_update = [] + for snapshot in snapshots: + snapshot_model_update = { + 'id': snapshot.id, + 'status': 'deleted' + } + snapshots_model_update.append(snapshot_model_update) + snapshot_name = self._get_snapshot_name(snapshot) + + if not self._check_snapshot_exist(snapshot.volume, snapshot): + LOG.info("snapshot %s not exist in array, " + "don't need to delete, try next one" % snapshot_name) + continue + self.client.delete_snapshot(snapshot_name=snapshot_name) + LOG.info("Delete snapshot successfully," + " the deleted snapshots is %s" % snapshot_name) + + return snapshots_model_update + class DSWAREDriver(DSWAREBaseDriver): def get_volume_stats(self, refresh=False): @@ -721,7 +1248,7 @@ def initialize_connection(self, volume, connector): vol_wwn = volume_info.get('wwn') by_id_path = "/dev/disk/by-id/" + "wwn-0x%s" % vol_wwn properties = {'device_path': by_id_path} - import time + LOG.info("Wait %(t)s second(s) for scanning the target device %(dev)s." % {"t": self.configuration.scan_device_timeout, "dev": by_id_path}) diff --git a/Cinder/Victoria/fs_client.py b/Cinder/Victoria/fs_client.py index 234d7f1..09d9581 100644 --- a/Cinder/Victoria/fs_client.py +++ b/Cinder/Victoria/fs_client.py @@ -14,16 +14,16 @@ # under the License. import json + import requests import six -import time +from oslo_log import log as logging from requests.adapters import HTTPAdapter from cinder import exception from cinder.i18n import _ from cinder.volume.drivers.fusionstorage import constants -from oslo_log import log as logging LOG = logging.getLogger(__name__) @@ -43,7 +43,8 @@ def __init__(self, fs_address, fs_user, fs_password, **extend_conf): self.session = None self.token = None self.version = None - mutual_authentication = extend_conf.get("mutual_authentication") + self.esn = None + mutual_authentication = extend_conf.get("mutual_authentication", {}) self.init_http_head(mutual_authentication) LOG.warning("Suppressing requests library SSL Warnings") @@ -147,6 +148,13 @@ def get_version(self): if result.get("currentVersion"): self.version = result["currentVersion"] + def get_esn(self): + url = "/cluster/sn" + result = self.call(url, "get") + self._assert_rest_result(result, _('Get cluster esn error.')) + self.esn = result.get("sn") + return self.esn + def login(self): self.get_version() url = '/sec/login' @@ -160,6 +168,7 @@ def login(self): self.session.headers.update({ "x-auth-token": self.token }) + self.get_esn() def logout(self): url = '/sec/logout' @@ -264,6 +273,15 @@ def query_volume_by_name(self, vol_name): result, _("Query volume by name session error")) return result.get('lunDetailInfo') + def query_volume_by_name_v2(self, vol_name): + url = '/api/v2/block_service/volumes?name=' + vol_name + result = self.call(url, 'GET', get_system_time=True) + if result.get('errorCode') in constants.VOLUME_NOT_EXIST: + return {} + self._assert_rest_result( + result, _("Query volume by name session error")) + return result.get('data', {}) + def query_volume_by_id(self, vol_id): url = 'v1.3/volume/queryById?volId=' + vol_id result = self.call(url, 'GET', get_version=True) @@ -746,3 +764,57 @@ def get_iscsi_links_info(self, iscsi_link_count, pool_list): return [iscsi["ip"] for iscsi in result.get("iscsiLinks", []) if iscsi.get("ip")] + + def create_lun_migration(self, src_lun_id, dst_lun_id, speed=2): + url = "/api/v2/block_service/lun_migration" + params = { + "parent_id": src_lun_id, + "target_lun_id": dst_lun_id, + "speed": speed, + "work_mode": 0 + } + result = self.call(url, "POST", params, get_system_time=True) + self._assert_rest_result(result, + _("create lun migration task error.")) + + def get_lun_migration_task_by_id(self, src_lun_id): + url = "/api/v2/block_service/lun_migration" + params = { + "id": src_lun_id + } + result = self.call(url, "GET", params, get_system_time=True) + self._assert_rest_result(result, + _("get lun migration task error.")) + return result.get('data', {}) + + def delete_lun_migration(self, src_lun_id): + url = "/api/v2/block_service/lun_migration" + params = { + 'id': src_lun_id + } + result = self.call(url, "DELETE", params, get_system_time=True) + self._assert_rest_result(result, + _("Delete lun migration task error.")) + + def get_volume_snapshot(self, volume_name): + url = "/volume/snapshot/list" + params = { + 'volName': volume_name, + 'batchNum': 1, + 'batchLimit': 10 + } + result = self.call(url, "POST", params) + return result.get('snapshotList', []) + + def create_consistent_snapshot_by_name(self, snapshot_group_list): + url = "/api/v2/block_service/consistency_snapshots" + result = self.call(url, "POST", snapshot_group_list, get_system_time=True) + self._assert_rest_result(result, _("create consistent_snapshot error.")) + return result.get('data', []) + + def create_full_volume_from_snapshot(self, vol_name, snapshot_name): + url = '/api/v2/block_service/createFullVolumeFromSnap' + params = {"snap_name_src": snapshot_name, "volume_name_dst": vol_name} + result = self.call(url, "POST", params, get_system_time=True) + self._assert_rest_result( + result, _("create full volume from snap fails")) diff --git a/Cinder/Victoria/fs_qos.py b/Cinder/Victoria/fs_qos.py index 731c45e..286dbc3 100644 --- a/Cinder/Victoria/fs_qos.py +++ b/Cinder/Victoria/fs_qos.py @@ -29,7 +29,11 @@ def __init__(self, client): def add(self, qos, vol_name): localtime = time.strftime('%Y%m%d%H%M%S', time.localtime()) - qos_name = constants.QOS_PREFIX + localtime + # QoS policy name. The value contains 1 to 63 characters. + # So we intercept volume_name Ensure that the length does not exceed 63 + vol_str = vol_name[-constants.QOS_MAX_INTERCEPT_LENGTH::] \ + if len(vol_name) >= constants.QOS_MAX_INTERCEPT_LENGTH else vol_name + qos_name = constants.QOS_PREFIX + localtime + '_' + vol_str self.client.create_qos(qos_name, qos) try: self.client.associate_qos_with_volume(vol_name, qos_name) diff --git a/Cinder/Victoria/fs_utils.py b/Cinder/Victoria/fs_utils.py index 8b9ae78..0856038 100644 --- a/Cinder/Victoria/fs_utils.py +++ b/Cinder/Victoria/fs_utils.py @@ -16,11 +16,11 @@ import datetime import hashlib import ipaddress -import pytz import random -import six import time +import pytz +import six from oslo_log import log as logging from oslo_service import loopingcall from oslo_utils import units @@ -758,3 +758,9 @@ def get_iscsi_info_from_storage(manager_ips, use_ipv6, valid_iscsi_ips, valid_node_ips): return _get_target_info(manager_ips, use_ipv6, valid_iscsi_ips, valid_node_ips) + + +def encode_name(my_uuid): + encoded_name = hashlib.md5(my_uuid.encode('utf-8')).hexdigest() + target_lun_prefix = my_uuid.split('-')[0] + '-' + return target_lun_prefix + encoded_name diff --git a/Cinder/Wallaby/constants.py b/Cinder/Wallaby/constants.py index 5f46ece..b4cb843 100644 --- a/Cinder/Wallaby/constants.py +++ b/Cinder/Wallaby/constants.py @@ -45,6 +45,14 @@ CONF_STORAGE_CERT_FILEPATH = "storage_cert_filepath" CONF_STORAGE_SSL_TWO_WAY_AUTH = "storage_ssl_two_way_auth" +DEFAULT_WAIT_INTERVAL = 5 +MIGRATION_COMPLETE = 76 +MIGRATION_FAULT = 74 +STATUS_HEALTH = 1 +STATUS_VOLUME_READY = 27 +MIGRATION_WAIT_INTERVAL = 5 +DEFAULT_WAIT_TIMEOUT = 3600 * 24 * 30 + QOS_MUST_SET = ["maxIOPS", "maxMBPS"] QOS_KEYS = ["maxIOPS", "maxMBPS", "total_iops_sec", "total_bytes_sec"] QOS_SCHEDULER_KEYS = ["scheduleType", "startDate", "startTime", @@ -53,6 +61,7 @@ QOS_SCHEDULER_DEFAULT_TYPE = "0" QOS_SCHEDULER_WEEK_TYPE = "3" QOS_SUPPORT_SCHEDULE_VERSION = "8.0" +QOS_MAX_INTERCEPT_LENGTH = 36 SECONDS_OF_DAY = 24 * 60 * 60 SECONDS_OF_HOUR = 60 * 60 SNAPSHOT_HEALTH_STATUS = ( @@ -80,3 +89,9 @@ HOSTGROUP_ALREADY_EXIST = 50157044 INITIATOR_ALREADY_EXIST = 50155102 INITIATOR_IN_HOST = 50157021 + +CHECK_CLONED_INTERVAL = 2 +REST_VOLUME_CREATING_STATUS = 15 +REST_VOLUME_DUPLICATE_VOLUME = 6 +REST_VOLUME_CREATE_SUCCESS_STATUS = 0 +CLONE_VOLUME_TIMEOUT = 3600 * 24 * 30 diff --git a/Cinder/Wallaby/dsware.py b/Cinder/Wallaby/dsware.py index 75e1808..b03e039 100644 --- a/Cinder/Wallaby/dsware.py +++ b/Cinder/Wallaby/dsware.py @@ -14,16 +14,22 @@ # under the License. import json - +import time +import uuid from multiprocessing import Lock + +import six from oslo_config import cfg from oslo_log import log as logging +from oslo_utils import excutils from oslo_utils import units +from oslo_service import loopingcall from cinder import coordination from cinder import exception from cinder.i18n import _ from cinder import interface +from cinder import objects from cinder.volume import driver from cinder.volume.drivers.fusionstorage import constants from cinder.volume.drivers.fusionstorage import fs_client @@ -105,6 +111,9 @@ cfg.StrOpt('storage_key_filepath', default='', help='Client key directory.'), + cfg.BoolOpt('full_clone', + default=False, + help='Whether use full clone.'), ] CONF = cfg.CONF @@ -113,7 +122,7 @@ @interface.volumedriver class DSWAREBaseDriver(driver.VolumeDriver): - VERSION = '2.5.RC4' + VERSION = "2.6.1" CI_WIKI_NAME = 'Huawei_FusionStorage_CI' def __init__(self, *args, **kwargs): @@ -210,6 +219,7 @@ def _update_single_pool_info_status(self, pool_info): "total_capacity_gb": capacity['total_capacity_gb'], "free_capacity_gb": capacity['free_capacity_gb'], "provisioned_capacity_gb": capacity['provisioned_capacity_gb'], + "location_info": self.client.esn, "QoS_support": True, 'multiattach': True, "thin_provisioning_support": True, @@ -247,8 +257,12 @@ def _raise_exception(msg): raise exception.VolumeBackendAPIException(data=msg) def _get_pool_id(self, volume): - pool_id_list = [] pool_name = volume_utils.extract_host(volume.host, level='pool') + pool_id = self._get_pool_id_by_name(pool_name) + return pool_id + + def _get_pool_id_by_name(self, pool_name): + pool_id_list = [] all_pools = self.client.query_pool_info() for pool in all_pools: if pool_name == pool['poolName']: @@ -363,29 +377,111 @@ def _expand_volume_when_create(self, vol_name, vol_size): self.client.delete_volume(vol_name=vol_name) raise + def _check_create_cloned_volume_finish(self, new_volume_name, start_time): + LOG.debug('Loopcall: _check_create_cloned_volume_finish(), ' + 'volume-name %s', + new_volume_name) + current_volume = self.client.query_volume_by_name(new_volume_name) + + if current_volume and 'status' in current_volume: + status = int(current_volume['status']) + LOG.debug('Wait clone volume %(volume_name)s, status:%(status)s.', + {"volume_name": new_volume_name, + "status": status}) + if status in {constants.REST_VOLUME_CREATING_STATUS, + constants.REST_VOLUME_DUPLICATE_VOLUME}: + LOG.debug(_("Volume %s is cloning"), new_volume_name) + elif status == constants.REST_VOLUME_CREATE_SUCCESS_STATUS: + raise loopingcall.LoopingCallDone(retvalue=True) + else: + msg = _('Clone volume %(new_volume_name)s failed, ' + 'the status is:%(status)s.') + LOG.error(msg, {'new_volume_name': new_volume_name, + 'status': status}) + raise loopingcall.LoopingCallDone(retvalue=False) + + max_time_out = constants.CLONE_VOLUME_TIMEOUT + current_time = time.time() + if (current_time - start_time) > max_time_out: + msg = _('Dsware clone volume time out. ' + 'Volume: %(new_volume_name)s, status: %(status)s') + LOG.error(msg, {'new_volume_name': new_volume_name, + 'status': current_volume['status']}) + raise loopingcall.LoopingCallDone(retvalue=False) + else: + LOG.warning(_('Can not find volume %s'), new_volume_name) + msg = "DSWARE clone volume failed:volume can not find from dsware" + LOG.error(msg) + raise loopingcall.LoopingCallDone(retvalue=False) + + def _wait_for_create_cloned_volume_finish_timer(self, new_volume_name): + timer = loopingcall.FixedIntervalLoopingCall( + self._check_create_cloned_volume_finish, + new_volume_name, time.time()) + LOG.debug('Calling _check_create_cloned_volume_finish: volume-name %s', + new_volume_name) + ret = timer.start(interval=constants.CHECK_CLONED_INTERVAL).wait() + timer.stop() + return ret + def create_volume_from_snapshot(self, volume, snapshot): vol_name = self._get_vol_name(volume) snapshot_name = self._get_snapshot_name(snapshot) vol_size = volume.size + pool_id = self._get_pool_id(volume) if not self._check_snapshot_exist(snapshot.volume, snapshot): msg = _("Snapshot: %(name)s does not exist!" ) % {"name": snapshot_name} self._raise_exception(msg) - elif self._check_volume_exist(volume): + if self._check_volume_exist(volume): msg = _("Volume: %(vol_name)s already exists!" ) % {'vol_name': vol_name} self._raise_exception(msg) - else: - vol_size *= units.Ki + + vol_size *= units.Ki + if not self.configuration.full_clone: self.client.create_volume_from_snapshot( snapshot_name=snapshot_name, vol_name=vol_name, vol_size=vol_size) - self._add_qos_to_volume(volume, vol_name) - self._expand_volume_when_create(vol_name, vol_size) - result = self.client.query_volume_by_name(vol_name=vol_name) - return ({"metadata": {'lun_wwn': result.get('wwn')}} - if result else {}) + else: + self.client.create_volume(vol_name, vol_size, pool_id) + self.client.create_full_volume_from_snapshot(vol_name, + snapshot_name) + ret = self._wait_for_create_cloned_volume_finish_timer(vol_name) + if not ret: + msg = _('Create full volume %s from snap failed') % vol_name + self._raise_exception(msg) + self._add_qos_to_volume(volume, vol_name) + self._expand_volume_when_create(vol_name, vol_size) + result = self.client.query_volume_by_name(vol_name=vol_name) + return ({"metadata": {'lun_wwn': result.get('wwn')}} + if result else {}) + + def _create_volume_from_volume_full_clone(self, vol_name, vol_size, pool_id, + src_vol_name): + tmp_snap_name = "temp" + src_vol_name + "clone" + vol_name + + self.client.create_snapshot(tmp_snap_name, src_vol_name) + try: + self.client.create_volume(vol_name, vol_size, pool_id) + except Exception as err: + self.client.delete_snapshot(tmp_snap_name) + raise err + + try: + self.client.create_full_volume_from_snapshot( + vol_name, tmp_snap_name) + except Exception as err: + self.client.delete_snapshot(tmp_snap_name) + self.client.delete_volume(vol_name) + raise err + + ret = self._wait_for_create_cloned_volume_finish_timer(vol_name) + if not ret: + msg = _('Create full volume %s from snap failed') % vol_name + self._raise_exception(msg) + self.client.delete_snapshot(tmp_snap_name) def create_cloned_volume(self, volume, src_volume): vol_name = self._get_vol_name(volume) @@ -398,15 +494,22 @@ def create_cloned_volume(self, volume, src_volume): msg = _("Volume: %(vol_name)s does not exist!" ) % {"vol_name": src_vol_name} self._raise_exception(msg) - else: + + if not self.configuration.full_clone: self.client.create_volume_from_volume( vol_name=vol_name, vol_size=vol_size, src_vol_name=src_vol_name) - self._add_qos_to_volume(volume, vol_name) - self._expand_volume_when_create(vol_name, vol_size) - result = self.client.query_volume_by_name(vol_name=vol_name) - return ({"metadata": {'lun_wwn': result.get('wwn')}} - if result else {}) + else: + pool_id = self._get_pool_id(volume) + self._create_volume_from_volume_full_clone( + vol_name=vol_name, vol_size=vol_size, pool_id=pool_id, + src_vol_name=src_vol_name) + + self._add_qos_to_volume(volume, vol_name) + self._expand_volume_when_create(vol_name, vol_size) + result = self.client.query_volume_by_name(vol_name=vol_name) + return ({"metadata": {'lun_wwn': result.get('wwn')}} + if result else {}) def create_snapshot(self, snapshot): snapshot_name = self._get_snapshot_name(snapshot) @@ -581,12 +684,13 @@ def unmanage_snapshot(self, snapshot): def _check_need_changes_for_retype(self, volume, new_type, host, vol_name): before_change = {} after_change = {} - if volume.host != host["host"]: - msg = (_("Do not support retype between different host. Volume's " + migrate = False + if volume.host != host.get("host"): + migrate = True + msg = (_("retype support migration between different host. Volume's " "host: %(vol_host)s, host's host: %(host)s") - % {"vol_host": volume.host, "host": host['host']}) - LOG.error(msg) - raise exception.InvalidInput(msg) + % {"vol_host": volume.host, "host": host.get("host")}) + LOG.info(msg) old_opts = fs_utils.get_volume_specs(self.client, vol_name) new_opts = fs_utils.get_volume_type_params(new_type, self.client) @@ -596,7 +700,7 @@ def _check_need_changes_for_retype(self, volume, new_type, host, vol_name): change_opts = {"old_opts": before_change, "new_opts": after_change} - return change_opts + return migrate, change_opts def retype(self, context, volume, new_type, diff, host): LOG.info("Retype volume: %(vol)s, new_type: %(new_type)s, " @@ -607,13 +711,177 @@ def retype(self, context, volume, new_type, diff, host): "host": host}) vol_name = self._get_vol_name(volume) - change_opts = self._check_need_changes_for_retype( + migrate, change_opts = self._check_need_changes_for_retype( volume, new_type, host, vol_name) + if migrate: + src_lun_id = self._check_volume_exist_on_array(volume) + LOG.debug("Begin to migrate LUN(id: %(lun_id)s) with " + "change %(change_opts)s.", + {"lun_id": src_lun_id, "change_opts": change_opts}) + moved = self._migrate_volume(volume, host, src_lun_id) + if not moved: + LOG.warning("Storage-assisted migration failed during " + "retype.") + return False, None self._change_lun(vol_name, change_opts.get("new_opts"), change_opts.get("old_opts")) return True, None + def migrate_volume(self, context, volume, host): + """Migrate a volume within the same array.""" + LOG.info("Migrate Volume:%(volume)s, host:%(host)s", + {"volume": volume.id, + "host": host}) + src_lun_id = self._check_volume_exist_on_array(volume) + + moved = self._migrate_volume(volume, host, src_lun_id) + return moved, {} + + def _create_dst_volume(self, volume, host): + pool_name = host['capabilities']['pool_name'] + pool_id = self._get_pool_id_by_name(pool_name) + vol_name = fs_utils.encode_name(six.text_type(uuid.uuid4())) + vol_size = volume.size + vol_size *= units.Ki + self.client.create_volume( + pool_id=pool_id, vol_name=vol_name, vol_size=vol_size) + + result = self.client.query_volume_by_name_v2(vol_name=vol_name) + dst_lun_id = result.get('id') + self._wait_volume_ready(vol_name) + return vol_name, dst_lun_id + + def _migrate_volume(self, volume, host, src_lun_id): + """create migration task and wait for task done""" + if not self._check_migration_valid(host): + return False + + vol_name, dst_lun_id = self._create_dst_volume(volume, host) + + try: + self.client.create_lun_migration(src_lun_id, dst_lun_id) + + def _is_lun_migration_complete(): + return self._is_lun_migration_complete(src_lun_id, dst_lun_id) + + wait_interval = constants.MIGRATION_WAIT_INTERVAL + fs_utils.wait_for_condition(_is_lun_migration_complete, + wait_interval, + constants.DEFAULT_WAIT_TIMEOUT) + # Clean up if migration failed. + except Exception as ex: + raise exception.VolumeBackendAPIException(data=ex) + finally: + if self._is_lun_migration_exist(src_lun_id, dst_lun_id): + self.client.delete_lun_migration(src_lun_id) + self._delete_lun_with_check(vol_name) + + LOG.info("Migrate lun %s successfully.", src_lun_id) + return True + + def _delete_lun_with_check(self, vol_name): + if self.client.query_volume_by_name(vol_name): + # migrate_dst_lun don't have qos, so don't + # need to remove qos, Delete the LUN directly. + self.client.delete_volume(vol_name) + + def _is_lun_migration_complete(self, src_lun_id, dst_lun_id): + result = self.client.get_lun_migration_task_by_id(src_lun_id) + found_migration_task = False + if not result: + return False + + if (str(src_lun_id) == result.get('parent_id') and + str(dst_lun_id) == result.get('target_lun_id')): + found_migration_task = True + if constants.MIGRATION_COMPLETE == result.get('running_status'): + return True + if constants.MIGRATION_FAULT == result.get('running_status'): + msg = _("Lun migration error. " + "the migration task running_status is abnormal") + LOG.error(msg) + raise exception.VolumeBackendAPIException(data=msg) + + if not found_migration_task: + err_msg = _("lun migration error, Cannot find migration task.") + LOG.error(err_msg) + raise exception.VolumeBackendAPIException(data=err_msg) + + return False + + def _is_lun_migration_exist(self, src_lun_id, dst_lun_id): + try: + result = self.client.get_lun_migration_task_by_id(src_lun_id) + except Exception: + LOG.error("Get LUN migration error.") + return False + + if (str(src_lun_id) == result.get('parent_id') and + str(dst_lun_id) == result.get('target_lun_id')): + return True + return False + + def _wait_volume_ready(self, vol_name): + wait_interval = constants.DEFAULT_WAIT_INTERVAL + + def _volume_ready(): + result = self.client.query_volume_by_name_v2(vol_name) + if not result: + return False + + if (result.get('health_status') == constants.STATUS_HEALTH + and result.get('running_status') == constants.STATUS_VOLUME_READY): + return True + return False + + fs_utils.wait_for_condition(_volume_ready, + wait_interval, + wait_interval * 10) + + def _check_migration_valid(self, host): + if 'pool_name' not in host.get('capabilities', {}): + return False + + target_device = host.get('capabilities', {}).get('location_info') + + # Source and destination should be on same array. + if target_device != self.client.esn: + LOG.error("lun migration error, " + "Source and destination should be on same array") + return False + + pool_name = host.get('capabilities', {}).get('pool_name', '') + if len(pool_name) == 0: + LOG.error("lun migration error, pool_name not exists") + return False + + return True + + def _check_volume_exist_on_array(self, volume): + volume_name = self._get_vol_name(volume) + result = self._check_volume_exist(volume) + if not result: + msg = _("Volume %s does not exist on the array." + ) % volume.id + self._raise_exception(msg) + + lun_wwn = result.get('wwn') + if not lun_wwn: + LOG.debug("No LUN WWN recorded for volume %s.", volume.id) + + lun_id = result.get('volId') + if not lun_id: + msg = _("Volume %s does not exist on the array." + ) % volume.id + self._raise_exception(msg) + + if self.client.get_volume_snapshot(volume_name): + msg = _("Volume %s which have snapshot cannot do lun migration" + ) % volume.id + self._raise_exception(msg) + return lun_id + def _rollback_snapshot(self, vol_name, snap_name): def _snapshot_rollback_finish(): snapshot_info = self.client.get_snapshot_info_by_name(snap_name) @@ -669,6 +937,265 @@ def ensure_export(self, context, volume): def remove_export(self, context, volume): pass + def create_group(self, context, group): + """Creates a group. Driver only need to return state""" + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.create_consistencygroup(context, group) + + def create_consistencygroup(self, context, group): + """Creates a group. Driver only need to return state""" + LOG.info("Create group successfully") + return {'status': 'available'} + + def update_group(self, context, group, + add_volumes=None, remove_volumes=None): + """ + The volume manager will adds/removes the volume to/from the + group in the database, if need add_volumes, Driver just need + to check whether volume is in array or not + """ + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.update_consistencygroup( + context, group, add_volumes, remove_volumes) + + def update_consistencygroup(self, context, group, + add_volumes=None, remove_volumes=None): + """ + The volume manager will adds/removes the volume to/from the + group in the database, if need add_volumes, Driver just need + to check whether volume is in array or not + """ + if add_volumes is None: + add_volumes = [] + for volume in add_volumes: + try: + self._check_volume_exist_on_array(volume) + except Exception: + with excutils.save_and_reraise_exception(): + LOG.error("The add_volume %s not exist on array" % volume.id) + + model_update = {'status': 'available'} + LOG.info("Update group successfully") + return model_update, None, None + + def delete_group(self, context, group, volumes): + """delete the group, Driver need to delete relation lun on array""" + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.delete_consistencygroup(context, group, volumes) + + def delete_consistencygroup(self, context, group, volumes): + """delete the group, Driver need to delete relation lun on array""" + volumes_model_update = [] + model_update = {'status': 'deleted'} + for volume in volumes: + volume_model_update = {'id': volume.id} + try: + self.delete_volume(volume) + except Exception: + LOG.error('Delete volume %s failed.' % volume) + volume_model_update.update({'status': 'error_deleting'}) + else: + volume_model_update.update({'status': 'deleted'}) + + LOG.info('Deleted volume %s successfully' % volume) + volumes_model_update.append(volume_model_update) + + LOG.info("Delete group successfully") + return model_update, volumes_model_update + + def create_group_from_src(self, context, group, volumes, + group_snapshot=None, snapshots=None, + source_group=None, source_vols=None): + """ + create group from group or group-snapshot, + Driver need to create volume from volume or snapshot + """ + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.create_consistencygroup_from_src(context, group, volumes, + group_snapshot, snapshots, + source_group, source_vols) + + def create_consistencygroup_from_src(self, context, group, volumes, + group_snapshot=None, snapshots=None, + source_group=None, source_vols=None): + """ + create group from group or group-snapshot, + Driver need to create volume from volume or snapshot + """ + model_update = self.create_consistencygroup(context, group) + volumes_model_update = [] + delete_snapshots = False + + if not snapshots and source_vols: + snapshots = [] + for src_volume in source_vols: + volume_kwargs = { + 'id': src_volume.id, + '_name_id': None, + 'host': src_volume.host + } + snapshot_kwargs = { + 'id': six.text_type(uuid.uuid4()), + 'volume': objects.Volume(**volume_kwargs) + } + snapshots.append(objects.Snapshot(**snapshot_kwargs)) + + self._create_group_snapshot(snapshots) + delete_snapshots = True + + if snapshots: + volumes_model_update = self._create_volume_from_group_snapshot( + volumes, snapshots, delete_snapshots) + + if delete_snapshots: + self._delete_group_snapshot(snapshots) + + LOG.info("Create group from src successfully") + return model_update, volumes_model_update + + def _create_volume_from_group_snapshot(self, volumes, snapshots, delete_snapshots): + volumes_model_update = [] + added_volumes = [] + for i, volume in enumerate(volumes): + try: + vol_model_update = self.create_volume_from_snapshot( + volume, snapshots[i]) + vol_model_update.update({'id': volume.id}) + volumes_model_update.append(vol_model_update) + added_volumes.append(volume) + except Exception: + LOG.error("Create volume from snapshot error, Delete the newly created lun.") + with excutils.save_and_reraise_exception(): + self._delete_added_volume_snapshots( + added_volumes, snapshots, delete_snapshots) + + return volumes_model_update + + def _delete_added_volume_snapshots( + self, added_volumes, snapshots, delete_snapshots): + if delete_snapshots: + self._delete_group_snapshot(snapshots) + for add_volume in added_volumes: + vol_name = self._get_vol_name(add_volume) + self.fs_qos.remove(vol_name) + self.client.delete_volume(vol_name=vol_name) + LOG.info("delete storage newly added " + "volume success, volume is %s" % add_volume.id) + + def create_group_snapshot(self, context, group_snapshot, snapshots): + """Create group snapshot.""" + if not volume_utils.is_group_a_cg_snapshot_type(group_snapshot): + LOG.info("group_snapshot's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.create_cgsnapshot(context, group_snapshot, snapshots) + + def create_cgsnapshot(self, context, group_snapshot, snapshots): + """Create group snapshot.""" + LOG.info('Create group snapshot for group: %(group_snapshot)s', + {'group_snapshot': group_snapshot}) + + try: + snapshots_model_update = self._create_group_snapshot(snapshots) + except Exception as err: + msg = ("Create group snapshots failed. " + "Group snapshot id: %s. Reason is %s") % (group_snapshot.id, err) + LOG.error(msg) + raise exception.CinderException(msg) + + model_update = {'status': 'available'} + return model_update, snapshots_model_update + + def _create_group_snapshot(self, snapshots): + """Generate snapshots for all volumes in the group.""" + snapshots_model_update = [] + snapshot_group_list = [] + + for snapshot in snapshots: + snapshot_name = self._get_snapshot_name(snapshot) + vol_name = self._get_vol_name(snapshot.volume) + snapshot_group_list.append({ + 'name': snapshot_name, + 'sub_type': '0', + 'volume_name': vol_name + }) + snapshot_model_update = { + 'id': snapshot.id, + 'status': 'available', + } + snapshots_model_update.append(snapshot_model_update) + try: + self.client.create_consistent_snapshot_by_name(snapshot_group_list) + except Exception: + with excutils.save_and_reraise_exception(): + LOG.error("Create consistent snapshot failed, " + "snapshot_group_list is %s" % snapshot_group_list) + + return snapshots_model_update + + def delete_group_snapshot(self, context, group_snapshot, snapshots): + """Delete group snapshot.""" + if not volume_utils.is_group_a_cg_snapshot_type(group_snapshot): + LOG.info("group_snapshot's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.delete_cgsnapshot(context, group_snapshot, snapshots) + + def delete_cgsnapshot(self, context, group_snapshot, snapshots): + """Delete group snapshot.""" + LOG.info("Delete group_snapshot %s for " + "consistency group: %s" % (group_snapshot.id, group_snapshot)) + + try: + snapshots_model_update = self._delete_group_snapshot(snapshots) + except Exception as err: + msg = ("Delete cg snapshots failed. " + "group snapshot id: %s, reason is %s") % (group_snapshot.id, err) + LOG.error(msg) + raise exception.CinderException(msg) + + model_update = {'status': 'deleted'} + return model_update, snapshots_model_update + + def _delete_group_snapshot(self, snapshots): + """Delete all snapshots in snapshot group""" + snapshots_model_update = [] + for snapshot in snapshots: + snapshot_model_update = { + 'id': snapshot.id, + 'status': 'deleted' + } + snapshots_model_update.append(snapshot_model_update) + snapshot_name = self._get_snapshot_name(snapshot) + + if not self._check_snapshot_exist(snapshot.volume, snapshot): + LOG.info("snapshot %s not exist in array, " + "don't need to delete, try next one" % snapshot_name) + continue + self.client.delete_snapshot(snapshot_name=snapshot_name) + LOG.info("Delete snapshot successfully," + " the deleted snapshots is %s" % snapshot_name) + + return snapshots_model_update + class DSWAREDriver(DSWAREBaseDriver): def get_volume_stats(self, refresh=False): @@ -721,7 +1248,7 @@ def initialize_connection(self, volume, connector): vol_wwn = volume_info.get('wwn') by_id_path = "/dev/disk/by-id/" + "wwn-0x%s" % vol_wwn properties = {'device_path': by_id_path} - import time + LOG.info("Wait %(t)s second(s) for scanning the target device %(dev)s." % {"t": self.configuration.scan_device_timeout, "dev": by_id_path}) diff --git a/Cinder/Wallaby/fs_client.py b/Cinder/Wallaby/fs_client.py index 234d7f1..09d9581 100644 --- a/Cinder/Wallaby/fs_client.py +++ b/Cinder/Wallaby/fs_client.py @@ -14,16 +14,16 @@ # under the License. import json + import requests import six -import time +from oslo_log import log as logging from requests.adapters import HTTPAdapter from cinder import exception from cinder.i18n import _ from cinder.volume.drivers.fusionstorage import constants -from oslo_log import log as logging LOG = logging.getLogger(__name__) @@ -43,7 +43,8 @@ def __init__(self, fs_address, fs_user, fs_password, **extend_conf): self.session = None self.token = None self.version = None - mutual_authentication = extend_conf.get("mutual_authentication") + self.esn = None + mutual_authentication = extend_conf.get("mutual_authentication", {}) self.init_http_head(mutual_authentication) LOG.warning("Suppressing requests library SSL Warnings") @@ -147,6 +148,13 @@ def get_version(self): if result.get("currentVersion"): self.version = result["currentVersion"] + def get_esn(self): + url = "/cluster/sn" + result = self.call(url, "get") + self._assert_rest_result(result, _('Get cluster esn error.')) + self.esn = result.get("sn") + return self.esn + def login(self): self.get_version() url = '/sec/login' @@ -160,6 +168,7 @@ def login(self): self.session.headers.update({ "x-auth-token": self.token }) + self.get_esn() def logout(self): url = '/sec/logout' @@ -264,6 +273,15 @@ def query_volume_by_name(self, vol_name): result, _("Query volume by name session error")) return result.get('lunDetailInfo') + def query_volume_by_name_v2(self, vol_name): + url = '/api/v2/block_service/volumes?name=' + vol_name + result = self.call(url, 'GET', get_system_time=True) + if result.get('errorCode') in constants.VOLUME_NOT_EXIST: + return {} + self._assert_rest_result( + result, _("Query volume by name session error")) + return result.get('data', {}) + def query_volume_by_id(self, vol_id): url = 'v1.3/volume/queryById?volId=' + vol_id result = self.call(url, 'GET', get_version=True) @@ -746,3 +764,57 @@ def get_iscsi_links_info(self, iscsi_link_count, pool_list): return [iscsi["ip"] for iscsi in result.get("iscsiLinks", []) if iscsi.get("ip")] + + def create_lun_migration(self, src_lun_id, dst_lun_id, speed=2): + url = "/api/v2/block_service/lun_migration" + params = { + "parent_id": src_lun_id, + "target_lun_id": dst_lun_id, + "speed": speed, + "work_mode": 0 + } + result = self.call(url, "POST", params, get_system_time=True) + self._assert_rest_result(result, + _("create lun migration task error.")) + + def get_lun_migration_task_by_id(self, src_lun_id): + url = "/api/v2/block_service/lun_migration" + params = { + "id": src_lun_id + } + result = self.call(url, "GET", params, get_system_time=True) + self._assert_rest_result(result, + _("get lun migration task error.")) + return result.get('data', {}) + + def delete_lun_migration(self, src_lun_id): + url = "/api/v2/block_service/lun_migration" + params = { + 'id': src_lun_id + } + result = self.call(url, "DELETE", params, get_system_time=True) + self._assert_rest_result(result, + _("Delete lun migration task error.")) + + def get_volume_snapshot(self, volume_name): + url = "/volume/snapshot/list" + params = { + 'volName': volume_name, + 'batchNum': 1, + 'batchLimit': 10 + } + result = self.call(url, "POST", params) + return result.get('snapshotList', []) + + def create_consistent_snapshot_by_name(self, snapshot_group_list): + url = "/api/v2/block_service/consistency_snapshots" + result = self.call(url, "POST", snapshot_group_list, get_system_time=True) + self._assert_rest_result(result, _("create consistent_snapshot error.")) + return result.get('data', []) + + def create_full_volume_from_snapshot(self, vol_name, snapshot_name): + url = '/api/v2/block_service/createFullVolumeFromSnap' + params = {"snap_name_src": snapshot_name, "volume_name_dst": vol_name} + result = self.call(url, "POST", params, get_system_time=True) + self._assert_rest_result( + result, _("create full volume from snap fails")) diff --git a/Cinder/Wallaby/fs_qos.py b/Cinder/Wallaby/fs_qos.py index 731c45e..286dbc3 100644 --- a/Cinder/Wallaby/fs_qos.py +++ b/Cinder/Wallaby/fs_qos.py @@ -29,7 +29,11 @@ def __init__(self, client): def add(self, qos, vol_name): localtime = time.strftime('%Y%m%d%H%M%S', time.localtime()) - qos_name = constants.QOS_PREFIX + localtime + # QoS policy name. The value contains 1 to 63 characters. + # So we intercept volume_name Ensure that the length does not exceed 63 + vol_str = vol_name[-constants.QOS_MAX_INTERCEPT_LENGTH::] \ + if len(vol_name) >= constants.QOS_MAX_INTERCEPT_LENGTH else vol_name + qos_name = constants.QOS_PREFIX + localtime + '_' + vol_str self.client.create_qos(qos_name, qos) try: self.client.associate_qos_with_volume(vol_name, qos_name) diff --git a/Cinder/Wallaby/fs_utils.py b/Cinder/Wallaby/fs_utils.py index 8b9ae78..0856038 100644 --- a/Cinder/Wallaby/fs_utils.py +++ b/Cinder/Wallaby/fs_utils.py @@ -16,11 +16,11 @@ import datetime import hashlib import ipaddress -import pytz import random -import six import time +import pytz +import six from oslo_log import log as logging from oslo_service import loopingcall from oslo_utils import units @@ -758,3 +758,9 @@ def get_iscsi_info_from_storage(manager_ips, use_ipv6, valid_iscsi_ips, valid_node_ips): return _get_target_info(manager_ips, use_ipv6, valid_iscsi_ips, valid_node_ips) + + +def encode_name(my_uuid): + encoded_name = hashlib.md5(my_uuid.encode('utf-8')).hexdigest() + target_lun_prefix = my_uuid.split('-')[0] + '-' + return target_lun_prefix + encoded_name diff --git a/Cinder/Xena/constants.py b/Cinder/Xena/constants.py index 5f46ece..b4cb843 100644 --- a/Cinder/Xena/constants.py +++ b/Cinder/Xena/constants.py @@ -45,6 +45,14 @@ CONF_STORAGE_CERT_FILEPATH = "storage_cert_filepath" CONF_STORAGE_SSL_TWO_WAY_AUTH = "storage_ssl_two_way_auth" +DEFAULT_WAIT_INTERVAL = 5 +MIGRATION_COMPLETE = 76 +MIGRATION_FAULT = 74 +STATUS_HEALTH = 1 +STATUS_VOLUME_READY = 27 +MIGRATION_WAIT_INTERVAL = 5 +DEFAULT_WAIT_TIMEOUT = 3600 * 24 * 30 + QOS_MUST_SET = ["maxIOPS", "maxMBPS"] QOS_KEYS = ["maxIOPS", "maxMBPS", "total_iops_sec", "total_bytes_sec"] QOS_SCHEDULER_KEYS = ["scheduleType", "startDate", "startTime", @@ -53,6 +61,7 @@ QOS_SCHEDULER_DEFAULT_TYPE = "0" QOS_SCHEDULER_WEEK_TYPE = "3" QOS_SUPPORT_SCHEDULE_VERSION = "8.0" +QOS_MAX_INTERCEPT_LENGTH = 36 SECONDS_OF_DAY = 24 * 60 * 60 SECONDS_OF_HOUR = 60 * 60 SNAPSHOT_HEALTH_STATUS = ( @@ -80,3 +89,9 @@ HOSTGROUP_ALREADY_EXIST = 50157044 INITIATOR_ALREADY_EXIST = 50155102 INITIATOR_IN_HOST = 50157021 + +CHECK_CLONED_INTERVAL = 2 +REST_VOLUME_CREATING_STATUS = 15 +REST_VOLUME_DUPLICATE_VOLUME = 6 +REST_VOLUME_CREATE_SUCCESS_STATUS = 0 +CLONE_VOLUME_TIMEOUT = 3600 * 24 * 30 diff --git a/Cinder/Xena/dsware.py b/Cinder/Xena/dsware.py index 75e1808..b03e039 100644 --- a/Cinder/Xena/dsware.py +++ b/Cinder/Xena/dsware.py @@ -14,16 +14,22 @@ # under the License. import json - +import time +import uuid from multiprocessing import Lock + +import six from oslo_config import cfg from oslo_log import log as logging +from oslo_utils import excutils from oslo_utils import units +from oslo_service import loopingcall from cinder import coordination from cinder import exception from cinder.i18n import _ from cinder import interface +from cinder import objects from cinder.volume import driver from cinder.volume.drivers.fusionstorage import constants from cinder.volume.drivers.fusionstorage import fs_client @@ -105,6 +111,9 @@ cfg.StrOpt('storage_key_filepath', default='', help='Client key directory.'), + cfg.BoolOpt('full_clone', + default=False, + help='Whether use full clone.'), ] CONF = cfg.CONF @@ -113,7 +122,7 @@ @interface.volumedriver class DSWAREBaseDriver(driver.VolumeDriver): - VERSION = '2.5.RC4' + VERSION = "2.6.1" CI_WIKI_NAME = 'Huawei_FusionStorage_CI' def __init__(self, *args, **kwargs): @@ -210,6 +219,7 @@ def _update_single_pool_info_status(self, pool_info): "total_capacity_gb": capacity['total_capacity_gb'], "free_capacity_gb": capacity['free_capacity_gb'], "provisioned_capacity_gb": capacity['provisioned_capacity_gb'], + "location_info": self.client.esn, "QoS_support": True, 'multiattach': True, "thin_provisioning_support": True, @@ -247,8 +257,12 @@ def _raise_exception(msg): raise exception.VolumeBackendAPIException(data=msg) def _get_pool_id(self, volume): - pool_id_list = [] pool_name = volume_utils.extract_host(volume.host, level='pool') + pool_id = self._get_pool_id_by_name(pool_name) + return pool_id + + def _get_pool_id_by_name(self, pool_name): + pool_id_list = [] all_pools = self.client.query_pool_info() for pool in all_pools: if pool_name == pool['poolName']: @@ -363,29 +377,111 @@ def _expand_volume_when_create(self, vol_name, vol_size): self.client.delete_volume(vol_name=vol_name) raise + def _check_create_cloned_volume_finish(self, new_volume_name, start_time): + LOG.debug('Loopcall: _check_create_cloned_volume_finish(), ' + 'volume-name %s', + new_volume_name) + current_volume = self.client.query_volume_by_name(new_volume_name) + + if current_volume and 'status' in current_volume: + status = int(current_volume['status']) + LOG.debug('Wait clone volume %(volume_name)s, status:%(status)s.', + {"volume_name": new_volume_name, + "status": status}) + if status in {constants.REST_VOLUME_CREATING_STATUS, + constants.REST_VOLUME_DUPLICATE_VOLUME}: + LOG.debug(_("Volume %s is cloning"), new_volume_name) + elif status == constants.REST_VOLUME_CREATE_SUCCESS_STATUS: + raise loopingcall.LoopingCallDone(retvalue=True) + else: + msg = _('Clone volume %(new_volume_name)s failed, ' + 'the status is:%(status)s.') + LOG.error(msg, {'new_volume_name': new_volume_name, + 'status': status}) + raise loopingcall.LoopingCallDone(retvalue=False) + + max_time_out = constants.CLONE_VOLUME_TIMEOUT + current_time = time.time() + if (current_time - start_time) > max_time_out: + msg = _('Dsware clone volume time out. ' + 'Volume: %(new_volume_name)s, status: %(status)s') + LOG.error(msg, {'new_volume_name': new_volume_name, + 'status': current_volume['status']}) + raise loopingcall.LoopingCallDone(retvalue=False) + else: + LOG.warning(_('Can not find volume %s'), new_volume_name) + msg = "DSWARE clone volume failed:volume can not find from dsware" + LOG.error(msg) + raise loopingcall.LoopingCallDone(retvalue=False) + + def _wait_for_create_cloned_volume_finish_timer(self, new_volume_name): + timer = loopingcall.FixedIntervalLoopingCall( + self._check_create_cloned_volume_finish, + new_volume_name, time.time()) + LOG.debug('Calling _check_create_cloned_volume_finish: volume-name %s', + new_volume_name) + ret = timer.start(interval=constants.CHECK_CLONED_INTERVAL).wait() + timer.stop() + return ret + def create_volume_from_snapshot(self, volume, snapshot): vol_name = self._get_vol_name(volume) snapshot_name = self._get_snapshot_name(snapshot) vol_size = volume.size + pool_id = self._get_pool_id(volume) if not self._check_snapshot_exist(snapshot.volume, snapshot): msg = _("Snapshot: %(name)s does not exist!" ) % {"name": snapshot_name} self._raise_exception(msg) - elif self._check_volume_exist(volume): + if self._check_volume_exist(volume): msg = _("Volume: %(vol_name)s already exists!" ) % {'vol_name': vol_name} self._raise_exception(msg) - else: - vol_size *= units.Ki + + vol_size *= units.Ki + if not self.configuration.full_clone: self.client.create_volume_from_snapshot( snapshot_name=snapshot_name, vol_name=vol_name, vol_size=vol_size) - self._add_qos_to_volume(volume, vol_name) - self._expand_volume_when_create(vol_name, vol_size) - result = self.client.query_volume_by_name(vol_name=vol_name) - return ({"metadata": {'lun_wwn': result.get('wwn')}} - if result else {}) + else: + self.client.create_volume(vol_name, vol_size, pool_id) + self.client.create_full_volume_from_snapshot(vol_name, + snapshot_name) + ret = self._wait_for_create_cloned_volume_finish_timer(vol_name) + if not ret: + msg = _('Create full volume %s from snap failed') % vol_name + self._raise_exception(msg) + self._add_qos_to_volume(volume, vol_name) + self._expand_volume_when_create(vol_name, vol_size) + result = self.client.query_volume_by_name(vol_name=vol_name) + return ({"metadata": {'lun_wwn': result.get('wwn')}} + if result else {}) + + def _create_volume_from_volume_full_clone(self, vol_name, vol_size, pool_id, + src_vol_name): + tmp_snap_name = "temp" + src_vol_name + "clone" + vol_name + + self.client.create_snapshot(tmp_snap_name, src_vol_name) + try: + self.client.create_volume(vol_name, vol_size, pool_id) + except Exception as err: + self.client.delete_snapshot(tmp_snap_name) + raise err + + try: + self.client.create_full_volume_from_snapshot( + vol_name, tmp_snap_name) + except Exception as err: + self.client.delete_snapshot(tmp_snap_name) + self.client.delete_volume(vol_name) + raise err + + ret = self._wait_for_create_cloned_volume_finish_timer(vol_name) + if not ret: + msg = _('Create full volume %s from snap failed') % vol_name + self._raise_exception(msg) + self.client.delete_snapshot(tmp_snap_name) def create_cloned_volume(self, volume, src_volume): vol_name = self._get_vol_name(volume) @@ -398,15 +494,22 @@ def create_cloned_volume(self, volume, src_volume): msg = _("Volume: %(vol_name)s does not exist!" ) % {"vol_name": src_vol_name} self._raise_exception(msg) - else: + + if not self.configuration.full_clone: self.client.create_volume_from_volume( vol_name=vol_name, vol_size=vol_size, src_vol_name=src_vol_name) - self._add_qos_to_volume(volume, vol_name) - self._expand_volume_when_create(vol_name, vol_size) - result = self.client.query_volume_by_name(vol_name=vol_name) - return ({"metadata": {'lun_wwn': result.get('wwn')}} - if result else {}) + else: + pool_id = self._get_pool_id(volume) + self._create_volume_from_volume_full_clone( + vol_name=vol_name, vol_size=vol_size, pool_id=pool_id, + src_vol_name=src_vol_name) + + self._add_qos_to_volume(volume, vol_name) + self._expand_volume_when_create(vol_name, vol_size) + result = self.client.query_volume_by_name(vol_name=vol_name) + return ({"metadata": {'lun_wwn': result.get('wwn')}} + if result else {}) def create_snapshot(self, snapshot): snapshot_name = self._get_snapshot_name(snapshot) @@ -581,12 +684,13 @@ def unmanage_snapshot(self, snapshot): def _check_need_changes_for_retype(self, volume, new_type, host, vol_name): before_change = {} after_change = {} - if volume.host != host["host"]: - msg = (_("Do not support retype between different host. Volume's " + migrate = False + if volume.host != host.get("host"): + migrate = True + msg = (_("retype support migration between different host. Volume's " "host: %(vol_host)s, host's host: %(host)s") - % {"vol_host": volume.host, "host": host['host']}) - LOG.error(msg) - raise exception.InvalidInput(msg) + % {"vol_host": volume.host, "host": host.get("host")}) + LOG.info(msg) old_opts = fs_utils.get_volume_specs(self.client, vol_name) new_opts = fs_utils.get_volume_type_params(new_type, self.client) @@ -596,7 +700,7 @@ def _check_need_changes_for_retype(self, volume, new_type, host, vol_name): change_opts = {"old_opts": before_change, "new_opts": after_change} - return change_opts + return migrate, change_opts def retype(self, context, volume, new_type, diff, host): LOG.info("Retype volume: %(vol)s, new_type: %(new_type)s, " @@ -607,13 +711,177 @@ def retype(self, context, volume, new_type, diff, host): "host": host}) vol_name = self._get_vol_name(volume) - change_opts = self._check_need_changes_for_retype( + migrate, change_opts = self._check_need_changes_for_retype( volume, new_type, host, vol_name) + if migrate: + src_lun_id = self._check_volume_exist_on_array(volume) + LOG.debug("Begin to migrate LUN(id: %(lun_id)s) with " + "change %(change_opts)s.", + {"lun_id": src_lun_id, "change_opts": change_opts}) + moved = self._migrate_volume(volume, host, src_lun_id) + if not moved: + LOG.warning("Storage-assisted migration failed during " + "retype.") + return False, None self._change_lun(vol_name, change_opts.get("new_opts"), change_opts.get("old_opts")) return True, None + def migrate_volume(self, context, volume, host): + """Migrate a volume within the same array.""" + LOG.info("Migrate Volume:%(volume)s, host:%(host)s", + {"volume": volume.id, + "host": host}) + src_lun_id = self._check_volume_exist_on_array(volume) + + moved = self._migrate_volume(volume, host, src_lun_id) + return moved, {} + + def _create_dst_volume(self, volume, host): + pool_name = host['capabilities']['pool_name'] + pool_id = self._get_pool_id_by_name(pool_name) + vol_name = fs_utils.encode_name(six.text_type(uuid.uuid4())) + vol_size = volume.size + vol_size *= units.Ki + self.client.create_volume( + pool_id=pool_id, vol_name=vol_name, vol_size=vol_size) + + result = self.client.query_volume_by_name_v2(vol_name=vol_name) + dst_lun_id = result.get('id') + self._wait_volume_ready(vol_name) + return vol_name, dst_lun_id + + def _migrate_volume(self, volume, host, src_lun_id): + """create migration task and wait for task done""" + if not self._check_migration_valid(host): + return False + + vol_name, dst_lun_id = self._create_dst_volume(volume, host) + + try: + self.client.create_lun_migration(src_lun_id, dst_lun_id) + + def _is_lun_migration_complete(): + return self._is_lun_migration_complete(src_lun_id, dst_lun_id) + + wait_interval = constants.MIGRATION_WAIT_INTERVAL + fs_utils.wait_for_condition(_is_lun_migration_complete, + wait_interval, + constants.DEFAULT_WAIT_TIMEOUT) + # Clean up if migration failed. + except Exception as ex: + raise exception.VolumeBackendAPIException(data=ex) + finally: + if self._is_lun_migration_exist(src_lun_id, dst_lun_id): + self.client.delete_lun_migration(src_lun_id) + self._delete_lun_with_check(vol_name) + + LOG.info("Migrate lun %s successfully.", src_lun_id) + return True + + def _delete_lun_with_check(self, vol_name): + if self.client.query_volume_by_name(vol_name): + # migrate_dst_lun don't have qos, so don't + # need to remove qos, Delete the LUN directly. + self.client.delete_volume(vol_name) + + def _is_lun_migration_complete(self, src_lun_id, dst_lun_id): + result = self.client.get_lun_migration_task_by_id(src_lun_id) + found_migration_task = False + if not result: + return False + + if (str(src_lun_id) == result.get('parent_id') and + str(dst_lun_id) == result.get('target_lun_id')): + found_migration_task = True + if constants.MIGRATION_COMPLETE == result.get('running_status'): + return True + if constants.MIGRATION_FAULT == result.get('running_status'): + msg = _("Lun migration error. " + "the migration task running_status is abnormal") + LOG.error(msg) + raise exception.VolumeBackendAPIException(data=msg) + + if not found_migration_task: + err_msg = _("lun migration error, Cannot find migration task.") + LOG.error(err_msg) + raise exception.VolumeBackendAPIException(data=err_msg) + + return False + + def _is_lun_migration_exist(self, src_lun_id, dst_lun_id): + try: + result = self.client.get_lun_migration_task_by_id(src_lun_id) + except Exception: + LOG.error("Get LUN migration error.") + return False + + if (str(src_lun_id) == result.get('parent_id') and + str(dst_lun_id) == result.get('target_lun_id')): + return True + return False + + def _wait_volume_ready(self, vol_name): + wait_interval = constants.DEFAULT_WAIT_INTERVAL + + def _volume_ready(): + result = self.client.query_volume_by_name_v2(vol_name) + if not result: + return False + + if (result.get('health_status') == constants.STATUS_HEALTH + and result.get('running_status') == constants.STATUS_VOLUME_READY): + return True + return False + + fs_utils.wait_for_condition(_volume_ready, + wait_interval, + wait_interval * 10) + + def _check_migration_valid(self, host): + if 'pool_name' not in host.get('capabilities', {}): + return False + + target_device = host.get('capabilities', {}).get('location_info') + + # Source and destination should be on same array. + if target_device != self.client.esn: + LOG.error("lun migration error, " + "Source and destination should be on same array") + return False + + pool_name = host.get('capabilities', {}).get('pool_name', '') + if len(pool_name) == 0: + LOG.error("lun migration error, pool_name not exists") + return False + + return True + + def _check_volume_exist_on_array(self, volume): + volume_name = self._get_vol_name(volume) + result = self._check_volume_exist(volume) + if not result: + msg = _("Volume %s does not exist on the array." + ) % volume.id + self._raise_exception(msg) + + lun_wwn = result.get('wwn') + if not lun_wwn: + LOG.debug("No LUN WWN recorded for volume %s.", volume.id) + + lun_id = result.get('volId') + if not lun_id: + msg = _("Volume %s does not exist on the array." + ) % volume.id + self._raise_exception(msg) + + if self.client.get_volume_snapshot(volume_name): + msg = _("Volume %s which have snapshot cannot do lun migration" + ) % volume.id + self._raise_exception(msg) + return lun_id + def _rollback_snapshot(self, vol_name, snap_name): def _snapshot_rollback_finish(): snapshot_info = self.client.get_snapshot_info_by_name(snap_name) @@ -669,6 +937,265 @@ def ensure_export(self, context, volume): def remove_export(self, context, volume): pass + def create_group(self, context, group): + """Creates a group. Driver only need to return state""" + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.create_consistencygroup(context, group) + + def create_consistencygroup(self, context, group): + """Creates a group. Driver only need to return state""" + LOG.info("Create group successfully") + return {'status': 'available'} + + def update_group(self, context, group, + add_volumes=None, remove_volumes=None): + """ + The volume manager will adds/removes the volume to/from the + group in the database, if need add_volumes, Driver just need + to check whether volume is in array or not + """ + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.update_consistencygroup( + context, group, add_volumes, remove_volumes) + + def update_consistencygroup(self, context, group, + add_volumes=None, remove_volumes=None): + """ + The volume manager will adds/removes the volume to/from the + group in the database, if need add_volumes, Driver just need + to check whether volume is in array or not + """ + if add_volumes is None: + add_volumes = [] + for volume in add_volumes: + try: + self._check_volume_exist_on_array(volume) + except Exception: + with excutils.save_and_reraise_exception(): + LOG.error("The add_volume %s not exist on array" % volume.id) + + model_update = {'status': 'available'} + LOG.info("Update group successfully") + return model_update, None, None + + def delete_group(self, context, group, volumes): + """delete the group, Driver need to delete relation lun on array""" + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.delete_consistencygroup(context, group, volumes) + + def delete_consistencygroup(self, context, group, volumes): + """delete the group, Driver need to delete relation lun on array""" + volumes_model_update = [] + model_update = {'status': 'deleted'} + for volume in volumes: + volume_model_update = {'id': volume.id} + try: + self.delete_volume(volume) + except Exception: + LOG.error('Delete volume %s failed.' % volume) + volume_model_update.update({'status': 'error_deleting'}) + else: + volume_model_update.update({'status': 'deleted'}) + + LOG.info('Deleted volume %s successfully' % volume) + volumes_model_update.append(volume_model_update) + + LOG.info("Delete group successfully") + return model_update, volumes_model_update + + def create_group_from_src(self, context, group, volumes, + group_snapshot=None, snapshots=None, + source_group=None, source_vols=None): + """ + create group from group or group-snapshot, + Driver need to create volume from volume or snapshot + """ + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.create_consistencygroup_from_src(context, group, volumes, + group_snapshot, snapshots, + source_group, source_vols) + + def create_consistencygroup_from_src(self, context, group, volumes, + group_snapshot=None, snapshots=None, + source_group=None, source_vols=None): + """ + create group from group or group-snapshot, + Driver need to create volume from volume or snapshot + """ + model_update = self.create_consistencygroup(context, group) + volumes_model_update = [] + delete_snapshots = False + + if not snapshots and source_vols: + snapshots = [] + for src_volume in source_vols: + volume_kwargs = { + 'id': src_volume.id, + '_name_id': None, + 'host': src_volume.host + } + snapshot_kwargs = { + 'id': six.text_type(uuid.uuid4()), + 'volume': objects.Volume(**volume_kwargs) + } + snapshots.append(objects.Snapshot(**snapshot_kwargs)) + + self._create_group_snapshot(snapshots) + delete_snapshots = True + + if snapshots: + volumes_model_update = self._create_volume_from_group_snapshot( + volumes, snapshots, delete_snapshots) + + if delete_snapshots: + self._delete_group_snapshot(snapshots) + + LOG.info("Create group from src successfully") + return model_update, volumes_model_update + + def _create_volume_from_group_snapshot(self, volumes, snapshots, delete_snapshots): + volumes_model_update = [] + added_volumes = [] + for i, volume in enumerate(volumes): + try: + vol_model_update = self.create_volume_from_snapshot( + volume, snapshots[i]) + vol_model_update.update({'id': volume.id}) + volumes_model_update.append(vol_model_update) + added_volumes.append(volume) + except Exception: + LOG.error("Create volume from snapshot error, Delete the newly created lun.") + with excutils.save_and_reraise_exception(): + self._delete_added_volume_snapshots( + added_volumes, snapshots, delete_snapshots) + + return volumes_model_update + + def _delete_added_volume_snapshots( + self, added_volumes, snapshots, delete_snapshots): + if delete_snapshots: + self._delete_group_snapshot(snapshots) + for add_volume in added_volumes: + vol_name = self._get_vol_name(add_volume) + self.fs_qos.remove(vol_name) + self.client.delete_volume(vol_name=vol_name) + LOG.info("delete storage newly added " + "volume success, volume is %s" % add_volume.id) + + def create_group_snapshot(self, context, group_snapshot, snapshots): + """Create group snapshot.""" + if not volume_utils.is_group_a_cg_snapshot_type(group_snapshot): + LOG.info("group_snapshot's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.create_cgsnapshot(context, group_snapshot, snapshots) + + def create_cgsnapshot(self, context, group_snapshot, snapshots): + """Create group snapshot.""" + LOG.info('Create group snapshot for group: %(group_snapshot)s', + {'group_snapshot': group_snapshot}) + + try: + snapshots_model_update = self._create_group_snapshot(snapshots) + except Exception as err: + msg = ("Create group snapshots failed. " + "Group snapshot id: %s. Reason is %s") % (group_snapshot.id, err) + LOG.error(msg) + raise exception.CinderException(msg) + + model_update = {'status': 'available'} + return model_update, snapshots_model_update + + def _create_group_snapshot(self, snapshots): + """Generate snapshots for all volumes in the group.""" + snapshots_model_update = [] + snapshot_group_list = [] + + for snapshot in snapshots: + snapshot_name = self._get_snapshot_name(snapshot) + vol_name = self._get_vol_name(snapshot.volume) + snapshot_group_list.append({ + 'name': snapshot_name, + 'sub_type': '0', + 'volume_name': vol_name + }) + snapshot_model_update = { + 'id': snapshot.id, + 'status': 'available', + } + snapshots_model_update.append(snapshot_model_update) + try: + self.client.create_consistent_snapshot_by_name(snapshot_group_list) + except Exception: + with excutils.save_and_reraise_exception(): + LOG.error("Create consistent snapshot failed, " + "snapshot_group_list is %s" % snapshot_group_list) + + return snapshots_model_update + + def delete_group_snapshot(self, context, group_snapshot, snapshots): + """Delete group snapshot.""" + if not volume_utils.is_group_a_cg_snapshot_type(group_snapshot): + LOG.info("group_snapshot's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.delete_cgsnapshot(context, group_snapshot, snapshots) + + def delete_cgsnapshot(self, context, group_snapshot, snapshots): + """Delete group snapshot.""" + LOG.info("Delete group_snapshot %s for " + "consistency group: %s" % (group_snapshot.id, group_snapshot)) + + try: + snapshots_model_update = self._delete_group_snapshot(snapshots) + except Exception as err: + msg = ("Delete cg snapshots failed. " + "group snapshot id: %s, reason is %s") % (group_snapshot.id, err) + LOG.error(msg) + raise exception.CinderException(msg) + + model_update = {'status': 'deleted'} + return model_update, snapshots_model_update + + def _delete_group_snapshot(self, snapshots): + """Delete all snapshots in snapshot group""" + snapshots_model_update = [] + for snapshot in snapshots: + snapshot_model_update = { + 'id': snapshot.id, + 'status': 'deleted' + } + snapshots_model_update.append(snapshot_model_update) + snapshot_name = self._get_snapshot_name(snapshot) + + if not self._check_snapshot_exist(snapshot.volume, snapshot): + LOG.info("snapshot %s not exist in array, " + "don't need to delete, try next one" % snapshot_name) + continue + self.client.delete_snapshot(snapshot_name=snapshot_name) + LOG.info("Delete snapshot successfully," + " the deleted snapshots is %s" % snapshot_name) + + return snapshots_model_update + class DSWAREDriver(DSWAREBaseDriver): def get_volume_stats(self, refresh=False): @@ -721,7 +1248,7 @@ def initialize_connection(self, volume, connector): vol_wwn = volume_info.get('wwn') by_id_path = "/dev/disk/by-id/" + "wwn-0x%s" % vol_wwn properties = {'device_path': by_id_path} - import time + LOG.info("Wait %(t)s second(s) for scanning the target device %(dev)s." % {"t": self.configuration.scan_device_timeout, "dev": by_id_path}) diff --git a/Cinder/Xena/fs_client.py b/Cinder/Xena/fs_client.py index 234d7f1..09d9581 100644 --- a/Cinder/Xena/fs_client.py +++ b/Cinder/Xena/fs_client.py @@ -14,16 +14,16 @@ # under the License. import json + import requests import six -import time +from oslo_log import log as logging from requests.adapters import HTTPAdapter from cinder import exception from cinder.i18n import _ from cinder.volume.drivers.fusionstorage import constants -from oslo_log import log as logging LOG = logging.getLogger(__name__) @@ -43,7 +43,8 @@ def __init__(self, fs_address, fs_user, fs_password, **extend_conf): self.session = None self.token = None self.version = None - mutual_authentication = extend_conf.get("mutual_authentication") + self.esn = None + mutual_authentication = extend_conf.get("mutual_authentication", {}) self.init_http_head(mutual_authentication) LOG.warning("Suppressing requests library SSL Warnings") @@ -147,6 +148,13 @@ def get_version(self): if result.get("currentVersion"): self.version = result["currentVersion"] + def get_esn(self): + url = "/cluster/sn" + result = self.call(url, "get") + self._assert_rest_result(result, _('Get cluster esn error.')) + self.esn = result.get("sn") + return self.esn + def login(self): self.get_version() url = '/sec/login' @@ -160,6 +168,7 @@ def login(self): self.session.headers.update({ "x-auth-token": self.token }) + self.get_esn() def logout(self): url = '/sec/logout' @@ -264,6 +273,15 @@ def query_volume_by_name(self, vol_name): result, _("Query volume by name session error")) return result.get('lunDetailInfo') + def query_volume_by_name_v2(self, vol_name): + url = '/api/v2/block_service/volumes?name=' + vol_name + result = self.call(url, 'GET', get_system_time=True) + if result.get('errorCode') in constants.VOLUME_NOT_EXIST: + return {} + self._assert_rest_result( + result, _("Query volume by name session error")) + return result.get('data', {}) + def query_volume_by_id(self, vol_id): url = 'v1.3/volume/queryById?volId=' + vol_id result = self.call(url, 'GET', get_version=True) @@ -746,3 +764,57 @@ def get_iscsi_links_info(self, iscsi_link_count, pool_list): return [iscsi["ip"] for iscsi in result.get("iscsiLinks", []) if iscsi.get("ip")] + + def create_lun_migration(self, src_lun_id, dst_lun_id, speed=2): + url = "/api/v2/block_service/lun_migration" + params = { + "parent_id": src_lun_id, + "target_lun_id": dst_lun_id, + "speed": speed, + "work_mode": 0 + } + result = self.call(url, "POST", params, get_system_time=True) + self._assert_rest_result(result, + _("create lun migration task error.")) + + def get_lun_migration_task_by_id(self, src_lun_id): + url = "/api/v2/block_service/lun_migration" + params = { + "id": src_lun_id + } + result = self.call(url, "GET", params, get_system_time=True) + self._assert_rest_result(result, + _("get lun migration task error.")) + return result.get('data', {}) + + def delete_lun_migration(self, src_lun_id): + url = "/api/v2/block_service/lun_migration" + params = { + 'id': src_lun_id + } + result = self.call(url, "DELETE", params, get_system_time=True) + self._assert_rest_result(result, + _("Delete lun migration task error.")) + + def get_volume_snapshot(self, volume_name): + url = "/volume/snapshot/list" + params = { + 'volName': volume_name, + 'batchNum': 1, + 'batchLimit': 10 + } + result = self.call(url, "POST", params) + return result.get('snapshotList', []) + + def create_consistent_snapshot_by_name(self, snapshot_group_list): + url = "/api/v2/block_service/consistency_snapshots" + result = self.call(url, "POST", snapshot_group_list, get_system_time=True) + self._assert_rest_result(result, _("create consistent_snapshot error.")) + return result.get('data', []) + + def create_full_volume_from_snapshot(self, vol_name, snapshot_name): + url = '/api/v2/block_service/createFullVolumeFromSnap' + params = {"snap_name_src": snapshot_name, "volume_name_dst": vol_name} + result = self.call(url, "POST", params, get_system_time=True) + self._assert_rest_result( + result, _("create full volume from snap fails")) diff --git a/Cinder/Xena/fs_qos.py b/Cinder/Xena/fs_qos.py index 731c45e..286dbc3 100644 --- a/Cinder/Xena/fs_qos.py +++ b/Cinder/Xena/fs_qos.py @@ -29,7 +29,11 @@ def __init__(self, client): def add(self, qos, vol_name): localtime = time.strftime('%Y%m%d%H%M%S', time.localtime()) - qos_name = constants.QOS_PREFIX + localtime + # QoS policy name. The value contains 1 to 63 characters. + # So we intercept volume_name Ensure that the length does not exceed 63 + vol_str = vol_name[-constants.QOS_MAX_INTERCEPT_LENGTH::] \ + if len(vol_name) >= constants.QOS_MAX_INTERCEPT_LENGTH else vol_name + qos_name = constants.QOS_PREFIX + localtime + '_' + vol_str self.client.create_qos(qos_name, qos) try: self.client.associate_qos_with_volume(vol_name, qos_name) diff --git a/Cinder/Xena/fs_utils.py b/Cinder/Xena/fs_utils.py index 8b9ae78..0856038 100644 --- a/Cinder/Xena/fs_utils.py +++ b/Cinder/Xena/fs_utils.py @@ -16,11 +16,11 @@ import datetime import hashlib import ipaddress -import pytz import random -import six import time +import pytz +import six from oslo_log import log as logging from oslo_service import loopingcall from oslo_utils import units @@ -758,3 +758,9 @@ def get_iscsi_info_from_storage(manager_ips, use_ipv6, valid_iscsi_ips, valid_node_ips): return _get_target_info(manager_ips, use_ipv6, valid_iscsi_ips, valid_node_ips) + + +def encode_name(my_uuid): + encoded_name = hashlib.md5(my_uuid.encode('utf-8')).hexdigest() + target_lun_prefix = my_uuid.split('-')[0] + '-' + return target_lun_prefix + encoded_name diff --git a/Cinder/Yoga/constants.py b/Cinder/Yoga/constants.py index 5f46ece..b4cb843 100644 --- a/Cinder/Yoga/constants.py +++ b/Cinder/Yoga/constants.py @@ -45,6 +45,14 @@ CONF_STORAGE_CERT_FILEPATH = "storage_cert_filepath" CONF_STORAGE_SSL_TWO_WAY_AUTH = "storage_ssl_two_way_auth" +DEFAULT_WAIT_INTERVAL = 5 +MIGRATION_COMPLETE = 76 +MIGRATION_FAULT = 74 +STATUS_HEALTH = 1 +STATUS_VOLUME_READY = 27 +MIGRATION_WAIT_INTERVAL = 5 +DEFAULT_WAIT_TIMEOUT = 3600 * 24 * 30 + QOS_MUST_SET = ["maxIOPS", "maxMBPS"] QOS_KEYS = ["maxIOPS", "maxMBPS", "total_iops_sec", "total_bytes_sec"] QOS_SCHEDULER_KEYS = ["scheduleType", "startDate", "startTime", @@ -53,6 +61,7 @@ QOS_SCHEDULER_DEFAULT_TYPE = "0" QOS_SCHEDULER_WEEK_TYPE = "3" QOS_SUPPORT_SCHEDULE_VERSION = "8.0" +QOS_MAX_INTERCEPT_LENGTH = 36 SECONDS_OF_DAY = 24 * 60 * 60 SECONDS_OF_HOUR = 60 * 60 SNAPSHOT_HEALTH_STATUS = ( @@ -80,3 +89,9 @@ HOSTGROUP_ALREADY_EXIST = 50157044 INITIATOR_ALREADY_EXIST = 50155102 INITIATOR_IN_HOST = 50157021 + +CHECK_CLONED_INTERVAL = 2 +REST_VOLUME_CREATING_STATUS = 15 +REST_VOLUME_DUPLICATE_VOLUME = 6 +REST_VOLUME_CREATE_SUCCESS_STATUS = 0 +CLONE_VOLUME_TIMEOUT = 3600 * 24 * 30 diff --git a/Cinder/Yoga/dsware.py b/Cinder/Yoga/dsware.py index 75e1808..b03e039 100644 --- a/Cinder/Yoga/dsware.py +++ b/Cinder/Yoga/dsware.py @@ -14,16 +14,22 @@ # under the License. import json - +import time +import uuid from multiprocessing import Lock + +import six from oslo_config import cfg from oslo_log import log as logging +from oslo_utils import excutils from oslo_utils import units +from oslo_service import loopingcall from cinder import coordination from cinder import exception from cinder.i18n import _ from cinder import interface +from cinder import objects from cinder.volume import driver from cinder.volume.drivers.fusionstorage import constants from cinder.volume.drivers.fusionstorage import fs_client @@ -105,6 +111,9 @@ cfg.StrOpt('storage_key_filepath', default='', help='Client key directory.'), + cfg.BoolOpt('full_clone', + default=False, + help='Whether use full clone.'), ] CONF = cfg.CONF @@ -113,7 +122,7 @@ @interface.volumedriver class DSWAREBaseDriver(driver.VolumeDriver): - VERSION = '2.5.RC4' + VERSION = "2.6.1" CI_WIKI_NAME = 'Huawei_FusionStorage_CI' def __init__(self, *args, **kwargs): @@ -210,6 +219,7 @@ def _update_single_pool_info_status(self, pool_info): "total_capacity_gb": capacity['total_capacity_gb'], "free_capacity_gb": capacity['free_capacity_gb'], "provisioned_capacity_gb": capacity['provisioned_capacity_gb'], + "location_info": self.client.esn, "QoS_support": True, 'multiattach': True, "thin_provisioning_support": True, @@ -247,8 +257,12 @@ def _raise_exception(msg): raise exception.VolumeBackendAPIException(data=msg) def _get_pool_id(self, volume): - pool_id_list = [] pool_name = volume_utils.extract_host(volume.host, level='pool') + pool_id = self._get_pool_id_by_name(pool_name) + return pool_id + + def _get_pool_id_by_name(self, pool_name): + pool_id_list = [] all_pools = self.client.query_pool_info() for pool in all_pools: if pool_name == pool['poolName']: @@ -363,29 +377,111 @@ def _expand_volume_when_create(self, vol_name, vol_size): self.client.delete_volume(vol_name=vol_name) raise + def _check_create_cloned_volume_finish(self, new_volume_name, start_time): + LOG.debug('Loopcall: _check_create_cloned_volume_finish(), ' + 'volume-name %s', + new_volume_name) + current_volume = self.client.query_volume_by_name(new_volume_name) + + if current_volume and 'status' in current_volume: + status = int(current_volume['status']) + LOG.debug('Wait clone volume %(volume_name)s, status:%(status)s.', + {"volume_name": new_volume_name, + "status": status}) + if status in {constants.REST_VOLUME_CREATING_STATUS, + constants.REST_VOLUME_DUPLICATE_VOLUME}: + LOG.debug(_("Volume %s is cloning"), new_volume_name) + elif status == constants.REST_VOLUME_CREATE_SUCCESS_STATUS: + raise loopingcall.LoopingCallDone(retvalue=True) + else: + msg = _('Clone volume %(new_volume_name)s failed, ' + 'the status is:%(status)s.') + LOG.error(msg, {'new_volume_name': new_volume_name, + 'status': status}) + raise loopingcall.LoopingCallDone(retvalue=False) + + max_time_out = constants.CLONE_VOLUME_TIMEOUT + current_time = time.time() + if (current_time - start_time) > max_time_out: + msg = _('Dsware clone volume time out. ' + 'Volume: %(new_volume_name)s, status: %(status)s') + LOG.error(msg, {'new_volume_name': new_volume_name, + 'status': current_volume['status']}) + raise loopingcall.LoopingCallDone(retvalue=False) + else: + LOG.warning(_('Can not find volume %s'), new_volume_name) + msg = "DSWARE clone volume failed:volume can not find from dsware" + LOG.error(msg) + raise loopingcall.LoopingCallDone(retvalue=False) + + def _wait_for_create_cloned_volume_finish_timer(self, new_volume_name): + timer = loopingcall.FixedIntervalLoopingCall( + self._check_create_cloned_volume_finish, + new_volume_name, time.time()) + LOG.debug('Calling _check_create_cloned_volume_finish: volume-name %s', + new_volume_name) + ret = timer.start(interval=constants.CHECK_CLONED_INTERVAL).wait() + timer.stop() + return ret + def create_volume_from_snapshot(self, volume, snapshot): vol_name = self._get_vol_name(volume) snapshot_name = self._get_snapshot_name(snapshot) vol_size = volume.size + pool_id = self._get_pool_id(volume) if not self._check_snapshot_exist(snapshot.volume, snapshot): msg = _("Snapshot: %(name)s does not exist!" ) % {"name": snapshot_name} self._raise_exception(msg) - elif self._check_volume_exist(volume): + if self._check_volume_exist(volume): msg = _("Volume: %(vol_name)s already exists!" ) % {'vol_name': vol_name} self._raise_exception(msg) - else: - vol_size *= units.Ki + + vol_size *= units.Ki + if not self.configuration.full_clone: self.client.create_volume_from_snapshot( snapshot_name=snapshot_name, vol_name=vol_name, vol_size=vol_size) - self._add_qos_to_volume(volume, vol_name) - self._expand_volume_when_create(vol_name, vol_size) - result = self.client.query_volume_by_name(vol_name=vol_name) - return ({"metadata": {'lun_wwn': result.get('wwn')}} - if result else {}) + else: + self.client.create_volume(vol_name, vol_size, pool_id) + self.client.create_full_volume_from_snapshot(vol_name, + snapshot_name) + ret = self._wait_for_create_cloned_volume_finish_timer(vol_name) + if not ret: + msg = _('Create full volume %s from snap failed') % vol_name + self._raise_exception(msg) + self._add_qos_to_volume(volume, vol_name) + self._expand_volume_when_create(vol_name, vol_size) + result = self.client.query_volume_by_name(vol_name=vol_name) + return ({"metadata": {'lun_wwn': result.get('wwn')}} + if result else {}) + + def _create_volume_from_volume_full_clone(self, vol_name, vol_size, pool_id, + src_vol_name): + tmp_snap_name = "temp" + src_vol_name + "clone" + vol_name + + self.client.create_snapshot(tmp_snap_name, src_vol_name) + try: + self.client.create_volume(vol_name, vol_size, pool_id) + except Exception as err: + self.client.delete_snapshot(tmp_snap_name) + raise err + + try: + self.client.create_full_volume_from_snapshot( + vol_name, tmp_snap_name) + except Exception as err: + self.client.delete_snapshot(tmp_snap_name) + self.client.delete_volume(vol_name) + raise err + + ret = self._wait_for_create_cloned_volume_finish_timer(vol_name) + if not ret: + msg = _('Create full volume %s from snap failed') % vol_name + self._raise_exception(msg) + self.client.delete_snapshot(tmp_snap_name) def create_cloned_volume(self, volume, src_volume): vol_name = self._get_vol_name(volume) @@ -398,15 +494,22 @@ def create_cloned_volume(self, volume, src_volume): msg = _("Volume: %(vol_name)s does not exist!" ) % {"vol_name": src_vol_name} self._raise_exception(msg) - else: + + if not self.configuration.full_clone: self.client.create_volume_from_volume( vol_name=vol_name, vol_size=vol_size, src_vol_name=src_vol_name) - self._add_qos_to_volume(volume, vol_name) - self._expand_volume_when_create(vol_name, vol_size) - result = self.client.query_volume_by_name(vol_name=vol_name) - return ({"metadata": {'lun_wwn': result.get('wwn')}} - if result else {}) + else: + pool_id = self._get_pool_id(volume) + self._create_volume_from_volume_full_clone( + vol_name=vol_name, vol_size=vol_size, pool_id=pool_id, + src_vol_name=src_vol_name) + + self._add_qos_to_volume(volume, vol_name) + self._expand_volume_when_create(vol_name, vol_size) + result = self.client.query_volume_by_name(vol_name=vol_name) + return ({"metadata": {'lun_wwn': result.get('wwn')}} + if result else {}) def create_snapshot(self, snapshot): snapshot_name = self._get_snapshot_name(snapshot) @@ -581,12 +684,13 @@ def unmanage_snapshot(self, snapshot): def _check_need_changes_for_retype(self, volume, new_type, host, vol_name): before_change = {} after_change = {} - if volume.host != host["host"]: - msg = (_("Do not support retype between different host. Volume's " + migrate = False + if volume.host != host.get("host"): + migrate = True + msg = (_("retype support migration between different host. Volume's " "host: %(vol_host)s, host's host: %(host)s") - % {"vol_host": volume.host, "host": host['host']}) - LOG.error(msg) - raise exception.InvalidInput(msg) + % {"vol_host": volume.host, "host": host.get("host")}) + LOG.info(msg) old_opts = fs_utils.get_volume_specs(self.client, vol_name) new_opts = fs_utils.get_volume_type_params(new_type, self.client) @@ -596,7 +700,7 @@ def _check_need_changes_for_retype(self, volume, new_type, host, vol_name): change_opts = {"old_opts": before_change, "new_opts": after_change} - return change_opts + return migrate, change_opts def retype(self, context, volume, new_type, diff, host): LOG.info("Retype volume: %(vol)s, new_type: %(new_type)s, " @@ -607,13 +711,177 @@ def retype(self, context, volume, new_type, diff, host): "host": host}) vol_name = self._get_vol_name(volume) - change_opts = self._check_need_changes_for_retype( + migrate, change_opts = self._check_need_changes_for_retype( volume, new_type, host, vol_name) + if migrate: + src_lun_id = self._check_volume_exist_on_array(volume) + LOG.debug("Begin to migrate LUN(id: %(lun_id)s) with " + "change %(change_opts)s.", + {"lun_id": src_lun_id, "change_opts": change_opts}) + moved = self._migrate_volume(volume, host, src_lun_id) + if not moved: + LOG.warning("Storage-assisted migration failed during " + "retype.") + return False, None self._change_lun(vol_name, change_opts.get("new_opts"), change_opts.get("old_opts")) return True, None + def migrate_volume(self, context, volume, host): + """Migrate a volume within the same array.""" + LOG.info("Migrate Volume:%(volume)s, host:%(host)s", + {"volume": volume.id, + "host": host}) + src_lun_id = self._check_volume_exist_on_array(volume) + + moved = self._migrate_volume(volume, host, src_lun_id) + return moved, {} + + def _create_dst_volume(self, volume, host): + pool_name = host['capabilities']['pool_name'] + pool_id = self._get_pool_id_by_name(pool_name) + vol_name = fs_utils.encode_name(six.text_type(uuid.uuid4())) + vol_size = volume.size + vol_size *= units.Ki + self.client.create_volume( + pool_id=pool_id, vol_name=vol_name, vol_size=vol_size) + + result = self.client.query_volume_by_name_v2(vol_name=vol_name) + dst_lun_id = result.get('id') + self._wait_volume_ready(vol_name) + return vol_name, dst_lun_id + + def _migrate_volume(self, volume, host, src_lun_id): + """create migration task and wait for task done""" + if not self._check_migration_valid(host): + return False + + vol_name, dst_lun_id = self._create_dst_volume(volume, host) + + try: + self.client.create_lun_migration(src_lun_id, dst_lun_id) + + def _is_lun_migration_complete(): + return self._is_lun_migration_complete(src_lun_id, dst_lun_id) + + wait_interval = constants.MIGRATION_WAIT_INTERVAL + fs_utils.wait_for_condition(_is_lun_migration_complete, + wait_interval, + constants.DEFAULT_WAIT_TIMEOUT) + # Clean up if migration failed. + except Exception as ex: + raise exception.VolumeBackendAPIException(data=ex) + finally: + if self._is_lun_migration_exist(src_lun_id, dst_lun_id): + self.client.delete_lun_migration(src_lun_id) + self._delete_lun_with_check(vol_name) + + LOG.info("Migrate lun %s successfully.", src_lun_id) + return True + + def _delete_lun_with_check(self, vol_name): + if self.client.query_volume_by_name(vol_name): + # migrate_dst_lun don't have qos, so don't + # need to remove qos, Delete the LUN directly. + self.client.delete_volume(vol_name) + + def _is_lun_migration_complete(self, src_lun_id, dst_lun_id): + result = self.client.get_lun_migration_task_by_id(src_lun_id) + found_migration_task = False + if not result: + return False + + if (str(src_lun_id) == result.get('parent_id') and + str(dst_lun_id) == result.get('target_lun_id')): + found_migration_task = True + if constants.MIGRATION_COMPLETE == result.get('running_status'): + return True + if constants.MIGRATION_FAULT == result.get('running_status'): + msg = _("Lun migration error. " + "the migration task running_status is abnormal") + LOG.error(msg) + raise exception.VolumeBackendAPIException(data=msg) + + if not found_migration_task: + err_msg = _("lun migration error, Cannot find migration task.") + LOG.error(err_msg) + raise exception.VolumeBackendAPIException(data=err_msg) + + return False + + def _is_lun_migration_exist(self, src_lun_id, dst_lun_id): + try: + result = self.client.get_lun_migration_task_by_id(src_lun_id) + except Exception: + LOG.error("Get LUN migration error.") + return False + + if (str(src_lun_id) == result.get('parent_id') and + str(dst_lun_id) == result.get('target_lun_id')): + return True + return False + + def _wait_volume_ready(self, vol_name): + wait_interval = constants.DEFAULT_WAIT_INTERVAL + + def _volume_ready(): + result = self.client.query_volume_by_name_v2(vol_name) + if not result: + return False + + if (result.get('health_status') == constants.STATUS_HEALTH + and result.get('running_status') == constants.STATUS_VOLUME_READY): + return True + return False + + fs_utils.wait_for_condition(_volume_ready, + wait_interval, + wait_interval * 10) + + def _check_migration_valid(self, host): + if 'pool_name' not in host.get('capabilities', {}): + return False + + target_device = host.get('capabilities', {}).get('location_info') + + # Source and destination should be on same array. + if target_device != self.client.esn: + LOG.error("lun migration error, " + "Source and destination should be on same array") + return False + + pool_name = host.get('capabilities', {}).get('pool_name', '') + if len(pool_name) == 0: + LOG.error("lun migration error, pool_name not exists") + return False + + return True + + def _check_volume_exist_on_array(self, volume): + volume_name = self._get_vol_name(volume) + result = self._check_volume_exist(volume) + if not result: + msg = _("Volume %s does not exist on the array." + ) % volume.id + self._raise_exception(msg) + + lun_wwn = result.get('wwn') + if not lun_wwn: + LOG.debug("No LUN WWN recorded for volume %s.", volume.id) + + lun_id = result.get('volId') + if not lun_id: + msg = _("Volume %s does not exist on the array." + ) % volume.id + self._raise_exception(msg) + + if self.client.get_volume_snapshot(volume_name): + msg = _("Volume %s which have snapshot cannot do lun migration" + ) % volume.id + self._raise_exception(msg) + return lun_id + def _rollback_snapshot(self, vol_name, snap_name): def _snapshot_rollback_finish(): snapshot_info = self.client.get_snapshot_info_by_name(snap_name) @@ -669,6 +937,265 @@ def ensure_export(self, context, volume): def remove_export(self, context, volume): pass + def create_group(self, context, group): + """Creates a group. Driver only need to return state""" + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.create_consistencygroup(context, group) + + def create_consistencygroup(self, context, group): + """Creates a group. Driver only need to return state""" + LOG.info("Create group successfully") + return {'status': 'available'} + + def update_group(self, context, group, + add_volumes=None, remove_volumes=None): + """ + The volume manager will adds/removes the volume to/from the + group in the database, if need add_volumes, Driver just need + to check whether volume is in array or not + """ + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.update_consistencygroup( + context, group, add_volumes, remove_volumes) + + def update_consistencygroup(self, context, group, + add_volumes=None, remove_volumes=None): + """ + The volume manager will adds/removes the volume to/from the + group in the database, if need add_volumes, Driver just need + to check whether volume is in array or not + """ + if add_volumes is None: + add_volumes = [] + for volume in add_volumes: + try: + self._check_volume_exist_on_array(volume) + except Exception: + with excutils.save_and_reraise_exception(): + LOG.error("The add_volume %s not exist on array" % volume.id) + + model_update = {'status': 'available'} + LOG.info("Update group successfully") + return model_update, None, None + + def delete_group(self, context, group, volumes): + """delete the group, Driver need to delete relation lun on array""" + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.delete_consistencygroup(context, group, volumes) + + def delete_consistencygroup(self, context, group, volumes): + """delete the group, Driver need to delete relation lun on array""" + volumes_model_update = [] + model_update = {'status': 'deleted'} + for volume in volumes: + volume_model_update = {'id': volume.id} + try: + self.delete_volume(volume) + except Exception: + LOG.error('Delete volume %s failed.' % volume) + volume_model_update.update({'status': 'error_deleting'}) + else: + volume_model_update.update({'status': 'deleted'}) + + LOG.info('Deleted volume %s successfully' % volume) + volumes_model_update.append(volume_model_update) + + LOG.info("Delete group successfully") + return model_update, volumes_model_update + + def create_group_from_src(self, context, group, volumes, + group_snapshot=None, snapshots=None, + source_group=None, source_vols=None): + """ + create group from group or group-snapshot, + Driver need to create volume from volume or snapshot + """ + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.create_consistencygroup_from_src(context, group, volumes, + group_snapshot, snapshots, + source_group, source_vols) + + def create_consistencygroup_from_src(self, context, group, volumes, + group_snapshot=None, snapshots=None, + source_group=None, source_vols=None): + """ + create group from group or group-snapshot, + Driver need to create volume from volume or snapshot + """ + model_update = self.create_consistencygroup(context, group) + volumes_model_update = [] + delete_snapshots = False + + if not snapshots and source_vols: + snapshots = [] + for src_volume in source_vols: + volume_kwargs = { + 'id': src_volume.id, + '_name_id': None, + 'host': src_volume.host + } + snapshot_kwargs = { + 'id': six.text_type(uuid.uuid4()), + 'volume': objects.Volume(**volume_kwargs) + } + snapshots.append(objects.Snapshot(**snapshot_kwargs)) + + self._create_group_snapshot(snapshots) + delete_snapshots = True + + if snapshots: + volumes_model_update = self._create_volume_from_group_snapshot( + volumes, snapshots, delete_snapshots) + + if delete_snapshots: + self._delete_group_snapshot(snapshots) + + LOG.info("Create group from src successfully") + return model_update, volumes_model_update + + def _create_volume_from_group_snapshot(self, volumes, snapshots, delete_snapshots): + volumes_model_update = [] + added_volumes = [] + for i, volume in enumerate(volumes): + try: + vol_model_update = self.create_volume_from_snapshot( + volume, snapshots[i]) + vol_model_update.update({'id': volume.id}) + volumes_model_update.append(vol_model_update) + added_volumes.append(volume) + except Exception: + LOG.error("Create volume from snapshot error, Delete the newly created lun.") + with excutils.save_and_reraise_exception(): + self._delete_added_volume_snapshots( + added_volumes, snapshots, delete_snapshots) + + return volumes_model_update + + def _delete_added_volume_snapshots( + self, added_volumes, snapshots, delete_snapshots): + if delete_snapshots: + self._delete_group_snapshot(snapshots) + for add_volume in added_volumes: + vol_name = self._get_vol_name(add_volume) + self.fs_qos.remove(vol_name) + self.client.delete_volume(vol_name=vol_name) + LOG.info("delete storage newly added " + "volume success, volume is %s" % add_volume.id) + + def create_group_snapshot(self, context, group_snapshot, snapshots): + """Create group snapshot.""" + if not volume_utils.is_group_a_cg_snapshot_type(group_snapshot): + LOG.info("group_snapshot's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.create_cgsnapshot(context, group_snapshot, snapshots) + + def create_cgsnapshot(self, context, group_snapshot, snapshots): + """Create group snapshot.""" + LOG.info('Create group snapshot for group: %(group_snapshot)s', + {'group_snapshot': group_snapshot}) + + try: + snapshots_model_update = self._create_group_snapshot(snapshots) + except Exception as err: + msg = ("Create group snapshots failed. " + "Group snapshot id: %s. Reason is %s") % (group_snapshot.id, err) + LOG.error(msg) + raise exception.CinderException(msg) + + model_update = {'status': 'available'} + return model_update, snapshots_model_update + + def _create_group_snapshot(self, snapshots): + """Generate snapshots for all volumes in the group.""" + snapshots_model_update = [] + snapshot_group_list = [] + + for snapshot in snapshots: + snapshot_name = self._get_snapshot_name(snapshot) + vol_name = self._get_vol_name(snapshot.volume) + snapshot_group_list.append({ + 'name': snapshot_name, + 'sub_type': '0', + 'volume_name': vol_name + }) + snapshot_model_update = { + 'id': snapshot.id, + 'status': 'available', + } + snapshots_model_update.append(snapshot_model_update) + try: + self.client.create_consistent_snapshot_by_name(snapshot_group_list) + except Exception: + with excutils.save_and_reraise_exception(): + LOG.error("Create consistent snapshot failed, " + "snapshot_group_list is %s" % snapshot_group_list) + + return snapshots_model_update + + def delete_group_snapshot(self, context, group_snapshot, snapshots): + """Delete group snapshot.""" + if not volume_utils.is_group_a_cg_snapshot_type(group_snapshot): + LOG.info("group_snapshot's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.delete_cgsnapshot(context, group_snapshot, snapshots) + + def delete_cgsnapshot(self, context, group_snapshot, snapshots): + """Delete group snapshot.""" + LOG.info("Delete group_snapshot %s for " + "consistency group: %s" % (group_snapshot.id, group_snapshot)) + + try: + snapshots_model_update = self._delete_group_snapshot(snapshots) + except Exception as err: + msg = ("Delete cg snapshots failed. " + "group snapshot id: %s, reason is %s") % (group_snapshot.id, err) + LOG.error(msg) + raise exception.CinderException(msg) + + model_update = {'status': 'deleted'} + return model_update, snapshots_model_update + + def _delete_group_snapshot(self, snapshots): + """Delete all snapshots in snapshot group""" + snapshots_model_update = [] + for snapshot in snapshots: + snapshot_model_update = { + 'id': snapshot.id, + 'status': 'deleted' + } + snapshots_model_update.append(snapshot_model_update) + snapshot_name = self._get_snapshot_name(snapshot) + + if not self._check_snapshot_exist(snapshot.volume, snapshot): + LOG.info("snapshot %s not exist in array, " + "don't need to delete, try next one" % snapshot_name) + continue + self.client.delete_snapshot(snapshot_name=snapshot_name) + LOG.info("Delete snapshot successfully," + " the deleted snapshots is %s" % snapshot_name) + + return snapshots_model_update + class DSWAREDriver(DSWAREBaseDriver): def get_volume_stats(self, refresh=False): @@ -721,7 +1248,7 @@ def initialize_connection(self, volume, connector): vol_wwn = volume_info.get('wwn') by_id_path = "/dev/disk/by-id/" + "wwn-0x%s" % vol_wwn properties = {'device_path': by_id_path} - import time + LOG.info("Wait %(t)s second(s) for scanning the target device %(dev)s." % {"t": self.configuration.scan_device_timeout, "dev": by_id_path}) diff --git a/Cinder/Yoga/fs_client.py b/Cinder/Yoga/fs_client.py index 234d7f1..09d9581 100644 --- a/Cinder/Yoga/fs_client.py +++ b/Cinder/Yoga/fs_client.py @@ -14,16 +14,16 @@ # under the License. import json + import requests import six -import time +from oslo_log import log as logging from requests.adapters import HTTPAdapter from cinder import exception from cinder.i18n import _ from cinder.volume.drivers.fusionstorage import constants -from oslo_log import log as logging LOG = logging.getLogger(__name__) @@ -43,7 +43,8 @@ def __init__(self, fs_address, fs_user, fs_password, **extend_conf): self.session = None self.token = None self.version = None - mutual_authentication = extend_conf.get("mutual_authentication") + self.esn = None + mutual_authentication = extend_conf.get("mutual_authentication", {}) self.init_http_head(mutual_authentication) LOG.warning("Suppressing requests library SSL Warnings") @@ -147,6 +148,13 @@ def get_version(self): if result.get("currentVersion"): self.version = result["currentVersion"] + def get_esn(self): + url = "/cluster/sn" + result = self.call(url, "get") + self._assert_rest_result(result, _('Get cluster esn error.')) + self.esn = result.get("sn") + return self.esn + def login(self): self.get_version() url = '/sec/login' @@ -160,6 +168,7 @@ def login(self): self.session.headers.update({ "x-auth-token": self.token }) + self.get_esn() def logout(self): url = '/sec/logout' @@ -264,6 +273,15 @@ def query_volume_by_name(self, vol_name): result, _("Query volume by name session error")) return result.get('lunDetailInfo') + def query_volume_by_name_v2(self, vol_name): + url = '/api/v2/block_service/volumes?name=' + vol_name + result = self.call(url, 'GET', get_system_time=True) + if result.get('errorCode') in constants.VOLUME_NOT_EXIST: + return {} + self._assert_rest_result( + result, _("Query volume by name session error")) + return result.get('data', {}) + def query_volume_by_id(self, vol_id): url = 'v1.3/volume/queryById?volId=' + vol_id result = self.call(url, 'GET', get_version=True) @@ -746,3 +764,57 @@ def get_iscsi_links_info(self, iscsi_link_count, pool_list): return [iscsi["ip"] for iscsi in result.get("iscsiLinks", []) if iscsi.get("ip")] + + def create_lun_migration(self, src_lun_id, dst_lun_id, speed=2): + url = "/api/v2/block_service/lun_migration" + params = { + "parent_id": src_lun_id, + "target_lun_id": dst_lun_id, + "speed": speed, + "work_mode": 0 + } + result = self.call(url, "POST", params, get_system_time=True) + self._assert_rest_result(result, + _("create lun migration task error.")) + + def get_lun_migration_task_by_id(self, src_lun_id): + url = "/api/v2/block_service/lun_migration" + params = { + "id": src_lun_id + } + result = self.call(url, "GET", params, get_system_time=True) + self._assert_rest_result(result, + _("get lun migration task error.")) + return result.get('data', {}) + + def delete_lun_migration(self, src_lun_id): + url = "/api/v2/block_service/lun_migration" + params = { + 'id': src_lun_id + } + result = self.call(url, "DELETE", params, get_system_time=True) + self._assert_rest_result(result, + _("Delete lun migration task error.")) + + def get_volume_snapshot(self, volume_name): + url = "/volume/snapshot/list" + params = { + 'volName': volume_name, + 'batchNum': 1, + 'batchLimit': 10 + } + result = self.call(url, "POST", params) + return result.get('snapshotList', []) + + def create_consistent_snapshot_by_name(self, snapshot_group_list): + url = "/api/v2/block_service/consistency_snapshots" + result = self.call(url, "POST", snapshot_group_list, get_system_time=True) + self._assert_rest_result(result, _("create consistent_snapshot error.")) + return result.get('data', []) + + def create_full_volume_from_snapshot(self, vol_name, snapshot_name): + url = '/api/v2/block_service/createFullVolumeFromSnap' + params = {"snap_name_src": snapshot_name, "volume_name_dst": vol_name} + result = self.call(url, "POST", params, get_system_time=True) + self._assert_rest_result( + result, _("create full volume from snap fails")) diff --git a/Cinder/Yoga/fs_qos.py b/Cinder/Yoga/fs_qos.py index 731c45e..286dbc3 100644 --- a/Cinder/Yoga/fs_qos.py +++ b/Cinder/Yoga/fs_qos.py @@ -29,7 +29,11 @@ def __init__(self, client): def add(self, qos, vol_name): localtime = time.strftime('%Y%m%d%H%M%S', time.localtime()) - qos_name = constants.QOS_PREFIX + localtime + # QoS policy name. The value contains 1 to 63 characters. + # So we intercept volume_name Ensure that the length does not exceed 63 + vol_str = vol_name[-constants.QOS_MAX_INTERCEPT_LENGTH::] \ + if len(vol_name) >= constants.QOS_MAX_INTERCEPT_LENGTH else vol_name + qos_name = constants.QOS_PREFIX + localtime + '_' + vol_str self.client.create_qos(qos_name, qos) try: self.client.associate_qos_with_volume(vol_name, qos_name) diff --git a/Cinder/Yoga/fs_utils.py b/Cinder/Yoga/fs_utils.py index 8b9ae78..0856038 100644 --- a/Cinder/Yoga/fs_utils.py +++ b/Cinder/Yoga/fs_utils.py @@ -16,11 +16,11 @@ import datetime import hashlib import ipaddress -import pytz import random -import six import time +import pytz +import six from oslo_log import log as logging from oslo_service import loopingcall from oslo_utils import units @@ -758,3 +758,9 @@ def get_iscsi_info_from_storage(manager_ips, use_ipv6, valid_iscsi_ips, valid_node_ips): return _get_target_info(manager_ips, use_ipv6, valid_iscsi_ips, valid_node_ips) + + +def encode_name(my_uuid): + encoded_name = hashlib.md5(my_uuid.encode('utf-8')).hexdigest() + target_lun_prefix = my_uuid.split('-')[0] + '-' + return target_lun_prefix + encoded_name diff --git a/Cinder/Zed/constants.py b/Cinder/Zed/constants.py index 5f46ece..b4cb843 100644 --- a/Cinder/Zed/constants.py +++ b/Cinder/Zed/constants.py @@ -45,6 +45,14 @@ CONF_STORAGE_CERT_FILEPATH = "storage_cert_filepath" CONF_STORAGE_SSL_TWO_WAY_AUTH = "storage_ssl_two_way_auth" +DEFAULT_WAIT_INTERVAL = 5 +MIGRATION_COMPLETE = 76 +MIGRATION_FAULT = 74 +STATUS_HEALTH = 1 +STATUS_VOLUME_READY = 27 +MIGRATION_WAIT_INTERVAL = 5 +DEFAULT_WAIT_TIMEOUT = 3600 * 24 * 30 + QOS_MUST_SET = ["maxIOPS", "maxMBPS"] QOS_KEYS = ["maxIOPS", "maxMBPS", "total_iops_sec", "total_bytes_sec"] QOS_SCHEDULER_KEYS = ["scheduleType", "startDate", "startTime", @@ -53,6 +61,7 @@ QOS_SCHEDULER_DEFAULT_TYPE = "0" QOS_SCHEDULER_WEEK_TYPE = "3" QOS_SUPPORT_SCHEDULE_VERSION = "8.0" +QOS_MAX_INTERCEPT_LENGTH = 36 SECONDS_OF_DAY = 24 * 60 * 60 SECONDS_OF_HOUR = 60 * 60 SNAPSHOT_HEALTH_STATUS = ( @@ -80,3 +89,9 @@ HOSTGROUP_ALREADY_EXIST = 50157044 INITIATOR_ALREADY_EXIST = 50155102 INITIATOR_IN_HOST = 50157021 + +CHECK_CLONED_INTERVAL = 2 +REST_VOLUME_CREATING_STATUS = 15 +REST_VOLUME_DUPLICATE_VOLUME = 6 +REST_VOLUME_CREATE_SUCCESS_STATUS = 0 +CLONE_VOLUME_TIMEOUT = 3600 * 24 * 30 diff --git a/Cinder/Zed/dsware.py b/Cinder/Zed/dsware.py index 75e1808..b03e039 100644 --- a/Cinder/Zed/dsware.py +++ b/Cinder/Zed/dsware.py @@ -14,16 +14,22 @@ # under the License. import json - +import time +import uuid from multiprocessing import Lock + +import six from oslo_config import cfg from oslo_log import log as logging +from oslo_utils import excutils from oslo_utils import units +from oslo_service import loopingcall from cinder import coordination from cinder import exception from cinder.i18n import _ from cinder import interface +from cinder import objects from cinder.volume import driver from cinder.volume.drivers.fusionstorage import constants from cinder.volume.drivers.fusionstorage import fs_client @@ -105,6 +111,9 @@ cfg.StrOpt('storage_key_filepath', default='', help='Client key directory.'), + cfg.BoolOpt('full_clone', + default=False, + help='Whether use full clone.'), ] CONF = cfg.CONF @@ -113,7 +122,7 @@ @interface.volumedriver class DSWAREBaseDriver(driver.VolumeDriver): - VERSION = '2.5.RC4' + VERSION = "2.6.1" CI_WIKI_NAME = 'Huawei_FusionStorage_CI' def __init__(self, *args, **kwargs): @@ -210,6 +219,7 @@ def _update_single_pool_info_status(self, pool_info): "total_capacity_gb": capacity['total_capacity_gb'], "free_capacity_gb": capacity['free_capacity_gb'], "provisioned_capacity_gb": capacity['provisioned_capacity_gb'], + "location_info": self.client.esn, "QoS_support": True, 'multiattach': True, "thin_provisioning_support": True, @@ -247,8 +257,12 @@ def _raise_exception(msg): raise exception.VolumeBackendAPIException(data=msg) def _get_pool_id(self, volume): - pool_id_list = [] pool_name = volume_utils.extract_host(volume.host, level='pool') + pool_id = self._get_pool_id_by_name(pool_name) + return pool_id + + def _get_pool_id_by_name(self, pool_name): + pool_id_list = [] all_pools = self.client.query_pool_info() for pool in all_pools: if pool_name == pool['poolName']: @@ -363,29 +377,111 @@ def _expand_volume_when_create(self, vol_name, vol_size): self.client.delete_volume(vol_name=vol_name) raise + def _check_create_cloned_volume_finish(self, new_volume_name, start_time): + LOG.debug('Loopcall: _check_create_cloned_volume_finish(), ' + 'volume-name %s', + new_volume_name) + current_volume = self.client.query_volume_by_name(new_volume_name) + + if current_volume and 'status' in current_volume: + status = int(current_volume['status']) + LOG.debug('Wait clone volume %(volume_name)s, status:%(status)s.', + {"volume_name": new_volume_name, + "status": status}) + if status in {constants.REST_VOLUME_CREATING_STATUS, + constants.REST_VOLUME_DUPLICATE_VOLUME}: + LOG.debug(_("Volume %s is cloning"), new_volume_name) + elif status == constants.REST_VOLUME_CREATE_SUCCESS_STATUS: + raise loopingcall.LoopingCallDone(retvalue=True) + else: + msg = _('Clone volume %(new_volume_name)s failed, ' + 'the status is:%(status)s.') + LOG.error(msg, {'new_volume_name': new_volume_name, + 'status': status}) + raise loopingcall.LoopingCallDone(retvalue=False) + + max_time_out = constants.CLONE_VOLUME_TIMEOUT + current_time = time.time() + if (current_time - start_time) > max_time_out: + msg = _('Dsware clone volume time out. ' + 'Volume: %(new_volume_name)s, status: %(status)s') + LOG.error(msg, {'new_volume_name': new_volume_name, + 'status': current_volume['status']}) + raise loopingcall.LoopingCallDone(retvalue=False) + else: + LOG.warning(_('Can not find volume %s'), new_volume_name) + msg = "DSWARE clone volume failed:volume can not find from dsware" + LOG.error(msg) + raise loopingcall.LoopingCallDone(retvalue=False) + + def _wait_for_create_cloned_volume_finish_timer(self, new_volume_name): + timer = loopingcall.FixedIntervalLoopingCall( + self._check_create_cloned_volume_finish, + new_volume_name, time.time()) + LOG.debug('Calling _check_create_cloned_volume_finish: volume-name %s', + new_volume_name) + ret = timer.start(interval=constants.CHECK_CLONED_INTERVAL).wait() + timer.stop() + return ret + def create_volume_from_snapshot(self, volume, snapshot): vol_name = self._get_vol_name(volume) snapshot_name = self._get_snapshot_name(snapshot) vol_size = volume.size + pool_id = self._get_pool_id(volume) if not self._check_snapshot_exist(snapshot.volume, snapshot): msg = _("Snapshot: %(name)s does not exist!" ) % {"name": snapshot_name} self._raise_exception(msg) - elif self._check_volume_exist(volume): + if self._check_volume_exist(volume): msg = _("Volume: %(vol_name)s already exists!" ) % {'vol_name': vol_name} self._raise_exception(msg) - else: - vol_size *= units.Ki + + vol_size *= units.Ki + if not self.configuration.full_clone: self.client.create_volume_from_snapshot( snapshot_name=snapshot_name, vol_name=vol_name, vol_size=vol_size) - self._add_qos_to_volume(volume, vol_name) - self._expand_volume_when_create(vol_name, vol_size) - result = self.client.query_volume_by_name(vol_name=vol_name) - return ({"metadata": {'lun_wwn': result.get('wwn')}} - if result else {}) + else: + self.client.create_volume(vol_name, vol_size, pool_id) + self.client.create_full_volume_from_snapshot(vol_name, + snapshot_name) + ret = self._wait_for_create_cloned_volume_finish_timer(vol_name) + if not ret: + msg = _('Create full volume %s from snap failed') % vol_name + self._raise_exception(msg) + self._add_qos_to_volume(volume, vol_name) + self._expand_volume_when_create(vol_name, vol_size) + result = self.client.query_volume_by_name(vol_name=vol_name) + return ({"metadata": {'lun_wwn': result.get('wwn')}} + if result else {}) + + def _create_volume_from_volume_full_clone(self, vol_name, vol_size, pool_id, + src_vol_name): + tmp_snap_name = "temp" + src_vol_name + "clone" + vol_name + + self.client.create_snapshot(tmp_snap_name, src_vol_name) + try: + self.client.create_volume(vol_name, vol_size, pool_id) + except Exception as err: + self.client.delete_snapshot(tmp_snap_name) + raise err + + try: + self.client.create_full_volume_from_snapshot( + vol_name, tmp_snap_name) + except Exception as err: + self.client.delete_snapshot(tmp_snap_name) + self.client.delete_volume(vol_name) + raise err + + ret = self._wait_for_create_cloned_volume_finish_timer(vol_name) + if not ret: + msg = _('Create full volume %s from snap failed') % vol_name + self._raise_exception(msg) + self.client.delete_snapshot(tmp_snap_name) def create_cloned_volume(self, volume, src_volume): vol_name = self._get_vol_name(volume) @@ -398,15 +494,22 @@ def create_cloned_volume(self, volume, src_volume): msg = _("Volume: %(vol_name)s does not exist!" ) % {"vol_name": src_vol_name} self._raise_exception(msg) - else: + + if not self.configuration.full_clone: self.client.create_volume_from_volume( vol_name=vol_name, vol_size=vol_size, src_vol_name=src_vol_name) - self._add_qos_to_volume(volume, vol_name) - self._expand_volume_when_create(vol_name, vol_size) - result = self.client.query_volume_by_name(vol_name=vol_name) - return ({"metadata": {'lun_wwn': result.get('wwn')}} - if result else {}) + else: + pool_id = self._get_pool_id(volume) + self._create_volume_from_volume_full_clone( + vol_name=vol_name, vol_size=vol_size, pool_id=pool_id, + src_vol_name=src_vol_name) + + self._add_qos_to_volume(volume, vol_name) + self._expand_volume_when_create(vol_name, vol_size) + result = self.client.query_volume_by_name(vol_name=vol_name) + return ({"metadata": {'lun_wwn': result.get('wwn')}} + if result else {}) def create_snapshot(self, snapshot): snapshot_name = self._get_snapshot_name(snapshot) @@ -581,12 +684,13 @@ def unmanage_snapshot(self, snapshot): def _check_need_changes_for_retype(self, volume, new_type, host, vol_name): before_change = {} after_change = {} - if volume.host != host["host"]: - msg = (_("Do not support retype between different host. Volume's " + migrate = False + if volume.host != host.get("host"): + migrate = True + msg = (_("retype support migration between different host. Volume's " "host: %(vol_host)s, host's host: %(host)s") - % {"vol_host": volume.host, "host": host['host']}) - LOG.error(msg) - raise exception.InvalidInput(msg) + % {"vol_host": volume.host, "host": host.get("host")}) + LOG.info(msg) old_opts = fs_utils.get_volume_specs(self.client, vol_name) new_opts = fs_utils.get_volume_type_params(new_type, self.client) @@ -596,7 +700,7 @@ def _check_need_changes_for_retype(self, volume, new_type, host, vol_name): change_opts = {"old_opts": before_change, "new_opts": after_change} - return change_opts + return migrate, change_opts def retype(self, context, volume, new_type, diff, host): LOG.info("Retype volume: %(vol)s, new_type: %(new_type)s, " @@ -607,13 +711,177 @@ def retype(self, context, volume, new_type, diff, host): "host": host}) vol_name = self._get_vol_name(volume) - change_opts = self._check_need_changes_for_retype( + migrate, change_opts = self._check_need_changes_for_retype( volume, new_type, host, vol_name) + if migrate: + src_lun_id = self._check_volume_exist_on_array(volume) + LOG.debug("Begin to migrate LUN(id: %(lun_id)s) with " + "change %(change_opts)s.", + {"lun_id": src_lun_id, "change_opts": change_opts}) + moved = self._migrate_volume(volume, host, src_lun_id) + if not moved: + LOG.warning("Storage-assisted migration failed during " + "retype.") + return False, None self._change_lun(vol_name, change_opts.get("new_opts"), change_opts.get("old_opts")) return True, None + def migrate_volume(self, context, volume, host): + """Migrate a volume within the same array.""" + LOG.info("Migrate Volume:%(volume)s, host:%(host)s", + {"volume": volume.id, + "host": host}) + src_lun_id = self._check_volume_exist_on_array(volume) + + moved = self._migrate_volume(volume, host, src_lun_id) + return moved, {} + + def _create_dst_volume(self, volume, host): + pool_name = host['capabilities']['pool_name'] + pool_id = self._get_pool_id_by_name(pool_name) + vol_name = fs_utils.encode_name(six.text_type(uuid.uuid4())) + vol_size = volume.size + vol_size *= units.Ki + self.client.create_volume( + pool_id=pool_id, vol_name=vol_name, vol_size=vol_size) + + result = self.client.query_volume_by_name_v2(vol_name=vol_name) + dst_lun_id = result.get('id') + self._wait_volume_ready(vol_name) + return vol_name, dst_lun_id + + def _migrate_volume(self, volume, host, src_lun_id): + """create migration task and wait for task done""" + if not self._check_migration_valid(host): + return False + + vol_name, dst_lun_id = self._create_dst_volume(volume, host) + + try: + self.client.create_lun_migration(src_lun_id, dst_lun_id) + + def _is_lun_migration_complete(): + return self._is_lun_migration_complete(src_lun_id, dst_lun_id) + + wait_interval = constants.MIGRATION_WAIT_INTERVAL + fs_utils.wait_for_condition(_is_lun_migration_complete, + wait_interval, + constants.DEFAULT_WAIT_TIMEOUT) + # Clean up if migration failed. + except Exception as ex: + raise exception.VolumeBackendAPIException(data=ex) + finally: + if self._is_lun_migration_exist(src_lun_id, dst_lun_id): + self.client.delete_lun_migration(src_lun_id) + self._delete_lun_with_check(vol_name) + + LOG.info("Migrate lun %s successfully.", src_lun_id) + return True + + def _delete_lun_with_check(self, vol_name): + if self.client.query_volume_by_name(vol_name): + # migrate_dst_lun don't have qos, so don't + # need to remove qos, Delete the LUN directly. + self.client.delete_volume(vol_name) + + def _is_lun_migration_complete(self, src_lun_id, dst_lun_id): + result = self.client.get_lun_migration_task_by_id(src_lun_id) + found_migration_task = False + if not result: + return False + + if (str(src_lun_id) == result.get('parent_id') and + str(dst_lun_id) == result.get('target_lun_id')): + found_migration_task = True + if constants.MIGRATION_COMPLETE == result.get('running_status'): + return True + if constants.MIGRATION_FAULT == result.get('running_status'): + msg = _("Lun migration error. " + "the migration task running_status is abnormal") + LOG.error(msg) + raise exception.VolumeBackendAPIException(data=msg) + + if not found_migration_task: + err_msg = _("lun migration error, Cannot find migration task.") + LOG.error(err_msg) + raise exception.VolumeBackendAPIException(data=err_msg) + + return False + + def _is_lun_migration_exist(self, src_lun_id, dst_lun_id): + try: + result = self.client.get_lun_migration_task_by_id(src_lun_id) + except Exception: + LOG.error("Get LUN migration error.") + return False + + if (str(src_lun_id) == result.get('parent_id') and + str(dst_lun_id) == result.get('target_lun_id')): + return True + return False + + def _wait_volume_ready(self, vol_name): + wait_interval = constants.DEFAULT_WAIT_INTERVAL + + def _volume_ready(): + result = self.client.query_volume_by_name_v2(vol_name) + if not result: + return False + + if (result.get('health_status') == constants.STATUS_HEALTH + and result.get('running_status') == constants.STATUS_VOLUME_READY): + return True + return False + + fs_utils.wait_for_condition(_volume_ready, + wait_interval, + wait_interval * 10) + + def _check_migration_valid(self, host): + if 'pool_name' not in host.get('capabilities', {}): + return False + + target_device = host.get('capabilities', {}).get('location_info') + + # Source and destination should be on same array. + if target_device != self.client.esn: + LOG.error("lun migration error, " + "Source and destination should be on same array") + return False + + pool_name = host.get('capabilities', {}).get('pool_name', '') + if len(pool_name) == 0: + LOG.error("lun migration error, pool_name not exists") + return False + + return True + + def _check_volume_exist_on_array(self, volume): + volume_name = self._get_vol_name(volume) + result = self._check_volume_exist(volume) + if not result: + msg = _("Volume %s does not exist on the array." + ) % volume.id + self._raise_exception(msg) + + lun_wwn = result.get('wwn') + if not lun_wwn: + LOG.debug("No LUN WWN recorded for volume %s.", volume.id) + + lun_id = result.get('volId') + if not lun_id: + msg = _("Volume %s does not exist on the array." + ) % volume.id + self._raise_exception(msg) + + if self.client.get_volume_snapshot(volume_name): + msg = _("Volume %s which have snapshot cannot do lun migration" + ) % volume.id + self._raise_exception(msg) + return lun_id + def _rollback_snapshot(self, vol_name, snap_name): def _snapshot_rollback_finish(): snapshot_info = self.client.get_snapshot_info_by_name(snap_name) @@ -669,6 +937,265 @@ def ensure_export(self, context, volume): def remove_export(self, context, volume): pass + def create_group(self, context, group): + """Creates a group. Driver only need to return state""" + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.create_consistencygroup(context, group) + + def create_consistencygroup(self, context, group): + """Creates a group. Driver only need to return state""" + LOG.info("Create group successfully") + return {'status': 'available'} + + def update_group(self, context, group, + add_volumes=None, remove_volumes=None): + """ + The volume manager will adds/removes the volume to/from the + group in the database, if need add_volumes, Driver just need + to check whether volume is in array or not + """ + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.update_consistencygroup( + context, group, add_volumes, remove_volumes) + + def update_consistencygroup(self, context, group, + add_volumes=None, remove_volumes=None): + """ + The volume manager will adds/removes the volume to/from the + group in the database, if need add_volumes, Driver just need + to check whether volume is in array or not + """ + if add_volumes is None: + add_volumes = [] + for volume in add_volumes: + try: + self._check_volume_exist_on_array(volume) + except Exception: + with excutils.save_and_reraise_exception(): + LOG.error("The add_volume %s not exist on array" % volume.id) + + model_update = {'status': 'available'} + LOG.info("Update group successfully") + return model_update, None, None + + def delete_group(self, context, group, volumes): + """delete the group, Driver need to delete relation lun on array""" + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.delete_consistencygroup(context, group, volumes) + + def delete_consistencygroup(self, context, group, volumes): + """delete the group, Driver need to delete relation lun on array""" + volumes_model_update = [] + model_update = {'status': 'deleted'} + for volume in volumes: + volume_model_update = {'id': volume.id} + try: + self.delete_volume(volume) + except Exception: + LOG.error('Delete volume %s failed.' % volume) + volume_model_update.update({'status': 'error_deleting'}) + else: + volume_model_update.update({'status': 'deleted'}) + + LOG.info('Deleted volume %s successfully' % volume) + volumes_model_update.append(volume_model_update) + + LOG.info("Delete group successfully") + return model_update, volumes_model_update + + def create_group_from_src(self, context, group, volumes, + group_snapshot=None, snapshots=None, + source_group=None, source_vols=None): + """ + create group from group or group-snapshot, + Driver need to create volume from volume or snapshot + """ + if not volume_utils.is_group_a_cg_snapshot_type(group): + LOG.info("Group's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.create_consistencygroup_from_src(context, group, volumes, + group_snapshot, snapshots, + source_group, source_vols) + + def create_consistencygroup_from_src(self, context, group, volumes, + group_snapshot=None, snapshots=None, + source_group=None, source_vols=None): + """ + create group from group or group-snapshot, + Driver need to create volume from volume or snapshot + """ + model_update = self.create_consistencygroup(context, group) + volumes_model_update = [] + delete_snapshots = False + + if not snapshots and source_vols: + snapshots = [] + for src_volume in source_vols: + volume_kwargs = { + 'id': src_volume.id, + '_name_id': None, + 'host': src_volume.host + } + snapshot_kwargs = { + 'id': six.text_type(uuid.uuid4()), + 'volume': objects.Volume(**volume_kwargs) + } + snapshots.append(objects.Snapshot(**snapshot_kwargs)) + + self._create_group_snapshot(snapshots) + delete_snapshots = True + + if snapshots: + volumes_model_update = self._create_volume_from_group_snapshot( + volumes, snapshots, delete_snapshots) + + if delete_snapshots: + self._delete_group_snapshot(snapshots) + + LOG.info("Create group from src successfully") + return model_update, volumes_model_update + + def _create_volume_from_group_snapshot(self, volumes, snapshots, delete_snapshots): + volumes_model_update = [] + added_volumes = [] + for i, volume in enumerate(volumes): + try: + vol_model_update = self.create_volume_from_snapshot( + volume, snapshots[i]) + vol_model_update.update({'id': volume.id}) + volumes_model_update.append(vol_model_update) + added_volumes.append(volume) + except Exception: + LOG.error("Create volume from snapshot error, Delete the newly created lun.") + with excutils.save_and_reraise_exception(): + self._delete_added_volume_snapshots( + added_volumes, snapshots, delete_snapshots) + + return volumes_model_update + + def _delete_added_volume_snapshots( + self, added_volumes, snapshots, delete_snapshots): + if delete_snapshots: + self._delete_group_snapshot(snapshots) + for add_volume in added_volumes: + vol_name = self._get_vol_name(add_volume) + self.fs_qos.remove(vol_name) + self.client.delete_volume(vol_name=vol_name) + LOG.info("delete storage newly added " + "volume success, volume is %s" % add_volume.id) + + def create_group_snapshot(self, context, group_snapshot, snapshots): + """Create group snapshot.""" + if not volume_utils.is_group_a_cg_snapshot_type(group_snapshot): + LOG.info("group_snapshot's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.create_cgsnapshot(context, group_snapshot, snapshots) + + def create_cgsnapshot(self, context, group_snapshot, snapshots): + """Create group snapshot.""" + LOG.info('Create group snapshot for group: %(group_snapshot)s', + {'group_snapshot': group_snapshot}) + + try: + snapshots_model_update = self._create_group_snapshot(snapshots) + except Exception as err: + msg = ("Create group snapshots failed. " + "Group snapshot id: %s. Reason is %s") % (group_snapshot.id, err) + LOG.error(msg) + raise exception.CinderException(msg) + + model_update = {'status': 'available'} + return model_update, snapshots_model_update + + def _create_group_snapshot(self, snapshots): + """Generate snapshots for all volumes in the group.""" + snapshots_model_update = [] + snapshot_group_list = [] + + for snapshot in snapshots: + snapshot_name = self._get_snapshot_name(snapshot) + vol_name = self._get_vol_name(snapshot.volume) + snapshot_group_list.append({ + 'name': snapshot_name, + 'sub_type': '0', + 'volume_name': vol_name + }) + snapshot_model_update = { + 'id': snapshot.id, + 'status': 'available', + } + snapshots_model_update.append(snapshot_model_update) + try: + self.client.create_consistent_snapshot_by_name(snapshot_group_list) + except Exception: + with excutils.save_and_reraise_exception(): + LOG.error("Create consistent snapshot failed, " + "snapshot_group_list is %s" % snapshot_group_list) + + return snapshots_model_update + + def delete_group_snapshot(self, context, group_snapshot, snapshots): + """Delete group snapshot.""" + if not volume_utils.is_group_a_cg_snapshot_type(group_snapshot): + LOG.info("group_snapshot's type is not a " + "consistent snapshot group enabled type") + raise NotImplementedError() + + return self.delete_cgsnapshot(context, group_snapshot, snapshots) + + def delete_cgsnapshot(self, context, group_snapshot, snapshots): + """Delete group snapshot.""" + LOG.info("Delete group_snapshot %s for " + "consistency group: %s" % (group_snapshot.id, group_snapshot)) + + try: + snapshots_model_update = self._delete_group_snapshot(snapshots) + except Exception as err: + msg = ("Delete cg snapshots failed. " + "group snapshot id: %s, reason is %s") % (group_snapshot.id, err) + LOG.error(msg) + raise exception.CinderException(msg) + + model_update = {'status': 'deleted'} + return model_update, snapshots_model_update + + def _delete_group_snapshot(self, snapshots): + """Delete all snapshots in snapshot group""" + snapshots_model_update = [] + for snapshot in snapshots: + snapshot_model_update = { + 'id': snapshot.id, + 'status': 'deleted' + } + snapshots_model_update.append(snapshot_model_update) + snapshot_name = self._get_snapshot_name(snapshot) + + if not self._check_snapshot_exist(snapshot.volume, snapshot): + LOG.info("snapshot %s not exist in array, " + "don't need to delete, try next one" % snapshot_name) + continue + self.client.delete_snapshot(snapshot_name=snapshot_name) + LOG.info("Delete snapshot successfully," + " the deleted snapshots is %s" % snapshot_name) + + return snapshots_model_update + class DSWAREDriver(DSWAREBaseDriver): def get_volume_stats(self, refresh=False): @@ -721,7 +1248,7 @@ def initialize_connection(self, volume, connector): vol_wwn = volume_info.get('wwn') by_id_path = "/dev/disk/by-id/" + "wwn-0x%s" % vol_wwn properties = {'device_path': by_id_path} - import time + LOG.info("Wait %(t)s second(s) for scanning the target device %(dev)s." % {"t": self.configuration.scan_device_timeout, "dev": by_id_path}) diff --git a/Cinder/Zed/fs_client.py b/Cinder/Zed/fs_client.py index 234d7f1..09d9581 100644 --- a/Cinder/Zed/fs_client.py +++ b/Cinder/Zed/fs_client.py @@ -14,16 +14,16 @@ # under the License. import json + import requests import six -import time +from oslo_log import log as logging from requests.adapters import HTTPAdapter from cinder import exception from cinder.i18n import _ from cinder.volume.drivers.fusionstorage import constants -from oslo_log import log as logging LOG = logging.getLogger(__name__) @@ -43,7 +43,8 @@ def __init__(self, fs_address, fs_user, fs_password, **extend_conf): self.session = None self.token = None self.version = None - mutual_authentication = extend_conf.get("mutual_authentication") + self.esn = None + mutual_authentication = extend_conf.get("mutual_authentication", {}) self.init_http_head(mutual_authentication) LOG.warning("Suppressing requests library SSL Warnings") @@ -147,6 +148,13 @@ def get_version(self): if result.get("currentVersion"): self.version = result["currentVersion"] + def get_esn(self): + url = "/cluster/sn" + result = self.call(url, "get") + self._assert_rest_result(result, _('Get cluster esn error.')) + self.esn = result.get("sn") + return self.esn + def login(self): self.get_version() url = '/sec/login' @@ -160,6 +168,7 @@ def login(self): self.session.headers.update({ "x-auth-token": self.token }) + self.get_esn() def logout(self): url = '/sec/logout' @@ -264,6 +273,15 @@ def query_volume_by_name(self, vol_name): result, _("Query volume by name session error")) return result.get('lunDetailInfo') + def query_volume_by_name_v2(self, vol_name): + url = '/api/v2/block_service/volumes?name=' + vol_name + result = self.call(url, 'GET', get_system_time=True) + if result.get('errorCode') in constants.VOLUME_NOT_EXIST: + return {} + self._assert_rest_result( + result, _("Query volume by name session error")) + return result.get('data', {}) + def query_volume_by_id(self, vol_id): url = 'v1.3/volume/queryById?volId=' + vol_id result = self.call(url, 'GET', get_version=True) @@ -746,3 +764,57 @@ def get_iscsi_links_info(self, iscsi_link_count, pool_list): return [iscsi["ip"] for iscsi in result.get("iscsiLinks", []) if iscsi.get("ip")] + + def create_lun_migration(self, src_lun_id, dst_lun_id, speed=2): + url = "/api/v2/block_service/lun_migration" + params = { + "parent_id": src_lun_id, + "target_lun_id": dst_lun_id, + "speed": speed, + "work_mode": 0 + } + result = self.call(url, "POST", params, get_system_time=True) + self._assert_rest_result(result, + _("create lun migration task error.")) + + def get_lun_migration_task_by_id(self, src_lun_id): + url = "/api/v2/block_service/lun_migration" + params = { + "id": src_lun_id + } + result = self.call(url, "GET", params, get_system_time=True) + self._assert_rest_result(result, + _("get lun migration task error.")) + return result.get('data', {}) + + def delete_lun_migration(self, src_lun_id): + url = "/api/v2/block_service/lun_migration" + params = { + 'id': src_lun_id + } + result = self.call(url, "DELETE", params, get_system_time=True) + self._assert_rest_result(result, + _("Delete lun migration task error.")) + + def get_volume_snapshot(self, volume_name): + url = "/volume/snapshot/list" + params = { + 'volName': volume_name, + 'batchNum': 1, + 'batchLimit': 10 + } + result = self.call(url, "POST", params) + return result.get('snapshotList', []) + + def create_consistent_snapshot_by_name(self, snapshot_group_list): + url = "/api/v2/block_service/consistency_snapshots" + result = self.call(url, "POST", snapshot_group_list, get_system_time=True) + self._assert_rest_result(result, _("create consistent_snapshot error.")) + return result.get('data', []) + + def create_full_volume_from_snapshot(self, vol_name, snapshot_name): + url = '/api/v2/block_service/createFullVolumeFromSnap' + params = {"snap_name_src": snapshot_name, "volume_name_dst": vol_name} + result = self.call(url, "POST", params, get_system_time=True) + self._assert_rest_result( + result, _("create full volume from snap fails")) diff --git a/Cinder/Zed/fs_qos.py b/Cinder/Zed/fs_qos.py index 731c45e..286dbc3 100644 --- a/Cinder/Zed/fs_qos.py +++ b/Cinder/Zed/fs_qos.py @@ -29,7 +29,11 @@ def __init__(self, client): def add(self, qos, vol_name): localtime = time.strftime('%Y%m%d%H%M%S', time.localtime()) - qos_name = constants.QOS_PREFIX + localtime + # QoS policy name. The value contains 1 to 63 characters. + # So we intercept volume_name Ensure that the length does not exceed 63 + vol_str = vol_name[-constants.QOS_MAX_INTERCEPT_LENGTH::] \ + if len(vol_name) >= constants.QOS_MAX_INTERCEPT_LENGTH else vol_name + qos_name = constants.QOS_PREFIX + localtime + '_' + vol_str self.client.create_qos(qos_name, qos) try: self.client.associate_qos_with_volume(vol_name, qos_name) diff --git a/Cinder/Zed/fs_utils.py b/Cinder/Zed/fs_utils.py index 8b9ae78..0856038 100644 --- a/Cinder/Zed/fs_utils.py +++ b/Cinder/Zed/fs_utils.py @@ -16,11 +16,11 @@ import datetime import hashlib import ipaddress -import pytz import random -import six import time +import pytz +import six from oslo_log import log as logging from oslo_service import loopingcall from oslo_utils import units @@ -758,3 +758,9 @@ def get_iscsi_info_from_storage(manager_ips, use_ipv6, valid_iscsi_ips, valid_node_ips): return _get_target_info(manager_ips, use_ipv6, valid_iscsi_ips, valid_node_ips) + + +def encode_name(my_uuid): + encoded_name = hashlib.md5(my_uuid.encode('utf-8')).hexdigest() + target_lun_prefix = my_uuid.split('-')[0] + '-' + return target_lun_prefix + encoded_name diff --git a/ReleaseDoc/en/FusionStorage OpenStack Driver Configuration Guide.pdf b/ReleaseDoc/en/FusionStorage OpenStack Driver Configuration Guide.pdf index 233eb82e302ddf39214654eecd0ab7845b5dab26..f12919ab6012e2c6a372e39b7e03fdfbde9d5ea6 100644 GIT binary patch delta 133980 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

5>OW&^lHGSvELiKvybp#Fh!-G|*ufvH3Z6z6z6 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

C2ud+D{;eH8-84A%LaD^$ehn(r)KX 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%0DV-(i=!j}+pn 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 G@P7auTCK_e delta 189844 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%0A@~_;N!?P$F#e; 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

-k65xYy{ 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%0DyNz_(m>=VYumb~I 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