diff --git a/Manila/file_driver_dir/huawei/oceanstorPacific/connection.py b/Manila/file_driver_dir/huawei/oceanstorPacific/connection.py index 8b86d07..309b05d 100644 --- a/Manila/file_driver_dir/huawei/oceanstorPacific/connection.py +++ b/Manila/file_driver_dir/huawei/oceanstorPacific/connection.py @@ -62,34 +62,34 @@ def update_share_stats(self, data): def create_share(self, context, share, share_server): """创建共享,同时返回挂载路径信息""" - location = driver_api.OperateShare(self.helper, share).create_share(self.root, self.free_pool) + location = driver_api.OperateShare(self.helper, share, self.root).create_share(self.free_pool) return location def delete_share(self, context, share, share_server): """删除共享""" - driver_api.OperateShare(self.helper, share).delete_share() + driver_api.OperateShare(self.helper, share, self.root).delete_share() def ensure_share(self, share, share_server): """检查共享状态,同时返回挂载路径信息""" - location = driver_api.OperateShare(self.helper, share).ensure_share() + location = driver_api.OperateShare(self.helper, share, self.root).ensure_share() return location def extend_share(self, share, new_size, share_server): """扩容共享""" - driver_api.OperateShare(self.helper, share).change_share(new_size, 'extend') + driver_api.OperateShare(self.helper, share, self.root).change_share(new_size, 'extend') def shrink_share(self, share, new_size, share_server): """缩容共享""" - driver_api.OperateShare(self.helper, share).change_share(new_size, 'shrink') + driver_api.OperateShare(self.helper, share, self.root).change_share(new_size, 'shrink') def allow_access(self, share, access, share_server): """在共享上添加一条鉴权信息""" - driver_api.ChangeAccess(self.helper, share).allow_access(access) + driver_api.ChangeAccess(self.helper, share, self.root).allow_access(access) def deny_access(self, share, access, share_server): """在共享上删除一条鉴权信息""" - driver_api.ChangeAccess(self.helper, share).deny_access(access) + driver_api.ChangeAccess(self.helper, share, self.root).deny_access(access) def update_access(self, share, access_rules, add_rules, delete_rules, share_server): """更新共享的鉴权信息,主要用于批量添加/删除鉴权信息""" - driver_api.ChangeAccess(self.helper, share).update_access(access_rules, add_rules, delete_rules) + driver_api.ChangeAccess(self.helper, share, self.root).update_access(access_rules, add_rules, delete_rules) diff --git a/Manila/file_driver_dir/huawei/oceanstorPacific/customization_connection.py b/Manila/file_driver_dir/huawei/oceanstorPacific/customization_connection.py index be1ff0e..75b2d46 100644 --- a/Manila/file_driver_dir/huawei/oceanstorPacific/customization_connection.py +++ b/Manila/file_driver_dir/huawei/oceanstorPacific/customization_connection.py @@ -34,12 +34,12 @@ def __init__(self, root): def create_share(self, context, share, share_server): """苏研qos为定制的参数,所以此处重写qos相关解析方法""" - location = driver_api.CustomizationOperate(self.helper, share).create_share(self.root, self.free_pool) + location = driver_api.CustomizationOperate(self.helper, share, self.root).create_share(self.free_pool) return location def delete_share(self, context, share, share_server): """删除share接口,苏研配置单独的一个账户用于创建ip""" - driver_api.CustomizationOperate(self.helper, share).set_root(self.root).delete_share() + driver_api.CustomizationOperate(self.helper, share, self.root).delete_share() def allow_access(self, share, access, share_server): """在共享上添加一条鉴权信息,苏研配置单独的一个账户用于创建ip""" @@ -78,7 +78,7 @@ def get_share_usage(self, share, share_usages): “used_space”: 已使用容量 } """ - share_capacity = driver_api.CustomizationOperate(self.helper, share).get_share_usage(share_usages) + share_capacity = driver_api.CustomizationOperate(self.helper, share, self.root).get_share_usage(share_usages) return share_capacity def update_qos(self, share, qos_specs): @@ -92,7 +92,7 @@ def update_qos(self, share, qos_specs): } :return: None """ - driver_api.CustomizationOperate(self.helper, share).update_qos(qos_specs, self.root) + driver_api.CustomizationOperate(self.helper, share, self.root).update_qos(qos_specs) def parse_cmcc_qos_options(self, share): """ @@ -104,20 +104,20 @@ def parse_cmcc_qos_options(self, share): “total_iops_sec”: 总IOPS, } """ - share_qos_info = driver_api.CustomizationOperate(self.helper, share).parse_cmcc_qos_options() + share_qos_info = driver_api.CustomizationOperate(self.helper, share, self.root).parse_cmcc_qos_options() return share_qos_info def ensure_share(self, share, share_server): """ 校验shre的状态,苏研定制接口下二级目录获取namespace的方式有变化 """ - location = driver_api.CustomizationOperate(self.helper, share).ensure_share() + location = driver_api.CustomizationOperate(self.helper, share, self.root).ensure_share() return location def extend_share(self, share, new_size, share_server): """苏研定制需求需要对二级目录实现扩容,因此重新此方法""" - driver_api.CustomizationOperate(self.helper, share).change_share(new_size, 'extend') + driver_api.CustomizationOperate(self.helper, share, self.root).change_share(new_size, 'extend') def shrink_share(self, share, new_size, share_server): """苏研定制需求需要对二级目录实现缩容,因此重新此方法""" - driver_api.CustomizationOperate(self.helper, share).change_share(new_size, 'shrink') + driver_api.CustomizationOperate(self.helper, share, self.root).change_share(new_size, 'shrink') diff --git a/Manila/file_driver_dir/huawei/oceanstorPacific/driver_api/base_share_property.py b/Manila/file_driver_dir/huawei/oceanstorPacific/driver_api/base_share_property.py new file mode 100644 index 0000000..f9ddc36 --- /dev/null +++ b/Manila/file_driver_dir/huawei/oceanstorPacific/driver_api/base_share_property.py @@ -0,0 +1,89 @@ +# coding=utf-8 +# Copyright (c) 2024 Huawei Technologies Co., Ltd. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import netaddr +from oslo_log import log +from manila import exception +from manila.share import share_types +from manila.i18n import _ + +LOG = log.getLogger(__name__) + + +class BaseShareProperty(object): + def __init__(self, helper, share=None, root=None): + self.helper = helper + self.share = share + self.root = root + self.account_id = None + self.account_name = None + self.share_proto = self._get_share_proto() + + @staticmethod + def standard_ipaddr(access): + """ + When the added client permission is an IP address, + standardize it. Otherwise, do not process it. + """ + try: + format_ip = netaddr.IPAddress(access) + access_to = str(format_ip.format(dialect=netaddr.ipv6_compact)) + return access_to + except Exception: + return access + + @staticmethod + def is_ipv4_address(ip_address): + try: + if netaddr.IPAddress(ip_address).version == 4: + return True + return False + except Exception: + return False + + def _get_account_name(self): + LOG.info("Get account name from xml.") + if self.root is None: + err_msg = _("Can not get account name from config.") + LOG.error(err_msg) + raise exception.InvalidShare(reason=err_msg) + account_name = self.root.findtext('Filesystem/AccountName').strip() + if not account_name: + err_msg = "Can not get account_name from xml, please check." + LOG.error(err_msg) + raise exception.InvalidShare(reason=err_msg) + return account_name + + def _get_account_id(self): + self.account_name = self._get_account_name() + result = self.helper.query_account_by_name(self.account_name) + self.account_id = result.get('id') + + def _get_share_proto(self): + share_proto = [] + if self.share is None: + return share_proto + + type_id = self.share.get('share_type_id') + extra_specs = share_types.get_share_type_extra_specs(type_id) + tmp_share_proto = extra_specs.get('share_proto', '').split('&') + + if 'DPC' in tmp_share_proto: + share_proto.append('DPC') + return share_proto + + return self.share.get('share_proto', '').split('&') + diff --git a/Manila/file_driver_dir/huawei/oceanstorPacific/driver_api/change_access.py b/Manila/file_driver_dir/huawei/oceanstorPacific/driver_api/change_access.py index 3300e27..ba7cbdf 100644 --- a/Manila/file_driver_dir/huawei/oceanstorPacific/driver_api/change_access.py +++ b/Manila/file_driver_dir/huawei/oceanstorPacific/driver_api/change_access.py @@ -14,26 +14,22 @@ # License for the specific language governing permissions and limitations # under the License. -import netaddr from oslo_log import log from manila import exception from manila.common import constants as common_constants from manila.i18n import _ +from .base_share_property import BaseShareProperty LOG = log.getLogger(__name__) -class ChangeAccess(object): - def __init__(self, helper, share): - self.helper = helper - self.share = share - - self.account_id = None +class ChangeAccess(BaseShareProperty): + def __init__(self, helper, share, root): + super(ChangeAccess, self).__init__(helper, share=share, root=root) self.namespace_name = None self.namespace_id = None - self.share_proto = self.share.get('share_proto', '').split('&') self.share_path = None self.export_locations = None # share路径信息 self.nfs_share_id = None @@ -55,13 +51,8 @@ def deny_access(self, access): self._get_account_and_namespace_information() self._classify_rules([access], 'deny') - def _find_account_id(self): - account_name = self.share.get('project_id') - result = self.helper.query_account_by_name(account_name) - self.account_id = result.get('id') - def _get_account_and_namespace_information(self): - self._find_account_id() + self._get_account_id() self._get_export_location_info() self._get_share_related_info() self._query_and_set_share_info() @@ -139,50 +130,92 @@ def _deal_access_for_cifs(self, action): LOG.info(_("The access_to {0} does not exist").format(access_to)) def _deal_access_for_dpc(self, action): - if action == 'allow': LOG.info(_("Will be add dpc access.(nums: {0})".format(len(self.dpc_rules)))) if action == 'deny': LOG.info(_("Will be delete dpc access.(nums: {0})".format(len(self.dpc_rules)))) for index in range(0, len(self.dpc_rules), 200): - dpc_ips = "" + dpc_ips = [] for access in self.dpc_rules[index:index + 200]: access_to = self.standard_ipaddr(access.get('access_to')) - - if not dpc_ips: - dpc_ips += access_to - else: - dpc_ips += ',' + access_to + if action == "deny" and not self.is_ipv4_address(access_to): + LOG.warning('DPC authentication now is not support IPV6 address, ' + 'skip it , ipaddress is %s', access_to) + continue + dpc_ips.append(access_to) if action == "allow": - self.helper.allow_access_for_dpc(self.namespace_name, dpc_ips) - elif action == "deny": - self.helper.deny_access_for_dpc(self.namespace_name, dpc_ips) + self.helper.allow_access_for_dpc(self.namespace_name, ','.join(dpc_ips)) + elif dpc_ips: + self.helper.deny_access_for_dpc(self.namespace_name, ','.join(dpc_ips)) - def _clear_access(self): - """Remove all access rules of the share""" + def _sync_access(self, access_rules): + """Sync all access rules of the share between storage and platform""" if 'NFS' in self.share_proto: result = self.helper.query_nfs_share_clients_information(self.nfs_share_id, self.account_id) - for data in result: - self.helper.deny_access_for_nfs(data.get('id'), self.account_id) - if self.share_proto == 'CIFS': + deny_rules, allow_rules, change_rules = self._get_need_update_access( + result, access_rules, 'access_name', 'access_value') + for deny_rule in deny_rules: + self.helper.deny_access_for_nfs(deny_rule.get('client_id'), self.account_id) + for allow_rule in allow_rules: + self.helper.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: + self.helper.change_access_for_nfs( + change_rule.get('client_id'), + change_rule.get('access_value'), self.account_id) + if 'CIFS' in self.share_proto: result = self.helper.query_cifs_share_user_information(self.cifs_share_id, self.account_id) - for data in result: - self.helper.deny_access_for_cifs(data.get('id'), self.account_id) - - @staticmethod - def standard_ipaddr(access): - """ - When the added client permission is an IP address, - standardize it. Otherwise, do not process it. - """ - try: - format_ip = netaddr.IPAddress(access) - access_to = str(format_ip.format(dialect=netaddr.ipv6_compact)) - return access_to - except Exception: - return access + deny_rules, allow_rules, change_rules = self._get_need_update_access( + result, access_rules, 'name', 'permission') + for deny_rule in deny_rules: + self.helper.deny_access_for_cifs(deny_rule.get('client_id'), self.account_id) + for allow_rule in allow_rules: + self.helper.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: + self.helper.change_access_for_cifs( + change_rule.get('client_id'), + change_rule.get('access_value'), self.account_id) + if 'DPC' in self.share_proto: + self.helper.deny_access_for_dpc(self.namespace_name, '*') + self._classify_rules(access_rules, 'allow') + + def _get_need_update_access(self, storage_access_list, access_rules, access_param, + permission_param): + """get all need deny access rules/allow access rules/change access rules""" + need_remove_access_info = {} + need_add_access_info = {} + need_change_access_info = {} + for data in storage_access_list: + access_name = self.standard_ipaddr(data.get(access_param)) + need_remove_access_info[access_name] = { + 'access_to': access_name, + 'access_level': data.get(permission_param), + 'client_id': data.get('id') + } + for rule in access_rules: + access_to = self.standard_ipaddr(rule.get('access_to')) + access_level = 0 if rule.get('access_level') == 'ro' else 1 + access_info = need_remove_access_info.get(access_to) + if not access_info: + need_add_access_info[access_to] = { + 'access_to': access_to, + 'access_level': rule.get('access_level') + } + elif access_info.get('access_level') != access_level: + need_change_access_info['access_to'] = { + 'client_id': access_info.get('client_id'), + 'access_value': rule.get('access_level'), + } + need_remove_access_info.pop(access_to) + else: + need_remove_access_info.pop(access_to) + + return need_remove_access_info, need_add_access_info, need_change_access_info def _get_export_location_info(self): """校验share是否包含path信息,有则初始化""" @@ -234,5 +267,4 @@ def _update_access_for_share(self, access_rules, add_rules, delete_rules): if delete_rules: self._classify_rules(delete_rules, 'deny') if not (add_rules or delete_rules): - self._clear_access() - self._classify_rules(access_rules, 'allow') + self._sync_access(access_rules) diff --git a/Manila/file_driver_dir/huawei/oceanstorPacific/driver_api/check_update_storage.py b/Manila/file_driver_dir/huawei/oceanstorPacific/driver_api/check_update_storage.py index 3041e32..1432f95 100644 --- a/Manila/file_driver_dir/huawei/oceanstorPacific/driver_api/check_update_storage.py +++ b/Manila/file_driver_dir/huawei/oceanstorPacific/driver_api/check_update_storage.py @@ -19,16 +19,15 @@ from manila import exception from manila.i18n import _ +from .base_share_property import BaseShareProperty from ..helper import constants LOG = log.getLogger(__name__) -class CheckUpdateStorage(object): +class CheckUpdateStorage(BaseShareProperty): def __init__(self, helper, root): - self.helper = helper - self.root = root - + super(CheckUpdateStorage, self).__init__(helper, root=root) self.pools_free = {} self.free_pool = None diff --git a/Manila/file_driver_dir/huawei/oceanstorPacific/driver_api/customization_for_suyan.py b/Manila/file_driver_dir/huawei/oceanstorPacific/driver_api/customization_for_suyan.py index 3a938ac..8cc4df1 100644 --- a/Manila/file_driver_dir/huawei/oceanstorPacific/driver_api/customization_for_suyan.py +++ b/Manila/file_driver_dir/huawei/oceanstorPacific/driver_api/customization_for_suyan.py @@ -19,7 +19,6 @@ from manila import exception from manila.i18n import _ -from manila.share import share_types from .operate_share import OperateShare from .change_access import ChangeAccess @@ -30,22 +29,16 @@ class CustomizationOperate(OperateShare): - def __init__(self, helper, share): - super(CustomizationOperate, self).__init__(helper, share) - self.share_proto = self._get_share_share_proto() # 共享协议类型 + def __init__(self, helper, share, root): + super(CustomizationOperate, self).__init__(helper, share, root) self.share_parent_id = self.share.get('parent_share_id') self.dtree_name = None self.dtree_id = None - def set_root(self, root): - self.root = root - return self - - def create_share(self, root, free_pool): + def create_share(self, free_pool): if not self.share_parent_id: - return super(CustomizationOperate, self).create_share(root, free_pool) + return super(CustomizationOperate, self).create_share(free_pool) - self.root = root self.free_pool = free_pool self._check_domain() self._get_or_create_account() @@ -72,7 +65,7 @@ def change_share(self, new_size, action): LOG.info("{0} share done. New size:{1}.".format(action, new_size)) return True - def update_qos(self, qos_specs, root): + def update_qos(self, qos_specs): """ 苏研定制接口,根据传递的qos_specs,刷新share的qos信息, 如果没有则创建对应qos, 此接口的share不是share_instance对象是share对象 @@ -83,9 +76,7 @@ def update_qos(self, qos_specs, root): self._get_update_qos_config(qos_specs) - account_name = self._find_account_name(root) - result = self.helper.query_account_by_name(account_name) - self.account_id = result.get('id') + self._get_account_id() self._get_namespace_name_for_qos() qos_name = self.namespace_name @@ -126,7 +117,9 @@ def delete_share(self): return False self._get_account_id() - self._get_dtree_namespace_info() + if not self._get_dtree_namespace_info(): + LOG.warn(_("Delete share fail, cannot find namespace info of share")) + return False if not self._get_dtree_info(): LOG.warn(_("Delete share fail, cannot find dtree info of share")) return False @@ -268,20 +261,6 @@ def _get_share_parent_info(self): LOG.error(err_msg) raise exception.InvalidInput(reason=err_msg) - def _create_namespace(self): - """苏研定制接口创建namespace时直接使用share的ID作为命名空间的名称""" - - self.namespace_name = 'share-' + self.share.get('share_id') - try: - forbidden_dpc = constants.NOT_FORBIDDEN_DPC if 'DPC' in self.share_proto else constants.FORBIDDEN_DPC - storage_pool_id = self.free_pool[0] - result = self.helper.create_namespace(self.namespace_name, storage_pool_id, self.account_id, - forbidden_dpc, self.tier_info.get('atime_mode')) - self.namespace_id = result.get('id') - except Exception as e: - self._rollback_creat(1) - raise e - def _create_dtree(self): """创建二级目录的dtree""" @@ -361,6 +340,8 @@ def _get_dtree_location(self): location.append('NFS:' + self.domain + ":/" + share_path) if 'CIFS' in self.share_proto: location.append('CIFS:\\\\' + self.domain + '\\' + share_path) + if 'DPC' in self.share_proto: + location.append('DPC:/' + share_path) return location @@ -446,29 +427,10 @@ def _get_dtree_quota_info(self, action, parent_id, new_size, parent_type): err_msg = (_("Shrink share fail for space used({0}G) > new sizre({1}G)".format(cur_size, new_size))) raise exception.InvalidInput(reason=err_msg) - def _get_share_share_proto(self): - """临时方案,share_proto为nfs,且share_type为dpc时为dpc共享,其他情况不变""" - ans = [] - share_proto = self.share.get('share_proto', '').split('&') - - type_id = self.share.get('share_type_id') - extra_specs = share_types.get_share_type_extra_specs(type_id) - tmp_share_proto = extra_specs.get('share_proto', '').split('&') - - if "DPC" in tmp_share_proto: - ans.append("DPC") - elif "NFS" in share_proto: - ans.append("NFS") - elif "CIFS" in share_proto: - ans.append("CIFS") - return ans - class CustomizationChangeAccess(ChangeAccess): def __init__(self, helper, share, root): - super(CustomizationChangeAccess, self).__init__(helper, share) - self.root = root - self.share_proto = self._get_share_share_proto() # 共享协议类型 + super(CustomizationChangeAccess, self).__init__(helper, share, root) self.share_parent_id = self.share.get('parent_share_id') self.dtree_name = None self.dtree_id = None @@ -505,16 +467,9 @@ def deny_access(self, access): self._classify_rules([access], 'deny') return True - def _find_account_id(self): - """通过xml文件配置的账户名称获取账户信息""" - LOG.info("Find account id from xml, call by ChangeAccess") - account_name = self.root.findtext('Filesystem/AccountName').strip() - result = self.helper.query_account_by_name(account_name) - self.account_id = result.get('id') - def _get_account_and_share_related_information(self): """二级目录场景下,share_path需要包含dtree名称""" - self._find_account_id() + self._get_account_id() self._get_export_location_info() self._get_dtree_share_related_info() self._query_and_set_share_info(self.dtree_id, self.dtree_name) @@ -533,27 +488,10 @@ def _get_dtree_share_related_info(self): for info in dtree_info: self.dtree_id = info.get('id') - def _get_share_share_proto(self): - ans = [] - share_proto = self.share.get('share_proto', '').split('&') - - type_id = self.share.get('share_type_id') - extra_specs = share_types.get_share_type_extra_specs(type_id) - tmp_share_proto = extra_specs.get('share_proto', '').split('&') - - if "DPC" in tmp_share_proto: - ans.append("DPC") - elif "NFS" in share_proto: - ans.append("NFS") - elif "CIFS" in share_proto: - ans.append("CIFS") - return ans - class CustomizationChangeCheckUpdateStorage(CheckUpdateStorage): def __init__(self, helper, root): super(CustomizationChangeCheckUpdateStorage, self).__init__(helper, root) - self.account_id = None def _get_all_share_usages(self, all_namespace_info): """ @@ -591,13 +529,6 @@ def _get_all_share_usages(self, all_namespace_info): def get_all_share_usage(self): """苏研定制接口,获取对应帐户下所有的share信息""" LOG.info("begin to query all share usages") - self._find_account_id() + self._get_account_id() all_namespace_info = self.helper.get_all_namespace_info(self.account_id) return self._get_all_share_usages(all_namespace_info) - - def _find_account_id(self): - """获取账户信息""" - - account_name = self.root.findtext('Filesystem/AccountName').strip() - result = self.helper.query_account_by_name(account_name) - self.account_id = result.get('id') diff --git a/Manila/file_driver_dir/huawei/oceanstorPacific/driver_api/operate_share.py b/Manila/file_driver_dir/huawei/oceanstorPacific/driver_api/operate_share.py index 22f345e..ce38e7e 100644 --- a/Manila/file_driver_dir/huawei/oceanstorPacific/driver_api/operate_share.py +++ b/Manila/file_driver_dir/huawei/oceanstorPacific/driver_api/operate_share.py @@ -23,32 +23,28 @@ from manila.share import api from manila.share import share_types +from .base_share_property import BaseShareProperty from ..helper import constants + LOG = log.getLogger(__name__) share_api = api.API() -class OperateShare(object): - def __init__(self, helper, share): - self.helper = helper - self.share = share +class OperateShare(BaseShareProperty): + def __init__(self, helper, share, root): + super(OperateShare, self).__init__(helper, share=share, root=root) - self.root = None self.free_pool = None self.domain = None # 集群域名 - self.account_id = None # 账户Id self.namespace_name = None # 命名空间名称 self.namespace_id = None # 命名空间Id self.export_locations = None # share路径信息 self.quota_id = None # 配额ID - self.share_proto = self.share.get('share_proto', '').split('&') # 共享协议类型 self.tier_info = {} # 分级策略信息 self.qos_config = {} # QOS策略信息 - def create_share(self, root, free_pool): - - self.root = root + def create_share(self, free_pool): self.free_pool = free_pool self._check_domain() @@ -56,7 +52,7 @@ def create_share(self, root, free_pool): self._get_qos_config() self._get_or_create_account() self._create_namespace() - self._create_quote() + self._create_quota() self._create_qos() self._create_tier_migrate_policy() self._create_share_protocol() @@ -69,7 +65,9 @@ def delete_share(self): return False self._get_account_id() - self._get_namespace_info() + if not self._get_namespace_info(): + LOG.warn(_("Delete share fail, cannot find namespace info of share")) + return False self._delete_share_protocol() self.helper.delete_qos(self.namespace_name) self.helper.delete_namespace(self.namespace_name) @@ -103,7 +101,8 @@ def change_share(self, new_size, action): def _check_domain(self): """当共享协议类型存在Nfs或Cifs时,检查配置文件集群域名是否存在""" - self.domain = self.root.findtext('Filesystem/ClusterDomainName').strip() + domain_name = self.root.findtext('Filesystem/ClusterDomainName') + self.domain = domain_name.strip() if domain_name else domain_name if ('NFS' in self.share_proto or 'CIFS' in self.share_proto) and not self.domain: err_msg = _("Create namespace({0}) error, because can't " "get the domain name of cluster...".format(self.share['id'])) @@ -210,48 +209,25 @@ def _get_qos_config(self): self._get_basic_band_width_qos_config(extra_specs) self._get_bps_density_qos_config(extra_specs) - def _find_account_name(self, root=None): - return self.share.get("project_id") - def _get_or_create_account(self): """ Driver在创建文件系统时先查询projectId对应的租户是否存在,如果存在,直接使用租户Id。 如果不存在,创建一个租户,租户名称为公有云下发的projectId,返回的租户accountId供系统内部使用。 """ - - account_name = self._find_account_name(self.root) - result = self.helper.query_account_by_name(account_name) - if result: - self.account_id = result.get('id') - LOG.info("Account({0}) already exist. No need create.".format(account_name)) + self._get_account_id() + if self.account_id is not None: + LOG.info("Account({0}) already exist. No need create.".format(self.account_name)) else: - result = self.helper.create_account(account_name) + result = self.helper.create_account(self.account_name) self.account_id = result.get('id') - def _create_namespace_find_namespace_name(self, share_name): - self.namespace_name = share_name - for i in range(1, 12): - result = self.helper.query_namespace_by_name(self.namespace_name) - if result: - LOG.info(_("Namespace({0}) has been used, Try to find other".format(self.namespace_name))) - self.namespace_name = share_name + '_{0:0>2d}'.format(i) - if i == 11: - err_msg = _("Duplicate namespace:{0} (_01~10).".format(self.namespace_name)) - raise exception.InvalidInput(reason=err_msg) - else: - return - def _create_namespace(self): """ 在对应账户下创建命名空间 命名空间名称首先取用户指定的名称,如果用户取指定去share_instance_id """ - if self.share['display_name']: - self.namespace_name = 'share-' + self.share.get('display_name') - else: - self.namespace_name = 'share-' + self.share.get('id') - + self.namespace_name = 'share-' + self.share.get('share_id') try: forbidden_dpc = constants.NOT_FORBIDDEN_DPC if 'DPC' in self.share_proto else constants.FORBIDDEN_DPC storage_pool_id = self.free_pool[0] @@ -264,7 +240,7 @@ def _create_namespace(self): self._rollback_creat(1) raise e - def _create_quote(self): + def _create_quota(self): """创建命名空间配额""" quota_size = self.share['size'] @@ -326,7 +302,6 @@ def _rollback_creat(self, level): LOG.info(_("Rollback done.")) def _delete_share_protocol(self): - if 'NFS' in self.share_proto: result = self.helper.query_nfs_share_information(self.account_id, self.namespace_id) for nfs_share in result: @@ -369,12 +344,6 @@ def _delete_account(self): LOG.info("The account has namespace or access zone. " "Cannot delete.(account_id: {0})".format(self.account_id)) - def _get_account_id(self): - """通过账户名称去存储查询账户信息并获取账户ID""" - account_name = self._find_account_name(self.root) - result = self.helper.query_account_by_name(account_name) - self.account_id = result.get('id') - def _get_namespace_info(self): """ 先通过share的location获取namespace名称, diff --git a/Manila/file_driver_dir/huawei/oceanstorPacific/helper/helper.py b/Manila/file_driver_dir/huawei/oceanstorPacific/helper/helper.py index 1063d48..366263f 100644 --- a/Manila/file_driver_dir/huawei/oceanstorPacific/helper/helper.py +++ b/Manila/file_driver_dir/huawei/oceanstorPacific/helper/helper.py @@ -234,9 +234,9 @@ def creat_quota(self, namespace_id, quota_size, quota_type): result = self.call(url, data, "POST") if result.get('result', {}).get('code') == 0 and result.get("data"): - LOG.info(_("Create quote success. (quota_size: {0}GB)".format(quota_size))) + LOG.info(_("Create quota success. (quota_size: {0}GB)".format(quota_size))) else: - err_msg = _("Create quote failed.") + err_msg = _("Create quota failed.") raise exception.InvalidShare(reason=err_msg) def change_quota_size(self, quota_id, new_size): @@ -419,7 +419,7 @@ def query_nfs_share_information(self, account_id, fs_id, dtree_id=0): data = jsonutils.dumps(nfs_para) result = self.call(url, data, "GET") - if result.get('result', {}).get('code') == 0 and result.get('data'): + if result.get('result', {}).get('code') == 0: LOG.info(_("Query NFS share success.(account_id: {0})".format(account_id))) else: err_msg = _("Query NFS share failed.(account_id: {0})".format(account_id)) @@ -440,7 +440,7 @@ def query_cifs_share_information(self, account_id, share_name): data = jsonutils.dumps(cifs_para) result = self.call(url, data, "GET") - if result.get('result', {}).get('code') == 0 and result.get('data'): + if result.get('result', {}).get('code') == 0: LOG.info(_("Query CIFS share success.(account_id: {0})".format(account_id))) else: err_msg = _("Query CIFS share failed.(account_id: {0})".format(account_id)) @@ -536,11 +536,12 @@ def delete_unix_user_group(self, group_name, account_id): def allow_access_for_nfs(self, share_id, access_to, access_level, account_id): """This interface is used to add an NFS share client.""" + access_value = 0 if access_level == 'ro' else 1 url = "nas_protocol/nfs_share_auth_client" access_para = { 'access_name': access_to, 'share_id': share_id, - 'access_value': 0 if access_level == 'ro' else 1, + 'access_value': access_value, 'sync': 1, 'all_squash': 1, 'root_squash': 1, @@ -553,20 +554,60 @@ def allow_access_for_nfs(self, share_id, access_to, access_level, account_id): if result.get('result', {}).get('code') == 0: LOG.info(_("Add an NFS share client success.(access_to: {0})".format(access_to))) elif result.get('result', {}).get('code') == constants.NFS_SHARE_CLIENT_EXIST: - LOG.info(_("Add an NFS share client already exist.(access_to: {0})".format(access_to))) + share_auth_info = self._query_nfs_share_clients_information( + 0, [share_id, account_id], access_to).get('data', []) + if self._is_needed_change_access(share_auth_info, access_to, access_value, 'access_value'): + self.change_access_for_nfs( + share_auth_info[0].get('id'), access_value, account_id) else: err_msg = _("Add an NFS shared client for share failed.(access_to: {0})".format(share_id)) raise exception.InvalidShare(reason=err_msg) + @staticmethod + def _is_needed_change_access(share_auth_info, access_to, access_value, access_param): + if not share_auth_info: + err_msg = _("Add an NFS shared client for share failed.(access_to: {0})".format( + access_to)) + raise exception.InvalidShare(reason=err_msg) + if share_auth_info[0].get(access_param) == access_value: + LOG.info(_("Add an share client already exist.(access_to: {0})".format( + access_to))) + return False + + return True + + def change_access_for_nfs(self, client_id, access_value, account_id): + """This interface is used to change a CIFS share auth client access_value.""" + url = "nas_protocol/nfs_share_auth_client" + access_para = { + 'id': client_id, + 'access_value': access_value, + 'sync': 1, + 'all_squash': 1, + 'root_squash': 1, + 'account_id': account_id, + } + data = jsonutils.dumps(access_para) + result = self.call(url, data, "PUT") + + if result.get('result', {}).get('code') == 0: + LOG.info(_("change an NFS share client success.(client id: {0})".format(client_id))) + else: + err_msg = _("change an NFS shared client for share failed.(client id: {0})". + format(client_id)) + raise exception.InvalidShare(reason=err_msg) + return result + def allow_access_for_cifs(self, share_id, access_to, access_level, account_id): """This interface is used to add a CIFS share user or user group.""" url = "file_service/cifs_share_auth_client" + access_value = 0 if access_level == 'ro' else 1 query_para = { "share_id": share_id, "name": access_to, "domain_type": 2, - "permission": 0 if access_level == 'ro' else 1, + "permission": access_value, "account_id": account_id } data = jsonutils.dumps(query_para) @@ -575,22 +616,52 @@ def allow_access_for_cifs(self, share_id, access_to, access_level, account_id): if result.get('result', {}).get('code') == 0: LOG.info(_("Add an CIFS share user success.(access_to: {0})".format(access_to))) elif result.get('result', {}).get('code') == constants.CIFS_SHARE_CLIENT_EXIST: - LOG.info(_("Add an CIFS share user({0}) already exist.(access_to: {0})".format(access_to))) + share_auth_info = self._query_cifs_share_user_information( + 0, [share_id, account_id], access_to).get('data', []) + if self._is_needed_change_access(share_auth_info, access_to, + access_value, 'permission'): + self.change_access_for_cifs( + share_auth_info[0].get('id'), access_value, account_id) else: err_msg = _("Add an CIFS shared client for share failed.(access_to: {0})".format(share_id)) raise exception.InvalidShare(reason=err_msg) + def change_access_for_cifs(self, client_id, access_value, account_id): + """This interface is used to change a CIFS share auth client permission.""" + url = "file_service/cifs_share_auth_client" + access_para = { + "id": client_id, + "permission": access_value, + "account_id": account_id + } + data = jsonutils.dumps(access_para) + result = self.call(url, data, "PUT") + + if result.get('result', {}).get('code') == 0: + LOG.info(_("change an CIFS share client success.(client id: {0})".format( + client_id))) + else: + err_msg = _("change an CIFS shared client for share failed.(client id: {0})". + format(client_id)) + raise exception.InvalidShare(reason=err_msg) + return result + def query_nfs_share_clients_information(self, share_id, account_id=None): totals = self.get_total_info_by_offset( self._query_nfs_share_clients_information, [share_id, account_id]) return totals - def _query_nfs_share_clients_information(self, offset, extra_param): + def _query_nfs_share_clients_information(self, offset, extra_param, access_name=None): """This interface is used to batch query NFS share client information.""" url = "nas_protocol/nfs_share_auth_client_list" + if access_name is not None: + filter_str = "[{\"share_id\": \"%s\", \"access_name\": \"%s\"}]" % ( + str(extra_param[0]), access_name) + else: + filter_str = "[{\"share_id\": \"%s\"}]" % str(extra_param[0]) filter_para = { - "filter": "[{\"share_id\": \"%s\"}]" % str(extra_param[0]), + "filter": filter_str, "range": { "offset": offset, "limit": constants.MAX_QUERY_COUNT @@ -614,12 +685,17 @@ def query_cifs_share_user_information(self, share_id, account_id=None): self._query_cifs_share_user_information, [share_id, account_id]) return totals - def _query_cifs_share_user_information(self, offset, extra_param): + def _query_cifs_share_user_information(self, offset, extra_param, access_name=None): """This interface is used to query CIFS share users or user groups in batches.""" url = "file_service/cifs_share_auth_client_list" + if access_name is not None: + filter_str = "[{\"share_id\": \"%s\", \"name\": \"like %s\"}]" % ( + str(extra_param[0]), access_name) + else: + filter_str = "[{\"share_id\": \"%s\"}]" % str(extra_param[0]) filter_para = { - "filter": "[{\"share_id\": \"%s\"}]" % str(extra_param[0]), + "filter": filter_str, "range": { "offset": offset, "limit": constants.MAX_QUERY_COUNT @@ -884,11 +960,17 @@ def delete_dtree(self, dtree_name, namespace_name): result = self.call(url, None, "DELETE") if result.get('result', {}).get('code') == 0: - LOG.info(_("Delete dtree of namespace success.(dtree_name: {0}," - " namespace_name: {1})".format(dtree_name, namespace_name))) + LOG.info(_("Delete dtree of namespace success." + "(dtree_name: {0}, namespace_name: {1})". + format(dtree_name, namespace_name))) elif result.get('result', {}).get('code') == constants.NAMESPACE_NOT_EXIST: - LOG.info(_("the dtree {0} of namespace {1} does not exist.(dtree_name: {0}, " - " namespace_name: {1})".format(dtree_name, namespace_name))) + LOG.info(_("theparent namespace {1} of dtree {0} does not exist." + "(dtree_name: {0}, namespace_name: {1})". + format(namespace_name, dtree_name))) + elif result.get('result', {}).get('code') == constants.DTREE_NOT_EXIST: + LOG.info(_("the dtree {0} of namespace {1} does not exist." + "(dtree_name: {0}, namespace_name: {1})". + format(dtree_name, namespace_name))) else: err_msg = _("Delete dtree of namespace failed.(dtree_name: {0}, " "namespace_name: {1})".format(dtree_name, namespace_name)) diff --git a/Manila/file_driver_dir/huawei/oceanstorPacific/oceanstorpacific_nas.py b/Manila/file_driver_dir/huawei/oceanstorPacific/oceanstorpacific_nas.py index 481b2e8..f774319 100644 --- a/Manila/file_driver_dir/huawei/oceanstorPacific/oceanstorpacific_nas.py +++ b/Manila/file_driver_dir/huawei/oceanstorPacific/oceanstorpacific_nas.py @@ -115,7 +115,7 @@ def _update_share_stats(self): share_backend_name=backend_name or 'OceanStorPacific_NFS_CIFS', vendor_name='OceanStorPacific', driver_version='1.0', - storage_protocol='NFS_CIFS', + storage_protocol='NFS_CIFS_DPC', driver_handles_share_servers=False, qos=True, snapshot_support=False,