From d3f2f0b0e9cd646ec90d2dfbc47571579d7538ed Mon Sep 17 00:00:00 2001 From: Wilson Liu Date: Sat, 23 Jan 2016 10:46:56 +0800 Subject: [PATCH] Huawei: Check the QoS status before we use Currently we use a existing QoS without check whether the QoS is for block storage or NAS, but one QoS on the array should be used for either block storage or NAS, not both. Also, we add check with QoS parameter. Closes-Bug: #1537301 Change-Id: I9842044249cc59d9c29e887b68d48cf97595efcc --- cinder/tests/unit/test_huawei_drivers.py | 8 ++++ cinder/volume/drivers/huawei/constants.py | 6 ++- cinder/volume/drivers/huawei/huawei_driver.py | 7 ++-- cinder/volume/drivers/huawei/rest_client.py | 30 +++++++++++---- cinder/volume/drivers/huawei/smartx.py | 38 ++++++++++++++++--- 5 files changed, 71 insertions(+), 18 deletions(-) diff --git a/cinder/tests/unit/test_huawei_drivers.py b/cinder/tests/unit/test_huawei_drivers.py index 68e428efe..af7f098f1 100644 --- a/cinder/tests/unit/test_huawei_drivers.py +++ b/cinder/tests/unit/test_huawei_drivers.py @@ -2184,7 +2184,11 @@ class HuaweiISCSIDriverTestCase(test.TestCase): "data": [{ "ID": "11", "MAXIOPS": "100", + "LATENCY": "0", "IOType": "2", + "FSLIST": u'[""]', + 'RUNNINGSTATUS': "2", + "NAME": "OpenStack_57_20151225102851", "LUNLIST": u'["1", "2", "3", "4", "5", "6", "7", "8", "9",\ "10", ,"11", "12", "13", "14", "15", "16", "17", "18", "19",\ "20", ,"21", "22", "23", "24", "25", "26", "27", "28", "29",\ @@ -2208,7 +2212,11 @@ class HuaweiISCSIDriverTestCase(test.TestCase): "data": [{ "ID": "11", "MAXIOPS": "100", + "LATENCY": "0", "IOType": "2", + "FSLIST": u'[""]', + 'RUNNINGSTATUS': "2", + "NAME": "OpenStack_57_20151225102851", "LUNLIST": u'["0", "1", "2"]' }] } diff --git a/cinder/volume/drivers/huawei/constants.py b/cinder/volume/drivers/huawei/constants.py index 68e047ff2..1c441a527 100644 --- a/cinder/volume/drivers/huawei/constants.py +++ b/cinder/volume/drivers/huawei/constants.py @@ -70,8 +70,10 @@ OS_TYPE = {'Linux': '0', HUAWEI_VALID_KEYS = ['maxIOPS', 'minIOPS', 'minBandWidth', 'maxBandWidth', 'latency', 'IOType'] -QOS_KEYS = ['MAXIOPS', 'MINIOPS', 'MINBANDWidth', - 'MAXBANDWidth', 'LATENCY', 'IOTYPE'] +QOS_KEYS = [i.upper() for i in HUAWEI_VALID_KEYS] +EXTRA_QOS_KEYS = ['MAXIOPS', 'MINIOPS', 'MINBANDWIDTH', 'MAXBANDWIDTH'] +LOWER_LIMIT_KEYS = ['MINIOPS', 'LATENCY', 'MINBANDWIDTH'] +UPPER_LIMIT_KEYS = ['MAXIOPS', 'MAXBANDWIDTH'] MAX_LUN_NUM_IN_QOS = 64 DEFAULT_REPLICA_WAIT_INTERVAL = 1 diff --git a/cinder/volume/drivers/huawei/huawei_driver.py b/cinder/volume/drivers/huawei/huawei_driver.py index b57a166ea..ec04587ba 100644 --- a/cinder/volume/drivers/huawei/huawei_driver.py +++ b/cinder/volume/drivers/huawei/huawei_driver.py @@ -1017,11 +1017,12 @@ class HuaweiBaseDriver(driver.VolumeDriver): qos_info = self.client.get_qos_info(qos_id) for key, value in qos_info.items(): - if key.upper() in constants.QOS_KEYS: - if key.upper() == 'LATENCY' and value == '0': + key = key.upper() + if key in constants.QOS_KEYS: + if key == 'LATENCY' and value == '0': continue else: - qos[key.upper()] = value + qos[key] = value return qos def create_export(self, context, volume, connector): diff --git a/cinder/volume/drivers/huawei/rest_client.py b/cinder/volume/drivers/huawei/rest_client.py index 3d6a1b4eb..d42686716 100644 --- a/cinder/volume/drivers/huawei/rest_client.py +++ b/cinder/volume/drivers/huawei/rest_client.py @@ -1515,24 +1515,40 @@ class RestClient(object): """"Find available QoS on the array.""" qos_id = None lun_list = [] + extra_qos = [i for i in constants.EXTRA_QOS_KEYS if i not in qos] result = self.get_qos() if 'data' in result: - for item in result['data']: + for items in result['data']: qos_flag = 0 + extra_flag = False + if 'LATENCY' not in qos and items['LATENCY'] != '0': + extra_flag = True + else: + for item in items: + if item in extra_qos: + extra_flag = True + break for key in qos: - if key not in item: + if key not in items: break - elif qos[key] != item[key]: + elif qos[key] != items[key]: break qos_flag = qos_flag + 1 - lun_num = len(item['LUNLIST'].split(",")) + lun_num = len(items['LUNLIST'].split(",")) + qos_name = items['NAME'] + qos_status = items['RUNNINGSTATUS'] # We use this QoS only if the LUNs in it is less than 64, + # created by OpenStack and does not contain filesystem, # else we cannot add LUN to this QoS any more. if (qos_flag == len(qos) - and lun_num < constants.MAX_LUN_NUM_IN_QOS): - qos_id = item['ID'] - lun_list = item['LUNLIST'] + and not extra_flag + and lun_num < constants.MAX_LUN_NUM_IN_QOS + and qos_name.startswith(constants.QOS_NAME_PREFIX) + and qos_status == constants.STATUS_QOS_ACTIVE + and items['FSLIST'] == '[""]'): + qos_id = items['ID'] + lun_list = items['LUNLIST'] break return (qos_id, lun_list) diff --git a/cinder/volume/drivers/huawei/smartx.py b/cinder/volume/drivers/huawei/smartx.py index 37c0cb149..2569e5707 100644 --- a/cinder/volume/drivers/huawei/smartx.py +++ b/cinder/volume/drivers/huawei/smartx.py @@ -42,24 +42,50 @@ class SmartQos(object): return {} qos = {} + io_type_flag = None ctxt = context.get_admin_context() kvs = qos_specs.get_qos_specs(ctxt, qos_specs_id)['specs'] LOG.info(_LI('The QoS sepcs is: %s.'), kvs) for k, v in kvs.items(): if k not in constants.HUAWEI_VALID_KEYS: continue - - if k.upper() != 'IOTYPE' and int(v) <= 0: + if k != 'IOType' and int(v) <= 0: msg = _('QoS config is wrong. %s must > 0.') % k LOG.error(msg) raise exception.InvalidInput(reason=msg) - elif k.upper() == 'IOTYPE' and v not in ['0', '1', '2']: - msg = _('Illegal value specified for IOTYPE: 0, 1, or 2.') - LOG.error(msg) - raise exception.InvalidInput(reason=msg) + if k == 'IOType': + if v not in ['0', '1', '2']: + msg = _('Illegal value specified for IOTYPE: 0, 1, or 2.') + LOG.error(msg) + raise exception.InvalidInput(reason=msg) + io_type_flag = 1 + qos[k.upper()] = v else: qos[k.upper()] = v + if not io_type_flag: + msg = (_('QoS policy must specify for IOTYPE: 0, 1, or 2, ' + 'QoS policy: %(qos_policy)s ') % {'qos_policy': qos}) + LOG.error(msg) + raise exception.InvalidInput(reason=msg) + + # QoS policy must specify for IOTYPE and another qos_specs. + if len(qos) < 2: + msg = (_('QoS policy must specify for IOTYPE and another ' + 'qos_specs, QoS policy: %(qos_policy)s.') + % {'qos_policy': qos}) + LOG.error(msg) + raise exception.InvalidInput(reason=msg) + + for upper_limit in constants.UPPER_LIMIT_KEYS: + for lower_limit in constants.LOWER_LIMIT_KEYS: + if upper_limit in qos and lower_limit in qos: + msg = (_('QoS policy upper_limit and lower_limit ' + 'conflict, QoS policy: %(qos_policy)s.') + % {'qos_policy': qos}) + LOG.error(msg) + raise exception.InvalidInput(reason=msg) + return qos def _is_high_priority(self, qos): -- 2.45.2