Merge "Allow skipping manila tempest tests."
diff --git a/manila_tempest_tests/config.py b/manila_tempest_tests/config.py
index 9314da0..1cd553e 100644
--- a/manila_tempest_tests/config.py
+++ b/manila_tempest_tests/config.py
@@ -30,7 +30,7 @@
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.23",
+ default="2.25",
help="The maximum api microversion is configured to be the "
"value of the latest microversion supported by Manila."),
cfg.StrOpt("region",
@@ -96,6 +96,13 @@
"capability called 'snapshot_support' and will be used "
"for setting up custom share type. Defaults to value of "
"other config option 'run_snapshot_tests'."),
+ cfg.BoolOpt("capability_create_share_from_snapshot_support",
+ help="Defines extra spec that satisfies specific back end "
+ "capability called 'create_share_from_snapshot_support' "
+ "and will be used for setting up a custom share type. "
+ "Defaults to the value of run_snapshot_tests. Set it to "
+ "False if the driver being tested does not support "
+ "creating shares from snapshots."),
cfg.StrOpt("share_network_id",
default="",
@@ -189,7 +196,7 @@
"careful enabling this opt."),
cfg.StrOpt("image_with_share_tools",
- default="manila-service-image",
+ default="manila-service-image-master",
help="Image name for vm booting with nfs/smb clients tool."),
cfg.StrOpt("image_username",
default="manila",
diff --git a/manila_tempest_tests/plugin.py b/manila_tempest_tests/plugin.py
index 0a97747..dfec0b1 100644
--- a/manila_tempest_tests/plugin.py
+++ b/manila_tempest_tests/plugin.py
@@ -35,14 +35,21 @@
conf.register_group(config_share.share_group)
conf.register_opts(config_share.ShareGroup, group='share')
- # NOTE(vponomaryov): set opt 'capability_snapshot_support' by
- # default equal to opt 'run_snapshot_tests'.
+ # NOTE(vponomaryov): Set options 'capability_snapshot_support' and
+ # 'capability_create_share_from_snapshot_support' to opt
+ # 'run_snapshot_tests' if not configured.
if conf.share.capability_snapshot_support is None:
conf.set_default(
"capability_snapshot_support",
conf.share.run_snapshot_tests,
group="share",
)
+ if conf.share.capability_create_share_from_snapshot_support is None:
+ conf.set_default(
+ "capability_create_share_from_snapshot_support",
+ conf.share.run_snapshot_tests,
+ group="share",
+ )
def get_opt_lists(self):
return [(config_share.share_group.name, config_share.ShareGroup),
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 0ccc18b..cbc26b5 100644
--- a/manila_tempest_tests/services/share/v2/json/shares_client.py
+++ b/manila_tempest_tests/services/share/v2/json/shares_client.py
@@ -726,6 +726,13 @@
self.expected_success(200, resp.status)
return self._parse_resp(body)
+ def delete_share_type_extra_spec(self, share_type_id, extra_spec_name,
+ version=LATEST_MICROVERSION):
+ uri = "types/%s/extra_specs/%s" % (share_type_id, extra_spec_name)
+ resp, body = self.delete(uri, version=version)
+ self.expected_success(202, resp.status)
+ return body
+
def list_access_to_share_type(self, share_type_id,
version=LATEST_MICROVERSION,
action_name=None):
@@ -778,6 +785,17 @@
self.expected_success(202, resp.status)
return body
+ def detail_quotas(self, tenant_id, user_id=None, url=None,
+ version=LATEST_MICROVERSION):
+ if url is None:
+ url = self._get_quotas_url(version)
+ url += '/%s/detail' % tenant_id
+ if user_id is not None:
+ url += "?user_id=%s" % user_id
+ resp, body = self.get(url, version=version)
+ self.expected_success(200, resp.status)
+ return self._parse_resp(body)
+
def update_quotas(self, tenant_id, user_id=None, shares=None,
snapshots=None, gigabytes=None, snapshot_gigabytes=None,
share_networks=None, force=True, url=None,
diff --git a/manila_tempest_tests/tests/api/admin/test_consistency_group_actions.py b/manila_tempest_tests/tests/api/admin/test_consistency_group_actions.py
index b9d349c..8b2a21c 100644
--- a/manila_tempest_tests/tests/api/admin/test_consistency_group_actions.py
+++ b/manila_tempest_tests/tests/api/admin/test_consistency_group_actions.py
@@ -32,7 +32,7 @@
super(ConsistencyGroupActionsTest, cls).resource_setup()
# Create 2 share_types
name = data_utils.rand_name("tempest-manila")
- extra_specs = cls.add_required_extra_specs_to_dict()
+ extra_specs = cls.add_extra_specs_to_dict()
share_type = cls.create_share_type(name, extra_specs=extra_specs)
cls.share_type = share_type['share_type']
diff --git a/manila_tempest_tests/tests/api/admin/test_consistency_groups.py b/manila_tempest_tests/tests/api/admin/test_consistency_groups.py
index efa2471..22678e5 100644
--- a/manila_tempest_tests/tests/api/admin/test_consistency_groups.py
+++ b/manila_tempest_tests/tests/api/admin/test_consistency_groups.py
@@ -34,7 +34,7 @@
super(ConsistencyGroupsTest, cls).resource_setup()
# Create 2 share_types
name = data_utils.rand_name("tempest-manila")
- extra_specs = cls.add_required_extra_specs_to_dict()
+ extra_specs = cls.add_extra_specs_to_dict()
share_type = cls.create_share_type(name, extra_specs=extra_specs)
cls.share_type = share_type['share_type']
diff --git a/manila_tempest_tests/tests/api/admin/test_consistency_groups_negative.py b/manila_tempest_tests/tests/api/admin/test_consistency_groups_negative.py
index 0a0d0f4..a850379 100644
--- a/manila_tempest_tests/tests/api/admin/test_consistency_groups_negative.py
+++ b/manila_tempest_tests/tests/api/admin/test_consistency_groups_negative.py
@@ -33,7 +33,7 @@
super(ConsistencyGroupsNegativeTest, cls).resource_setup()
# Create share_type
name = data_utils.rand_name("tempest-manila")
- extra_specs = cls.add_required_extra_specs_to_dict()
+ extra_specs = cls.add_extra_specs_to_dict()
share_type = cls.create_share_type(name, extra_specs=extra_specs)
cls.share_type = share_type['share_type']
diff --git a/manila_tempest_tests/tests/api/admin/test_multi_backend.py b/manila_tempest_tests/tests/api/admin/test_multi_backend.py
index 8b7e078..8aeabc3 100644
--- a/manila_tempest_tests/tests/api/admin/test_multi_backend.py
+++ b/manila_tempest_tests/tests/api/admin/test_multi_backend.py
@@ -48,7 +48,7 @@
}
st = cls.create_share_type(
name=st_name,
- extra_specs=cls.add_required_extra_specs_to_dict(extra_specs))
+ extra_specs=cls.add_extra_specs_to_dict(extra_specs))
cls.sts.append(st["share_type"])
st_id = st["share_type"]["id"]
share_data_list.append({"kwargs": {"share_type_id": st_id}})
diff --git a/manila_tempest_tests/tests/api/admin/test_quotas_negative.py b/manila_tempest_tests/tests/api/admin/test_quotas_negative.py
index d6c47e5..b8557e1 100644
--- a/manila_tempest_tests/tests/api/admin/test_quotas_negative.py
+++ b/manila_tempest_tests/tests/api/admin/test_quotas_negative.py
@@ -203,3 +203,15 @@
self.shares_v2_client.tenant_id,
version=version, url=url,
)
+
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+ def test_show_quota_detail_with_wrong_versions(self):
+ version = '2.24'
+ url = 'quota-sets'
+
+ self.assertRaises(
+ lib_exc.NotFound,
+ self.shares_v2_client.detail_quotas,
+ self.shares_v2_client.tenant_id,
+ version=version, url=url,
+ )
diff --git a/manila_tempest_tests/tests/api/admin/test_replication.py b/manila_tempest_tests/tests/api/admin/test_replication.py
index 38546e3..e41c92b 100644
--- a/manila_tempest_tests/tests/api/admin/test_replication.py
+++ b/manila_tempest_tests/tests/api/admin/test_replication.py
@@ -48,7 +48,7 @@
cls.share_zone = cls.zones[0]
cls.replica_zone = cls.zones[-1]
- cls.extra_specs = cls.add_required_extra_specs_to_dict(
+ cls.extra_specs = cls.add_extra_specs_to_dict(
{"replication_type": cls.replication_type})
share_type = cls.create_share_type(
name,
diff --git a/manila_tempest_tests/tests/api/admin/test_replication_actions.py b/manila_tempest_tests/tests/api/admin/test_replication_actions.py
index 377bb41..5b56533 100644
--- a/manila_tempest_tests/tests/api/admin/test_replication_actions.py
+++ b/manila_tempest_tests/tests/api/admin/test_replication_actions.py
@@ -49,7 +49,7 @@
cls.share_zone = cls.zones[0]
cls.replica_zone = cls.zones[-1]
- cls.extra_specs = cls.add_required_extra_specs_to_dict(
+ cls.extra_specs = cls.add_extra_specs_to_dict(
{"replication_type": cls.replication_type})
share_type = cls.create_share_type(
name,
diff --git a/manila_tempest_tests/tests/api/admin/test_scheduler_stats.py b/manila_tempest_tests/tests/api/admin/test_scheduler_stats.py
index d77b7ea..aa29828 100644
--- a/manila_tempest_tests/tests/api/admin/test_scheduler_stats.py
+++ b/manila_tempest_tests/tests/api/admin/test_scheduler_stats.py
@@ -12,7 +12,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+import ddt
from tempest import config
+from tempest.lib.common.utils import data_utils
from testtools import testcase as tc
from manila_tempest_tests.tests.api import base
@@ -20,8 +22,29 @@
CONF = config.CONF
+@ddt.ddt
class SchedulerStatsAdminTest(base.BaseSharesAdminTest):
+ @classmethod
+ def _create_share_type(cls, negative=False):
+ name = data_utils.rand_name("unique_st_name")
+ extra_specs = None
+
+ if negative:
+ extra_specs = {
+ 'share_backend_name': data_utils.rand_name("fake_name"),
+ }
+
+ extra_specs = cls.add_extra_specs_to_dict(extra_specs=extra_specs)
+ return cls.create_share_type(
+ name, extra_specs=extra_specs,
+ client=cls.admin_client)
+
+ @classmethod
+ def resource_setup(cls):
+ super(SchedulerStatsAdminTest, cls).resource_setup()
+ cls.admin_client = cls.shares_v2_client
+
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_pool_list(self):
@@ -138,5 +161,44 @@
# Ensure we got no pools
self.assertEmpty(pool_list)
+ @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+ @base.skip_if_microversion_not_supported("2.23")
+ @ddt.data((True, "name"), (True, "id"), (False, "name"), (False, "id"))
+ @ddt.unpack
+ def test_pool_list_with_share_type_filter_with_detail(
+ self, detail, share_type_key):
+ st = self._create_share_type()
+ search_opts = {"share_type": st["share_type"][share_type_key]}
+ kwargs = {'search_opts': search_opts}
+
+ if detail:
+ kwargs.update({'detail': True})
+
+ pools = self.admin_client.list_pools(**kwargs)['pools']
+
+ self.assertIsNotNone(pools, 'No pools returned from pools API')
+ self.assertNotEmpty(pools)
+ for pool in pools:
+ pool_keys = list(pool.keys())
+ self.assertIn("name", pool_keys)
+ self.assertIn("host", pool_keys)
+ self.assertIn("backend", pool_keys)
+ self.assertIn("pool", pool_keys)
+ self.assertIs(detail, "capabilities" in pool_keys)
+
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+ @base.skip_if_microversion_not_supported("2.23")
+ @ddt.data((True, "name"), (True, "id"), (False, "name"), (False, "id"))
+ @ddt.unpack
+ def test_pool_list_with_share_type_filter_with_detail_negative(
+ self, detail, share_type_key):
+ st_negative = self._create_share_type(negative=True)
+ search_opts = {"share_type": st_negative["share_type"][share_type_key]}
+
+ pools = self.admin_client.list_pools(
+ detail=detail, search_opts=search_opts)['pools']
+
+ self.assertEmpty(pools)
+
def _wrap_regex_for_exact_match(self, regex):
return '^%s$' % regex
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 8100040..f943284 100644
--- a/manila_tempest_tests/tests/api/admin/test_share_manage.py
+++ b/manila_tempest_tests/tests/api/admin/test_share_manage.py
@@ -54,12 +54,16 @@
'driver_handles_share_servers': False,
'snapshot_support': six.text_type(
CONF.share.capability_snapshot_support),
+ 'create_share_from_snapshot_support': six.text_type(
+ CONF.share.capability_create_share_from_snapshot_support)
}
cls.extra_specs_invalid = {
'storage_protocol': CONF.share.capability_storage_protocol,
'driver_handles_share_servers': True,
'snapshot_support': six.text_type(
CONF.share.capability_snapshot_support),
+ 'create_share_from_snapshot_support': six.text_type(
+ CONF.share.capability_create_share_from_snapshot_support),
}
cls.st = cls.create_share_type(
diff --git a/manila_tempest_tests/tests/api/admin/test_share_type_filter.py b/manila_tempest_tests/tests/api/admin/test_share_type_filter.py
deleted file mode 100644
index e34f943..0000000
--- a/manila_tempest_tests/tests/api/admin/test_share_type_filter.py
+++ /dev/null
@@ -1,55 +0,0 @@
-# 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.lib.common.utils import data_utils
-from testtools import testcase as tc
-
-from manila_tempest_tests.tests.api import base
-
-
-@ddt.ddt
-class ShareTypeFilterTest(base.BaseSharesAdminTest):
-
- @classmethod
- def _create_share_type(cls):
- name = data_utils.rand_name("unique_st_name")
- extra_specs = cls.add_required_extra_specs_to_dict()
- return cls.create_share_type(
- name, extra_specs=extra_specs,
- client=cls.admin_client)
-
- @classmethod
- def resource_setup(cls):
- super(ShareTypeFilterTest, cls).resource_setup()
- cls.admin_client = cls.shares_v2_client
- cls.st = cls._create_share_type()
-
- @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
- @base.skip_if_microversion_not_supported("2.23")
- @ddt.data(True, False)
- def test_get_pools_with_share_type_filter_with_detail(self, detail):
- share_type = self.st["share_type"]["id"]
- search_opts = {"share_type": share_type}
- kwargs = {'search_opts': search_opts}
-
- if detail:
- kwargs.update({'detail': True})
-
- pools = self.admin_client.list_pools(**kwargs)['pools']
- for pool in pools:
- pool_keys = pool.keys()
- self.assertIn("name", pool_keys)
- self.assertIn("host", pool_keys)
- self.assertIn("backend", pool_keys)
- self.assertIn("pool", pool_keys)
- self.assertIs(detail, "capabilities" in pool_keys)
diff --git a/manila_tempest_tests/tests/api/admin/test_share_type_filter_negative.py b/manila_tempest_tests/tests/api/admin/test_share_type_filter_negative.py
deleted file mode 100644
index 80f8d66..0000000
--- a/manila_tempest_tests/tests/api/admin/test_share_type_filter_negative.py
+++ /dev/null
@@ -1,54 +0,0 @@
-# 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 oslo_utils import uuidutils
-from tempest import config
-from tempest.lib.common.utils import data_utils
-from testtools import testcase as tc
-
-from manila_tempest_tests.tests.api import base
-
-CONF = config.CONF
-
-
-@ddt.ddt
-class ShareTypeFilterNegativeTest(base.BaseSharesAdminTest):
-
- @classmethod
- def _create_share_type(cls):
- name = data_utils.rand_name("unique_st_name")
- extra_specs = {
- 'share_backend_name': uuidutils.generate_uuid(),
- }
- extra_specs = cls.add_required_extra_specs_to_dict(
- extra_specs=extra_specs)
- return cls.create_share_type(
- name, extra_specs=extra_specs,
- client=cls.admin_client)
-
- @classmethod
- def resource_setup(cls):
- super(ShareTypeFilterNegativeTest, cls).resource_setup()
- cls.admin_client = cls.shares_v2_client
- cls.st = cls._create_share_type()
-
- @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
- @base.skip_if_microversion_not_supported("2.23")
- @ddt.data(True, False)
- def test_get_pools_invalid_share_type_filter_with_detail(self, detail):
- share_type = self.st["share_type"]["name"]
- search_opts = {"share_type": share_type}
- pools = self.admin_client.list_pools(
- detail=detail, search_opts=search_opts)['pools']
-
- self.assertEmpty(pools)
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 af354bb..076e4bc 100644
--- a/manila_tempest_tests/tests/api/admin/test_share_types.py
+++ b/manila_tempest_tests/tests/api/admin/test_share_types.py
@@ -31,7 +31,7 @@
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_share_type_create_delete(self):
name = data_utils.rand_name("tempest-manila")
- extra_specs = self.add_required_extra_specs_to_dict()
+ extra_specs = self.add_extra_specs_to_dict()
# Create share type
st_create = self.shares_v2_client.create_share_type(
@@ -64,7 +64,7 @@
self.skip_if_microversion_not_supported(version)
name = data_utils.rand_name("tempest-manila")
- extra_specs = self.add_required_extra_specs_to_dict({"key": "value", })
+ extra_specs = self.add_extra_specs_to_dict({"key": "value", })
# Create share type
st_create = self.create_share_type(
@@ -89,7 +89,7 @@
self.skip_if_microversion_not_supported(version)
name = data_utils.rand_name("tempest-manila")
- extra_specs = self.add_required_extra_specs_to_dict()
+ extra_specs = self.add_extra_specs_to_dict()
# Create share type
st_create = self.create_share_type(
@@ -117,7 +117,7 @@
# Data
share_name = data_utils.rand_name("share")
shr_type_name = data_utils.rand_name("share-type")
- extra_specs = self.add_required_extra_specs_to_dict({
+ extra_specs = self.add_extra_specs_to_dict({
"storage_protocol": CONF.share.capability_storage_protocol,
})
@@ -144,7 +144,7 @@
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_private_share_type_access(self):
name = data_utils.rand_name("tempest-manila")
- extra_specs = self.add_required_extra_specs_to_dict({"key": "value", })
+ extra_specs = self.add_extra_specs_to_dict({"key": "value", })
project_id = self.shares_client.tenant_id
# Create private share type
diff --git a/manila_tempest_tests/tests/api/admin/test_share_types_extra_specs.py b/manila_tempest_tests/tests/api/admin/test_share_types_extra_specs.py
index 81d130f..f4c21b8 100644
--- a/manila_tempest_tests/tests/api/admin/test_share_types_extra_specs.py
+++ b/manila_tempest_tests/tests/api/admin/test_share_types_extra_specs.py
@@ -15,19 +15,25 @@
import copy
+import ddt
+from tempest import config
from tempest.lib.common.utils import data_utils
from testtools import testcase as tc
from manila_tempest_tests.tests.api import base
+CONF = config.CONF
+LATEST_MICROVERSION = CONF.share.max_api_microversion
+
+
class ExtraSpecsReadAdminTest(base.BaseSharesAdminTest):
@classmethod
def resource_setup(cls):
super(ExtraSpecsReadAdminTest, cls).resource_setup()
cls.share_type_name = data_utils.rand_name("share-type")
- cls.required_extra_specs = cls.add_required_extra_specs_to_dict()
+ cls.required_extra_specs = cls.add_extra_specs_to_dict()
cls.share_type = cls.create_share_type(
cls.share_type_name, extra_specs=cls.required_extra_specs)
@@ -54,11 +60,12 @@
self.assertEqual(self.expected_extra_specs, es_get_all)
+@ddt.ddt
class ExtraSpecsWriteAdminTest(base.BaseSharesAdminTest):
def setUp(self):
super(ExtraSpecsWriteAdminTest, self).setUp()
- self.required_extra_specs = self.add_required_extra_specs_to_dict()
+ self.required_extra_specs = self.add_extra_specs_to_dict()
self.custom_extra_specs = {"key1": "value1", "key2": "value2"}
self.share_type_name = data_utils.rand_name("share-type")
@@ -109,3 +116,17 @@
get = self.shares_client.get_share_type_extra_specs(self.st_id)
self.assertNotIn('key1', get)
+
+ @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+ @ddt.data(*set(['2.24', LATEST_MICROVERSION]))
+ def test_delete_snapshot_support_extra_spec(self, version):
+ self.skip_if_microversion_not_supported(version)
+ # Delete one extra spec for share type
+ self.shares_v2_client.delete_share_type_extra_spec(
+ self.st_id, 'snapshot_support', version=version)
+
+ # Get metadata
+ share_type_extra_specs = self.shares_client.get_share_type_extra_specs(
+ self.st_id)
+
+ self.assertNotIn('snapshot_support', share_type_extra_specs)
diff --git a/manila_tempest_tests/tests/api/admin/test_share_types_extra_specs_negative.py b/manila_tempest_tests/tests/api/admin/test_share_types_extra_specs_negative.py
index 34e5009..85cbc5d 100644
--- a/manila_tempest_tests/tests/api/admin/test_share_types_extra_specs_negative.py
+++ b/manila_tempest_tests/tests/api/admin/test_share_types_extra_specs_negative.py
@@ -13,6 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+import ddt
from tempest.lib.common.utils import data_utils
from tempest.lib import exceptions as lib_exc
from testtools import testcase as tc
@@ -20,11 +21,12 @@
from manila_tempest_tests.tests.api import base
+@ddt.ddt
class ExtraSpecsAdminNegativeTest(base.BaseSharesMixedTest):
def _create_share_type(self):
name = data_utils.rand_name("unique_st_name")
- extra_specs = self.add_required_extra_specs_to_dict({"key": "value"})
+ extra_specs = self.add_extra_specs_to_dict({"key": "value"})
return self.create_share_type(
name, extra_specs=extra_specs, client=self.admin_shares_v2_client)
@@ -35,7 +37,7 @@
lib_exc.Forbidden,
self.shares_v2_client.create_share_type_extra_specs,
st["share_type"]["id"],
- self.add_required_extra_specs_to_dict({"key": "new_value"}))
+ self.add_extra_specs_to_dict({"key": "new_value"}))
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_list_extra_specs_with_user(self):
@@ -67,7 +69,8 @@
share_type = self.shares_v2_client.get_share_type(
st['share_type']['id'])
# Verify a non-admin can only read the required extra-specs
- expected_keys = ['driver_handles_share_servers', 'snapshot_support']
+ expected_keys = ['driver_handles_share_servers', 'snapshot_support',
+ 'create_share_from_snapshot_support']
actual_keys = share_type['share_type']['extra_specs'].keys()
self.assertEqual(sorted(expected_keys), sorted(actual_keys),
'Incorrect extra specs visible to non-admin user; '
@@ -105,7 +108,7 @@
lib_exc.BadRequest,
self.admin_shares_v2_client.create_share_type_extra_specs,
st["share_type"]["id"],
- self.add_required_extra_specs_to_dict({too_big_key: "value"}))
+ self.add_extra_specs_to_dict({too_big_key: "value"}))
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_set_too_long_value_with_creation(self):
@@ -115,7 +118,7 @@
lib_exc.BadRequest,
self.admin_shares_v2_client.create_share_type_extra_specs,
st["share_type"]["id"],
- self.add_required_extra_specs_to_dict({"key": too_big_value}))
+ self.add_extra_specs_to_dict({"key": too_big_value}))
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_set_too_long_value_with_update(self):
@@ -123,12 +126,12 @@
st = self._create_share_type()
self.admin_shares_v2_client.create_share_type_extra_specs(
st["share_type"]["id"],
- self.add_required_extra_specs_to_dict({"key": "value"}))
+ self.add_extra_specs_to_dict({"key": "value"}))
self.assertRaises(
lib_exc.BadRequest,
self.admin_shares_v2_client.update_share_type_extra_specs,
st["share_type"]["id"],
- self.add_required_extra_specs_to_dict({"key": too_big_value}))
+ self.add_extra_specs_to_dict({"key": too_big_value}))
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_set_too_long_value_with_update_of_one_key(self):
@@ -136,7 +139,7 @@
st = self._create_share_type()
self.admin_shares_v2_client.create_share_type_extra_specs(
st["share_type"]["id"],
- self.add_required_extra_specs_to_dict({"key": "value"}))
+ self.add_extra_specs_to_dict({"key": "value"}))
self.assertRaises(
lib_exc.BadRequest,
self.admin_shares_v2_client.update_share_type_extra_spec,
@@ -286,12 +289,12 @@
"driver_handles_share_servers")
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
- def test_try_delete_spec_snapshot_support(self):
+ @ddt.data('2.0', '2.23')
+ def test_try_delete_required_spec_snapshot_support_version(self, version):
+ self.skip_if_microversion_not_supported(version)
st = self._create_share_type()
-
# Try delete extra spec 'snapshot_support'
self.assertRaises(
lib_exc.Forbidden,
self.admin_shares_v2_client.delete_share_type_extra_spec,
- st["share_type"]["id"],
- "snapshot_support")
+ st["share_type"]["id"], "snapshot_support", version=version)
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 b0fb9db..b3bf855 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
@@ -24,7 +24,7 @@
def _create_share_type(self):
name = data_utils.rand_name("unique_st_name")
- extra_specs = self.add_required_extra_specs_to_dict({"key": "value"})
+ extra_specs = self.add_extra_specs_to_dict({"key": "value"})
return self.create_share_type(
name, extra_specs=extra_specs, client=self.admin_shares_v2_client)
@@ -66,7 +66,7 @@
self.assertRaises(lib_exc.Conflict,
self.create_share_type,
st["share_type"]["name"],
- extra_specs=self.add_required_extra_specs_to_dict(),
+ extra_specs=self.add_extra_specs_to_dict(),
client=self.admin_shares_v2_client)
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
diff --git a/manila_tempest_tests/tests/api/admin/test_shares_actions.py b/manila_tempest_tests/tests/api/admin/test_shares_actions.py
index eb049c6..779cd18 100644
--- a/manila_tempest_tests/tests/api/admin/test_shares_actions.py
+++ b/manila_tempest_tests/tests/api/admin/test_shares_actions.py
@@ -34,7 +34,7 @@
# create share type for share filtering purposes
cls.st_name = data_utils.rand_name("tempest-st-name")
- cls.extra_specs = cls.add_required_extra_specs_to_dict(
+ cls.extra_specs = cls.add_extra_specs_to_dict(
{'storage_protocol': CONF.share.capability_storage_protocol})
cls.st = cls.create_share_type(
name=cls.st_name,
@@ -64,20 +64,23 @@
cls.snap = cls.create_snapshot_wait_for_active(
cls.shares[0]["id"], cls.snap_name, cls.snap_desc)
- # create second share from snapshot for purposes of sorting and
- # snapshot filtering
- cls.share_name2 = data_utils.rand_name("tempest-share-name")
- cls.share_desc2 = data_utils.rand_name("tempest-share-description")
- cls.metadata2 = {
- 'foo_key_share_2': 'foo_value_share_2',
- 'bar_key_share_2': 'foo_value_share_2',
- }
- cls.shares.append(cls.create_share(
- name=cls.share_name2,
- description=cls.share_desc2,
- metadata=cls.metadata2,
- snapshot_id=cls.snap['id'],
- ))
+ if CONF.share.capability_create_share_from_snapshot_support:
+
+ # create second share from snapshot for purposes of sorting and
+ # snapshot filtering
+ cls.share_name2 = data_utils.rand_name("tempest-share-name")
+ cls.share_desc2 = data_utils.rand_name(
+ "tempest-share-description")
+ cls.metadata2 = {
+ 'foo_key_share_2': 'foo_value_share_2',
+ 'bar_key_share_2': 'foo_value_share_2',
+ }
+ cls.shares.append(cls.create_share(
+ name=cls.share_name2,
+ description=cls.share_desc2,
+ metadata=cls.metadata2,
+ snapshot_id=cls.snap['id'],
+ ))
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_get_share(self):
@@ -154,7 +157,7 @@
for share in shares:
self.assertDictContainsSubset(
filters['metadata'], share['metadata'])
- if CONF.share.run_snapshot_tests:
+ if CONF.share.capability_create_share_from_snapshot_support:
self.assertFalse(self.shares[1]['id'] in [s['id'] for s in shares])
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@@ -250,8 +253,9 @@
filters['share_network_id'], share['share_network_id'])
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
- @testtools.skipUnless(CONF.share.run_snapshot_tests,
- "Snapshot tests are disabled.")
+ @testtools.skipUnless(
+ CONF.share.capability_create_share_from_snapshot_support,
+ "Create share from snapshot tests are disabled.")
def test_list_shares_with_detail_filter_by_snapshot_id(self):
filters = {'snapshot_id': self.snap['id']}
diff --git a/manila_tempest_tests/tests/api/admin/test_snapshot_manage.py b/manila_tempest_tests/tests/api/admin/test_snapshot_manage.py
index 3cde3e6..6436e5b 100644
--- a/manila_tempest_tests/tests/api/admin/test_snapshot_manage.py
+++ b/manila_tempest_tests/tests/api/admin/test_snapshot_manage.py
@@ -55,6 +55,8 @@
'driver_handles_share_servers': False,
'snapshot_support': six.text_type(
CONF.share.capability_snapshot_support),
+ 'create_share_from_snapshot_support': six.text_type(
+ CONF.share.capability_create_share_from_snapshot_support)
}
cls.st = cls.create_share_type(
diff --git a/manila_tempest_tests/tests/api/admin/test_snapshot_manage_negative.py b/manila_tempest_tests/tests/api/admin/test_snapshot_manage_negative.py
index dfd892c..3825be1 100644
--- a/manila_tempest_tests/tests/api/admin/test_snapshot_manage_negative.py
+++ b/manila_tempest_tests/tests/api/admin/test_snapshot_manage_negative.py
@@ -49,6 +49,8 @@
'driver_handles_share_servers': False,
'snapshot_support': six.text_type(
CONF.share.capability_snapshot_support),
+ 'create_share_from_snapshot_support': six.text_type(
+ CONF.share.capability_create_share_from_snapshot_support),
}
cls.st = cls.create_share_type(
diff --git a/manila_tempest_tests/tests/api/base.py b/manila_tempest_tests/tests/api/base.py
index d5d1175..5810a7e 100644
--- a/manila_tempest_tests/tests/api/base.py
+++ b/manila_tempest_tests/tests/api/base.py
@@ -733,17 +733,30 @@
return share_type
@staticmethod
- def add_required_extra_specs_to_dict(extra_specs=None):
+ def add_extra_specs_to_dict(extra_specs=None):
+ """Add any required extra-specs to share type dictionary"""
dhss = six.text_type(CONF.share.multitenancy_enabled)
snapshot_support = six.text_type(
CONF.share.capability_snapshot_support)
- required = {
+ create_from_snapshot_support = six.text_type(
+ CONF.share.capability_create_share_from_snapshot_support)
+
+ extra_specs_dict = {
"driver_handles_share_servers": dhss,
- "snapshot_support": snapshot_support,
}
+
+ optional = {
+ "snapshot_support": snapshot_support,
+ "create_share_from_snapshot_support": create_from_snapshot_support,
+ }
+ # NOTE(gouthamr): In micro-versions < 2.24, snapshot_support is a
+ # required extra-spec
+ extra_specs_dict.update(optional)
+
if extra_specs:
- required.update(extra_specs)
- return required
+ extra_specs_dict.update(extra_specs)
+
+ return extra_specs_dict
@classmethod
def clear_isolated_creds(cls, creds=None):
diff --git a/manila_tempest_tests/tests/api/test_quotas.py b/manila_tempest_tests/tests/api/test_quotas.py
index e9f5042..a7540ed 100644
--- a/manila_tempest_tests/tests/api/test_quotas.py
+++ b/manila_tempest_tests/tests/api/test_quotas.py
@@ -64,3 +64,28 @@
self.assertGreater(int(quotas["shares"]), -2)
self.assertGreater(int(quotas["snapshots"]), -2)
self.assertGreater(int(quotas["share_networks"]), -2)
+
+ @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+ @base.skip_if_microversion_not_supported("2.25")
+ def test_show_quotas_detail(self):
+ quotas = self.shares_v2_client.detail_quotas(self.tenant_id)
+ quota_keys = list(quotas.keys())
+ for outer in ('gigabytes', 'snapshot_gigabytes', 'shares',
+ 'snapshots', 'share_networks'):
+ self.assertIn(outer, quota_keys)
+ for inner in ('in_use', 'limit', 'reserved'):
+ self.assertIn(inner, list(quotas[outer].keys()))
+ self.assertGreater(int(quotas[outer][inner]), -2)
+
+ @tc.attr(base.TAG_POSITIVE, base.TAG_API)
+ @base.skip_if_microversion_not_supported("2.25")
+ def test_show_quotas_detail_for_user(self):
+ quotas = self.shares_v2_client.detail_quotas(self.tenant_id,
+ self.user_id)
+ quota_keys = list(quotas.keys())
+ for outer in ('gigabytes', 'snapshot_gigabytes', 'shares',
+ 'snapshots', 'share_networks'):
+ self.assertIn(outer, quota_keys)
+ for inner in ('in_use', 'limit', 'reserved'):
+ self.assertIn(inner, list(quotas[outer].keys()))
+ self.assertGreater(int(quotas[outer][inner]), -2)
diff --git a/manila_tempest_tests/tests/api/test_replication.py b/manila_tempest_tests/tests/api/test_replication.py
index 0bdb7ad..1738e87 100644
--- a/manila_tempest_tests/tests/api/test_replication.py
+++ b/manila_tempest_tests/tests/api/test_replication.py
@@ -51,7 +51,7 @@
cls.share_zone = cls.zones[0]
cls.replica_zone = cls.zones[-1]
- cls.extra_specs = cls.add_required_extra_specs_to_dict(
+ cls.extra_specs = cls.add_extra_specs_to_dict(
{"replication_type": cls.replication_type})
share_type = cls.create_share_type(
name,
@@ -307,7 +307,7 @@
cls.share_zone = cls.zones[0]
cls.replica_zone = cls.zones[-1]
- cls.extra_specs = cls.add_required_extra_specs_to_dict(
+ cls.extra_specs = cls.add_extra_specs_to_dict(
{"replication_type": cls.replication_type})
share_type = cls.create_share_type(
name,
diff --git a/manila_tempest_tests/tests/api/test_replication_negative.py b/manila_tempest_tests/tests/api/test_replication_negative.py
index cfbf210..48b8d5c 100644
--- a/manila_tempest_tests/tests/api/test_replication_negative.py
+++ b/manila_tempest_tests/tests/api/test_replication_negative.py
@@ -48,7 +48,7 @@
cls.share_zone = cls.zones[0]
cls.replica_zone = cls.zones[-1]
- cls.extra_specs = cls.add_required_extra_specs_to_dict(
+ cls.extra_specs = cls.add_extra_specs_to_dict(
{"replication_type": cls.replication_type})
share_type = cls.create_share_type(
name,
@@ -80,7 +80,7 @@
# Create share without replication type
share_type = self.create_share_type(
data_utils.rand_name(constants.TEMPEST_MANILA_PREFIX),
- extra_specs=self.add_required_extra_specs_to_dict(),
+ extra_specs=self.add_extra_specs_to_dict(),
client=self.admin_client)["share_type"]
share = self.create_share(share_type_id=share_type["id"])
self.assertRaises(lib_exc.BadRequest,
diff --git a/manila_tempest_tests/tests/api/test_replication_snapshots.py b/manila_tempest_tests/tests/api/test_replication_snapshots.py
index e3081cc..331437c 100644
--- a/manila_tempest_tests/tests/api/test_replication_snapshots.py
+++ b/manila_tempest_tests/tests/api/test_replication_snapshots.py
@@ -49,7 +49,7 @@
cls.share_zone = cls.zones[0]
cls.replica_zone = cls.zones[-1]
- cls.extra_specs = cls.add_required_extra_specs_to_dict(
+ cls.extra_specs = cls.add_extra_specs_to_dict(
{"replication_type": cls.replication_type})
share_type = cls.create_share_type(
name,
@@ -86,7 +86,12 @@
snapshot = self.create_snapshot_wait_for_active(share["id"])
self.promote_share_replica(share_replica['id'])
self.delete_share_replica(original_replica['id'])
- self.create_share(snapshot_id=snapshot['id'])
+
+ snapshot = self.shares_v2_client.get_snapshot(snapshot['id'])
+ self.assertEqual(constants.STATUS_AVAILABLE, snapshot['status'])
+
+ if CONF.share.capability_create_share_from_snapshot_support:
+ self.create_share(snapshot_id=snapshot['id'])
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
def test_snapshot_before_share_replica(self):
@@ -116,7 +121,12 @@
self.promote_share_replica(share_replica['id'])
self.delete_share_replica(original_replica['id'])
- self.create_share(snapshot_id=snapshot['id'])
+
+ snapshot = self.shares_v2_client.get_snapshot(snapshot['id'])
+ self.assertEqual(constants.STATUS_AVAILABLE, snapshot['status'])
+
+ if CONF.share.capability_create_share_from_snapshot_support:
+ self.create_share(snapshot_id=snapshot['id'])
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
def test_snapshot_before_and_after_share_replica(self):
@@ -152,8 +162,15 @@
# still being created successfully.
self.delete_share_replica(original_replica['id'])
- self.create_share(snapshot_id=snapshot1['id'])
- self.create_share(snapshot_id=snapshot2['id'])
+ snapshot1 = self.shares_v2_client.get_snapshot(snapshot1['id'])
+ self.assertEqual(constants.STATUS_AVAILABLE, snapshot1['status'])
+
+ snapshot2 = self.shares_v2_client.get_snapshot(snapshot2['id'])
+ self.assertEqual(constants.STATUS_AVAILABLE, snapshot2['status'])
+
+ if CONF.share.capability_create_share_from_snapshot_support:
+ self.create_share(snapshot_id=snapshot1['id'])
+ self.create_share(snapshot_id=snapshot2['id'])
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
def test_delete_snapshot_after_adding_replica(self):
@@ -176,6 +193,9 @@
snapshot_id=snapshot["id"])
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
+ @testtools.skipUnless(
+ CONF.share.capability_create_share_from_snapshot_support,
+ "Create share from snapshot tests are disabled.")
def test_create_replica_from_snapshot_share(self):
"""Test replica for a share that was created from snapshot."""
diff --git a/manila_tempest_tests/tests/api/test_share_types_negative.py b/manila_tempest_tests/tests/api/test_share_types_negative.py
index 9c7883b..8a24325 100644
--- a/manila_tempest_tests/tests/api/test_share_types_negative.py
+++ b/manila_tempest_tests/tests/api/test_share_types_negative.py
@@ -25,7 +25,7 @@
@classmethod
def _create_share_type(cls):
name = data_utils.rand_name("unique_st_name")
- extra_specs = cls.add_required_extra_specs_to_dict()
+ extra_specs = cls.add_extra_specs_to_dict()
return cls.create_share_type(
name, extra_specs=extra_specs,
client=cls.admin_client)
diff --git a/manila_tempest_tests/tests/api/test_shares.py b/manila_tempest_tests/tests/api/test_shares.py
index af4a54a..d78c913 100644
--- a/manila_tempest_tests/tests/api/test_shares.py
+++ b/manila_tempest_tests/tests/api/test_shares.py
@@ -92,6 +92,12 @@
detailed_elements.add('user_id')
self.assertTrue(detailed_elements.issubset(share.keys()), msg)
+ # In v 2.24 and beyond, we add create_share_from_snapshot_support in
+ # show/create/manage share echo.
+ if utils.is_microversion_supported('2.24'):
+ detailed_elements.add('create_share_from_snapshot_support')
+ self.assertTrue(detailed_elements.issubset(share.keys()), msg)
+
# Delete share
self.shares_v2_client.delete_share(share['id'])
self.shares_v2_client.wait_for_resource_deletion(share_id=share['id'])
@@ -136,6 +142,9 @@
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@testtools.skipUnless(CONF.share.run_snapshot_tests,
"Snapshot tests are disabled.")
+ @testtools.skipUnless(
+ CONF.share.capability_create_share_from_snapshot_support,
+ "Create share from snapshot tests are disabled.")
def test_create_share_from_snapshot(self):
# If multitenant driver used, share_network will be provided by default
@@ -164,9 +173,13 @@
"Only for multitenancy.")
@testtools.skipUnless(CONF.share.run_snapshot_tests,
"Snapshot tests are disabled.")
+ @testtools.skipUnless(
+ CONF.share.capability_create_share_from_snapshot_support,
+ "Create share from snapshot tests are disabled.")
def test_create_share_from_snapshot_share_network_not_provided(self):
# We expect usage of share network from parent's share
- # when creating share from snapshot using multitenant driver.
+ # when creating share from snapshot using a driver that supports
+ # multi-tenancy.
# get parent share
parent = self.shares_client.get_share(self.share["id"])
diff --git a/manila_tempest_tests/tests/api/test_shares_actions.py b/manila_tempest_tests/tests/api/test_shares_actions.py
index da44c7c..d03df33 100644
--- a/manila_tempest_tests/tests/api/test_shares_actions.py
+++ b/manila_tempest_tests/tests/api/test_shares_actions.py
@@ -58,20 +58,23 @@
cls.snap = cls.create_snapshot_wait_for_active(
cls.shares[0]["id"], cls.snap_name, cls.snap_desc)
- # create second share from snapshot for purposes of sorting and
- # snapshot filtering
- cls.share_name2 = data_utils.rand_name("tempest-share-name")
- cls.share_desc2 = data_utils.rand_name("tempest-share-description")
- cls.metadata2 = {
- 'foo_key_share_2': 'foo_value_share_2',
- 'bar_key_share_2': 'foo_value_share_2',
- }
- cls.shares.append(cls.create_share(
- name=cls.share_name2,
- description=cls.share_desc2,
- metadata=cls.metadata2,
- snapshot_id=cls.snap['id'],
- ))
+ if CONF.share.capability_create_share_from_snapshot_support:
+
+ # create second share from snapshot for purposes of sorting and
+ # snapshot filtering
+ cls.share_name2 = data_utils.rand_name("tempest-share-name")
+ cls.share_desc2 = data_utils.rand_name(
+ "tempest-share-description")
+ cls.metadata2 = {
+ 'foo_key_share_2': 'foo_value_share_2',
+ 'bar_key_share_2': 'foo_value_share_2',
+ }
+ cls.shares.append(cls.create_share(
+ name=cls.share_name2,
+ description=cls.share_desc2,
+ metadata=cls.metadata2,
+ snapshot_id=cls.snap['id'],
+ ))
def _get_share(self, version):
@@ -101,6 +104,8 @@
expected_keys.append("replication_type")
if utils.is_microversion_ge(version, '2.16'):
expected_keys.append("user_id")
+ if utils.is_microversion_ge(version, '2.24'):
+ expected_keys.append("create_share_from_snapshot_support")
actual_keys = list(share.keys())
[self.assertIn(key, actual_keys) for key in expected_keys]
@@ -158,6 +163,11 @@
self._get_share('2.16')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+ @utils.skip_if_microversion_not_supported('2.24')
+ def test_get_share_with_create_share_from_snapshot_support(self):
+ self._get_share('2.24')
+
+ @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_list_shares(self):
# list shares
@@ -201,6 +211,8 @@
keys.append("replication_type")
if utils.is_microversion_ge(version, '2.16'):
keys.append("user_id")
+ if utils.is_microversion_ge(version, '2.24'):
+ keys.append("create_share_from_snapshot_support")
[self.assertIn(key, sh.keys()) for sh in shares for key in keys]
# our shares in list and have no duplicates
@@ -248,6 +260,11 @@
self._list_shares_with_detail('2.16')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+ def test_list_shares_with_detail_and_create_share_from_snapshot_support(
+ self):
+ self._list_shares_with_detail('2.24')
+
+ @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_list_shares_with_detail_filter_by_metadata(self):
filters = {'metadata': self.metadata}
@@ -259,7 +276,7 @@
for share in shares:
self.assertDictContainsSubset(
filters['metadata'], share['metadata'])
- if CONF.share.run_snapshot_tests:
+ if CONF.share.capability_create_share_from_snapshot_support:
self.assertFalse(self.shares[1]['id'] in [s['id'] for s in shares])
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@@ -294,6 +311,9 @@
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipUnless(CONF.share.run_snapshot_tests,
"Snapshot tests are disabled.")
+ @testtools.skipUnless(
+ CONF.share.capability_create_share_from_snapshot_support,
+ "Create share from snapshot tests are disabled.")
def test_list_shares_with_detail_filter_by_snapshot_id(self):
filters = {'snapshot_id': self.snap['id']}
diff --git a/manila_tempest_tests/tests/api/test_shares_negative.py b/manila_tempest_tests/tests/api/test_shares_negative.py
index 7c5619e..42204e1 100644
--- a/manila_tempest_tests/tests/api/test_shares_negative.py
+++ b/manila_tempest_tests/tests/api/test_shares_negative.py
@@ -60,6 +60,9 @@
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipUnless(CONF.share.run_snapshot_tests,
"Snapshot tests are disabled.")
+ @testtools.skipUnless(
+ CONF.share.capability_create_share_from_snapshot_support,
+ "Create share from snapshot tests are disabled.")
def test_create_share_from_snap_with_less_size(self):
# requires minimum 5Gb available space
@@ -96,7 +99,13 @@
"Only for multitenancy.")
@testtools.skipUnless(CONF.share.run_snapshot_tests,
"Snapshot tests are disabled.")
+ @testtools.skipUnless(
+ CONF.share.capability_create_share_from_snapshot_support,
+ "Create share from snapshot tests are disabled.")
def test_create_share_from_snap_with_different_share_network(self):
+ # We can't create a share from a snapshot whose base share does not
+ # have 'create_share_from_snapshot_support'.
+
# create share
share = self.create_share(cleanup_in_class=False)
diff --git a/manila_tempest_tests/tests/scenario/manager_share.py b/manila_tempest_tests/tests/scenario/manager_share.py
index 116d0e3..e019733 100644
--- a/manila_tempest_tests/tests/scenario/manager_share.py
+++ b/manila_tempest_tests/tests/scenario/manager_share.py
@@ -103,6 +103,15 @@
client.wait_for_share_status(share['id'], 'available')
return share
+ def _create_snapshot(self, share_id, client=None, **kwargs):
+ client = client or self.shares_v2_client
+ snapshot = client.create_snapshot(share_id, **kwargs)
+ self.addCleanup(
+ client.wait_for_resource_deletion, snapshot_id=snapshot['id'])
+ self.addCleanup(client.delete_snapshot, snapshot['id'])
+ client.wait_for_snapshot_status(snapshot["id"], "available")
+ return snapshot
+
def _wait_for_share_server_deletion(self, sn_id, client=None):
"""Wait for a share server to be deleted
diff --git a/manila_tempest_tests/tests/scenario/test_share_basic_ops.py b/manila_tempest_tests/tests/scenario/test_share_basic_ops.py
index 10218a5..71ed0e3 100644
--- a/manila_tempest_tests/tests/scenario/test_share_basic_ops.py
+++ b/manila_tempest_tests/tests/scenario/test_share_basic_ops.py
@@ -49,9 +49,17 @@
def setUp(self):
super(ShareBasicOpsBase, self).setUp()
base.verify_test_has_appropriate_tags(self)
+ self.image_ref = None
# Setup image and flavor the test instance
# Support both configured and injected values
- self.image_ref = None
+ self.floatings = {}
+ if self.protocol not in CONF.share.enable_protocols:
+ message = "%s tests are disabled" % self.protocol
+ raise self.skipException(message)
+ if self.protocol not in CONF.share.enable_ip_rules_for_protocols:
+ message = ("%s tests for access rules other than IP are disabled" %
+ self.protocol)
+ raise self.skipException(message)
if not hasattr(self, 'flavor_ref'):
self.flavor_ref = CONF.share.client_vm_flavor_ref
if CONF.share.image_with_share_tools:
@@ -70,8 +78,7 @@
image=self.image_ref, flavor=self.flavor_ref,
ssh_user=self.ssh_user))
self.security_group = self._create_security_group()
- if CONF.share.multitenancy_enabled:
- self.create_share_network()
+ self.create_share_network()
def boot_instance(self, wait_until="ACTIVE"):
self.keypair = self.create_keypair()
@@ -91,6 +98,7 @@
# Obtain a floating IP
floating_ip = (self.compute_floating_ips_client.create_floating_ip()
['floating_ip'])
+ self.floatings[instance['id']] = floating_ip
self.addCleanup(test_utils.call_and_ignore_notfound_exc,
self.compute_floating_ips_client.delete_floating_ip,
floating_ip['id'])
@@ -112,11 +120,12 @@
ssh_client.exec_command("ping -c 1 %s" % server_ip)
return ssh_client
- def mount_share(self, location, ssh_client):
+ def mount_share(self, location, ssh_client, target_dir=None):
raise NotImplementedError
- def umount_share(self, ssh_client):
- ssh_client.exec_command("sudo umount /mnt")
+ def umount_share(self, ssh_client, target_dir=None):
+ target_dir = target_dir or "/mnt"
+ ssh_client.exec_command("sudo umount %s" % target_dir)
def write_data(self, data, ssh_client):
ssh_client.exec_command("echo \"%s\" | sudo tee /mnt/t1 && sudo sync" %
@@ -151,17 +160,20 @@
return self._create_share_type(
data_utils.rand_name("share_type"),
extra_specs={
+ 'snapshot_support': CONF.share.capability_snapshot_support,
'driver_handles_share_servers': CONF.share.multitenancy_enabled
},)['share_type']
- def create_share(self):
- kwargs = {
+ def create_share(self, **kwargs):
+ kwargs.update({
'share_protocol': self.protocol,
- 'share_type_id': self._get_share_type()['id'],
- }
+ })
+ if not ('share_type_id' in kwargs or 'snapshot_id' in kwargs):
+ kwargs.update({'share_type_id': self._get_share_type()['id']})
if CONF.share.multitenancy_enabled:
kwargs.update({'share_network_id': self.share_net['id']})
self.share = self._create_share(**kwargs)
+ return self.share
def allow_access_ip(self, share_id, ip=None, instance=None, cleanup=True):
if instance and not ip:
@@ -179,6 +191,18 @@
self._allow_access(share_id, access_type='ip', access_to=ip,
cleanup=cleanup)
+ def provide_access_to_auxiliary_instance(self, instance, share=None):
+ share = share or self.share
+ if self.protocol.lower() == 'cifs':
+ self.allow_access_ip(share['id'], instance=instance, cleanup=False)
+ elif not CONF.share.multitenancy_enabled:
+ self.allow_access_ip(
+ share['id'], ip=self.floatings[instance['id']]['ip'],
+ instance=instance, cleanup=False)
+ elif (CONF.share.multitenancy_enabled and
+ self.protocol.lower() == 'nfs'):
+ self.allow_access_ip(share['id'], instance=instance, cleanup=False)
+
def wait_for_active_instance(self, instance_id):
waiters.wait_for_server_status(
self.manager.servers_client, instance_id, "ACTIVE")
@@ -189,10 +213,10 @@
instance = self.boot_instance(wait_until="BUILD")
self.create_share()
instance = self.wait_for_active_instance(instance["id"])
- self.allow_access_ip(self.share['id'], instance=instance,
- cleanup=False)
ssh_client = self.init_ssh(instance)
+ self.provide_access_to_auxiliary_instance(instance)
+
if utils.is_microversion_lt(CONF.share.max_api_microversion, "2.9"):
locations = self.share['export_locations']
else:
@@ -217,9 +241,8 @@
instance2 = self.wait_for_active_instance(instance2["id"])
# Write data to first VM
- self.allow_access_ip(self.share['id'], instance=instance1,
- cleanup=False)
ssh_client_inst1 = self.init_ssh(instance1)
+ self.provide_access_to_auxiliary_instance(instance1)
if utils.is_microversion_lt(CONF.share.max_api_microversion, "2.9"):
locations = self.share['export_locations']
@@ -234,9 +257,8 @@
self.write_data(test_data, ssh_client_inst1)
# Read from second VM
- self.allow_access_ip(
- self.share['id'], instance=instance2, cleanup=False)
ssh_client_inst2 = self.init_ssh(instance2)
+ self.provide_access_to_auxiliary_instance(instance2)
self.mount_share(locations[0], ssh_client_inst2)
self.addCleanup(self.umount_share,
ssh_client_inst2)
@@ -249,7 +271,7 @@
"Share migration tests are disabled.")
def test_migration_files(self):
- if self.protocol != "NFS":
+ if self.protocol != "nfs":
raise self.skipException("Only NFS protocol supported "
"at this moment.")
@@ -275,9 +297,8 @@
dest_pool = dest_pool['name']
- self.allow_access_ip(
- self.share['id'], instance=instance, cleanup=False)
ssh_client = self.init_ssh(instance)
+ self.provide_access_to_auxiliary_instance(instance)
if utils.is_microversion_lt(CONF.share.max_api_microversion, "2.9"):
exports = self.share['export_locations']
@@ -290,24 +311,24 @@
self.mount_share(exports[0], ssh_client)
- ssh_client.exec_command("mkdir -p /mnt/f1")
- ssh_client.exec_command("mkdir -p /mnt/f2")
- ssh_client.exec_command("mkdir -p /mnt/f3")
- ssh_client.exec_command("mkdir -p /mnt/f4")
- ssh_client.exec_command("mkdir -p /mnt/f1/ff1")
+ ssh_client.exec_command("sudo mkdir -p /mnt/f1")
+ ssh_client.exec_command("sudo mkdir -p /mnt/f2")
+ ssh_client.exec_command("sudo mkdir -p /mnt/f3")
+ ssh_client.exec_command("sudo mkdir -p /mnt/f4")
+ ssh_client.exec_command("sudo mkdir -p /mnt/f1/ff1")
ssh_client.exec_command("sleep 1")
- ssh_client.exec_command("dd if=/dev/zero of=/mnt/f1/1m1.bin bs=1M"
- " count=1")
- ssh_client.exec_command("dd if=/dev/zero of=/mnt/f2/1m2.bin bs=1M"
- " count=1")
- ssh_client.exec_command("dd if=/dev/zero of=/mnt/f3/1m3.bin bs=1M"
- " count=1")
- ssh_client.exec_command("dd if=/dev/zero of=/mnt/f4/1m4.bin bs=1M"
- " count=1")
- ssh_client.exec_command("dd if=/dev/zero of=/mnt/f1/ff1/1m5.bin bs=1M"
- " count=1")
- ssh_client.exec_command("chmod -R 555 /mnt/f3")
- ssh_client.exec_command("chmod -R 777 /mnt/f4")
+ ssh_client.exec_command(
+ "sudo dd if=/dev/zero of=/mnt/f1/1m1.bin bs=1M count=1")
+ ssh_client.exec_command(
+ "sudo dd if=/dev/zero of=/mnt/f2/1m2.bin bs=1M count=1")
+ ssh_client.exec_command(
+ "sudo dd if=/dev/zero of=/mnt/f3/1m3.bin bs=1M count=1")
+ ssh_client.exec_command(
+ "sudo dd if=/dev/zero of=/mnt/f4/1m4.bin bs=1M count=1")
+ ssh_client.exec_command(
+ "sudo dd if=/dev/zero of=/mnt/f1/ff1/1m5.bin bs=1M count=1")
+ ssh_client.exec_command("sudo chmod -R 555 /mnt/f3")
+ ssh_client.exec_command("sudo chmod -R 777 /mnt/f4")
self.umount_share(ssh_client)
@@ -343,21 +364,114 @@
self.assertIn('1m4.bin', output)
self.assertIn('1m5.bin', output)
+ def _get_user_export_location(self, share):
+ if utils.is_microversion_lt(CONF.share.max_api_microversion, "2.9"):
+ user_export_location = share['export_locations'][0]
+ else:
+ exports = self.shares_v2_client.list_share_export_locations(
+ share['id'])
+ locations = [x['path'] for x in exports]
+ user_export_location = locations[0]
+ return user_export_location
+
+ @tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
+ @testtools.skipUnless(
+ CONF.share.run_snapshot_tests, "Snapshot tests are disabled.")
+ def test_write_data_to_share_created_from_snapshot(self):
+ if self.protocol.upper() == 'CIFS':
+ msg = "Skipped for CIFS protocol because of bug/1649573"
+ raise self.skipException(msg)
+
+ # 1 - Create UVM, ok, created
+ instance = self.boot_instance(wait_until="BUILD")
+
+ # 2 - Create share S1, ok, created
+ parent_share = self.create_share()
+ instance = self.wait_for_active_instance(instance["id"])
+ self.addCleanup(self.servers_client.delete_server, instance['id'])
+
+ # 3 - SSH to UVM, ok, connected
+ ssh_client = self.init_ssh(instance)
+
+ # 4 - Provide RW access to S1, ok, provided
+ self.provide_access_to_auxiliary_instance(instance, parent_share)
+
+ # 5 - Try mount S1 to UVM, ok, mounted
+ user_export_location = self._get_user_export_location(parent_share)
+ parent_share_dir = "/mnt/parent"
+ ssh_client.exec_command("sudo mkdir -p %s" % parent_share_dir)
+ self.mount_share(user_export_location, ssh_client, parent_share_dir)
+ self.addCleanup(self.umount_share, ssh_client, parent_share_dir)
+
+ # 6 - Create "file1", ok, created
+ ssh_client.exec_command("sudo touch %s/file1" % parent_share_dir)
+
+ # 7 - Create snapshot SS1 from S1, ok, created
+ snapshot = self._create_snapshot(parent_share['id'])
+
+ # 8 - Create "file2" in share S1 - ok, created. We expect that
+ # snapshot will not contain any data created after snapshot creation.
+ ssh_client.exec_command("sudo touch %s/file2" % parent_share_dir)
+
+ # 9 - Create share S2 from SS1, ok, created
+ child_share = self.create_share(snapshot_id=snapshot["id"])
+
+ # 10 - Try mount S2 - fail, access denied. We test that child share
+ # did not get access rules from parent share.
+ user_export_location = self._get_user_export_location(child_share)
+ child_share_dir = "/mnt/child"
+ ssh_client.exec_command("sudo mkdir -p %s" % child_share_dir)
+ self.assertRaises(
+ exceptions.SSHExecCommandFailed,
+ self.mount_share,
+ user_export_location, ssh_client, child_share_dir,
+ )
+
+ # 11 - Provide RW access to S2, ok, provided
+ self.provide_access_to_auxiliary_instance(instance, child_share)
+
+ # 12 - Try mount S2, ok, mounted
+ self.mount_share(user_export_location, ssh_client, child_share_dir)
+ self.addCleanup(self.umount_share, ssh_client, child_share_dir)
+
+ # 13 - List files on S2, only "file1" exists
+ output = ssh_client.exec_command("sudo ls -lRA %s" % child_share_dir)
+ self.assertIn('file1', output)
+ self.assertNotIn('file2', output)
+
+ # 14 - Create file3 on S2, ok, file created
+ ssh_client.exec_command("sudo touch %s/file3" % child_share_dir)
+
+ # 15 - List files on S1, two files exist - "file1" and "file2"
+ output = ssh_client.exec_command("sudo ls -lRA %s" % parent_share_dir)
+ self.assertIn('file1', output)
+ self.assertIn('file2', output)
+ self.assertNotIn('file3', output)
+
+ # 16 - List files on S2, two files exist - "file1" and "file3"
+ output = ssh_client.exec_command("sudo ls -lRA %s" % child_share_dir)
+ self.assertIn('file1', output)
+ self.assertNotIn('file2', output)
+ self.assertIn('file3', output)
+
class TestShareBasicOpsNFS(ShareBasicOpsBase):
- protocol = "NFS"
+ protocol = "nfs"
- def mount_share(self, location, ssh_client):
- ssh_client.exec_command("sudo mount -vt nfs \"%s\" /mnt" % location)
+ def mount_share(self, location, ssh_client, target_dir=None):
+ target_dir = target_dir or "/mnt"
+ ssh_client.exec_command(
+ "sudo mount -vt nfs \"%s\" %s" % (location, target_dir))
class TestShareBasicOpsCIFS(ShareBasicOpsBase):
- protocol = "CIFS"
+ protocol = "cifs"
- def mount_share(self, location, ssh_client):
+ def mount_share(self, location, ssh_client, target_dir=None):
location = location.replace("\\", "/")
+ target_dir = target_dir or "/mnt"
ssh_client.exec_command(
- "sudo mount.cifs \"%s\" /mnt -o guest" % location
+ "sudo mount.cifs \"%s\" %s -o guest" % (location, target_dir)
)