QoS support for Huawei Driver

QoS is a common attribute, so add the QoS
capability in Huawei Driver.

Partially implements: bp manila-support-qos
Change-Id: I394f7d2ece96bf75edbea604e5db0f030f4d8970
This commit is contained in:
zhongjun 2016-01-11 10:54:16 +08:00
parent 29d5a10cab
commit fb80e16126
7 changed files with 458 additions and 18 deletions

View File

@ -19,15 +19,20 @@ STATUS_FS_RUNNING = "27"
STATUS_JOIN_DOMAIN = '1'
STATUS_EXIT_DOMAIN = '0'
STATUS_SERVICE_RUNNING = "2"
STATUS_QOS_ACTIVE = '2'
DEFAULT_WAIT_INTERVAL = 3
DEFAULT_TIMEOUT = 60
MAX_FS_NUM_IN_QOS = 64
MSG_SNAPSHOT_NOT_FOUND = 1073754118
IP_ALLOCATIONS_DHSS_FALSE = 0
IP_ALLOCATIONS_DHSS_TRUE = 1
SOCKET_TIMEOUT = 52
LOGIN_SOCKET_TIMEOUT = 4
QOS_NAME_PREFIX = 'OpenStack_'
SYSTEM_NAME_PREFIX = "Array-"
ARRAY_VERSION = 'V300R003C00'
ACCESS_NFS_RW = "1"
ACCESS_NFS_RO = "0"
@ -51,6 +56,14 @@ ALLOC_TYPE_THICK = "Thick"
THIN_PROVISIONING = "true"
THICK_PROVISIONING = "false"
OPTS_QOS_VALUE = {
'maxiops': None,
'miniops': None,
'minbandwidth': None,
'maxbandwidth': None,
'latency': None,
'iotype': None
}
OPTS_CAPABILITIES = {
'dedupe': False,
@ -58,6 +71,7 @@ OPTS_CAPABILITIES = {
'huawei_smartcache': False,
'huawei_smartpartition': False,
'thin_provisioning': False,
'qos': False,
}
OPTS_VALUE = {
@ -65,7 +79,10 @@ OPTS_VALUE = {
'partitionname': None,
}
OPTS_VALUE.update(OPTS_QOS_VALUE)
OPTS_ASSOCIATE = {
'huawei_smartcache': 'cachename',
'huawei_smartpartition': 'partitionname',
'qos': OPTS_QOS_VALUE,
}

View File

@ -54,6 +54,7 @@ class HuaweiNasDriver(driver.ShareDriver):
Support multi pools in one backend.
1.2 - Add share server support.
Add ensure share.
Add QoS support.
"""
def __init__(self, *args, **kwargs):
@ -175,6 +176,7 @@ class HuaweiNasDriver(driver.ShareDriver):
vendor_name='Huawei',
driver_version='1.2',
storage_protocol='NFS_CIFS',
qos=True,
total_capacity_gb=0.0,
free_capacity_gb=0.0)

View File

@ -72,6 +72,6 @@ def _get_opts_from_specs(specs):
if ((scope in constants.OPTS_CAPABILITIES) and
(key in constants.OPTS_VALUE)):
if ((scope in constants.OPTS_ASSOCIATE) and
(constants.OPTS_ASSOCIATE[scope] == key)):
(key in constants.OPTS_ASSOCIATE[scope])):
opts[key] = value
return opts

View File

@ -95,6 +95,9 @@ class V3StorageConnection(driver.HuaweiBase):
'running': fs['RUNNINGSTATUS']}))
except Exception as err:
if fs_id is not None:
qos_id = self.helper.get_qosid_by_fsid(fs_id)
if qos_id:
self.remove_qos_fs(fs_id, qos_id)
self.helper._delete_fs(fs_id)
message = (_('Failed to create share %(name)s.'
'Reason: %(err)s.')
@ -106,6 +109,9 @@ class V3StorageConnection(driver.HuaweiBase):
self.helper._create_share(share_name, fs_id, share_proto)
except Exception as err:
if fs_id is not None:
qos_id = self.helper.get_qosid_by_fsid(fs_id)
if qos_id:
self.remove_qos_fs(fs_id, qos_id)
self.helper._delete_fs(fs_id)
raise exception.InvalidShare(
reason=(_('Failed to create share %(name)s. Reason: %(err)s.')
@ -277,7 +283,7 @@ class V3StorageConnection(driver.HuaweiBase):
self.configuration.safe_get(
'max_over_subscription_ratio')),
allocated_capacity_gb=capacity['CONSUMEDCAPACITY'],
qos=False,
qos=True,
reserved_percentage=0,
thin_provisioning=[True, False],
dedupe=[True, False],
@ -315,6 +321,9 @@ class V3StorageConnection(driver.HuaweiBase):
self.helper._delete_share_by_id(share_id, share_url_type)
if share_fs_id:
qos_id = self.helper.get_qosid_by_fsid(share_fs_id)
if qos_id:
self.remove_qos_fs(share_fs_id, qos_id)
self.helper._delete_fs(share_fs_id)
return share
@ -498,12 +507,16 @@ class V3StorageConnection(driver.HuaweiBase):
smartx_opts = constants.OPTS_CAPABILITIES
if opts is not None:
smart = smartx.SmartX()
smartx_opts = smart.get_smartx_extra_specs_opts(opts)
smartx_opts, qos = smart.get_smartx_extra_specs_opts(opts)
fileParam = self._init_filesys_para(share, poolinfo, smartx_opts)
fsid = self.helper._create_filesystem(fileParam)
try:
if qos:
smart_qos = smartx.SmartQos(self.helper)
smart_qos.create_qos(qos, fsid)
smartpartition = smartx.SmartPartition(self.helper)
smartpartition.add(opts, fsid)
@ -511,6 +524,9 @@ class V3StorageConnection(driver.HuaweiBase):
smartcache.add(opts, fsid)
except Exception as err:
if fsid is not None:
qos_id = self.helper.get_qosid_by_fsid(fsid)
if qos_id:
self.remove_qos_fs(fsid, qos_id)
self.helper._delete_fs(fsid)
message = (_('Failed to add smartx. Reason: %(err)s.')
% {'err': err})
@ -651,7 +667,7 @@ class V3StorageConnection(driver.HuaweiBase):
smartx_opts = constants.OPTS_CAPABILITIES
if opts is not None:
smart = smartx.SmartX()
smartx_opts = smart.get_smartx_extra_specs_opts(opts)
smartx_opts, qos = smart.get_smartx_extra_specs_opts(opts)
old_compression = fs['COMPRESSION']
new_compression = smartx_opts['compression']
@ -756,6 +772,17 @@ class V3StorageConnection(driver.HuaweiBase):
"new_compression": new_compression})
LOG.info(msg)
def remove_qos_fs(self, fs_id, qos_id):
fs_list = self.helper.get_fs_list_in_qos(qos_id)
fs_count = len(fs_list)
if fs_count <= 1:
qos = smartx.SmartQos(self.helper)
qos.delete_qos(qos_id)
else:
self.helper.remove_fs_from_qos(fs_id,
fs_list,
qos_id)
def _get_location_path(self, share_name, share_proto, ip=None):
location = None
if ip is None:

View File

@ -14,6 +14,7 @@
# under the License.
import base64
import time
from xml.etree import ElementTree as ET
from oslo_log import log
@ -811,6 +812,161 @@ class RestHelper(object):
self._assert_rest_result(result, _('Add filesystem to cache error.'))
def get_qos(self):
url = "/ioclass"
result = self.call(url, None, "GET")
self._assert_rest_result(result, _('Get QoS information error.'))
return result
def find_available_qos(self, qos):
""""Find available QoS on the array."""
qos_id = None
fs_list = []
result = self.get_qos()
if 'data' in result:
for item in result['data']:
qos_flag = 0
for key in qos:
if ((key not in item)
or qos[key] != item[key]
or int(item[key]) == 0):
break
qos_flag = qos_flag + 1
fs_num = len(item['FSLIST'].split(","))
# We use this QoS only if the filesystems in it is less
# than 64, else we cannot add filesystem to this QoS any more.
if (item['RUNNINGSTATUS'] == constants.STATUS_QOS_ACTIVE
and fs_num < constants.MAX_FS_NUM_IN_QOS
and constants.QOS_NAME_PREFIX in item['NAME']
and item['LUNLIST'] == '[""]'
and qos_flag == len(qos)):
qos_id = item['ID']
fs_list = item['FSLIST']
break
return (qos_id, fs_list)
def add_share_to_qos(self, qos_id, fs_id, fs_list):
"""Add filesystem to QoS."""
url = "/ioclass/" + qos_id
new_fs_list = []
fs_list_string = fs_list[1:-1]
for fs_string in fs_list_string.split(","):
tmp_fs_id = fs_string[1:-1]
if '' != tmp_fs_id and tmp_fs_id != fs_id:
new_fs_list.append(tmp_fs_id)
new_fs_list.append(fs_id)
data = jsonutils.dumps({"FSLIST": new_fs_list,
"TYPE": 230,
"ID": qos_id})
result = self.call(url, data, "PUT")
msg = _('Associate filesystem to Qos error.')
self._assert_rest_result(result, msg)
def create_qos_policy(self, qos, fs_id):
# Get local time.
localtime = time.strftime('%Y%m%d%H%M%S', time.localtime(time.time()))
# Package QoS name.
qos_name = constants.QOS_NAME_PREFIX + fs_id + '_' + localtime
mergedata = {
"TYPE": "230",
"NAME": qos_name,
"FSLIST": ["%s" % fs_id],
"CLASSTYPE": "1",
"SCHEDULEPOLICY": "2",
"SCHEDULESTARTTIME": "1410969600",
"STARTTIME": "08:00",
"DURATION": "86400",
"CYCLESET": "[1,2,3,4,5,6,0]",
}
mergedata.update(qos)
data = jsonutils.dumps(mergedata)
url = "/ioclass"
result = self.call(url, data)
self._assert_rest_result(result, _('Create QoS policy error.'))
return result['data']['ID']
def activate_deactivate_qos(self, qos_id, enablestatus):
"""Activate or deactivate QoS.
enablestatus: true (activate)
enablestatus: false (deactivate)
"""
url = "/ioclass/active/" + qos_id
data = jsonutils.dumps({
"TYPE": 230,
"ID": qos_id,
"ENABLESTATUS": enablestatus})
result = self.call(url, data, "PUT")
self._assert_rest_result(
result, _('Activate or deactivate QoS error.'))
def change_fs_priority_high(self, fs_id):
"""Change fs priority to high."""
url = "/filesystem/" + fs_id
data = jsonutils.dumps({"IOPRIORITY": "3"})
result = self.call(url, data, "PUT")
self._assert_rest_result(
result, _('Change filesystem priority error.'))
def delete_qos_policy(self, qos_id):
"""Delete a QoS policy."""
url = "/ioclass/" + qos_id
data = jsonutils.dumps({"TYPE": "230",
"ID": qos_id})
result = self.call(url, data, 'DELETE')
self._assert_rest_result(result, _('Delete QoS policy error.'))
def get_qosid_by_fsid(self, fs_id):
"""Get QoS id by fs id."""
url = "/filesystem/" + fs_id
result = self.call(url, None, "GET")
self._assert_rest_result(
result, _('Get QoS id by filesystem id error.'))
return result['data']['IOCLASSID']
def get_fs_list_in_qos(self, qos_id):
"""Get the filesystem list in QoS."""
qos_info = self.get_qos_info(qos_id)
fs_list = []
fs_string = qos_info['FSLIST'][1:-1]
for fs in fs_string.split(","):
fs_id = fs[1:-1]
fs_list.append(fs_id)
return fs_list
def get_qos_info(self, qos_id):
"""Get QoS information."""
url = "/ioclass/" + qos_id
result = self.call(url, None, "GET")
self._assert_rest_result(result, _('Get QoS information error.'))
return result['data']
def remove_fs_from_qos(self, fs_id, fs_list, qos_id):
"""Remove filesystem from QoS."""
fs_list = [i for i in fs_list if i != fs_id]
url = "/ioclass/" + qos_id
data = jsonutils.dumps({"FSLIST": fs_list,
"TYPE": 230,
"ID": qos_id})
result = self.call(url, data, "PUT")
msg = _('Remove filesystem from QoS error.')
self._assert_rest_result(result, msg)
def _remove_fs_from_cache(self, fs_id, cache_id):
url = "/SMARTCACHEPARTITION/REMOVE_ASSOCIATE"
data = jsonutils.dumps({"ID": cache_id,
@ -1094,3 +1250,9 @@ class RestHelper(object):
return True, result['LDAPSERVER']
return False, None
def find_array_version(self):
url = "/system/"
result = self.call(url, None)
self._assert_rest_result(result, _('Find array version error.'))
return result['data']['PRODUCTVERSION']

View File

@ -13,10 +13,12 @@
# License for the specific language governing permissions and limitations
# under the License.
from oslo_utils import excutils
from oslo_utils import strutils
from manila import exception
from manila.i18n import _
from manila.share.drivers.huawei import constants
class SmartPartition(object):
@ -60,6 +62,49 @@ class SmartCache(object):
self.helper._add_fs_to_cache(fsid, cache_id)
class SmartQos(object):
def __init__(self, helper):
self.helper = helper
def create_qos(self, qos, fs_id):
policy_id = None
try:
# Check QoS priority.
if self._check_qos_high_priority(qos):
self.helper.change_fs_priority_high(fs_id)
# Create QoS policy and activate it.
version = self.helper.find_array_version()
if version >= constants.ARRAY_VERSION:
(qos_id, fs_list) = self.helper.find_available_qos(qos)
if qos_id is not None:
self.helper.add_share_to_qos(qos_id, fs_id, fs_list)
else:
policy_id = self.helper.create_qos_policy(qos, fs_id)
self.helper.activate_deactivate_qos(policy_id, True)
else:
policy_id = self.helper.create_qos_policy(qos, fs_id)
self.helper.activate_deactivate_qos(policy_id, True)
except exception.InvalidInput:
with excutils.save_and_reraise_exception():
if policy_id is not None:
self.helper.delete_qos_policy(policy_id)
def _check_qos_high_priority(self, qos):
"""Check QoS priority."""
for key, value in qos.items():
if (key.find('MIN') == 0) or (key.find('LATENCY') == 0):
return True
return False
def delete_qos(self, qos_id):
qos_info = self.helper.get_qos_info(qos_id)
qos_status = qos_info['RUNNINGSTATUS']
if qos_status == constants.STATUS_QOS_ACTIVE:
self.helper.activate_deactivate_qos(qos_id, False)
self.helper.delete_qos_policy(qos_id)
class SmartX(object):
def get_smartx_extra_specs_opts(self, opts):
opts = self.get_capabilities_opts(opts, 'dedupe')
@ -67,7 +112,8 @@ class SmartX(object):
opts = self.get_smartprovisioning_opts(opts)
opts = self.get_smartcache_opts(opts)
opts = self.get_smartpartition_opts(opts)
return opts
qos = self.get_qos_opts(opts)
return opts, qos
def get_capabilities_opts(self, opts, key):
if strutils.bool_from_string(opts[key]):
@ -106,3 +152,24 @@ class SmartX(object):
opts['partitionname'] = None
return opts
def get_qos_opts(self, opts):
qos = {}
if not strutils.bool_from_string(opts.get('qos')):
return
for key, value in opts.items():
if (key in constants.OPTS_QOS_VALUE) and value is not None:
if (key.upper() != 'IOTYPE') and (int(value) <= 0):
err_msg = (_('QoS config is wrong. %(key)s'
' must be set greater than 0.')
% {'key': key})
raise exception.InvalidInput(reason=err_msg)
elif ((key.upper() == 'IOTYPE')
and (value not in ['0', '1', '2'])):
raise exception.InvalidInput(
reason=(_('Illegal value specified for IOTYPE: '
'set to either 0, 1, or 2.')))
else:
qos[key.upper()] = value
return qos

View File

@ -81,6 +81,8 @@ def filesystem(method, data, fs_status_flag):
data = """{"error":{"code":0},
"data":{"ID":"4",
"CAPACITY":"8388608"}}"""
elif data == """{"IOPRIORITY": "3"}""":
data = """{"error":{"code":0}}"""
elif method == "DELETE":
data = """{"error":{"code":0}}"""
elif method == "GET":
@ -94,7 +96,8 @@ def filesystem(method, data, fs_status_flag):
"ENABLECOMPRESSION":"false",
"ENABLEDEDUP":"false",
"CACHEPARTITIONID":"",
"SMARTCACHEPARTITIONID":""}}"""
"SMARTCACHEPARTITIONID":"",
"IOCLASSID":"11"}}"""
else:
data = """{"error":{"code":0},
"data":{"HEALTHSTATUS":"0",
@ -105,7 +108,8 @@ def filesystem(method, data, fs_status_flag):
"ENABLECOMPRESSION":"false",
"ENABLEDEDUP":"false",
"CACHEPARTITIONID":"",
"SMARTCACHEPARTITIONID":""}}"""
"SMARTCACHEPARTITIONID":"",
"IOCLASSID":"11"}}"""
else:
data = '{"error":{"code":31755596}}'
return (data, extend_share_flag, shrink_share_flag)
@ -148,7 +152,8 @@ def filesystem_thick(method, data, fs_status_flag):
"ENABLECOMPRESSION":"false",
"ENABLEDEDUP":"false",
"CACHEPARTITIONID":"",
"SMARTCACHEPARTITIONID":""}}"""
"SMARTCACHEPARTITIONID":"",
"IOCLASSID":"11"}}"""
else:
data = """{"error":{"code":0},
"data":{"HEALTHSTATUS":"0",
@ -159,7 +164,8 @@ def filesystem_thick(method, data, fs_status_flag):
"ENABLECOMPRESSION":"false",
"ENABLEDEDUP":"false",
"CACHEPARTITIONID":"",
"SMARTCACHEPARTITIONID":""}}"""
"SMARTCACHEPARTITIONID":"",
"IOCLASSID":"11"}}"""
else:
data = '{"error":{"code":31755596}}'
return (data, extend_share_flag, shrink_share_flag)
@ -211,7 +217,8 @@ def filesystem_inpartition(method, data, fs_status_flag):
"ENABLECOMPRESSION":"false",
"ENABLEDEDUP":"false",
"CACHEPARTITIONID":"1",
"SMARTCACHEPARTITIONID":"1"}}"""
"SMARTCACHEPARTITIONID":"1",
"IOCLASSID":"11"}}"""
else:
data = """{"error":{"code":0},
"data":{"HEALTHSTATUS":"0",
@ -222,7 +229,8 @@ def filesystem_inpartition(method, data, fs_status_flag):
"ENABLECOMPRESSION":"false",
"ENABLEDEDUP":"false",
"CACHEPARTITIONID":"1",
"SMARTCACHEPARTITIONID":"1"}}"""
"SMARTCACHEPARTITIONID":"1",
"IOCLASSID":"11"}}"""
else:
data = '{"error":{"code":31755596}}'
return (data, extend_share_flag, shrink_share_flag)
@ -272,6 +280,19 @@ def dec_driver_handles_share_servers(func):
return wrapper
def QoS_response(method):
if method == "GET":
data = """{"error":{"code":0},
"data":[{"NAME": "OpenStack_Fake_QoS", "MAXIOPS": "100",
"FSLIST": 4, "LUNLIST": ""}]}"""
elif method == "PUT":
data = """{"error":{"code":0}}"""
else:
data = """{"error":{"code":0},
"data":{"ID": "11"}}"""
return data
class FakeHuaweiNasHelper(helper.RestHelper):
def __init__(self, *args, **kwargs):
@ -336,12 +357,30 @@ class FakeHuaweiNasHelper(helper.RestHelper):
"NAME":"OpenStack_Pool",
"USERTOTALCAPACITY":"4194304",
"USAGETYPE":"2",
"USERCONSUMEDCAPACITY":"2097152"},
{"USERFREECAPACITY":"2097152",
"ID":"2",
"NAME":"OpenStack_Pool_Thick",
"USERTOTALCAPACITY":"4194304",
"USAGETYPE":"2",
"USERCONSUMEDCAPACITY":"2097152"}]}"""
if url == "/filesystem":
data = """{"error":{"code":0},"data":{
"ID":"4"}}"""
if url == "/system/":
data = """{"error":{"code":0},
"data":{"PRODUCTVERSION": "V300R003C10"}}"""
if url == "/ioclass" or url == "/ioclass/11":
data = QoS_response(method)
if url == "/ioclass/active/11":
data = """{"error":{"code":0},
"data":[{"ID": "11", "MAXIOPS": "100",
"FSLIST": ""}]}"""
if url == "/NFSHARE" or url == "/CIFSHARE":
if self.create_share_flag:
data = '{"error":{"code":31755596}}'
@ -1358,6 +1397,106 @@ class HuaweiShareDriverTestCase(test.TestCase):
'share_type_get',
mock.Mock(return_value=share_type))
self.driver.plugin.helper.login()
self.assertRaises(exception.InvalidShare,
self.driver.create_share,
self._context,
self.share_nfs_thick,
self.share_server)
@ddt.data({"fake_extra_specs_qos": {"qos:maxIOPS": "100",
"qos:minIOPS": "50"},
"fake_qos_info": {"MAXIOPS": "100", "MINIOPS": "50",
"NAME": "OpenStack_fake_qos"}},
{"fake_extra_specs_qos": {"qos:maxIOPS": "100",
"qos:minIOPS": "50"},
"fake_qos_info": {"NAME": "fake_qos", "MAXIOPS": "100"}})
@ddt.unpack
def test_create_share_with_qos(self, fake_extra_specs_qos, fake_qos_info):
fake_share_type_id = 'fooid-2'
fake_extra_specs = {"capabilities:qos": "<is> True"}
fake_extra_specs.update(fake_extra_specs_qos)
fake_type_error_extra = {
'test_with_extra': {
'created_at': 'fake_time',
'deleted': '0',
'deleted_at': None,
'extra_specs': fake_extra_specs,
'required_extra_specs': {},
'id': fake_share_type_id,
'name': 'test_with_extra',
'updated_at': None
}
}
fake_qos_info_respons = {
"error": {
"code": 0
},
"data": [{
"ID": "11",
"FSLIST": u'["1", "2", "3", "4"]',
"LUNLIST": '[""]',
"RUNNINGSTATUS": "2",
}]
}
fake_qos_info_respons["data"][0].update(fake_qos_info)
share_type = fake_type_error_extra['test_with_extra']
self.mock_object(db,
'share_type_get',
mock.Mock(return_value=share_type))
self.mock_object(helper.RestHelper,
'get_qos',
mock.Mock(return_value=fake_qos_info_respons))
self.driver.plugin.configuration.manila_huawei_conf_file = (
self.fake_conf_file)
self.driver.plugin.helper.login()
location = self.driver.create_share(self._context, self.share_nfs,
self.share_server)
self.assertEqual("100.115.10.68:/share_fake_uuid", location)
@ddt.data({'capabilities:qos': '<is> True',
'qos:maxIOPS': -1},
{'capabilities:qos': '<is> True',
'qos:IOTYPE': 4},
{'capabilities:qos': '<is> True',
'qos:IOTYPE': 100},
{'capabilities:qos': '<is> True',
'qos:maxIOPS': 0},
{'capabilities:qos': '<is> True',
'qos:minIOPS': 0},
{'capabilities:qos': '<is> True',
'qos:minBandWidth': 0},
{'capabilities:qos': '<is> True',
'qos:maxBandWidth': 0},
{'capabilities:qos': '<is> True',
'qos:latency': 0})
def test_create_share_with_invalid_qos(self, fake_extra_specs):
fake_share_type_id = 'fooid-2'
fake_type_error_extra = {
'test_with_extra': {
'created_at': 'fake_time',
'deleted': '0',
'deleted_at': None,
'extra_specs': fake_extra_specs,
'required_extra_specs': {},
'id': fake_share_type_id,
'name': 'test_with_extra',
'updated_at': None
}
}
share_type = fake_type_error_extra['test_with_extra']
self.mock_object(db,
'share_type_get',
mock.Mock(return_value=share_type))
self.driver.plugin.configuration.manila_huawei_conf_file = (
self.fake_conf_file)
self.driver.plugin.helper.login()
self.assertRaises(exception.InvalidShare,
self.driver.create_share,
self._context,
@ -1460,12 +1599,27 @@ class HuaweiShareDriverTestCase(test.TestCase):
self.share_nfs,
self.share_server)
def test_delete_share_nfs_success(self):
@ddt.data({"share_proto": "NFS",
"fake_qos_info_respons": {"ID": "11", "MAXIOPS": "100",
"IOType": "2",
"FSLIST": u'["0", "1", "4"]'}},
{"share_proto": "CIFS",
"fake_qos_info_respons": {"ID": "11", "MAXIOPS": "100",
"IOType": "2", "FSLIST": u'["4"]',
"RUNNINGSTATUS": "2"}})
@ddt.unpack
def test_delete_share_success(self, share_proto, fake_qos_info_respons):
self.driver.plugin.helper.login()
self.driver.plugin.helper.delete_flag = False
self.driver.delete_share(self._context,
self.share_nfs, self.share_server)
self.assertTrue(self.driver.plugin.helper.delete_flag)
if share_proto == 'NFS':
share = self.share_nfs
else:
share = self.share_cifs
with mock.patch.object(helper.RestHelper, 'get_qos_info',
return_value=fake_qos_info_respons):
self.driver.delete_share(self._context,
share, self.share_server)
self.assertTrue(self.driver.plugin.helper.delete_flag)
def test_check_snapshot_id_exist_fail(self):
snapshot_id = "4"
@ -1484,8 +1638,19 @@ class HuaweiShareDriverTestCase(test.TestCase):
self.assertTrue(self.driver.plugin.helper.delete_flag)
def test_delete_share_cifs_success(self):
self.driver.plugin.helper.login()
self.driver.plugin.helper.delete_flag = False
fake_qos_info_respons = {
"ID": "11",
"FSLIST": u'["1", "2", "3", "4"]',
"LUNLIST": '[""]',
"RUNNINGSTATUS": "2",
}
self.mock_object(helper.RestHelper,
'get_qos_info',
mock.Mock(return_value=fake_qos_info_respons))
self.driver.plugin.helper.login()
self.driver.delete_share(self._context, self.share_cifs,
self.share_server)
self.assertTrue(self.driver.plugin.helper.delete_flag)
@ -1527,7 +1692,7 @@ class HuaweiShareDriverTestCase(test.TestCase):
expected['reserved_percentage'] = 0
expected['total_capacity_gb'] = 0.0
expected['free_capacity_gb'] = 0.0
expected['qos'] = False
expected['qos'] = True
expected["snapshot_support"] = False
expected["pools"] = []
pool = dict(
@ -1535,7 +1700,7 @@ class HuaweiShareDriverTestCase(test.TestCase):
total_capacity_gb=2.0,
free_capacity_gb=1.0,
allocated_capacity_gb=1.0,
qos=False,
qos=True,
reserved_percentage=0,
compression=[True, False],
dedupe=[True, False],