Merge "Remove duplicate keys from dictionary"
diff --git a/manila_tempest_tests/services/share/v2/json/shares_client.py b/manila_tempest_tests/services/share/v2/json/shares_client.py
index 2282510..a965a36 100644
--- a/manila_tempest_tests/services/share/v2/json/shares_client.py
+++ b/manila_tempest_tests/services/share/v2/json/shares_client.py
@@ -17,12 +17,13 @@
import time
import urllib
+from tempest import config
from tempest_lib.common.utils import data_utils
from tempest_lib import exceptions
-from manila_tempest_tests.services.share.json import shares_client # noqa
+from manila_tempest_tests.services.share.json import shares_client
from manila_tempest_tests import share_exceptions
-from tempest import config # noqa
+from manila_tempest_tests import utils
CONF = config.CONF
LATEST_MICROVERSION = CONF.share.max_api_microversion
@@ -105,7 +106,7 @@
cgsnapshots.
"""
if action_name is None:
- if float(version) > 2.6:
+ if utils.is_microversion_gt(version, "2.6"):
action_name = 'reset_status'
else:
action_name = 'os-reset_status'
@@ -124,7 +125,7 @@
s_type: shares, snapshots
"""
if action_name is None:
- if float(version) > 2.6:
+ if utils.is_microversion_gt(version, "2.6"):
action_name = 'force_delete'
else:
action_name = 'os-force_delete'
@@ -292,7 +293,10 @@
def extend_share(self, share_id, new_size, version=LATEST_MICROVERSION,
action_name=None):
if action_name is None:
- action_name = 'extend' if float(version) > 2.6 else 'os-extend'
+ if utils.is_microversion_gt(version, "2.6"):
+ action_name = 'extend'
+ else:
+ action_name = 'os-extend'
post_body = {
action_name: {
"new_size": new_size,
@@ -307,7 +311,10 @@
def shrink_share(self, share_id, new_size, version=LATEST_MICROVERSION,
action_name=None):
if action_name is None:
- action_name = 'shrink' if float(version) > 2.6 else 'os-shrnk'
+ if utils.is_microversion_gt(version, "2.6"):
+ action_name = 'shrink'
+ else:
+ action_name = 'os-shrink'
post_body = {
action_name: {
"new_size": new_size,
@@ -337,7 +344,7 @@
}
}
if url is None:
- if float(version) > 2.6:
+ if utils.is_microversion_gt(version, "2.6"):
url = 'shares/manage'
else:
url = 'os-share-manage'
@@ -349,10 +356,16 @@
def unmanage_share(self, share_id, version=LATEST_MICROVERSION, url=None,
action_name=None, body=None):
if url is None:
- url = 'shares' if float(version) > 2.6 else 'os-share-unmanage'
+ if utils.is_microversion_gt(version, "2.6"):
+ url = 'shares'
+ else:
+ url = 'os-share-unmanage'
if action_name is None:
- action_name = 'action' if float(version) > 2.6 else 'unmanage'
- if body is None and float(version) > 2.6:
+ if utils.is_microversion_gt(version, "2.6"):
+ action_name = 'action'
+ else:
+ action_name = 'unmanage'
+ if body is None and utils.is_microversion_gt(version, "2.6"):
body = json.dumps({'unmanage': {}})
resp, body = self.post(
"%(url)s/%(share_id)s/%(action_name)s" % {
@@ -365,7 +378,7 @@
###############
def _get_access_action_name(self, version):
- if float(version) > 2.6:
+ if utils.is_microversion_gt(version, "2.6"):
return 'allow_access'
return 'os-allow_access'
@@ -412,7 +425,7 @@
version=LATEST_MICROVERSION):
"""Get list of availability zones."""
if url is None:
- if float(version) > 2.6:
+ if utils.is_microversion_gt(version, "2.6"):
url = 'availability-zones'
else:
url = 'os-availability-zone'
@@ -426,7 +439,10 @@
version=LATEST_MICROVERSION):
"""List services."""
if url is None:
- url = 'services' if float(version) > 2.6 else 'os-services'
+ if utils.is_microversion_gt(version, "2.6"):
+ url = 'services'
+ else:
+ url = 'os-services'
if params:
url += '?%s' % urllib.urlencode(params)
resp, body = self.get(url, version=version)
@@ -445,7 +461,7 @@
def create_share_type(self, name, is_public=True,
version=LATEST_MICROVERSION, **kwargs):
- if float(version) > 2.6:
+ if utils.is_microversion_gt(version, "2.6"):
is_public_keyname = 'share_type_access:is_public'
else:
is_public_keyname = 'os-share-type-access:is_public'
@@ -473,7 +489,7 @@
version=LATEST_MICROVERSION,
action_name=None):
if action_name is None:
- if float(version) > 2.6:
+ if utils.is_microversion_gt(version, "2.6"):
action_name = 'share_type_access'
else:
action_name = 'os-share-type-access'
@@ -487,7 +503,7 @@
###############
def _get_quotas_url(self, version):
- if float(version) > 2.6:
+ if utils.is_microversion_gt(version, "2.6"):
return 'quota-sets'
return 'os-quota-sets'
@@ -758,7 +774,7 @@
def migrate_share(self, share_id, host, version=LATEST_MICROVERSION,
action_name=None):
if action_name is None:
- if float(version) > 2.6:
+ if utils.is_microversion_gt(version, "2.6"):
action_name = 'migrate_share'
else:
action_name = 'os-migrate_share'
diff --git a/manila_tempest_tests/tests/api/admin/test_share_manage.py b/manila_tempest_tests/tests/api/admin/test_share_manage.py
index 78d28ee..c7efa01 100644
--- a/manila_tempest_tests/tests/api/admin/test_share_manage.py
+++ b/manila_tempest_tests/tests/api/admin/test_share_manage.py
@@ -14,13 +14,14 @@
# under the License.
import six
-from tempest import config # noqa
-from tempest import test # noqa
-from tempest_lib.common.utils import data_utils # noqa
-from tempest_lib import exceptions as lib_exc # noqa
-import testtools # noqa
+from tempest import config
+from tempest import test
+from tempest_lib.common.utils import data_utils
+from tempest_lib import exceptions as lib_exc
+import testtools
from manila_tempest_tests.tests.api import base
+from manila_tempest_tests import utils
CONF = config.CONF
@@ -78,7 +79,7 @@
# Data for creating shares in parallel
data = [creation_data, creation_data]
- if float(CONF.share.max_api_microversion) >= 2.8:
+ if utils.is_microversion_ge(CONF.share.max_api_microversion, "2.8"):
data.append(creation_data)
shares_created = cls.create_shares(data)
@@ -127,7 +128,7 @@
share = self.shares_v2_client.get_share(share['id'], version="2.6")
self.assertEqual(self.st['share_type']['id'], share['share_type'])
- if float(version) >= 2.8:
+ if utils.is_microversion_ge(version, "2.8"):
self.assertEqual(is_public, share['is_public'])
else:
self.assertFalse(share['is_public'])
@@ -139,9 +140,7 @@
self.shares_v2_client.get_share,
share['id'])
- @testtools.skipIf(
- float(CONF.share.max_api_microversion) < 2.8,
- "Only for API Microversion >= 2.8")
+ @base.skip_if_microversion_not_supported("2.8")
@test.attr(type=["gate", "smoke"])
def test_manage_with_is_public_True(self):
self._test_manage(share=self.shares[2], is_public=True)
diff --git a/manila_tempest_tests/tests/api/admin/test_share_types.py b/manila_tempest_tests/tests/api/admin/test_share_types.py
index d58c61c..a521aad 100644
--- a/manila_tempest_tests/tests/api/admin/test_share_types.py
+++ b/manila_tempest_tests/tests/api/admin/test_share_types.py
@@ -20,7 +20,7 @@
from tempest_lib import exceptions as lib_exc # noqa
from manila_tempest_tests.tests.api import base
-
+from manila_tempest_tests import utils
CONF = config.CONF
@@ -51,7 +51,7 @@
def _verify_is_public_key_name(self, share_type, version):
old_key_name = 'os-share-type-access:is_public'
new_key_name = 'share_type_access:is_public'
- if float(version) > 2.6:
+ if utils.is_microversion_gt(version, "2.6"):
self.assertIn(new_key_name, share_type)
self.assertNotIn(old_key_name, share_type)
else:
diff --git a/manila_tempest_tests/tests/api/admin/test_share_types_negative.py b/manila_tempest_tests/tests/api/admin/test_share_types_negative.py
index 62e4523..32c9620 100644
--- a/manila_tempest_tests/tests/api/admin/test_share_types_negative.py
+++ b/manila_tempest_tests/tests/api/admin/test_share_types_negative.py
@@ -68,3 +68,33 @@
self.create_share_type,
st["share_type"]["name"],
extra_specs=self.add_required_extra_specs_to_dict())
+
+ @test.attr(type=["gate", "smoke", ])
+ def test_add_share_type_allowed_for_public(self):
+ st = self._create_share_type()
+ self.assertRaises(lib_exc.Conflict,
+ self.shares_client.add_access_to_share_type,
+ st["share_type"]["id"],
+ self.shares_client.tenant_id)
+
+ @test.attr(type=["gate", "smoke", ])
+ def test_remove_share_type_allowed_for_public(self):
+ st = self._create_share_type()
+ self.assertRaises(lib_exc.Conflict,
+ self.shares_client.remove_access_from_share_type,
+ st["share_type"]["id"],
+ self.shares_client.tenant_id)
+
+ @test.attr(type=["gate", "smoke", ])
+ def test_add_share_type_by_nonexistent_id(self):
+ self.assertRaises(lib_exc.NotFound,
+ self.shares_client.add_access_to_share_type,
+ data_utils.rand_name("fake"),
+ self.shares_client.tenant_id)
+
+ @test.attr(type=["gate", "smoke", ])
+ def test_remove_share_type_by_nonexistent_id(self):
+ self.assertRaises(lib_exc.NotFound,
+ self.shares_client.remove_access_from_share_type,
+ data_utils.rand_name("fake"),
+ self.shares_client.tenant_id)
diff --git a/manila_tempest_tests/tests/api/base.py b/manila_tempest_tests/tests/api/base.py
index be56719..d57b493 100644
--- a/manila_tempest_tests/tests/api/base.py
+++ b/manila_tempest_tests/tests/api/base.py
@@ -15,7 +15,6 @@
import copy
import inspect
-import random
import traceback
from oslo_concurrency import lockutils
@@ -27,27 +26,15 @@
from tempest import test
from tempest_lib.common.utils import data_utils
from tempest_lib import exceptions
-import testtools
from manila_tempest_tests import clients_share as clients
from manila_tempest_tests import share_exceptions
+from manila_tempest_tests import utils
CONF = config.CONF
LOG = log.getLogger(__name__)
-def rand_ip():
- """This uses the TEST-NET-3 range of reserved IP addresses.
-
- Using this range, which are reserved solely for use in
- documentation and example source code, should avoid any potential
- conflicts in real-world testing.
- """
- TEST_NET_3 = '203.0.113.'
- final_octet = six.text_type(random.randint(0, 255))
- return TEST_NET_3 + final_octet
-
-
class handle_cleanup_exceptions(object):
"""Handle exceptions raised with cleanup operations.
@@ -91,19 +78,7 @@
return wrapped_func
-def is_microversion_supported(microversion):
- if (float(microversion) > float(CONF.share.max_api_microversion) or
- float(microversion) < float(CONF.share.min_api_microversion)):
- return False
- return True
-
-
-def skip_if_microversion_not_supported(microversion):
- """Decorator for tests that are microversion-specific."""
- if not is_microversion_supported(microversion):
- reason = ("Skipped. Test requires microversion '%s'." % microversion)
- return testtools.skip(reason)
- return lambda f: f
+skip_if_microversion_not_supported = utils.skip_if_microversion_not_supported
class BaseSharesTest(test.BaseTestCase):
@@ -125,7 +100,7 @@
method_isolated_creds = []
def skip_if_microversion_not_supported(self, microversion):
- if not is_microversion_supported(microversion):
+ if not utils.is_microversion_supported(microversion):
raise self.skipException(
"Microversion '%s' is not supported." % microversion)
@@ -657,8 +632,8 @@
data = {
"name": data_utils.rand_name("ss-name"),
"description": data_utils.rand_name("ss-desc"),
- "dns_ip": rand_ip(),
- "server": rand_ip(),
+ "dns_ip": utils.rand_ip(),
+ "server": utils.rand_ip(),
"domain": data_utils.rand_name("ss-domain"),
"user": data_utils.rand_name("ss-user"),
"password": data_utils.rand_name("ss-password"),
diff --git a/manila_tempest_tests/tests/api/test_shares_actions.py b/manila_tempest_tests/tests/api/test_shares_actions.py
index 58ddbfe..36fd6e5 100644
--- a/manila_tempest_tests/tests/api/test_shares_actions.py
+++ b/manila_tempest_tests/tests/api/test_shares_actions.py
@@ -14,12 +14,13 @@
# under the License.
import six
-from tempest import config # noqa
-from tempest import test # noqa
-from tempest_lib.common.utils import data_utils # noqa
-import testtools # noqa
+from tempest import config
+from tempest import test
+from tempest_lib.common.utils import data_utils
+import testtools
from manila_tempest_tests.tests.api import base
+from manila_tempest_tests import utils
CONF = config.CONF
@@ -79,11 +80,20 @@
self.shares[0]['id'], version=six.text_type(version))
# verify keys
- expected_keys = ["status", "description", "links", "availability_zone",
- "created_at", "export_location", "share_proto",
- "name", "snapshot_id", "id", "size"]
- if version > 2.1:
+ expected_keys = [
+ "status", "description", "links", "availability_zone",
+ "created_at", "export_location", "project_id",
+ "export_locations", "volume_type", "share_proto", "name",
+ "snapshot_id", "id", "size", "share_network_id", "metadata",
+ "host", "snapshot_id", "is_public",
+ ]
+ if utils.is_microversion_ge(version, '2.2'):
expected_keys.append("snapshot_support")
+ if utils.is_microversion_ge(version, '2.4'):
+ expected_keys.extend(["consistency_group_id",
+ "source_cgsnapshot_member_id"])
+ if utils.is_microversion_ge(version, '2.5'):
+ expected_keys.append("share_type_name")
actual_keys = list(share.keys())
[self.assertIn(key, actual_keys) for key in expected_keys]
@@ -103,12 +113,22 @@
self.assertEqual(self.share_size, int(share["size"]), msg)
@test.attr(type=["gate", ])
- def test_get_share_no_snapshot_support_key(self):
- self._get_share(2.1)
+ def test_get_share_v2_1(self):
+ self._get_share('2.1')
@test.attr(type=["gate", ])
def test_get_share_with_snapshot_support_key(self):
- self._get_share(2.2)
+ self._get_share('2.2')
+
+ @test.attr(type=["gate", ])
+ @utils.skip_if_microversion_not_supported('2.4')
+ def test_get_share_with_consistency_groups_keys(self):
+ self._get_share('2.4')
+
+ @test.attr(type=["gate", ])
+ @utils.skip_if_microversion_not_supported('2.6')
+ def test_get_share_with_share_type_name_key(self):
+ self._get_share('2.6')
@test.attr(type=["gate", ])
def test_list_shares(self):
@@ -135,11 +155,19 @@
# verify keys
keys = [
"status", "description", "links", "availability_zone",
- "created_at", "export_location", "share_proto", "host",
- "name", "snapshot_id", "id", "size", "project_id",
+ "created_at", "export_location", "project_id",
+ "export_locations", "volume_type", "share_proto", "name",
+ "snapshot_id", "id", "size", "share_network_id", "metadata",
+ "host", "snapshot_id", "is_public", "share_type",
]
- if version > 2.1:
+ if utils.is_microversion_ge(version, '2.2'):
keys.append("snapshot_support")
+ if utils.is_microversion_ge(version, '2.4'):
+ keys.extend(["consistency_group_id",
+ "source_cgsnapshot_member_id"])
+ if utils.is_microversion_ge(version, '2.6'):
+ keys.append("share_type_name")
+
[self.assertIn(key, sh.keys()) for sh in shares for key in keys]
# our shares in list and have no duplicates
@@ -149,12 +177,22 @@
self.assertEqual(1, len(gen), msg)
@test.attr(type=["gate", ])
- def test_list_shares_with_detail_without_snapshot_support_key(self):
- self._list_shares_with_detail(2.1)
+ def test_list_shares_with_detail_v2_1(self):
+ self._list_shares_with_detail('2.1')
@test.attr(type=["gate", ])
def test_list_shares_with_detail_and_snapshot_support_key(self):
- self._list_shares_with_detail(2.2)
+ self._list_shares_with_detail('2.2')
+
+ @test.attr(type=["gate", ])
+ @utils.skip_if_microversion_not_supported('2.4')
+ def test_list_shares_with_detail_consistency_groups_keys(self):
+ self._list_shares_with_detail('2.4')
+
+ @test.attr(type=["gate", ])
+ @utils.skip_if_microversion_not_supported('2.6')
+ def test_list_shares_with_detail_share_type_name_key(self):
+ self._list_shares_with_detail('2.6')
@test.attr(type=["gate", ])
def test_list_shares_with_detail_filter_by_metadata(self):
diff --git a/manila_tempest_tests/utils.py b/manila_tempest_tests/utils.py
new file mode 100644
index 0000000..94d8cd3
--- /dev/null
+++ b/manila_tempest_tests/utils.py
@@ -0,0 +1,93 @@
+# Copyright 2015 Mirantis 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 random
+import re
+
+import six
+from tempest import config
+import testtools
+
+CONF = config.CONF
+
+
+def get_microversion_as_tuple(microversion_str):
+ """Transforms string-like microversion to two-value tuple of integers.
+
+ Tuple of integers useful for microversion comparisons.
+ """
+ regex = r"^([1-9]\d*)\.([1-9]\d*|0)$"
+ match = re.match(regex, microversion_str)
+ if not match:
+ raise ValueError(
+ "Microversion does not fit template 'x.y' - %s" % microversion_str)
+ return int(match.group(1)), int(match.group(2))
+
+
+def is_microversion_gt(left, right):
+ """Is microversion for left is greater than the right one."""
+ return get_microversion_as_tuple(left) > get_microversion_as_tuple(right)
+
+
+def is_microversion_ge(left, right):
+ """Is microversion for left is greater than or equal to the right one."""
+ return get_microversion_as_tuple(left) >= get_microversion_as_tuple(right)
+
+
+def is_microversion_eq(left, right):
+ """Is microversion for left is equal to the right one."""
+ return get_microversion_as_tuple(left) == get_microversion_as_tuple(right)
+
+
+def is_microversion_ne(left, right):
+ """Is microversion for left is not equal to the right one."""
+ return get_microversion_as_tuple(left) != get_microversion_as_tuple(right)
+
+
+def is_microversion_le(left, right):
+ """Is microversion for left is less than or equal to the right one."""
+ return get_microversion_as_tuple(left) <= get_microversion_as_tuple(right)
+
+
+def is_microversion_lt(left, right):
+ """Is microversion for left is less than the right one."""
+ return get_microversion_as_tuple(left) < get_microversion_as_tuple(right)
+
+
+def is_microversion_supported(microversion):
+ bottom = get_microversion_as_tuple(CONF.share.min_api_microversion)
+ microversion = get_microversion_as_tuple(microversion)
+ top = get_microversion_as_tuple(CONF.share.max_api_microversion)
+ return bottom <= microversion <= top
+
+
+def skip_if_microversion_not_supported(microversion):
+ """Decorator for tests that are microversion-specific."""
+ if not is_microversion_supported(microversion):
+ reason = ("Skipped. Test requires microversion '%s'." % microversion)
+ return testtools.skip(reason)
+ return lambda f: f
+
+
+def rand_ip():
+ """This uses the TEST-NET-3 range of reserved IP addresses.
+
+ Using this range, which are reserved solely for use in
+ documentation and example source code, should avoid any potential
+ conflicts in real-world testing.
+ """
+ TEST_NET_3 = '203.0.113.'
+ final_octet = six.text_type(random.randint(0, 255))
+ return TEST_NET_3 + final_octet