Add tempest test for share access metadata

Depends-On: https://review.openstack.org/#/c/570708/
Change-Id: Ia794e1b13fec092b139c4859af48159869d6869e
Partially-implements bp: metadata-for-access-rule
This commit is contained in:
zhongjun2 2018-07-02 12:30:25 +00:00
parent 92f691c575
commit ac9fbb994c
6 changed files with 283 additions and 9 deletions

View File

@ -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'

View File

@ -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",

View File

@ -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',

View File

@ -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'])

View File

@ -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")

View File

@ -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)