* New method name_check() in utils.py to enforce name API document definition in 'Conventions' section: '[a-z][A-Z][0-9]_-'
* New constants: TargetdError.INVALID_ARGUMENT TargetdError.NO_SUPPORT TargetdError.NAME_CONFLICT TargetdError.EXISTS_INITIATOR
* New public method: access_group_create(ag_name, init_id, init_type): Create new access group. Parameters: ag_name (str): Access group name init_id (str): iSCSI initiator address init_type (str): Reserved for future use. Should be set as 'iscsi' Returns: N/A Errors: -32602: Invalid parameter. Provided ag_name is illegal. Check 'Conventions' for detail. -153: No support. The 'init_type' is not 'iscsi' -50: Name conflict. Requested 'ag_name' is in use -52: Exists initiator. Requested 'init_id' is in use
Signed-off-by: Gris Ge fge@redhat.com --- API.md | 16 ++++++++++++++++ targetd/block.py | 34 ++++++++++++++++++++++++++++++++-- targetd/main.py | 6 ++++-- targetd/utils.py | 16 ++++++++++++++++ 4 files changed, 68 insertions(+), 4 deletions(-)
diff --git a/API.md b/API.md index 56044ad..cb737b3 100644 --- a/API.md +++ b/API.md @@ -149,6 +149,22 @@ Returns: Errors: N/A
+### access_group_create(ag_name, init_id, init_type) +Create new access group. + +Parameters: + ag_name (str): Access group name + init_id (str): iSCSI initiator address + init_type (str): Reserved for future use. Should be set as 'iscsi' +Returns: + N/A +Errors: + -32602: Invalid parameter. Provided 'ag_name' is illegal. Check + 'Conventions' for detail. + -153: No support. The 'init_type' is not 'iscsi' + -50: Name conflict. Requested 'ag_name' is in use + -52: Exists initiator. Requested 'init_id' is in use + File system operations ---------------------- Ability to create different file systems and perform operation on them. The diff --git a/targetd/block.py b/targetd/block.py index 2e185ef..71c843b 100644 --- a/targetd/block.py +++ b/targetd/block.py @@ -18,10 +18,10 @@ import contextlib from rtslib_fb import ( Target, TPG, NodeACL, FabricModule, BlockStorageObject, RTSRoot, - NetworkPortal, LUN, MappedLUN, RTSLibError, RTSLibNotInCFS) + NetworkPortal, LUN, MappedLUN, RTSLibError, RTSLibNotInCFS, NodeACLGroup) import lvm from main import TargetdError -from utils import ignored +from utils import ignored, name_check
def get_vg_lv(pool_name): @@ -108,6 +108,7 @@ def initialize(config_dict): initiator_set_auth=initiator_set_auth, initiator_list=initiator_list, access_group_list=access_group_list, + access_group_create=access_group_create, )
@@ -397,3 +398,32 @@ def access_group_list(req): 'init_type': 'iscsi', } for node_acl_group in _get_iscsi_tpg().node_acl_groups) + + +def access_group_create(req, ag_name, init_id, init_type): + if init_type != 'iscsi': + raise TargetdError( + TargetdError.NO_SUPPORT, "Only support iscsi") + + name_check(ag_name) + + tpg = _get_iscsi_tpg() + + # Pre-check: + # 1. Name conflict: requested name is in use + # 2. Initiator conflict: request initiator is in use + + for node_acl_group in tpg.node_acl_groups: + if node_acl_group.name == ag_name: + raise TargetdError( + TargetdError.NAME_CONFLICT, + "Requested access group name is in use") + + if init_id in list(i.node_wwn for i in tpg.node_acls): + raise TargetdError( + TargetdError.EXISTS_INITIATOR, + "Requested init_id is in use") + + node_acl_group = NodeACLGroup(tpg, ag_name) + node_acl_group.add_acl(init_id) + RTSRoot().save_to_file() diff --git a/targetd/main.py b/targetd/main.py index 8af5300..04aff5e 100644 --- a/targetd/main.py +++ b/targetd/main.py @@ -113,7 +113,9 @@ class TargetHandler(BaseHTTPRequestHandler): log.debug(traceback.format_exc()) raise except TypeError: - error = (-32602, "invalid method parameter(s)") + error = ( + TargetdError.INVALID_PARMETER, + "invalid method parameter(s)") log.debug(traceback.format_exc()) raise except TargetdError, td: @@ -185,7 +187,7 @@ def load_config(config_path): # convert log level to int config['log_level'] = getattr(log, config['log_level'].upper(), log.INFO) log.basicConfig(level=config['log_level']) - +
def update_mapping(): # wait until now so submodules can import 'main' safely diff --git a/targetd/utils.py b/targetd/utils.py index 7150eba..522f445 100644 --- a/targetd/utils.py +++ b/targetd/utils.py @@ -17,6 +17,7 @@
from subprocess import Popen, PIPE from contextlib import contextmanager +import re
@contextmanager def ignored(*exceptions): @@ -26,7 +27,22 @@ def ignored(*exceptions): pass
+_NAME_REGEX = '^[a-zA-Z0-9_-]+$' + + +def name_check(name): + if not re.match(_NAME_REGEX, name): + raise TargetdError( + TargetdError.INVALID_ARGUMENT, + "Illegal name, should match: %s" % _NAME_REGEX) + + class TargetdError(Exception): + INVALID_ARGUMENT = -32602 + NO_SUPPORT = -153 + NAME_CONFLICT = -50 + EXISTS_INITIATOR = -52 + def __init__(self, error_code, *args, **kwargs): Exception.__init__(self, *args, **kwargs) self.error = error_code