Merge "Implement update_access() method in huawei driver"

This commit is contained in:
Jenkins 2016-02-29 18:25:39 +00:00 committed by Gerrit Code Review
commit 83d7bc60f4
5 changed files with 232 additions and 32 deletions

View File

@ -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."""

View File

@ -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.")

View File

@ -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')

View File

@ -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):

View File

@ -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):