Merge "Implement update_access() method in huawei driver"
This commit is contained in:
commit
83d7bc60f4
manila
share/drivers/huawei
tests/share/drivers/huawei
@ -55,6 +55,11 @@ class HuaweiBase(object):
|
||||
def ensure_share(self, share, share_server=None):
|
||||
"""Ensure that share is exported."""
|
||||
|
||||
@abc.abstractmethod
|
||||
def update_access(self, share, access_rules, add_rules,
|
||||
delete_rules, share_server):
|
||||
"""Update access rules list."""
|
||||
|
||||
@abc.abstractmethod
|
||||
def extend_share(self, share, new_size, share_server):
|
||||
"""Extends size of existing share."""
|
||||
|
@ -158,6 +158,13 @@ class HuaweiNasDriver(driver.ShareDriver):
|
||||
|
||||
self.plugin.deny_access(share, access, share_server)
|
||||
|
||||
def update_access(self, context, share, access_rules, add_rules=None,
|
||||
delete_rules=None, share_server=None):
|
||||
"""Update access rules list."""
|
||||
LOG.debug("Update access.")
|
||||
self.plugin.update_access(share, access_rules,
|
||||
add_rules, delete_rules, share_server)
|
||||
|
||||
def get_pool(self, share):
|
||||
"""Return pool name where the share resides on."""
|
||||
LOG.debug("Get pool.")
|
||||
|
@ -507,13 +507,12 @@ class V3StorageConnection(driver.HuaweiBase):
|
||||
"""Get access id of the share."""
|
||||
access_id = None
|
||||
share_name = share['name']
|
||||
share_url_type = self.helper._get_share_url_type(share['share_proto'])
|
||||
share_client_type = self.helper._get_share_client_type(
|
||||
share['share_proto'])
|
||||
share_proto = share['share_proto']
|
||||
share_url_type = self.helper._get_share_url_type(share_proto)
|
||||
access_to = access['access_to']
|
||||
share = self.helper._get_share_by_name(share_name, share_url_type)
|
||||
access_id = self.helper._get_access_from_share(share['ID'], access_to,
|
||||
share_client_type)
|
||||
share_proto)
|
||||
if access_id is None:
|
||||
LOG.debug('Cannot get access ID from share. '
|
||||
'share_name: %s', share_name)
|
||||
@ -640,7 +639,6 @@ class V3StorageConnection(driver.HuaweiBase):
|
||||
share_proto = share['share_proto']
|
||||
share_name = share['name']
|
||||
share_url_type = self.helper._get_share_url_type(share_proto)
|
||||
share_client_type = self.helper._get_share_client_type(share_proto)
|
||||
access_type = access['access_type']
|
||||
if share_proto == 'NFS' and access_type not in ('ip', 'user'):
|
||||
LOG.warning(_LW('Only IP or USER access types are allowed for '
|
||||
@ -654,17 +652,17 @@ class V3StorageConnection(driver.HuaweiBase):
|
||||
access_to = access['access_to']
|
||||
share = self.helper._get_share_by_name(share_name, share_url_type)
|
||||
if not share:
|
||||
LOG.warning(_LW('Can not get share. share_name: %s'), share_name)
|
||||
LOG.warning(_LW('Can not get share %s.'), share_name)
|
||||
return
|
||||
|
||||
access_id = self.helper._get_access_from_share(share['ID'], access_to,
|
||||
share_client_type)
|
||||
share_proto)
|
||||
if not access_id:
|
||||
LOG.warning(_LW('Can not get access id from share. '
|
||||
'share_name: %s'), share_name)
|
||||
return
|
||||
|
||||
self.helper._remove_access_from_share(access_id, share_client_type)
|
||||
self.helper._remove_access_from_share(access_id, share_proto)
|
||||
|
||||
def allow_access(self, share, access, share_server=None):
|
||||
"""Allow access to the share."""
|
||||
@ -712,8 +710,52 @@ class V3StorageConnection(driver.HuaweiBase):
|
||||
raise exception.InvalidShareAccess(reason=err_msg)
|
||||
|
||||
share_id = share['ID']
|
||||
self.helper._allow_access_rest(share_id, access_to,
|
||||
share_proto, access_level)
|
||||
|
||||
# Check if access already exists
|
||||
access_id = self.helper._get_access_from_share(share_id,
|
||||
access_to,
|
||||
share_proto)
|
||||
if access_id:
|
||||
# Check if the access level equal
|
||||
level_exist = self.helper._get_level_by_access_id(access_id,
|
||||
share_proto)
|
||||
if level_exist != access_level:
|
||||
# Change the access level
|
||||
self.helper._change_access_rest(access_id,
|
||||
share_proto, access_level)
|
||||
else:
|
||||
# Add this access to share
|
||||
self.helper._allow_access_rest(share_id, access_to,
|
||||
share_proto, access_level)
|
||||
|
||||
def clear_access(self, share, share_server=None):
|
||||
"""Remove all access rules of the share"""
|
||||
share_proto = share['share_proto']
|
||||
share_name = share['name']
|
||||
share_url_type = self.helper._get_share_url_type(share_proto)
|
||||
share_stor = self.helper._get_share_by_name(share_name, share_url_type)
|
||||
if not share_stor:
|
||||
LOG.warning(_LW('Cannot get share %s.'), share_name)
|
||||
return
|
||||
share_id = share_stor['ID']
|
||||
all_accesses = self.helper._get_all_access_from_share(share_id,
|
||||
share_proto)
|
||||
for access_id in all_accesses:
|
||||
self.helper._remove_access_from_share(access_id,
|
||||
share_proto)
|
||||
|
||||
def update_access(self, share, access_rules, add_rules=None,
|
||||
delete_rules=None, share_server=None):
|
||||
"""Update access rules list."""
|
||||
if not (add_rules or delete_rules):
|
||||
self.clear_access(share, share_server)
|
||||
for access in access_rules:
|
||||
self.allow_access(share, access, share_server)
|
||||
else:
|
||||
for access in delete_rules:
|
||||
self.deny_access(share, access, share_server)
|
||||
for access in add_rules:
|
||||
self.allow_access(share, access, share_server)
|
||||
|
||||
def get_pool(self, share):
|
||||
pool_name = share_utils.extract_host(share['host'], level='pool')
|
||||
|
@ -376,12 +376,13 @@ class RestHelper(object):
|
||||
raise exception.InvalidInput(reason=message)
|
||||
return root
|
||||
|
||||
def _remove_access_from_share(self, access_id, access_type):
|
||||
def _remove_access_from_share(self, access_id, share_proto):
|
||||
access_type = self._get_share_client_type(share_proto)
|
||||
url = "/" + access_type + "/" + access_id
|
||||
result = self.call(url, None, "DELETE")
|
||||
self._assert_rest_result(result, 'delete access from share error!')
|
||||
|
||||
def _get_access_from_count(self, share_id, share_client_type):
|
||||
def _get_access_count(self, share_id, share_client_type):
|
||||
url_subfix = ("/" + share_client_type + "/count?"
|
||||
+ "filter=PARENTID::" + share_id)
|
||||
url = url_subfix
|
||||
@ -393,26 +394,48 @@ class RestHelper(object):
|
||||
|
||||
return int(result['data']['COUNT'])
|
||||
|
||||
def _get_access_from_share(self, share_id, access_to, share_client_type):
|
||||
def _get_all_access_from_share(self, share_id, share_proto):
|
||||
"""Return a list of all the access IDs of the share"""
|
||||
share_client_type = self._get_share_client_type(share_proto)
|
||||
count = self._get_access_count(share_id, share_client_type)
|
||||
|
||||
access_ids = []
|
||||
range_begin = 0
|
||||
while count > 0:
|
||||
access_range = self._get_access_from_share_range(share_id,
|
||||
range_begin,
|
||||
share_client_type)
|
||||
for item in access_range:
|
||||
access_ids.append(item['ID'])
|
||||
range_begin += 100
|
||||
count -= 100
|
||||
|
||||
return access_ids
|
||||
|
||||
def _get_access_from_share(self, share_id, access_to, share_proto):
|
||||
"""Segments to find access for a period of 100."""
|
||||
count = self._get_access_from_count(share_id, share_client_type)
|
||||
share_client_type = self._get_share_client_type(share_proto)
|
||||
count = self._get_access_count(share_id, share_client_type)
|
||||
|
||||
access_id = None
|
||||
range_begin = 0
|
||||
while True:
|
||||
if count < 0 or access_id:
|
||||
while count > 0:
|
||||
if access_id:
|
||||
break
|
||||
access_id = self._get_access_from_share_range(share_id,
|
||||
access_to,
|
||||
range_begin,
|
||||
share_client_type)
|
||||
access_range = self._get_access_from_share_range(share_id,
|
||||
range_begin,
|
||||
share_client_type)
|
||||
for item in access_range:
|
||||
if item['NAME'] in (access_to, '@' + access_to):
|
||||
access_id = item['ID']
|
||||
|
||||
range_begin += 100
|
||||
count -= 100
|
||||
|
||||
return access_id
|
||||
|
||||
def _get_access_from_share_range(self, share_id,
|
||||
access_to, range_begin,
|
||||
range_begin,
|
||||
share_client_type):
|
||||
range_end = range_begin + 100
|
||||
url = ("/" + share_client_type + "?filter=PARENTID::"
|
||||
@ -420,10 +443,55 @@ class RestHelper(object):
|
||||
+ "-" + six.text_type(range_end) + "]")
|
||||
result = self.call(url, None, "GET")
|
||||
self._assert_rest_result(result, 'Get access id by share error!')
|
||||
return result.get('data', [])
|
||||
|
||||
for item in result.get('data', []):
|
||||
if item['NAME'] in (access_to, '@' + access_to):
|
||||
return item['ID']
|
||||
def _get_level_by_access_id(self, access_id, share_proto):
|
||||
share_client_type = self._get_share_client_type(share_proto)
|
||||
url = "/" + share_client_type + "/" + access_id
|
||||
result = self.call(url, None, "GET")
|
||||
self._assert_rest_result(result, 'Get access information error!')
|
||||
access_info = result.get('data', [])
|
||||
access_level = access_info.get('ACCESSVAL')
|
||||
if not access_level:
|
||||
access_level = access_info.get('PERMISSION')
|
||||
return access_level
|
||||
|
||||
def _change_access_rest(self, access_id,
|
||||
share_proto, access_level):
|
||||
"""Change access level of the share."""
|
||||
if share_proto == 'NFS':
|
||||
self._change_nfs_access_rest(access_id, access_level)
|
||||
elif share_proto == 'CIFS':
|
||||
self._change_cifs_access_rest(access_id, access_level)
|
||||
else:
|
||||
raise exception.InvalidInput(
|
||||
reason=(_('Invalid NAS protocol supplied: %s.')
|
||||
% share_proto))
|
||||
|
||||
def _change_nfs_access_rest(self, access_id, access_level):
|
||||
url = "/NFS_SHARE_AUTH_CLIENT/" + access_id
|
||||
access = {
|
||||
"ACCESSVAL": access_level,
|
||||
"SYNC": "0",
|
||||
"ALLSQUASH": "1",
|
||||
"ROOTSQUASH": "0",
|
||||
}
|
||||
data = jsonutils.dumps(access)
|
||||
result = self.call(url, data, "PUT")
|
||||
|
||||
msg = 'Change access error.'
|
||||
self._assert_rest_result(result, msg)
|
||||
|
||||
def _change_cifs_access_rest(self, access_id, access_level):
|
||||
url = "/CIFS_SHARE_AUTH_CLIENT/" + access_id
|
||||
access = {
|
||||
"PERMISSION": access_level,
|
||||
}
|
||||
data = jsonutils.dumps(access)
|
||||
result = self.call(url, data, "PUT")
|
||||
|
||||
msg = 'Change access error.'
|
||||
self._assert_rest_result(result, msg)
|
||||
|
||||
def _allow_access_rest(self, share_id, access_to,
|
||||
share_proto, access_level):
|
||||
|
@ -492,18 +492,31 @@ class FakeHuaweiNasHelper(helper.RestHelper):
|
||||
"filter=PARENTID::1&range=[100-200]":
|
||||
data = """{"error":{"code":0},
|
||||
"data":[{"ID":"5",
|
||||
"NAME":"100.112.0.1"}]}"""
|
||||
"NAME":"100.112.0.2"}]}"""
|
||||
|
||||
if url == "/CIFS_SHARE_AUTH_CLIENT?"\
|
||||
"filter=PARENTID::2&range=[100-200]":
|
||||
data = """{"error":{"code":0},
|
||||
"data":[{"ID":"6",
|
||||
"NAME":"user_name"}]}"""
|
||||
"NAME":"user_exist"}]}"""
|
||||
|
||||
if url == "/NFS_SHARE_AUTH_CLIENT/5"\
|
||||
or url == "/CIFS_SHARE_AUTH_CLIENT/6":
|
||||
data = """{"error":{"code":0}}"""
|
||||
self.deny_flag = True
|
||||
if url in ("/NFS_SHARE_AUTH_CLIENT/0",
|
||||
"/NFS_SHARE_AUTH_CLIENT/5",
|
||||
"/CIFS_SHARE_AUTH_CLIENT/0",
|
||||
"/CIFS_SHARE_AUTH_CLIENT/6"):
|
||||
if method == "DELETE":
|
||||
data = """{"error":{"code":0}}"""
|
||||
self.deny_flag = True
|
||||
elif method == "GET":
|
||||
if 'CIFS' in url:
|
||||
data = """{"error":{"code":0},
|
||||
"data":{"'PERMISSION'":"0"}}"""
|
||||
else:
|
||||
data = """{"error":{"code":0},
|
||||
"data":{"ACCESSVAL":"0"}}"""
|
||||
else:
|
||||
data = """{"error":{"code":0}}"""
|
||||
self.allow_rw_flagg = True
|
||||
|
||||
if url == "/NFSHARE/count" or url == "/CIFSHARE/count":
|
||||
data = """{"error":{"code":0},"data":{
|
||||
@ -944,12 +957,24 @@ class HuaweiShareDriverTestCase(test.TestCase):
|
||||
'access_level': 'rw',
|
||||
}
|
||||
|
||||
self.access_ip_exist = {
|
||||
'access_type': 'ip',
|
||||
'access_to': '100.112.0.2',
|
||||
'access_level': 'rw',
|
||||
}
|
||||
|
||||
self.access_user = {
|
||||
'access_type': 'user',
|
||||
'access_to': 'user_name',
|
||||
'access_level': 'rw',
|
||||
}
|
||||
|
||||
self.access_user_exist = {
|
||||
'access_type': 'user',
|
||||
'access_to': 'user_exist',
|
||||
'access_level': 'rw',
|
||||
}
|
||||
|
||||
self.access_group = {
|
||||
'access_type': 'user',
|
||||
'access_to': 'group_name',
|
||||
@ -2243,6 +2268,59 @@ class HuaweiShareDriverTestCase(test.TestCase):
|
||||
self._context, self.share_cifs,
|
||||
access_fail, self.share_server)
|
||||
|
||||
def test_update_access_add_delete(self):
|
||||
self.driver.plugin.helper.login()
|
||||
self.allow_flag = False
|
||||
self.allow_rw_flag = False
|
||||
self.deny_flag = False
|
||||
add_rules = [self.access_ip]
|
||||
delete_rules = [self.access_ip_exist]
|
||||
self.driver.update_access(self._context,
|
||||
self.share_nfs,
|
||||
None,
|
||||
add_rules,
|
||||
delete_rules,
|
||||
self.share_server)
|
||||
self.assertTrue(self.driver.plugin.helper.allow_flag)
|
||||
self.assertTrue(self.driver.plugin.helper.allow_rw_flag)
|
||||
self.assertTrue(self.driver.plugin.helper.deny_flag)
|
||||
|
||||
def test_update_access_nfs(self):
|
||||
self.driver.plugin.helper.login()
|
||||
self.allow_flag = False
|
||||
self.allow_rw_flag = False
|
||||
rules = [self.access_ip, self.access_ip_exist]
|
||||
self.driver.update_access(self._context,
|
||||
self.share_nfs,
|
||||
rules,
|
||||
None,
|
||||
None,
|
||||
self.share_server)
|
||||
self.assertTrue(self.driver.plugin.helper.allow_flag)
|
||||
self.assertTrue(self.driver.plugin.helper.allow_rw_flag)
|
||||
|
||||
def test_update_access_cifs(self):
|
||||
self.driver.plugin.helper.login()
|
||||
self.allow_flag = False
|
||||
self.allow_rw_flag = False
|
||||
rules = [self.access_user, self.access_user_exist]
|
||||
self.driver.update_access(self._context,
|
||||
self.share_cifs,
|
||||
rules,
|
||||
None,
|
||||
None,
|
||||
self.share_server)
|
||||
self.assertTrue(self.driver.plugin.helper.allow_flag)
|
||||
self.assertTrue(self.driver.plugin.helper.allow_rw_flag)
|
||||
|
||||
def test_update_access_rules_share_not_exist(self):
|
||||
self.driver.plugin.helper.login()
|
||||
rules = [self.access_ip]
|
||||
self.driver.plugin.helper.share_exist = False
|
||||
self.assertRaises(exception.InvalidShareAccess,
|
||||
self.driver.update_access, self._context,
|
||||
self.share_nfs, rules, None, None, self.share_server)
|
||||
|
||||
def test_get_share_client_type_fail(self):
|
||||
share_proto = 'fake_proto'
|
||||
self.assertRaises(exception.InvalidInput,
|
||||
@ -2329,14 +2407,14 @@ class HuaweiShareDriverTestCase(test.TestCase):
|
||||
self.driver.plugin.helper.login()
|
||||
self.deny_flag = False
|
||||
self.driver.deny_access(self._context, self.share_nfs,
|
||||
self.access_ip, self.share_server)
|
||||
self.access_ip_exist, self.share_server)
|
||||
self.assertTrue(self.driver.plugin.helper.deny_flag)
|
||||
|
||||
def test_deny_access_user_success(self):
|
||||
self.driver.plugin.helper.login()
|
||||
self.deny_flag = False
|
||||
self.driver.deny_access(self._context, self.share_cifs,
|
||||
self.access_user, self.share_server)
|
||||
self.access_user_exist, self.share_server)
|
||||
self.assertTrue(self.driver.plugin.helper.deny_flag)
|
||||
|
||||
def test_deny_access_ip_fail(self):
|
||||
|
Loading…
x
Reference in New Issue
Block a user