Merge "Add tempest test for share access metadata"
This commit is contained in:
commit
f0dd7a400b
|
@ -83,3 +83,5 @@ SHARE_GROUP_SNAPSHOT_DETAIL_REQUIRED_KEYS = {
|
|||
SHARE_GROUP_TYPE_REQUIRED_KEYS = {
|
||||
'id', 'name', 'share_types', 'is_public', 'group_specs',
|
||||
}
|
||||
|
||||
MIN_SHARE_ACCESS_METADATA_MICROVERSION = '2.45'
|
||||
|
|
|
@ -30,7 +30,7 @@ ShareGroup = [
|
|||
help="The minimum api microversion is configured to be the "
|
||||
"value of the minimum microversion supported by Manila."),
|
||||
cfg.StrOpt("max_api_microversion",
|
||||
default="2.44",
|
||||
default="2.45",
|
||||
help="The maximum api microversion is configured to be the "
|
||||
"value of the latest microversion supported by Manila."),
|
||||
cfg.StrOpt("region",
|
||||
|
|
|
@ -731,7 +731,8 @@ class SharesV2Client(shares_client.SharesClient):
|
|||
|
||||
def create_access_rule(self, share_id, access_type="ip",
|
||||
access_to="0.0.0.0", access_level=None,
|
||||
version=LATEST_MICROVERSION, action_name=None):
|
||||
version=LATEST_MICROVERSION, metadata=None,
|
||||
action_name=None):
|
||||
post_body = {
|
||||
self._get_access_action_name(version, 'os-allow_access'): {
|
||||
"access_type": access_type,
|
||||
|
@ -739,6 +740,8 @@ class SharesV2Client(shares_client.SharesClient):
|
|||
"access_level": access_level,
|
||||
}
|
||||
}
|
||||
if metadata is not None:
|
||||
post_body['allow_access']['metadata'] = metadata
|
||||
body = json.dumps(post_body)
|
||||
resp, body = self.post(
|
||||
"shares/%s/action" % share_id, body, version=version,
|
||||
|
@ -747,10 +750,34 @@ class SharesV2Client(shares_client.SharesClient):
|
|||
return self._parse_resp(body)
|
||||
|
||||
def list_access_rules(self, share_id, version=LATEST_MICROVERSION,
|
||||
action_name=None):
|
||||
body = {self._get_access_action_name(version, 'os-access_list'): None}
|
||||
resp, body = self.post(
|
||||
"shares/%s/action" % share_id, json.dumps(body), version=version)
|
||||
metadata=None, action_name=None):
|
||||
if utils.is_microversion_lt(version, "2.45"):
|
||||
body = {
|
||||
self._get_access_action_name(version, 'os-access_list'): None
|
||||
}
|
||||
resp, body = self.post(
|
||||
"shares/%s/action" % share_id, json.dumps(body),
|
||||
version=version)
|
||||
self.expected_success(200, resp.status)
|
||||
else:
|
||||
return self.list_access_rules_with_new_API(
|
||||
share_id, metadata=metadata, version=version,
|
||||
action_name=action_name)
|
||||
return self._parse_resp(body)
|
||||
|
||||
def list_access_rules_with_new_API(self, share_id, metadata=None,
|
||||
version=LATEST_MICROVERSION,
|
||||
action_name=None):
|
||||
metadata = metadata or {}
|
||||
query_string = ''
|
||||
|
||||
params = sorted(
|
||||
[(k, v) for (k, v) in list(metadata.items()) if v])
|
||||
if params:
|
||||
query_string = "&%s" % urlparse.urlencode(params)
|
||||
|
||||
url = 'share-access-rules?share_id=%s' % share_id + query_string
|
||||
resp, body = self.get(url, version=version)
|
||||
self.expected_success(200, resp.status)
|
||||
return self._parse_resp(body)
|
||||
|
||||
|
@ -767,6 +794,28 @@ class SharesV2Client(shares_client.SharesClient):
|
|||
self.expected_success(202, resp.status)
|
||||
return body
|
||||
|
||||
def get_access(self, access_id, version=LATEST_MICROVERSION):
|
||||
resp, body = self.get("share-access-rules/%s" % access_id,
|
||||
version=version)
|
||||
self.expected_success(200, resp.status)
|
||||
return self._parse_resp(body)
|
||||
|
||||
def update_access_metadata(self, access_id, metadata,
|
||||
version=LATEST_MICROVERSION):
|
||||
url = 'share-access-rules/%s/metadata' % access_id
|
||||
body = {"metadata": metadata}
|
||||
resp, body = self.put(url, json.dumps(body), version=version)
|
||||
self.expected_success(200, resp.status)
|
||||
return self._parse_resp(body)
|
||||
|
||||
def delete_access_metadata(self, access_id, key,
|
||||
version=LATEST_MICROVERSION):
|
||||
url = "share-access-rules/%s/metadata/%s" % (access_id, key)
|
||||
resp, body = self.delete(url, version=version)
|
||||
self.expected_success(200, resp.status)
|
||||
return body
|
||||
|
||||
|
||||
###############
|
||||
|
||||
def list_availability_zones(self, url='availability-zones',
|
||||
|
|
|
@ -0,0 +1,133 @@
|
|||
# Copyright 2018 Huawei Inc.
|
||||
# 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 ddt
|
||||
from tempest import config
|
||||
from testtools import testcase as tc
|
||||
|
||||
from manila_tempest_tests.common import constants
|
||||
from manila_tempest_tests.tests.api import base
|
||||
from manila_tempest_tests import utils
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
@base.skip_if_microversion_lt(
|
||||
constants.MIN_SHARE_ACCESS_METADATA_MICROVERSION)
|
||||
@ddt.ddt
|
||||
class AccessRulesMetadataTest(base.BaseSharesTest):
|
||||
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
super(AccessRulesMetadataTest, cls).resource_setup()
|
||||
# The share access rule metadata doesn't care about the value of
|
||||
# access type, access protocol, access_to, so we only get one of
|
||||
# the value that the driver support.
|
||||
if not (any(p in CONF.share.enable_ip_rules_for_protocols
|
||||
for p in cls.protocols) or
|
||||
any(p in CONF.share.enable_user_rules_for_protocols
|
||||
for p in cls.protocols) or
|
||||
any(p in CONF.share.enable_cert_rules_for_protocols
|
||||
for p in cls.protocols) or
|
||||
any(p in CONF.share.enable_cephx_rules_for_protocols
|
||||
for p in cls.protocols)):
|
||||
cls.message = "Rule tests are disabled"
|
||||
raise cls.skipException(cls.message)
|
||||
if CONF.share.enable_ip_rules_for_protocols:
|
||||
cls.protocol = CONF.share.enable_ip_rules_for_protocols[0]
|
||||
cls.access_type = "ip"
|
||||
elif CONF.share.enable_user_rules_for_protocols:
|
||||
cls.protocol = CONF.share.enable_user_rules_for_protocols[0]
|
||||
cls.access_type = "user"
|
||||
elif CONF.share.enable_cert_rules_for_protocols:
|
||||
cls.protocol = CONF.share.enable_cert_rules_for_protocols[0]
|
||||
cls.access_type = "cert"
|
||||
elif CONF.share.enable_cephx_rules_for_protocols:
|
||||
cls.protocol = CONF.share.enable_cephx_rules_for_protocols[0]
|
||||
cls.access_type = "cephx"
|
||||
cls.shares_v2_client.share_protocol = cls.protocol
|
||||
int_range = range(20, 50)
|
||||
cls.access_to = {
|
||||
# list of unique values is required for ability to create lots
|
||||
# of access rules for one share using different API microversions.
|
||||
'ip': set([utils.rand_ipv6_ip() for i in int_range]),
|
||||
# following users are fakes and access rules that use it are
|
||||
# expected to fail, but they are used only for API testing.
|
||||
'user': ['foo_user_%d' % i for i in int_range],
|
||||
'cert': ['tenant_%d.example.com' % i for i in int_range],
|
||||
'cephx': ['eve%d' % i for i in int_range],
|
||||
}
|
||||
cls.share = cls.create_share()
|
||||
cls.md1 = {"key1": "value1", "key2": "value2"}
|
||||
cls.access = cls.shares_v2_client.create_access_rule(
|
||||
cls.share["id"], cls.access_type,
|
||||
cls.access_to[cls.access_type].pop(), 'rw', metadata=cls.md1)
|
||||
|
||||
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
|
||||
def test_set_get_delete_access_metadata(self):
|
||||
data = {"key1": "v" * 255, "k" * 255: "value2"}
|
||||
# set metadata
|
||||
access = self.shares_v2_client.create_access_rule(
|
||||
self.share["id"], self.access_type,
|
||||
self.access_to[self.access_type].pop(), 'rw', metadata=data)
|
||||
|
||||
# read metadata
|
||||
get_access = self.shares_v2_client.get_access(access["id"])
|
||||
|
||||
# verify metadata
|
||||
self.assertEqual(data, get_access['metadata'])
|
||||
|
||||
# delete metadata
|
||||
for key in data.keys():
|
||||
self.shares_v2_client.delete_access_metadata(access["id"], key)
|
||||
|
||||
# verify deletion of metadata
|
||||
access_without_md = self.shares_v2_client.get_access(access["id"])
|
||||
self.assertEqual({}, access_without_md['metadata'])
|
||||
self.shares_v2_client.delete_access_rule(self.share["id"],
|
||||
access["id"])
|
||||
self.shares_v2_client.wait_for_resource_deletion(
|
||||
rule_id=access["id"], share_id=self.share["id"])
|
||||
|
||||
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
|
||||
def test_update_metadata_by_key(self):
|
||||
md2 = {"key7": "value7", "key2": "value6_new"}
|
||||
|
||||
# update metadata
|
||||
self.shares_v2_client.update_access_metadata(
|
||||
access_id=self.access['id'], metadata=md2)
|
||||
# get metadata
|
||||
get_access = self.shares_v2_client.get_access(self.access['id'])
|
||||
|
||||
# verify metadata
|
||||
self.md1.update(md2)
|
||||
self.assertEqual(self.md1, get_access['metadata'])
|
||||
|
||||
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
|
||||
def test_list_access_filter_by_metadata(self):
|
||||
data = {"key3": "v3", "key4": "value4"}
|
||||
# set metadata
|
||||
access = self.shares_v2_client.create_access_rule(
|
||||
self.share["id"], self.access_type,
|
||||
self.access_to[self.access_type].pop(), 'rw', metadata=data)
|
||||
|
||||
# list metadata with metadata filter
|
||||
list_access = self.shares_v2_client.list_access_rules(
|
||||
share_id=self.share["id"], metadata={'metadata': data})
|
||||
|
||||
# verify metadata
|
||||
self.assertEqual(1, len(list_access))
|
||||
self.assertEqual(access['metadata'], list_access[0]['metadata'])
|
||||
self.assertEqual(access['id'], list_access[0]['id'])
|
|
@ -0,0 +1,80 @@
|
|||
# Copyright 2018 Huawei Inc.
|
||||
# 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 ddt
|
||||
from tempest import config
|
||||
from tempest.lib import exceptions as lib_exc
|
||||
from testtools import testcase as tc
|
||||
|
||||
from manila_tempest_tests.common import constants
|
||||
from manila_tempest_tests.tests.api import base
|
||||
from manila_tempest_tests import utils
|
||||
|
||||
CONF = config.CONF
|
||||
|
||||
|
||||
@base.skip_if_microversion_lt(constants.MIN_SHARE_GROUP_MICROVERSION)
|
||||
@ddt.ddt
|
||||
class AccessesMetadataNegativeTest(base.BaseSharesTest):
|
||||
|
||||
@classmethod
|
||||
def resource_setup(cls):
|
||||
super(AccessesMetadataNegativeTest, cls).resource_setup()
|
||||
if not (any(p in CONF.share.enable_ip_rules_for_protocols
|
||||
for p in cls.protocols) or
|
||||
any(p in CONF.share.enable_user_rules_for_protocols
|
||||
for p in cls.protocols) or
|
||||
any(p in CONF.share.enable_cert_rules_for_protocols
|
||||
for p in cls.protocols) or
|
||||
any(p in CONF.share.enable_cephx_rules_for_protocols
|
||||
for p in cls.protocols)):
|
||||
cls.message = "Rule tests are disabled"
|
||||
raise cls.skipException(cls.message)
|
||||
if CONF.share.enable_ip_rules_for_protocols:
|
||||
cls.protocol = CONF.share.enable_ip_rules_for_protocols[0]
|
||||
cls.access_type = "ip"
|
||||
cls.access_to = utils.rand_ip()
|
||||
elif CONF.share.enable_user_rules_for_protocols:
|
||||
cls.protocol = CONF.share.enable_user_rules_for_protocols[0]
|
||||
cls.access_type = "user"
|
||||
cls.access_to = CONF.share.username_for_user_rules
|
||||
elif CONF.share.enable_cert_rules_for_protocols:
|
||||
cls.protocol = CONF.share.enable_cert_rules_for_protocols[0]
|
||||
cls.access_type = "cert"
|
||||
cls.access_to = "client3.com"
|
||||
elif CONF.share.enable_cephx_rules_for_protocols:
|
||||
cls.protocol = CONF.share.enable_cephx_rules_for_protocols[0]
|
||||
cls.access_type = "cephx"
|
||||
cls.access_to = "eve"
|
||||
cls.shares_v2_client.share_protocol = cls.protocol
|
||||
cls.share = cls.create_share()
|
||||
cls.access = cls.shares_v2_client.create_access_rule(
|
||||
cls.share["id"], cls.access_type, cls.access_to,
|
||||
'rw', metadata={u"key1": u"value1"})
|
||||
|
||||
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
|
||||
@ddt.data({'data': {"": "value"}}, {'data': {"k" * 256: "value"}},
|
||||
{'data': {"key": "x" * 1024}})
|
||||
@ddt.unpack
|
||||
def test_try_upd_access_metadata_error(self, data):
|
||||
self.assertRaises(lib_exc.BadRequest,
|
||||
self.shares_v2_client.update_access_metadata,
|
||||
self.access["id"], data)
|
||||
|
||||
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
|
||||
def test_try_delete_unexisting_access_metadata(self):
|
||||
self.assertRaises(lib_exc.NotFound,
|
||||
self.shares_v2_client.delete_access_metadata,
|
||||
self.access["id"], "wrong_key")
|
|
@ -488,7 +488,8 @@ class ShareRulesTest(base.BaseSharesTest):
|
|||
cls.share = cls.create_share()
|
||||
|
||||
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
|
||||
@ddt.data(*set(['1.0', '2.9', '2.27', '2.28', LATEST_MICROVERSION]))
|
||||
@ddt.data(*set(
|
||||
['1.0', '2.9', '2.27', '2.28', '2.45', LATEST_MICROVERSION]))
|
||||
def test_list_access_rules(self, version):
|
||||
if (utils.is_microversion_lt(version, '2.13') and
|
||||
CONF.share.enable_cephx_rules_for_protocols):
|
||||
|
@ -496,6 +497,9 @@ class ShareRulesTest(base.BaseSharesTest):
|
|||
"version >= 2.13." % version)
|
||||
raise self.skipException(msg)
|
||||
|
||||
metadata = None
|
||||
if utils.is_microversion_ge(version, '2.45'):
|
||||
metadata = {'key1': 'v1', 'key2': 'v2'}
|
||||
# create rule
|
||||
if utils.is_microversion_eq(version, '1.0'):
|
||||
rule = self.shares_client.create_access_rule(
|
||||
|
@ -503,7 +507,7 @@ class ShareRulesTest(base.BaseSharesTest):
|
|||
else:
|
||||
rule = self.shares_v2_client.create_access_rule(
|
||||
self.share["id"], self.access_type, self.access_to,
|
||||
version=version)
|
||||
metadata=metadata, version=version)
|
||||
|
||||
# verify added rule keys since 2.33 when create rule
|
||||
if utils.is_microversion_ge(version, '2.33'):
|
||||
|
@ -543,6 +547,8 @@ class ShareRulesTest(base.BaseSharesTest):
|
|||
keys += ("access_key", )
|
||||
if utils.is_microversion_ge(version, '2.33'):
|
||||
keys += ("created_at", "updated_at", )
|
||||
if utils.is_microversion_ge(version, '2.45'):
|
||||
keys += ("metadata",)
|
||||
for key in keys:
|
||||
[self.assertIn(key, r.keys()) for r in rules]
|
||||
for key in ('deleted', 'deleted_at', 'instance_mappings'):
|
||||
|
@ -625,7 +631,11 @@ class ShareRulesTest(base.BaseSharesTest):
|
|||
self.assertRaises(lib_exc.NotFound,
|
||||
self.shares_client.list_access_rules,
|
||||
share['id'])
|
||||
else:
|
||||
elif utils.is_microversion_lt(version, '2.45'):
|
||||
self.assertRaises(lib_exc.NotFound,
|
||||
self.shares_v2_client.list_access_rules,
|
||||
share['id'], version)
|
||||
else:
|
||||
self.assertRaises(lib_exc.BadRequest,
|
||||
self.shares_v2_client.list_access_rules,
|
||||
share['id'], version)
|
||||
|
|
Loading…
Reference in New Issue