Support metadata for access rule resource
Now only share have metadata property. We should support it for access rule as well. Depends-On: https://review.openstack.org/#/c/570708/ Change-Id: I41b2882ecd16ed03bece05a7a77a387c9077bf5c Partly-Implements: bp metadata-for-access-rule
This commit is contained in:
parent
b0b08cc650
commit
1aa12eb2f8
@ -27,7 +27,7 @@ from manilaclient import utils
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
MAX_VERSION = '2.43'
|
||||
MAX_VERSION = '2.45'
|
||||
MIN_VERSION = '2.0'
|
||||
DEPRECATED_VERSION = '1.0'
|
||||
_VERSIONED_METHOD_MAP = {}
|
||||
|
@ -982,7 +982,7 @@ class ManilaCLIClient(base.CLIClient):
|
||||
|
||||
@not_found_wrapper
|
||||
def list_access(self, entity_id, columns=None, microversion=None,
|
||||
is_snapshot=False):
|
||||
is_snapshot=False, metadata=None):
|
||||
"""Returns list of access rules for a share.
|
||||
|
||||
:param entity_id: str -- Name or ID of a share or snapshot.
|
||||
@ -997,6 +997,12 @@ class ManilaCLIClient(base.CLIClient):
|
||||
cmd = 'access-list %s ' % entity_id
|
||||
if columns is not None:
|
||||
cmd += ' --columns ' + columns
|
||||
if metadata:
|
||||
metadata_cli = ''
|
||||
for k, v in metadata.items():
|
||||
metadata_cli += '%(k)s=%(v)s ' % {'k': k, 'v': v}
|
||||
if metadata_cli:
|
||||
cmd += ' --metadata %s ' % metadata_cli
|
||||
access_list_raw = self.manila(cmd, microversion=microversion)
|
||||
return output_parser.listing(access_list_raw)
|
||||
|
||||
@ -1009,6 +1015,33 @@ class ManilaCLIClient(base.CLIClient):
|
||||
return access
|
||||
raise tempest_lib_exc.NotFound()
|
||||
|
||||
@not_found_wrapper
|
||||
def access_show(self, access_id, microversion=None):
|
||||
raw_access = self.manila("access-show %s" % access_id,
|
||||
microversion=microversion)
|
||||
return output_parser.details(raw_access)
|
||||
|
||||
@not_found_wrapper
|
||||
def access_set_metadata(self, access_id, metadata, microversion=None):
|
||||
if not (isinstance(metadata, dict) and metadata):
|
||||
msg = ('Provided invalid metadata for setting of access rule'
|
||||
' metadata - %s' % metadata)
|
||||
raise exceptions.InvalidData(message=msg)
|
||||
cmd = "access-metadata %s set " % access_id
|
||||
for k, v in metadata.items():
|
||||
cmd += '%(k)s=%(v)s ' % {'k': k, 'v': v}
|
||||
return self.manila(cmd, microversion=microversion)
|
||||
|
||||
@not_found_wrapper
|
||||
def access_unset_metadata(self, access_id, keys, microversion=None):
|
||||
if not (isinstance(keys, (list, tuple, set)) and keys):
|
||||
raise exceptions.InvalidData(
|
||||
message='Provided invalid keys - %s' % keys)
|
||||
cmd = 'access-metadata %s unset ' % access_id
|
||||
for key in keys:
|
||||
cmd += '%s ' % key
|
||||
return self.manila(cmd, microversion=microversion)
|
||||
|
||||
@not_found_wrapper
|
||||
def snapshot_access_allow(self, snapshot_id, access_type, access_to,
|
||||
microversion=None):
|
||||
@ -1032,16 +1065,20 @@ class ManilaCLIClient(base.CLIClient):
|
||||
|
||||
@not_found_wrapper
|
||||
def access_allow(self, share_id, access_type, access_to, access_level,
|
||||
microversion=None):
|
||||
raw_access = self.manila(
|
||||
'access-allow --access-level %(level)s %(id)s %(type)s '
|
||||
'%(access_to)s' % {
|
||||
'level': access_level,
|
||||
'id': share_id,
|
||||
'type': access_type,
|
||||
'access_to': access_to,
|
||||
},
|
||||
microversion=microversion)
|
||||
metadata=None, microversion=None):
|
||||
cmd = ('access-allow --access-level %(level)s %(id)s %(type)s '
|
||||
'%(access_to)s' % {
|
||||
'level': access_level,
|
||||
'id': share_id,
|
||||
'type': access_type,
|
||||
'access_to': access_to})
|
||||
if metadata:
|
||||
metadata_cli = ''
|
||||
for k, v in metadata.items():
|
||||
metadata_cli += '%(k)s=%(v)s ' % {'k': k, 'v': v}
|
||||
if metadata_cli:
|
||||
cmd += ' --metadata %s ' % metadata_cli
|
||||
raw_access = self.manila(cmd, microversion=microversion)
|
||||
return output_parser.details(raw_access)
|
||||
|
||||
@not_found_wrapper
|
||||
|
@ -13,6 +13,8 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import ast
|
||||
|
||||
import ddt
|
||||
from tempest.lib import exceptions as tempest_lib_exc
|
||||
|
||||
@ -68,16 +70,19 @@ class ShareAccessReadWriteBase(base.BaseTestCase):
|
||||
'ipv6': ['2001:db8::%d' % i for i in int_range],
|
||||
}
|
||||
|
||||
def _test_create_list_access_rule_for_share(self, microversion):
|
||||
def _test_create_list_access_rule_for_share(
|
||||
self, microversion, metadata=None):
|
||||
access_type = self.access_types[0]
|
||||
|
||||
access = self.user_client.access_allow(
|
||||
self.share['id'], access_type, self.access_to[access_type].pop(),
|
||||
self.access_level, microversion=microversion)
|
||||
self.access_level, metadata=metadata, microversion=microversion)
|
||||
|
||||
return access
|
||||
|
||||
@ddt.data("1.0", "2.0", "2.6", "2.7", "2.21", "2.33")
|
||||
@ddt.data(*set([
|
||||
"1.0", "2.0", "2.6", "2.7", "2.21", "2.33", "2.44", "2.45",
|
||||
api_versions.MAX_VERSION]))
|
||||
def test_create_list_access_rule_for_share(self, microversion):
|
||||
self.skip_if_microversion_not_supported(microversion)
|
||||
access = self._test_create_list_access_rule_for_share(
|
||||
@ -95,8 +100,9 @@ class ShareAccessReadWriteBase(base.BaseTestCase):
|
||||
if (api_versions.APIVersion(microversion) >=
|
||||
api_versions.APIVersion("2.33")):
|
||||
self.assertTrue(
|
||||
all(('access_key' and 'created_at' and 'updated_at')
|
||||
in a for a in access_list))
|
||||
all(all(key in access for key in (
|
||||
'access_key', 'created_at', 'updated_at'))
|
||||
for access in access_list))
|
||||
elif (api_versions.APIVersion(microversion) >=
|
||||
api_versions.APIVersion("2.21")):
|
||||
self.assertTrue(all('access_key' in a for a in access_list))
|
||||
@ -156,6 +162,89 @@ class ShareAccessReadWriteBase(base.BaseTestCase):
|
||||
self.assertRaises(tempest_lib_exc.NotFound,
|
||||
self.user_client.get_access, share_id, access['id'])
|
||||
|
||||
@ddt.data(*set(["2.45", api_versions.MAX_VERSION]))
|
||||
def test_create_list_access_rule_with_metadata(self, microversion):
|
||||
self.skip_if_microversion_not_supported(microversion)
|
||||
|
||||
md1 = {"key1": "value1", "key2": "value2"}
|
||||
md2 = {"key3": "value3", "key4": "value4"}
|
||||
self._test_create_list_access_rule_for_share(
|
||||
metadata=md1, microversion=microversion)
|
||||
access = self._test_create_list_access_rule_for_share(
|
||||
metadata=md2, microversion=microversion)
|
||||
access_list = self.user_client.list_access(
|
||||
self.share['id'], metadata={"key4": "value4"},
|
||||
microversion=microversion)
|
||||
self.assertEqual(1, len(access_list))
|
||||
# Verify share metadata
|
||||
get_access = self.user_client.access_show(
|
||||
access_list[0]['id'], microversion=microversion)
|
||||
metadata = ast.literal_eval(get_access['metadata'])
|
||||
self.assertEqual(2, len(metadata))
|
||||
self.assertIn('key3', metadata)
|
||||
self.assertIn('key4', metadata)
|
||||
self.assertEqual(md2['key3'], metadata['key3'])
|
||||
self.assertEqual(md2['key4'], metadata['key4'])
|
||||
self.assertEqual(access['id'], access_list[0]['id'])
|
||||
|
||||
self.user_client.access_deny(access['share_id'], access['id'])
|
||||
self.user_client.wait_for_access_rule_deletion(access['share_id'],
|
||||
access['id'])
|
||||
|
||||
@ddt.data(*set(["2.45", api_versions.MAX_VERSION]))
|
||||
def test_create_update_show_access_rule_with_metadata(self, microversion):
|
||||
self.skip_if_microversion_not_supported(microversion)
|
||||
|
||||
md1 = {"key1": "value1", "key2": "value2"}
|
||||
md2 = {"key3": "value3", "key2": "value4"}
|
||||
# create a access rule with metadata
|
||||
access = self._test_create_list_access_rule_for_share(
|
||||
metadata=md1, microversion=microversion)
|
||||
# get the access rule
|
||||
get_access = self.user_client.access_show(
|
||||
access['id'], microversion=microversion)
|
||||
# verify access rule
|
||||
self.assertEqual(access['id'], get_access['id'])
|
||||
self.assertEqual(md1, ast.literal_eval(get_access['metadata']))
|
||||
|
||||
# update access rule metadata
|
||||
self.user_client.access_set_metadata(
|
||||
access['id'], metadata=md2, microversion=microversion)
|
||||
get_access = self.user_client.access_show(
|
||||
access['id'], microversion=microversion)
|
||||
|
||||
# verify access rule after update access rule metadata
|
||||
self.assertEqual(
|
||||
{"key1": "value1", "key2": "value4", "key3": "value3"},
|
||||
ast.literal_eval(get_access['metadata']))
|
||||
self.assertEqual(access['id'], get_access['id'])
|
||||
|
||||
@ddt.data(*set(["2.45", api_versions.MAX_VERSION]))
|
||||
def test_delete_access_rule_metadata(self, microversion):
|
||||
self.skip_if_microversion_not_supported(microversion)
|
||||
|
||||
md = {"key1": "value1", "key2": "value2"}
|
||||
# create a access rule with metadata
|
||||
access = self._test_create_list_access_rule_for_share(
|
||||
metadata=md, microversion=microversion)
|
||||
# get the access rule
|
||||
get_access = self.user_client.access_show(
|
||||
access['id'], microversion=microversion)
|
||||
|
||||
# verify access rule
|
||||
self.assertEqual(access['id'], get_access['id'])
|
||||
self.assertEqual(md, ast.literal_eval(get_access['metadata']))
|
||||
|
||||
# delete access rule metadata
|
||||
self.user_client.access_unset_metadata(
|
||||
access['id'], keys=["key1", "key2"], microversion=microversion)
|
||||
get_access = self.user_client.access_show(
|
||||
access['id'], microversion=microversion)
|
||||
|
||||
# verify access rule after delete access rule metadata
|
||||
self.assertEqual({}, ast.literal_eval(get_access['metadata']))
|
||||
self.assertEqual(access['id'], get_access['id'])
|
||||
|
||||
@ddt.data("1.0", "2.0", "2.6", "2.7", "2.21", "2.33")
|
||||
def test_create_delete_ip_access_rule(self, microversion):
|
||||
self._create_delete_access_rule(
|
||||
|
@ -505,6 +505,45 @@ class FakeHTTPClient(fakes.FakeHTTPClient):
|
||||
raise AssertionError("Unexpected share action: %s" % action)
|
||||
return (resp, {}, _body)
|
||||
|
||||
def get_share_access_rules(self, **kw):
|
||||
access = {
|
||||
'access_list': [{
|
||||
'access_level': 'rw',
|
||||
'state': 'active',
|
||||
'id': '1122',
|
||||
'access_type': 'ip',
|
||||
'access_to': '10.0.0.7',
|
||||
'metadata': {'key1': 'v1'}
|
||||
}]
|
||||
}
|
||||
return (200, {}, access)
|
||||
|
||||
def get_share_access_rules_9999(self, **kw):
|
||||
access = {
|
||||
'access': {
|
||||
'access_level': 'rw',
|
||||
'state': 'active',
|
||||
'id': '9999',
|
||||
'access_type': 'ip',
|
||||
'access_to': '10.0.0.7',
|
||||
'metadata': {'key1': 'v1'}
|
||||
}
|
||||
}
|
||||
return (200, {}, access)
|
||||
|
||||
def put_share_access_rules_9999_metadata(self, **kw):
|
||||
return (200, {}, {'metadata': {'key1': 'v1', 'key2': 'v2'}})
|
||||
|
||||
def delete_share_access_rules_9999_metadata_key1(self, **kw):
|
||||
return (200, {}, None)
|
||||
|
||||
def get_shares_2222(self, **kw):
|
||||
share = {'share': {'id': 2222, 'name': 'sharename'}}
|
||||
return (200, {}, share)
|
||||
|
||||
def post_shares_2222_action(self, body, **kw):
|
||||
return (202, {}, {'access': {}})
|
||||
|
||||
def post_share_networks(self, **kwargs):
|
||||
return (202, {}, {'share_network': {}})
|
||||
|
||||
|
@ -49,7 +49,7 @@ class SharesTest(utils.TestCase):
|
||||
self.share.allow(access_type, access_to, access_level)
|
||||
|
||||
self.share.manager.allow.assert_called_once_with(
|
||||
self.share, access_type, access_to, access_level)
|
||||
self.share, access_type, access_to, access_level, None)
|
||||
|
||||
# Testcases for class ShareManager
|
||||
|
||||
|
@ -23,6 +23,7 @@ from oslo_utils import strutils
|
||||
import six
|
||||
from six.moves.urllib import parse
|
||||
|
||||
from manilaclient import api_versions
|
||||
from manilaclient import client
|
||||
from manilaclient.common.apiclient import utils as apiclient_utils
|
||||
from manilaclient.common import cliutils
|
||||
@ -1705,17 +1706,63 @@ class ShellTest(test_utils.TestCase):
|
||||
self.assertRaises(SystemExit, self.run_command,
|
||||
"access-allow --access-level fake 1111 ip 10.0.0.6")
|
||||
|
||||
def test_allow_access_with_metadata(self):
|
||||
expected = {
|
||||
"allow_access": {
|
||||
"access_type": "ip",
|
||||
"access_to": "10.0.0.6",
|
||||
"metadata": {"key1": "v1", "key2": "v2"},
|
||||
}
|
||||
}
|
||||
|
||||
self.run_command(
|
||||
"access-allow 2222 ip 10.0.0.6 --metadata key1=v1 key2=v2",
|
||||
version="2.45")
|
||||
self.assert_called("POST", "/shares/2222/action", body=expected)
|
||||
|
||||
def test_set_access_metadata(self):
|
||||
expected = {
|
||||
"metadata": {
|
||||
"key1": "v1",
|
||||
"key2": "v2",
|
||||
}
|
||||
}
|
||||
self.run_command(
|
||||
"access-metadata 9999 set key1=v1 key2=v2",
|
||||
version="2.45")
|
||||
self.assert_called("PUT", "/share-access-rules/9999/metadata",
|
||||
body=expected)
|
||||
|
||||
def test_unset_access_metadata(self):
|
||||
self.run_command(
|
||||
"access-metadata 9999 unset key1",
|
||||
version="2.45")
|
||||
self.assert_called("DELETE", "/share-access-rules/9999/metadata/key1")
|
||||
|
||||
@ddt.data("1.0", "2.0", "2.44")
|
||||
def test_allow_access_with_metadata_not_support_version(self, version):
|
||||
self.assertRaises(
|
||||
exceptions.CommandError,
|
||||
self.run_command,
|
||||
"access-allow 2222 ip 10.0.0.6 --metadata key1=v1",
|
||||
version=version,
|
||||
)
|
||||
|
||||
@mock.patch.object(cliutils, 'print_list', mock.Mock())
|
||||
def test_access_list(self):
|
||||
self.run_command("access-list 1111")
|
||||
@ddt.data(*set(["2.44", "2.45", api_versions.MAX_VERSION]))
|
||||
def test_access_list(self, version):
|
||||
self.run_command("access-list 1111", version=version)
|
||||
version = api_versions.APIVersion(version)
|
||||
cliutils.print_list.assert_called_with(
|
||||
mock.ANY,
|
||||
['id', 'access_type', 'access_to', 'access_level', 'state',
|
||||
'access_key', 'created_at', 'updated_at'])
|
||||
|
||||
@mock.patch.object(cliutils, 'print_list', mock.Mock())
|
||||
def test_access_list_select_column(self):
|
||||
self.run_command("access-list 1111 --columns id,access_type")
|
||||
@ddt.data(*set(["2.44", "2.45", api_versions.MAX_VERSION]))
|
||||
def test_access_list_select_column(self, version):
|
||||
self.run_command("access-list 1111 --columns id,access_type",
|
||||
version=version)
|
||||
cliutils.print_list.assert_called_with(
|
||||
mock.ANY,
|
||||
['Id', 'Access_Type'])
|
||||
|
@ -28,6 +28,7 @@ from manilaclient.v2 import quotas
|
||||
from manilaclient.v2 import scheduler_stats
|
||||
from manilaclient.v2 import security_services
|
||||
from manilaclient.v2 import services
|
||||
from manilaclient.v2 import share_access_rules
|
||||
from manilaclient.v2 import share_export_locations
|
||||
from manilaclient.v2 import share_group_snapshots
|
||||
from manilaclient.v2 import share_group_type_access
|
||||
@ -237,6 +238,8 @@ class Client(object):
|
||||
self.share_servers = share_servers.ShareServerManager(self)
|
||||
self.share_replicas = share_replicas.ShareReplicaManager(self)
|
||||
self.pools = scheduler_stats.PoolManager(self)
|
||||
self.share_access_rules = (
|
||||
share_access_rules.ShareAccessRuleManager(self))
|
||||
|
||||
self._load_extensions(extensions)
|
||||
|
||||
|
99
manilaclient/v2/share_access_rules.py
Normal file
99
manilaclient/v2/share_access_rules.py
Normal file
@ -0,0 +1,99 @@
|
||||
# Copyright 2018 Huawei Corporation.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Copyright 2018
|
||||
#
|
||||
# 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.
|
||||
"""Interface for share access rules extension."""
|
||||
|
||||
from six.moves.urllib import parse
|
||||
|
||||
from manilaclient import api_versions
|
||||
from manilaclient import base
|
||||
from manilaclient.common.apiclient import base as common_base
|
||||
from manilaclient import utils
|
||||
|
||||
|
||||
RESOURCE_PATH = '/share-access-rules/%s'
|
||||
RESOURCE_NAME = 'access'
|
||||
|
||||
RESOURCES_METADATA_PATH = '/share-access-rules/%s/metadata'
|
||||
RESOURCE_METADATA_PATH = '/share-access-rules/%s/metadata/%s'
|
||||
RESOURCE_LIST_PATH = '/share-access-rules?share_id=%s'
|
||||
|
||||
|
||||
class ShareAccessRule(common_base.Resource):
|
||||
"""A Share Access Rule."""
|
||||
|
||||
def __repr__(self):
|
||||
return "<Share Access Rule: %s>" % self.id
|
||||
|
||||
def delete(self):
|
||||
""""Delete this share access rule."""
|
||||
self.manager.delete(self)
|
||||
|
||||
|
||||
class ShareAccessRuleManager(base.ManagerWithFind):
|
||||
"""Manage :class:`ShareAccessRule` resources."""
|
||||
|
||||
resource_class = ShareAccessRule
|
||||
|
||||
@api_versions.wraps("2.45")
|
||||
def get(self, share_access_rule):
|
||||
"""Get a specific share access rule.
|
||||
|
||||
:param share_access_rule: either instance of ShareAccessRule, or text
|
||||
with UUID
|
||||
:rtype: :class:`ShareAccessRule`
|
||||
"""
|
||||
share_access_rule_id = common_base.getid(share_access_rule)
|
||||
url = RESOURCE_PATH % share_access_rule_id
|
||||
return self._get(url, RESOURCE_NAME)
|
||||
|
||||
@api_versions.wraps("2.45")
|
||||
def set_metadata(self, access, metadata):
|
||||
"""Set or update metadata for share access rule.
|
||||
|
||||
:param share_access_rule: either share access rule object or
|
||||
text with its ID.
|
||||
:param metadata: A list of keys to be set.
|
||||
"""
|
||||
body = {'metadata': metadata}
|
||||
access_id = common_base.getid(access)
|
||||
url = RESOURCES_METADATA_PATH % access_id
|
||||
return self._update(url, body, "metadata")
|
||||
|
||||
@api_versions.wraps("2.45")
|
||||
def unset_metadata(self, access, keys):
|
||||
"""Unset metadata on a share access rule.
|
||||
|
||||
:param keys: A list of keys on this object to be unset
|
||||
:return: None if successful, else API response on failure
|
||||
"""
|
||||
for k in keys:
|
||||
url = RESOURCE_METADATA_PATH % (common_base.getid(access), k)
|
||||
self._delete(url)
|
||||
|
||||
@api_versions.wraps("2.45")
|
||||
def access_list(self, share, search_opts):
|
||||
query_string = ""
|
||||
if search_opts:
|
||||
search_opts = utils.unicode_key_value_to_string(search_opts)
|
||||
params = sorted(
|
||||
[(k, v) for (k, v) in list(search_opts.items()) if v])
|
||||
if params:
|
||||
query_string = "&%s" % parse.urlencode(params)
|
||||
url = RESOURCE_LIST_PATH % common_base.getid(share) + query_string
|
||||
|
||||
return self._list(url, 'access_list')
|
@ -78,9 +78,10 @@ class Share(common_base.Resource):
|
||||
"""Delete the specified share ignoring its current state."""
|
||||
self.manager.force_delete(self)
|
||||
|
||||
def allow(self, access_type, access, access_level):
|
||||
def allow(self, access_type, access, access_level, metadata=None):
|
||||
"""Allow access to a share."""
|
||||
return self.manager.allow(self, access_type, access, access_level)
|
||||
return self.manager.allow(
|
||||
self, access_type, access, access_level, metadata)
|
||||
|
||||
def deny(self, id):
|
||||
"""Deny access from IP to a share."""
|
||||
@ -505,13 +506,15 @@ class ShareManager(base.ManagerWithFind):
|
||||
', '.join(valid_access_types))
|
||||
raise exceptions.CommandError(msg)
|
||||
|
||||
def _do_allow(self, share, access_type, access, access_level, action_name):
|
||||
def _do_allow(self, share, access_type, access, access_level, action_name,
|
||||
metadata=None):
|
||||
"""Allow access to a share.
|
||||
|
||||
:param share: either share object or text with its ID.
|
||||
:param access_type: string that represents access type ('ip','domain')
|
||||
:param access: string that represents access ('127.0.0.1')
|
||||
:param access_level: string that represents access level ('rw', 'ro')
|
||||
:param metadata: A dict of key/value pairs to be set
|
||||
"""
|
||||
access_params = {
|
||||
'access_type': access_type,
|
||||
@ -519,37 +522,47 @@ class ShareManager(base.ManagerWithFind):
|
||||
}
|
||||
if access_level:
|
||||
access_params['access_level'] = access_level
|
||||
if metadata:
|
||||
access_params['metadata'] = metadata
|
||||
access = self._action(action_name, share,
|
||||
access_params)[1]["access"]
|
||||
return access
|
||||
|
||||
@api_versions.wraps("1.0", "2.6")
|
||||
def allow(self, share, access_type, access, access_level):
|
||||
def allow(self, share, access_type, access, access_level, metadata=None):
|
||||
self._validate_access(access_type, access)
|
||||
return self._do_allow(
|
||||
share, access_type, access, access_level, "os-allow_access")
|
||||
|
||||
@api_versions.wraps("2.7", "2.12") # noqa
|
||||
def allow(self, share, access_type, access, access_level):
|
||||
def allow(self, share, access_type, access, access_level, metadata=None):
|
||||
self._validate_access(access_type, access)
|
||||
return self._do_allow(
|
||||
share, access_type, access, access_level, "allow_access")
|
||||
|
||||
@api_versions.wraps("2.13", "2.37") # noqa
|
||||
def allow(self, share, access_type, access, access_level):
|
||||
def allow(self, share, access_type, access, access_level, metadata=None):
|
||||
valid_access_types = ('ip', 'user', 'cert', 'cephx')
|
||||
self._validate_access(access_type, access, valid_access_types)
|
||||
return self._do_allow(
|
||||
share, access_type, access, access_level, "allow_access")
|
||||
|
||||
@api_versions.wraps("2.38") # noqa
|
||||
def allow(self, share, access_type, access, access_level):
|
||||
@api_versions.wraps("2.38", "2.44") # noqa
|
||||
def allow(self, share, access_type, access, access_level, metadata=None):
|
||||
valid_access_types = ('ip', 'user', 'cert', 'cephx')
|
||||
self._validate_access(access_type, access, valid_access_types,
|
||||
enable_ipv6=True)
|
||||
return self._do_allow(
|
||||
share, access_type, access, access_level, "allow_access")
|
||||
|
||||
@api_versions.wraps("2.45") # noqa
|
||||
def allow(self, share, access_type, access, access_level, metadata=None):
|
||||
valid_access_types = ('ip', 'user', 'cert', 'cephx')
|
||||
self._validate_access(access_type, access, valid_access_types,
|
||||
enable_ipv6=True)
|
||||
return self._do_allow(
|
||||
share, access_type, access, access_level, "allow_access", metadata)
|
||||
|
||||
def _do_deny(self, share, access_id, action_name):
|
||||
"""Deny access to a share.
|
||||
|
||||
@ -582,7 +595,7 @@ class ShareManager(base.ManagerWithFind):
|
||||
def access_list(self, share):
|
||||
return self._do_access_list(share, "os-access_list")
|
||||
|
||||
@api_versions.wraps("2.7") # noqa
|
||||
@api_versions.wraps("2.7", "2.44") # noqa
|
||||
def access_list(self, share):
|
||||
return self._do_access_list(share, "access_list")
|
||||
|
||||
|
@ -1302,13 +1302,72 @@ def do_show(cs, args):
|
||||
action='single_alias',
|
||||
help='Share access level ("rw" and "ro" access levels are supported). '
|
||||
'Defaults to rw.')
|
||||
@cliutils.arg(
|
||||
'--metadata',
|
||||
type=str,
|
||||
nargs='*',
|
||||
metavar='<key=value>',
|
||||
help='Space Separated list of key=value pairs of metadata items. '
|
||||
'OPTIONAL: Default=None. Available only for microversion >= 2.45.',
|
||||
default=None)
|
||||
def do_access_allow(cs, args):
|
||||
"""Allow access to the share."""
|
||||
"""Allow access to a given share."""
|
||||
access_metadata = None
|
||||
if cs.api_version.matches(api_versions.APIVersion("2.45"),
|
||||
api_versions.APIVersion()):
|
||||
access_metadata = _extract_metadata(args)
|
||||
elif getattr(args, 'metadata'):
|
||||
raise exceptions.CommandError(
|
||||
"Adding metadata to access rules is supported only beyond "
|
||||
"API version 2.45")
|
||||
|
||||
share = _find_share(cs, args.share)
|
||||
access = share.allow(args.access_type, args.access_to, args.access_level)
|
||||
access = share.allow(args.access_type, args.access_to, args.access_level,
|
||||
access_metadata)
|
||||
cliutils.print_dict(access)
|
||||
|
||||
|
||||
@api_versions.wraps("2.45")
|
||||
@cliutils.arg(
|
||||
'access_id',
|
||||
metavar='<access_id>',
|
||||
help='ID of the NAS share access rule.')
|
||||
def do_access_show(cs, args):
|
||||
"""Show details about a NAS share access rule."""
|
||||
access = cs.share_access_rules.get(args.access_id)
|
||||
view_data = access._info.copy()
|
||||
cliutils.print_dict(view_data)
|
||||
|
||||
|
||||
@api_versions.wraps("2.45")
|
||||
@cliutils.arg(
|
||||
'access_id',
|
||||
metavar='<access_id>',
|
||||
help='ID of the NAS share access rule.')
|
||||
@cliutils.arg(
|
||||
'action',
|
||||
metavar='<action>',
|
||||
choices=['set', 'unset'],
|
||||
help="Actions: 'set' or 'unset'.")
|
||||
@cliutils.arg(
|
||||
'metadata',
|
||||
metavar='<key=value>',
|
||||
nargs='+',
|
||||
default=[],
|
||||
help='Space separated key=value pairs of metadata items to set. '
|
||||
'To unset only keys are required. ')
|
||||
def do_access_metadata(cs, args):
|
||||
"""Set or delete metadata on a share access rule."""
|
||||
share_access = cs.share_access_rules.get(args.access_id)
|
||||
metadata = _extract_metadata(args)
|
||||
|
||||
if args.action == 'set':
|
||||
cs.share_access_rules.set_metadata(share_access, metadata)
|
||||
elif args.action == 'unset':
|
||||
cs.share_access_rules.unset_metadata(
|
||||
share_access, sorted(list(metadata), reverse=True))
|
||||
|
||||
|
||||
@api_versions.wraps("2.32")
|
||||
@cliutils.arg(
|
||||
'snapshot',
|
||||
@ -1437,6 +1496,14 @@ def do_access_list(cs, args):
|
||||
default=None,
|
||||
help='Comma separated list of columns to be displayed '
|
||||
'example --columns "access_type,access_to".')
|
||||
@cliutils.arg(
|
||||
'--metadata',
|
||||
type=str,
|
||||
nargs='*',
|
||||
metavar='<key=value>',
|
||||
help='Filters results by a metadata key and value. OPTIONAL: '
|
||||
'Default=None. Available only for microversion >= 2.45',
|
||||
default=None)
|
||||
def do_access_list(cs, args):
|
||||
"""Show access list for share."""
|
||||
list_of_keys = [
|
||||
@ -1444,11 +1511,18 @@ def do_access_list(cs, args):
|
||||
'access_key', 'created_at', 'updated_at',
|
||||
]
|
||||
|
||||
share = _find_share(cs, args.share)
|
||||
if cs.api_version < api_versions.APIVersion("2.45"):
|
||||
if getattr(args, 'metadata'):
|
||||
raise exceptions.CommandError(
|
||||
"Filtering access rules by metadata is supported only beyond "
|
||||
"API version 2.45")
|
||||
access_list = share.access_list()
|
||||
else:
|
||||
access_list = cs.share_access_rules.access_list(
|
||||
share, {'metadata': _extract_metadata(args)})
|
||||
if args.columns is not None:
|
||||
list_of_keys = _split_columns(columns=args.columns)
|
||||
|
||||
share = _find_share(cs, args.share)
|
||||
access_list = share.access_list()
|
||||
cliutils.print_list(access_list, list_of_keys)
|
||||
|
||||
|
||||
|
@ -0,0 +1,5 @@
|
||||
---
|
||||
features:
|
||||
- Added support to create share access rule metadata, update existing share
|
||||
access rule metadata and delete share access rule metadata. Also added a
|
||||
new shell command to show details of a share access rule.
|
Loading…
x
Reference in New Issue
Block a user