Huawei: Backend capabilies report optimization

Huawei backend reporting capabilities optimize. Huawei backend
reporting capabilities will be changed when huawei array License
is the failure. Driver will modify the processing module on the
create\manage\migrate\retype and so on. We will output the array
does not support this feature in the log file.

Also remove mock_sleep which will cause Jenkins error.

Implements: blueprint huawei-backend-capabilities-report-optimization
Change-Id: I33320cc01cd93c09ec3a868bfe0182bcb2114b17
This commit is contained in:
liuke2 2016-07-04 16:35:55 +08:00 committed by huananhuawei
parent 5e128a5740
commit c557f3bd91
5 changed files with 869 additions and 127 deletions

View File

@ -84,7 +84,7 @@ UPPER_LIMIT_KEYS = ['MAXIOPS', 'MAXBANDWIDTH']
MAX_LUN_NUM_IN_QOS = 64 MAX_LUN_NUM_IN_QOS = 64
DEFAULT_REPLICA_WAIT_INTERVAL = 1 DEFAULT_REPLICA_WAIT_INTERVAL = 1
DEFAULT_REPLICA_WAIT_TIMEOUT = 10 DEFAULT_REPLICA_WAIT_TIMEOUT = 20
REPLICA_SYNC_MODEL = '1' REPLICA_SYNC_MODEL = '1'
REPLICA_ASYNC_MODEL = '2' REPLICA_ASYNC_MODEL = '2'

View File

@ -94,9 +94,17 @@ class HuaweiBaseDriver(driver.VolumeDriver):
self.configuration.append_config_values(huawei_opts) self.configuration.append_config_values(huawei_opts)
self.huawei_conf = huawei_conf.HuaweiConf(self.configuration) self.huawei_conf = huawei_conf.HuaweiConf(self.configuration)
self.support_func = None
self.metro_flag = False self.metro_flag = False
self.replica = None self.replica = None
def check_func_support(self, obj_name):
try:
self.client._get_object_count(obj_name)
return True
except Exception:
return False
def get_local_and_remote_dev_conf(self): def get_local_and_remote_dev_conf(self):
self.loc_dev_conf = self.huawei_conf.get_local_device() self.loc_dev_conf = self.huawei_conf.get_local_device()
@ -161,7 +169,7 @@ class HuaweiBaseDriver(driver.VolumeDriver):
"""Get volume status and reload huawei config file.""" """Get volume status and reload huawei config file."""
self.huawei_conf.update_config_value() self.huawei_conf.update_config_value()
stats = self.client.update_volume_stats() stats = self.client.update_volume_stats()
stats = self.update_hypermetro_capability(stats) stats = self.update_support_capability(stats)
if self.replica: if self.replica:
stats = self.replica.update_replica_capability(stats) stats = self.replica.update_replica_capability(stats)
@ -171,15 +179,29 @@ class HuaweiBaseDriver(driver.VolumeDriver):
return stats return stats
def update_hypermetro_capability(self, stats): def update_support_capability(self, stats):
if self.metro_flag: for pool in stats['pools']:
version = self.client.find_array_version() pool['smartpartition'] = (
rmt_version = self.rmt_client.find_array_version() self.check_func_support("SMARTCACHEPARTITION"))
if (version >= constants.ARRAY_VERSION pool['smartcache'] = self.check_func_support("smartcachepool")
and rmt_version >= constants.ARRAY_VERSION): pool['QoS_support'] = self.check_func_support("ioclass")
for pool in stats['pools']: pool['splitmirror'] = self.check_func_support("splitmirror")
pool['hypermetro'] = True pool['luncopy'] = self.check_func_support("luncopy")
pool['consistencygroup_support'] = True pool['thick_provisioning_support'] = True
pool['thin_provisioning_support'] = True
pool['smarttier'] = True
if self.configuration.san_product == "Dorado":
pool['smarttier'] = False
pool['thick_provisioning_support'] = False
if self.metro_flag:
pool['hypermetro'] = self.check_func_support("HyperMetroPair")
pool['consistencygroup_support'] = (
self.check_func_support("HyperMetro_ConsistentGroup"))
# Asign the support function to global paramenter.
self.support_func = pool
return stats return stats
@ -335,8 +357,13 @@ class HuaweiBaseDriver(driver.VolumeDriver):
try: try:
qos = smartx.SmartQos.get_qos_by_volume_type(volume_type) qos = smartx.SmartQos.get_qos_by_volume_type(volume_type)
if qos: if qos:
smart_qos = smartx.SmartQos(self.client) if not self.support_func.get('QoS_support'):
smart_qos.add(qos, lun_id) msg = (_("Can't support qos on the array"))
LOG.error(msg)
raise exception.VolumeBackendAPIException(data=msg)
else:
smart_qos = smartx.SmartQos(self.client)
smart_qos.add(qos, lun_id)
smartpartition = smartx.SmartPartition(self.client) smartpartition = smartx.SmartPartition(self.client)
smartpartition.add(opts, lun_id) smartpartition.add(opts, lun_id)
@ -425,10 +452,11 @@ class HuaweiBaseDriver(driver.VolumeDriver):
if not lun_id: if not lun_id:
return return
qos_id = self.client.get_qosid_by_lunid(lun_id) if self.support_func.get('QoS_support'):
if qos_id: qos_id = self.client.get_qosid_by_lunid(lun_id)
smart_qos = smartx.SmartQos(self.client) if qos_id:
smart_qos.remove(qos_id, lun_id) smart_qos = smartx.SmartQos(self.client)
smart_qos.remove(qos_id, lun_id)
metadata = huawei_utils.get_volume_metadata(volume) metadata = huawei_utils.get_volume_metadata(volume)
if 'hypermetro_id' in metadata: if 'hypermetro_id' in metadata:
@ -461,10 +489,11 @@ class HuaweiBaseDriver(driver.VolumeDriver):
return return
if self.client.check_lun_exist(lun_id, lun_wwn): if self.client.check_lun_exist(lun_id, lun_wwn):
qos_id = self.client.get_qosid_by_lunid(lun_id) if self.support_func.get('QoS_support'):
if qos_id: qos_id = self.client.get_qosid_by_lunid(lun_id)
smart_qos = smartx.SmartQos(self.client) if qos_id:
smart_qos.remove(qos_id, lun_id) smart_qos = smartx.SmartQos(self.client)
smart_qos.remove(qos_id, lun_id)
self.client.delete_lun(lun_id) self.client.delete_lun(lun_id)
@ -655,6 +684,10 @@ class HuaweiBaseDriver(driver.VolumeDriver):
'WRITECACHEPOLICY': lun_info['WRITECACHEPOLICY'], 'WRITECACHEPOLICY': lun_info['WRITECACHEPOLICY'],
'OWNINGCONTROLLER': lun_info['OWNINGCONTROLLER'], } 'OWNINGCONTROLLER': lun_info['OWNINGCONTROLLER'], }
for item in lun_params.keys():
if lun_params.get(item) == '--':
del lun_params[item]
lun_info = self.client.create_lun(lun_params) lun_info = self.client.create_lun(lun_params)
lun_id = lun_info['ID'] lun_id = lun_info['ID']
@ -1025,12 +1058,47 @@ class HuaweiBaseDriver(driver.VolumeDriver):
return lun_opts return lun_opts
def _check_capability_support(self, new_opts, new_type):
new_cache_name = new_opts['cachename']
if new_cache_name:
if not self.support_func.get('smartcache'):
msg = (_(
"Can't support cache on the array, cache name is: "
"%(name)s.") % {'name': new_cache_name})
LOG.error(msg)
raise exception.VolumeBackendAPIException(data=msg)
new_partition_name = new_opts['partitionname']
if new_partition_name:
if not self.support_func.get('smartpartition'):
msg = (_(
"Can't support partition on the array, partition name is: "
"%(name)s.") % {'name': new_partition_name})
LOG.error(msg)
raise exception.VolumeBackendAPIException(data=msg)
if new_opts['policy']:
if (not self.support_func.get('smarttier')
and new_opts['policy'] != '0'):
msg = (_("Can't support tier on the array."))
LOG.error(msg)
raise exception.VolumeBackendAPIException(data=msg)
new_qos = smartx.SmartQos.get_qos_by_volume_type(new_type)
if not self.support_func.get('QoS_support'):
if new_qos:
msg = (_("Can't support qos on the array."))
LOG.error(msg)
raise exception.VolumeBackendAPIException(data=msg)
def _check_needed_changes(self, lun_id, old_opts, new_opts, def _check_needed_changes(self, lun_id, old_opts, new_opts,
change_opts, new_type): change_opts, new_type):
new_cache_id = None new_cache_id = None
new_cache_name = new_opts['cachename'] new_cache_name = new_opts['cachename']
if new_cache_name: if new_cache_name:
new_cache_id = self.client.get_cache_id_by_name(new_cache_name) if self.support_func.get('smartcache'):
new_cache_id = self.client.get_cache_id_by_name(
new_cache_name)
if new_cache_id is None: if new_cache_id is None:
msg = (_( msg = (_(
"Can't find cache name on the array, cache name is: " "Can't find cache name on the array, cache name is: "
@ -1041,8 +1109,9 @@ class HuaweiBaseDriver(driver.VolumeDriver):
new_partition_id = None new_partition_id = None
new_partition_name = new_opts['partitionname'] new_partition_name = new_opts['partitionname']
if new_partition_name: if new_partition_name:
new_partition_id = self.client.get_partition_id_by_name( if self.support_func.get('smartpartition'):
new_partition_name) new_partition_id = self.client.get_partition_id_by_name(
new_partition_name)
if new_partition_id is None: if new_partition_id is None:
msg = (_( msg = (_(
"Can't find partition name on the array, partition name " "Can't find partition name on the array, partition name "
@ -1052,26 +1121,37 @@ class HuaweiBaseDriver(driver.VolumeDriver):
# smarttier # smarttier
if old_opts['policy'] != new_opts['policy']: if old_opts['policy'] != new_opts['policy']:
change_opts['policy'] = (old_opts['policy'], new_opts['policy']) if not (old_opts['policy'] == '--'
and new_opts['policy'] is None):
change_opts['policy'] = (old_opts['policy'],
new_opts['policy'])
# smartcache # smartcache
old_cache_id = old_opts['cacheid'] old_cache_id = old_opts['cacheid']
if old_cache_id == '--':
old_cache_id = None
if old_cache_id != new_cache_id: if old_cache_id != new_cache_id:
old_cache_name = None old_cache_name = None
if old_cache_id: if self.support_func.get('smartcache'):
cache_info = self.client.get_cache_info_by_id(old_cache_id) if old_cache_id:
old_cache_name = cache_info['NAME'] cache_info = self.client.get_cache_info_by_id(
old_cache_id)
old_cache_name = cache_info['NAME']
change_opts['cacheid'] = ([old_cache_id, old_cache_name], change_opts['cacheid'] = ([old_cache_id, old_cache_name],
[new_cache_id, new_cache_name]) [new_cache_id, new_cache_name])
# smartpartition # smartpartition
old_partition_id = old_opts['partitionid'] old_partition_id = old_opts['partitionid']
if old_partition_id == '--':
old_partition_id = None
if old_partition_id != new_partition_id: if old_partition_id != new_partition_id:
old_partition_name = None old_partition_name = None
if old_partition_id: if self.support_func.get('smartpartition'):
partition_info = self.client.get_partition_info_by_id( if old_partition_id:
old_partition_id) partition_info = self.client.get_partition_info_by_id(
old_partition_name = partition_info['NAME'] old_partition_id)
old_partition_name = partition_info['NAME']
change_opts['partitionid'] = ([old_partition_id, change_opts['partitionid'] = ([old_partition_id,
old_partition_name], old_partition_name],
[new_partition_id, [new_partition_id,
@ -1079,10 +1159,16 @@ class HuaweiBaseDriver(driver.VolumeDriver):
# smartqos # smartqos
new_qos = smartx.SmartQos.get_qos_by_volume_type(new_type) new_qos = smartx.SmartQos.get_qos_by_volume_type(new_type)
old_qos_id = self.client.get_qosid_by_lunid(lun_id) if not self.support_func.get('QoS_support'):
old_qos = self._get_qos_specs_from_array(old_qos_id) if new_qos:
if old_qos != new_qos: msg = (_("Can't support qos on the array."))
change_opts['qos'] = ([old_qos_id, old_qos], new_qos) LOG.error(msg)
raise exception.VolumeBackendAPIException(data=msg)
else:
old_qos_id = self.client.get_qosid_by_lunid(lun_id)
old_qos = self._get_qos_specs_from_array(old_qos_id)
if old_qos != new_qos:
change_opts['qos'] = ([old_qos_id, old_qos], new_qos)
return change_opts return change_opts
@ -1235,44 +1321,47 @@ class HuaweiBaseDriver(driver.VolumeDriver):
existing_ref=external_ref, reason=msg) existing_ref=external_ref, reason=msg)
# Check whether the LUN exists in a HyperMetroPair. # Check whether the LUN exists in a HyperMetroPair.
try: if self.support_func.get('hypermetro'):
hypermetro_pairs = self.client.get_hypermetro_pairs() try:
except exception.VolumeBackendAPIException: hypermetro_pairs = self.client.get_hypermetro_pairs()
hypermetro_pairs = [] except exception.VolumeBackendAPIException:
LOG.debug("Can't get hypermetro info, pass the check.") hypermetro_pairs = []
LOG.debug("Can't get hypermetro info, pass the check.")
for pair in hypermetro_pairs: for pair in hypermetro_pairs:
if pair.get('LOCALOBJID') == lun_id: if pair.get('LOCALOBJID') == lun_id:
msg = (_("Can't import LUN %s to Cinder. Already exists in a " msg = (_("Can't import LUN %s to Cinder. Already exists "
"HyperMetroPair.") % lun_id) "in a HyperMetroPair.") % lun_id)
raise exception.ManageExistingInvalidReference( raise exception.ManageExistingInvalidReference(
existing_ref=external_ref, reason=msg) existing_ref=external_ref, reason=msg)
# Check whether the LUN exists in a SplitMirror. # Check whether the LUN exists in a SplitMirror.
try: if self.support_func.get('splitmirror'):
split_mirrors = self.client.get_split_mirrors()
except exception.VolumeBackendAPIException as ex:
if re.search('License is unavailable', ex.msg):
# Can't check whether the LUN has SplitMirror with it,
# just pass the check and log it.
split_mirrors = []
LOG.warning(_LW('No license for SplitMirror.'))
else:
msg = _("Failed to get SplitMirror.")
raise exception.VolumeBackendAPIException(data=msg)
for mirror in split_mirrors:
try: try:
target_luns = self.client.get_target_luns(mirror.get('ID')) split_mirrors = self.client.get_split_mirrors()
except exception.VolumeBackendAPIException: except exception.VolumeBackendAPIException as ex:
msg = _("Failed to get target LUN of SplitMirror.") if re.search('License is unavailable', ex.msg):
raise exception.VolumeBackendAPIException(data=msg) # Can't check whether the LUN has SplitMirror with it,
# just pass the check and log it.
split_mirrors = []
LOG.warning(_LW('No license for SplitMirror.'))
else:
msg = _("Failed to get SplitMirror.")
raise exception.VolumeBackendAPIException(data=msg)
if (mirror.get('PRILUNID') == lun_id) or (lun_id in target_luns): for mirror in split_mirrors:
msg = (_("Can't import LUN %s to Cinder. Already exists in a " try:
"SplitMirror.") % lun_id) target_luns = self.client.get_target_luns(mirror.get('ID'))
raise exception.ManageExistingInvalidReference( except exception.VolumeBackendAPIException:
existing_ref=external_ref, reason=msg) msg = _("Failed to get target LUN of SplitMirror.")
raise exception.VolumeBackendAPIException(data=msg)
if ((mirror.get('PRILUNID') == lun_id)
or (lun_id in target_luns)):
msg = (_("Can't import LUN %s to Cinder. Already exists "
"in a SplitMirror.") % lun_id)
raise exception.ManageExistingInvalidReference(
existing_ref=external_ref, reason=msg)
# Check whether the LUN exists in a migration task. # Check whether the LUN exists in a migration task.
try: try:
@ -1296,12 +1385,13 @@ class HuaweiBaseDriver(driver.VolumeDriver):
existing_ref=external_ref, reason=msg) existing_ref=external_ref, reason=msg)
# Check whether the LUN exists in a LUN copy task. # Check whether the LUN exists in a LUN copy task.
lun_copy = lun_info.get('LUNCOPYIDS') if self.support_func.get('luncopy'):
if lun_copy and lun_copy[1:-1]: lun_copy = lun_info.get('LUNCOPYIDS')
msg = (_("Can't import LUN %s to Cinder. Already exists in " if lun_copy and lun_copy[1:-1]:
"a LUN copy task.") % lun_id) msg = (_("Can't import LUN %s to Cinder. Already exists in "
raise exception.ManageExistingInvalidReference( "a LUN copy task.") % lun_id)
existing_ref=external_ref, reason=msg) raise exception.ManageExistingInvalidReference(
existing_ref=external_ref, reason=msg)
# Check whether the LUN exists in a remote replication task. # Check whether the LUN exists in a remote replication task.
rmt_replication = lun_info.get('REMOTEREPLICATIONIDS') rmt_replication = lun_info.get('REMOTEREPLICATIONIDS')
@ -1355,8 +1445,11 @@ class HuaweiBaseDriver(driver.VolumeDriver):
"LUN type mismatched.") % lun_id) "LUN type mismatched.") % lun_id)
raise exception.ManageExistingVolumeTypeMismatch(reason=msg) raise exception.ManageExistingVolumeTypeMismatch(reason=msg)
if volume_type: if volume_type:
self._check_capability_support(new_opts, volume_type)
change_opts = {'policy': None, 'partitionid': None, change_opts = {'policy': None, 'partitionid': None,
'cacheid': None, 'qos': None} 'cacheid': None, 'qos': None}
change_opts = self._check_needed_changes(lun_id, old_opts, change_opts = self._check_needed_changes(lun_id, old_opts,
new_opts, change_opts, new_opts, change_opts,
volume_type) volume_type)

View File

@ -1193,16 +1193,8 @@ class RestClient(object):
free_capacity_gb=capacity['free_capacity'], free_capacity_gb=capacity['free_capacity'],
reserved_percentage=self.configuration.safe_get( reserved_percentage=self.configuration.safe_get(
'reserved_percentage'), 'reserved_percentage'),
QoS_support=True,
max_over_subscription_ratio=self.configuration.safe_get( max_over_subscription_ratio=self.configuration.safe_get(
'max_over_subscription_ratio'), 'max_over_subscription_ratio'),
thin_provisioning_support=True,
thick_provisioning_support=True,
smarttier=True,
smartcache=True,
smartpartition=True,
hypermetro=True,
consistencygroup_support=True,
)) ))
if disk_type: if disk_type:
pool['disk_type'] = disk_type pool['disk_type'] = disk_type
@ -2340,3 +2332,13 @@ class RestClient(object):
if data is not None: if data is not None:
return data.get('ISADD2HOSTGROUP') == 'true' return data.get('ISADD2HOSTGROUP') == 'true'
return False return False
def _get_object_count(self, obj_name):
url = "/" + obj_name + "/count"
result = self.call(url, None, "GET")
if result['error']['code'] != 0:
raise
if result.get("data"):
return result.get("data").get("COUNT")

View File

@ -0,0 +1,3 @@
---
features:
- Optimize backend reporting capabilities for Huawei drivers.