Skip to content

Commit

Permalink
Merge pull request #68 from huangpeng5/suyan_715
Browse files Browse the repository at this point in the history
modify multi proto access func
  • Loading branch information
huangpeng5 authored Jul 19, 2024
2 parents b3ed876 + 407dbf5 commit 5eaec36
Show file tree
Hide file tree
Showing 5 changed files with 155 additions and 65 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -177,25 +177,6 @@ def _get_all_share_tier_policy(self):
self._get_share_tier_policy(tier_info, 'tier_migrate_expiration')
return tier_info

def _get_share_access_proto(self):
"""
1.Multi proto:Get access proto from metadata or share instance
from key access_proto
Priority Level: metadata > share_instance
2.Single proto: Get access proto from share type or share instance
from key share_proto
Priority Level: share type > share_instance
:return:
"""
metadata_access_proto = self.share_metadata.get('access_proto')
instance_access_proto = self.share.get('access_proto')

access_proto = metadata_access_proto or instance_access_proto
if access_proto:
return [access_proto]

return self.share_proto

def _get_forbidden_dpc_param(self):
if 'DPC' in self.share_proto:
return constants.NOT_FORBIDDEN_DPC
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from manila.i18n import _

from ..change_access import ChangeAccess
from ...utils import constants
from ...utils import constants, driver_utils

LOG = log.getLogger(__name__)

Expand All @@ -38,7 +38,8 @@ def __init__(self, client, share=None, driver_config=None,
self.export_locations = None # share路径信息
self.nfs_share_id = None
self.cifs_share_id = None
self.access_proto = None
self.allow_access_proto = {}
self.deny_access_proto = {}
self.nfs_rules = []
self.cifs_rules = []
self.dpc_rules = []
Expand All @@ -49,35 +50,50 @@ def get_impl_type():

def update_access(self, access_rules, add_rules, delete_rules):
"""Update access rules list."""
if add_rules:
self._get_share_access_proto(add_rules, True)
if delete_rules:
self._get_share_access_proto(delete_rules, False)
if not add_rules and not delete_rules:
self._get_share_access_proto(access_rules, True)
self._get_account_and_namespace_information()
self._update_access_for_share(access_rules, add_rules, delete_rules)
self._update_access_for_share(add_rules, delete_rules)

def allow_access(self, access):
self._get_share_access_proto([access], True)
self._get_account_and_namespace_information()
self._classify_rules([access], 'allow')
self._classify_rules(self.allow_access_proto, 'allow')

def deny_access(self, access):
self._get_share_access_proto([access], False)
self._get_account_and_namespace_information()
self._classify_rules([access], 'deny')
self._classify_rules(self.deny_access_proto, 'deny')

def _get_account_and_namespace_information(self):
self._get_account_id()
self._get_export_location_info()
self._get_share_related_info()
self._query_and_set_share_info()

def _classify_rules(self, rules, action):

for access in rules:
access_type = access['access_type']
if 'NFS' in self.access_proto and access_type == 'ip':
self.nfs_rules.append(access)
def _classify_rules(self, access_rules, action):
access_type_key = 'access_type'
self.nfs_rules = []
self.cifs_rules = []
self.dpc_rules = []
nfs_access_rules = access_rules.get('NFS', [])
cifs_access_rules = access_rules.get('CIFS', [])
dpc_access_rules = access_rules.get('DPC', [])
for nfs_access_rule in nfs_access_rules:
if nfs_access_rule.get(access_type_key) == 'ip':
self.nfs_rules.append(nfs_access_rule)

if 'CIFS' in self.access_proto and access_type == 'user':
self.cifs_rules.append(access)
for cifs_access_rule in cifs_access_rules:
if cifs_access_rule.get(access_type_key) == 'user':
self.cifs_rules.append(cifs_access_rule)

if 'DPC' in self.access_proto and access_type == 'ip':
self.dpc_rules.append(access)
for dpc_access_rule in dpc_access_rules:
if dpc_access_rule.get(access_type_key) == 'ip':
self.dpc_rules.append(dpc_access_rule)

if self.nfs_rules:
self._deal_access_for_nfs(action)
Expand Down Expand Up @@ -172,41 +188,42 @@ def _deal_access_for_dpc(self, action):
LOG.info("Will be remove dpc access.(nums: {0})".format(len(dpc_ips)))
self.client.deny_access_for_dpc(self.namespace_name, ','.join(dpc_ips))

def _sync_access(self, access_rules):
def _sync_access(self):
"""Sync all access rules of the share between storage and platform"""
access_value_key = 'access_value'
client_id_key = 'access_value'
if 'NFS' in self.access_proto:
client_id_key = 'client_id'
if 'NFS' in self.allow_access_proto:
result = self.client.query_nfs_share_clients_information(self.nfs_share_id, self.account_id)
deny_rules, allow_rules, change_rules = self._get_need_update_access(
result, access_rules, 'access_name', access_value_key)
for deny_rule in deny_rules:
result, self.allow_access_proto.get('NFS', []), 'access_name',
access_value_key)
for _, deny_rule in deny_rules.items():
self.client.deny_access_for_nfs(deny_rule.get(client_id_key), self.account_id)
for allow_rule in allow_rules:
for _, allow_rule in allow_rules.items():
self.client.allow_access_for_nfs(
self.nfs_share_id, allow_rule.get('access_to'),
allow_rule.get('access_level'), self.account_id)
for change_rule in change_rules:
for _, change_rule in change_rules.items():
self.client.change_access_for_nfs(
change_rule.get(client_id_key),
change_rule.get(access_value_key), self.account_id)
if 'CIFS' in self.access_proto:
if 'CIFS' in self.allow_access_proto:
result = self.client.query_cifs_share_user_information(self.cifs_share_id, self.account_id)
deny_rules, allow_rules, change_rules = self._get_need_update_access(
result, access_rules, 'name', 'permission')
for deny_rule in deny_rules:
result, self.allow_access_proto.get('CIFS', []), 'name', 'permission')
for _, deny_rule in deny_rules.items():
self.client.deny_access_for_cifs(deny_rule.get(client_id_key), self.account_id)
for allow_rule in allow_rules:
for _, allow_rule in allow_rules.items():
self.client.allow_access_for_cifs(
self.cifs_share_id, allow_rule.get('access_to'),
allow_rule.get('access_level'), self.account_id)
for change_rule in change_rules:
for _, change_rule in change_rules.items():
self.client.change_access_for_cifs(
change_rule.get(client_id_key),
change_rule.get(access_value_key), self.account_id)
if 'DPC' in self.access_proto:
if 'DPC' in self.allow_access_proto:
self.client.deny_access_for_dpc(self.namespace_name, '*')
self._classify_rules(access_rules, 'allow')
self._classify_rules(self.allow_access_proto, 'allow')

def _get_need_update_access(self, storage_access_list, access_rules, access_param,
permission_param):
Expand Down Expand Up @@ -236,7 +253,7 @@ def _get_need_update_access(self, storage_access_list, access_rules, access_para
elif access_info.get(access_level_key) != access_level:
need_change_access_info[access_to] = {
client_id_key: access_info.get(client_id_key),
'access_value': rule.get(access_level_key),
'access_value': access_level,
}
need_remove_access_info.pop(access_to)
else:
Expand Down Expand Up @@ -264,8 +281,7 @@ def _get_share_related_info(self):
def _query_and_set_share_info(self, dtree_id=0, dtree_name=None):
"""根据share_path信息查询对应的share信息"""

self.access_proto = self._get_share_access_proto()
if 'NFS' in self.access_proto:
if 'NFS' in (self.allow_access_proto or self.deny_access_proto):
result = self.client.query_nfs_share_information(
self.account_id, self.namespace_id, dtree_id)
for nfs_share in result:
Expand All @@ -276,7 +292,7 @@ def _query_and_set_share_info(self, dtree_id=0, dtree_name=None):
err_msg = _("Cannot get NFS share id(namespace_name:{0}).".format(self.namespace_name))
raise exception.InvalidShare(reason=err_msg)

if 'CIFS' in self.access_proto:
if 'CIFS' in (self.allow_access_proto or self.deny_access_proto):
result = self.client.query_cifs_share_information(
self.account_id, dtree_name if dtree_name else self.namespace_name)
for cifs_share in result:
Expand All @@ -287,12 +303,80 @@ def _query_and_set_share_info(self, dtree_id=0, dtree_name=None):
err_msg = _("Cannot get CIFS share id(namespace_name:{0}).".format(self.namespace_name))
raise exception.InvalidShare(reason=err_msg)

def _update_access_for_share(self, access_rules, add_rules, delete_rules):
def _update_access_for_share(self, add_rules, delete_rules):
"""根据传入的参数为共享添加或者移除权限"""

if add_rules:
self._classify_rules(add_rules, 'allow')
self._classify_rules(self.allow_access_proto, 'allow')
if delete_rules:
self._classify_rules(delete_rules, 'deny')
self._classify_rules(self.deny_access_proto, 'deny')
if not (add_rules or delete_rules):
self._sync_access(access_rules)
self._sync_access()

def _get_share_access_proto(self, all_rules, is_allow):
"""
1.Multi proto:Get access proto from metadata or access_rule
from key access_proto
Priority Level: metadata > access_rule
2.Single proto: Get access proto from share type or share instance
from key share_proto
Priority Level: share type > share_instance
:return:
"""
all_access_proto = {}
metadata_access_proto = self.share_metadata.get('access_proto')
if not metadata_access_proto:
all_access_proto = self._get_access_proto_by_access_rules(all_rules)
elif metadata_access_proto not in self.share_proto:
error_msg = ("access proto %s is not exist in share proto %s" %
(metadata_access_proto, self.share_proto))
LOG.error(error_msg)
raise exception.InvalidInput(error_msg)
else:
all_access_proto[metadata_access_proto] = all_rules

# 如果没有获取到一个权限列表,在同步权限的场景下,需要将存储上对应协议类型的已授权列表移除掉
if not all_access_proto:
for share_proto in self.share_proto:
all_access_proto[share_proto] = []

if is_allow:
self.allow_access_proto = all_access_proto
else:
self.deny_access_proto = all_access_proto

def _get_access_proto_by_access_rules(self, all_rules):
"""
In the multi-protocol scenario, when the upper layer
specifies the protocol authorization or removes the authorization,
the NFS or DPC request may be delivered at the same time.
In this case, the driver needs to classify the authorization
requests by protocol type.
:param all_rules: Total Authorization List
:return: Authorization dict classified by protocol
"""
all_access_proto = {}
if not all_rules:
return {}

for access_rule in all_rules:
access_proto = access_rule.get('access_proto')
# 如果上层未指定要授权的协议类型,则对当前share支持的所有协议类型进行授权
if not access_proto:
for share_proto in self.share_proto:
driver_utils.add_or_update_dict_key(
all_access_proto, share_proto, access_rule)
# 如果上层指定了要授权的协议类型,且指定的协议在当前share支持的协议白名单中,
# 则对指定的协议进行授权
elif access_proto in self.share_proto:
driver_utils.add_or_update_dict_key(
all_access_proto, access_proto, access_rule)
# 如果上层指定了要授权的协议类型,且指定的协议不在当前share支持的协议白名单中,则报错
else:
error_msg = ("the access_proto of access rule %s is not exist in "
"share proto %s, please check" %
(access_rule, self.share_proto))
LOG.error(error_msg)
raise exception.InvalidInput(error_msg)

return all_access_proto
Original file line number Diff line number Diff line change
Expand Up @@ -37,27 +37,35 @@ def get_impl_type():
return constants.PLUGIN_SUYAN_GFS_IMPL

def update_access(self, access_rules, add_rules, delete_rules):
if add_rules:
self._get_share_access_proto(add_rules, True)
if delete_rules:
self._get_share_access_proto(delete_rules, False)
if not add_rules and not delete_rules:
self._get_share_access_proto(access_rules, True)
self._get_share_info()
self._update_access_for_share(access_rules, add_rules, delete_rules)
self._update_access_for_share(add_rules, delete_rules)

def allow_access(self, access):
self._get_share_access_proto([access], True)
self._get_share_info()
self._classify_rules([access], 'allow')

def deny_access(self, access):
self._get_share_access_proto([access], False)
self._get_share_info()
self._classify_rules([access], 'deny')

def _sync_access(self, access_rules):
def _sync_access(self):
gfs_param = {
'cluster_classification_name': self.storage_pool_name,
'name': self.namespace_name,
'is_remove_all': True
}
result = self.client.remove_ipaddress_from_gfs(gfs_param)
self.client.wait_task_until_complete(result.get('task_id'))
if 'DPC' in self.access_proto:
self._classify_rules(access_rules, 'allow')
if 'DPC' in self.allow_access_proto:
self._classify_rules(self.allow_access_proto, 'allow')

def _get_share_info(self):
"""
Expand All @@ -71,8 +79,6 @@ def _get_share_info(self):
else:
self.namespace_name = 'share-' + self.share_parent_id

self.access_proto = self._get_share_access_proto()

def _deal_access_for_dpc(self, action):
"""
allow or deny dpc ips for dpc gfs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,14 @@ def update_access(self, access_rules, add_rules, delete_rules):
access_rules, add_rules, delete_rules)
return

if add_rules:
self._get_share_access_proto(add_rules, True)
if delete_rules:
self._get_share_access_proto(delete_rules, False)
if not add_rules and not delete_rules:
self._get_share_access_proto(access_rules, True)
self._get_account_and_share_related_information()
self._update_access_for_share(access_rules, add_rules, delete_rules)
self._update_access_for_share(add_rules, delete_rules)
return

def allow_access(self, access):
Expand All @@ -54,8 +60,9 @@ def allow_access(self, access):
super(SuyanSingleChangeAccess, self).allow_access(access)
return

self._get_share_access_proto([access], True)
self._get_account_and_share_related_information()
self._classify_rules([access], 'allow')
self._classify_rules(self.allow_access_proto, 'allow')
return

def deny_access(self, access):
Expand All @@ -65,8 +72,9 @@ def deny_access(self, access):
super(SuyanSingleChangeAccess, self).deny_access(access)
return

self._get_share_access_proto([access], False)
self._get_account_and_share_related_information()
self._classify_rules([access], 'deny')
self._classify_rules(self.deny_access_proto, 'deny')
return

def _get_account_and_share_related_information(self):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,17 @@ def convert_capacity(cap, org_unit, tgt_unit):
return cap


def add_or_update_dict_key(tgt_dict, tgt_key, tgt_value):
"""
when tgt dict not have tgt_key,and tgt_key and set tgt_value in a new list
otherwise, append new_value in existed list
"""
if tgt_key not in tgt_dict:
tgt_dict[tgt_key] = [tgt_value]
else:
tgt_dict.get(tgt_key).append(tgt_value)


class MyThread(threading.Thread):
def __init__(self, func, *args):
super(MyThread, self).__init__()
Expand Down

0 comments on commit 5eaec36

Please sign in to comment.