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:
parent
5e128a5740
commit
c557f3bd91
File diff suppressed because it is too large
Load Diff
@ -84,7 +84,7 @@ UPPER_LIMIT_KEYS = ['MAXIOPS', 'MAXBANDWIDTH']
|
||||
MAX_LUN_NUM_IN_QOS = 64
|
||||
|
||||
DEFAULT_REPLICA_WAIT_INTERVAL = 1
|
||||
DEFAULT_REPLICA_WAIT_TIMEOUT = 10
|
||||
DEFAULT_REPLICA_WAIT_TIMEOUT = 20
|
||||
|
||||
REPLICA_SYNC_MODEL = '1'
|
||||
REPLICA_ASYNC_MODEL = '2'
|
||||
|
@ -94,9 +94,17 @@ class HuaweiBaseDriver(driver.VolumeDriver):
|
||||
|
||||
self.configuration.append_config_values(huawei_opts)
|
||||
self.huawei_conf = huawei_conf.HuaweiConf(self.configuration)
|
||||
self.support_func = None
|
||||
self.metro_flag = False
|
||||
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):
|
||||
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."""
|
||||
self.huawei_conf.update_config_value()
|
||||
stats = self.client.update_volume_stats()
|
||||
stats = self.update_hypermetro_capability(stats)
|
||||
stats = self.update_support_capability(stats)
|
||||
|
||||
if self.replica:
|
||||
stats = self.replica.update_replica_capability(stats)
|
||||
@ -171,15 +179,29 @@ class HuaweiBaseDriver(driver.VolumeDriver):
|
||||
|
||||
return stats
|
||||
|
||||
def update_hypermetro_capability(self, stats):
|
||||
if self.metro_flag:
|
||||
version = self.client.find_array_version()
|
||||
rmt_version = self.rmt_client.find_array_version()
|
||||
if (version >= constants.ARRAY_VERSION
|
||||
and rmt_version >= constants.ARRAY_VERSION):
|
||||
for pool in stats['pools']:
|
||||
pool['hypermetro'] = True
|
||||
pool['consistencygroup_support'] = True
|
||||
def update_support_capability(self, stats):
|
||||
for pool in stats['pools']:
|
||||
pool['smartpartition'] = (
|
||||
self.check_func_support("SMARTCACHEPARTITION"))
|
||||
pool['smartcache'] = self.check_func_support("smartcachepool")
|
||||
pool['QoS_support'] = self.check_func_support("ioclass")
|
||||
pool['splitmirror'] = self.check_func_support("splitmirror")
|
||||
pool['luncopy'] = self.check_func_support("luncopy")
|
||||
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
|
||||
|
||||
@ -335,8 +357,13 @@ class HuaweiBaseDriver(driver.VolumeDriver):
|
||||
try:
|
||||
qos = smartx.SmartQos.get_qos_by_volume_type(volume_type)
|
||||
if qos:
|
||||
smart_qos = smartx.SmartQos(self.client)
|
||||
smart_qos.add(qos, lun_id)
|
||||
if not self.support_func.get('QoS_support'):
|
||||
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.add(opts, lun_id)
|
||||
@ -425,10 +452,11 @@ class HuaweiBaseDriver(driver.VolumeDriver):
|
||||
if not lun_id:
|
||||
return
|
||||
|
||||
qos_id = self.client.get_qosid_by_lunid(lun_id)
|
||||
if qos_id:
|
||||
smart_qos = smartx.SmartQos(self.client)
|
||||
smart_qos.remove(qos_id, lun_id)
|
||||
if self.support_func.get('QoS_support'):
|
||||
qos_id = self.client.get_qosid_by_lunid(lun_id)
|
||||
if qos_id:
|
||||
smart_qos = smartx.SmartQos(self.client)
|
||||
smart_qos.remove(qos_id, lun_id)
|
||||
|
||||
metadata = huawei_utils.get_volume_metadata(volume)
|
||||
if 'hypermetro_id' in metadata:
|
||||
@ -461,10 +489,11 @@ class HuaweiBaseDriver(driver.VolumeDriver):
|
||||
return
|
||||
|
||||
if self.client.check_lun_exist(lun_id, lun_wwn):
|
||||
qos_id = self.client.get_qosid_by_lunid(lun_id)
|
||||
if qos_id:
|
||||
smart_qos = smartx.SmartQos(self.client)
|
||||
smart_qos.remove(qos_id, lun_id)
|
||||
if self.support_func.get('QoS_support'):
|
||||
qos_id = self.client.get_qosid_by_lunid(lun_id)
|
||||
if qos_id:
|
||||
smart_qos = smartx.SmartQos(self.client)
|
||||
smart_qos.remove(qos_id, lun_id)
|
||||
|
||||
self.client.delete_lun(lun_id)
|
||||
|
||||
@ -655,6 +684,10 @@ class HuaweiBaseDriver(driver.VolumeDriver):
|
||||
'WRITECACHEPOLICY': lun_info['WRITECACHEPOLICY'],
|
||||
'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_id = lun_info['ID']
|
||||
|
||||
@ -1025,12 +1058,47 @@ class HuaweiBaseDriver(driver.VolumeDriver):
|
||||
|
||||
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,
|
||||
change_opts, new_type):
|
||||
new_cache_id = None
|
||||
new_cache_name = new_opts['cachename']
|
||||
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:
|
||||
msg = (_(
|
||||
"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_name = new_opts['partitionname']
|
||||
if new_partition_name:
|
||||
new_partition_id = self.client.get_partition_id_by_name(
|
||||
new_partition_name)
|
||||
if self.support_func.get('smartpartition'):
|
||||
new_partition_id = self.client.get_partition_id_by_name(
|
||||
new_partition_name)
|
||||
if new_partition_id is None:
|
||||
msg = (_(
|
||||
"Can't find partition name on the array, partition name "
|
||||
@ -1052,26 +1121,37 @@ class HuaweiBaseDriver(driver.VolumeDriver):
|
||||
|
||||
# smarttier
|
||||
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
|
||||
old_cache_id = old_opts['cacheid']
|
||||
if old_cache_id == '--':
|
||||
old_cache_id = None
|
||||
if old_cache_id != new_cache_id:
|
||||
old_cache_name = None
|
||||
if old_cache_id:
|
||||
cache_info = self.client.get_cache_info_by_id(old_cache_id)
|
||||
old_cache_name = cache_info['NAME']
|
||||
if self.support_func.get('smartcache'):
|
||||
if old_cache_id:
|
||||
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],
|
||||
[new_cache_id, new_cache_name])
|
||||
|
||||
# smartpartition
|
||||
old_partition_id = old_opts['partitionid']
|
||||
if old_partition_id == '--':
|
||||
old_partition_id = None
|
||||
if old_partition_id != new_partition_id:
|
||||
old_partition_name = None
|
||||
if old_partition_id:
|
||||
partition_info = self.client.get_partition_info_by_id(
|
||||
old_partition_id)
|
||||
old_partition_name = partition_info['NAME']
|
||||
if self.support_func.get('smartpartition'):
|
||||
if old_partition_id:
|
||||
partition_info = self.client.get_partition_info_by_id(
|
||||
old_partition_id)
|
||||
old_partition_name = partition_info['NAME']
|
||||
|
||||
change_opts['partitionid'] = ([old_partition_id,
|
||||
old_partition_name],
|
||||
[new_partition_id,
|
||||
@ -1079,10 +1159,16 @@ class HuaweiBaseDriver(driver.VolumeDriver):
|
||||
|
||||
# smartqos
|
||||
new_qos = smartx.SmartQos.get_qos_by_volume_type(new_type)
|
||||
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)
|
||||
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)
|
||||
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
|
||||
|
||||
@ -1235,44 +1321,47 @@ class HuaweiBaseDriver(driver.VolumeDriver):
|
||||
existing_ref=external_ref, reason=msg)
|
||||
|
||||
# Check whether the LUN exists in a HyperMetroPair.
|
||||
try:
|
||||
hypermetro_pairs = self.client.get_hypermetro_pairs()
|
||||
except exception.VolumeBackendAPIException:
|
||||
hypermetro_pairs = []
|
||||
LOG.debug("Can't get hypermetro info, pass the check.")
|
||||
if self.support_func.get('hypermetro'):
|
||||
try:
|
||||
hypermetro_pairs = self.client.get_hypermetro_pairs()
|
||||
except exception.VolumeBackendAPIException:
|
||||
hypermetro_pairs = []
|
||||
LOG.debug("Can't get hypermetro info, pass the check.")
|
||||
|
||||
for pair in hypermetro_pairs:
|
||||
if pair.get('LOCALOBJID') == lun_id:
|
||||
msg = (_("Can't import LUN %s to Cinder. Already exists in a "
|
||||
"HyperMetroPair.") % lun_id)
|
||||
raise exception.ManageExistingInvalidReference(
|
||||
existing_ref=external_ref, reason=msg)
|
||||
for pair in hypermetro_pairs:
|
||||
if pair.get('LOCALOBJID') == lun_id:
|
||||
msg = (_("Can't import LUN %s to Cinder. Already exists "
|
||||
"in a HyperMetroPair.") % lun_id)
|
||||
raise exception.ManageExistingInvalidReference(
|
||||
existing_ref=external_ref, reason=msg)
|
||||
|
||||
# Check whether the LUN exists in a SplitMirror.
|
||||
try:
|
||||
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:
|
||||
if self.support_func.get('splitmirror'):
|
||||
try:
|
||||
target_luns = self.client.get_target_luns(mirror.get('ID'))
|
||||
except exception.VolumeBackendAPIException:
|
||||
msg = _("Failed to get target LUN of SplitMirror.")
|
||||
raise exception.VolumeBackendAPIException(data=msg)
|
||||
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)
|
||||
|
||||
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)
|
||||
for mirror in split_mirrors:
|
||||
try:
|
||||
target_luns = self.client.get_target_luns(mirror.get('ID'))
|
||||
except exception.VolumeBackendAPIException:
|
||||
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.
|
||||
try:
|
||||
@ -1296,12 +1385,13 @@ class HuaweiBaseDriver(driver.VolumeDriver):
|
||||
existing_ref=external_ref, reason=msg)
|
||||
|
||||
# Check whether the LUN exists in a LUN copy task.
|
||||
lun_copy = lun_info.get('LUNCOPYIDS')
|
||||
if lun_copy and lun_copy[1:-1]:
|
||||
msg = (_("Can't import LUN %s to Cinder. Already exists in "
|
||||
"a LUN copy task.") % lun_id)
|
||||
raise exception.ManageExistingInvalidReference(
|
||||
existing_ref=external_ref, reason=msg)
|
||||
if self.support_func.get('luncopy'):
|
||||
lun_copy = lun_info.get('LUNCOPYIDS')
|
||||
if lun_copy and lun_copy[1:-1]:
|
||||
msg = (_("Can't import LUN %s to Cinder. Already exists in "
|
||||
"a LUN copy task.") % lun_id)
|
||||
raise exception.ManageExistingInvalidReference(
|
||||
existing_ref=external_ref, reason=msg)
|
||||
|
||||
# Check whether the LUN exists in a remote replication task.
|
||||
rmt_replication = lun_info.get('REMOTEREPLICATIONIDS')
|
||||
@ -1355,8 +1445,11 @@ class HuaweiBaseDriver(driver.VolumeDriver):
|
||||
"LUN type mismatched.") % lun_id)
|
||||
raise exception.ManageExistingVolumeTypeMismatch(reason=msg)
|
||||
if volume_type:
|
||||
self._check_capability_support(new_opts, volume_type)
|
||||
|
||||
change_opts = {'policy': None, 'partitionid': None,
|
||||
'cacheid': None, 'qos': None}
|
||||
|
||||
change_opts = self._check_needed_changes(lun_id, old_opts,
|
||||
new_opts, change_opts,
|
||||
volume_type)
|
||||
|
@ -1193,16 +1193,8 @@ class RestClient(object):
|
||||
free_capacity_gb=capacity['free_capacity'],
|
||||
reserved_percentage=self.configuration.safe_get(
|
||||
'reserved_percentage'),
|
||||
QoS_support=True,
|
||||
max_over_subscription_ratio=self.configuration.safe_get(
|
||||
'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:
|
||||
pool['disk_type'] = disk_type
|
||||
@ -2340,3 +2332,13 @@ class RestClient(object):
|
||||
if data is not None:
|
||||
return data.get('ISADD2HOSTGROUP') == 'true'
|
||||
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")
|
||||
|
@ -0,0 +1,3 @@
|
||||
---
|
||||
features:
|
||||
- Optimize backend reporting capabilities for Huawei drivers.
|
Loading…
Reference in New Issue
Block a user