Merge "Add py38 package metadata"
diff --git a/manila_tempest_tests/common/constants.py b/manila_tempest_tests/common/constants.py
index 4c8cbf7..2750760 100644
--- a/manila_tempest_tests/common/constants.py
+++ b/manila_tempest_tests/common/constants.py
@@ -40,6 +40,8 @@
REPLICATION_STATE_ACTIVE = 'active'
REPLICATION_STATE_IN_SYNC = 'in_sync'
REPLICATION_STATE_OUT_OF_SYNC = 'out_of_sync'
+MIN_SHARE_REPLICATION_VERSION = '2.11'
+SHARE_REPLICA_GRADUATION_VERSION = '2.56'
# Access Rules
RULE_STATE_ACTIVE = 'active'
@@ -95,6 +97,7 @@
# Share servers
SERVER_STATE_ACTIVE = 'active'
+SERVER_STATE_INACTIVE = 'inactive'
SERVER_STATE_CREATING = 'creating'
SERVER_STATE_DELETING = 'deleting'
SERVER_STATE_ERROR = 'error'
@@ -102,3 +105,5 @@
SERVER_STATE_MANAGE_STARTING = 'manage_starting'
SERVER_STATE_UNMANAGE_ERROR = 'unmanage_error'
SERVER_STATE_UNMANAGE_STARTING = 'unmanage_starting'
+STATUS_SERVER_MIGRATING = 'server_migrating'
+STATUS_SERVER_MIGRATING_TO = 'server_migrating_to'
diff --git a/manila_tempest_tests/common/remote_client.py b/manila_tempest_tests/common/remote_client.py
index 45f85d8..9970b0b 100644
--- a/manila_tempest_tests/common/remote_client.py
+++ b/manila_tempest_tests/common/remote_client.py
@@ -10,15 +10,14 @@
# License for the specific language governing permissions and limitations
# under the License.
-import six
import sys
from oslo_log import log
-
+import six
from tempest import config
from tempest.lib.common import ssh
from tempest.lib.common.utils import test_utils
-import tempest.lib.exceptions
+from tempest.lib import exceptions
CONF = config.CONF
@@ -30,7 +29,7 @@
def wrapper(self, *args, **kwargs):
try:
return function(self, *args, **kwargs)
- except tempest.lib.exceptions.SSHTimeout:
+ except exceptions.SSHTimeout:
try:
original_exception = sys.exc_info()
caller = test_utils.find_test_caller() or "not found"
diff --git a/manila_tempest_tests/config.py b/manila_tempest_tests/config.py
index 18f4be5..a24a064 100644
--- a/manila_tempest_tests/config.py
+++ b/manila_tempest_tests/config.py
@@ -14,6 +14,7 @@
# under the License.
from oslo_config import cfg
+from oslo_config import types
service_option = cfg.BoolOpt("manila",
default=True,
@@ -28,7 +29,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.55",
+ default="2.57",
help="The maximum api microversion is configured to be the "
"value of the latest microversion supported by Manila."),
cfg.StrOpt("region",
@@ -174,6 +175,24 @@
help="Whether to suppress errors with clean up operation "
"or not. There are cases when we may want to skip "
"such errors and catch only test errors."),
+ cfg.MultiOpt("security_service",
+ item_type=types.Dict(),
+ secret=True,
+ help="This option enables specifying security service "
+ "parameters needed to create security services "
+ "dynamically in order to run the tempest tests. "
+ "The configured security service must be reachable by "
+ "the project share networks created by the tests. So, "
+ "ideally project networks must be able to route to the "
+ "network where the pre-existing security services has "
+ "been deployed. The set of parameters that can be "
+ "configured is the same used in the security service "
+ "creation. You can repeat this option many times, and "
+ "each entry takes the standard dict config parameters: "
+ "security_service = "
+ "ss_type:<ldap, kerberos or active_directory>, "
+ "ss_dns_ip:value, ss_user:value, ss_password=value, "
+ "ss_domain:value, ss_server:value"),
# Switching ON/OFF test suites filtered by features
cfg.BoolOpt("run_quota_tests",
@@ -243,6 +262,10 @@
help="Defines whether to run tests that create share from "
"snapshots in another pool or az. Enable this "
"option if the used driver supports it."),
+ cfg.BoolOpt("run_share_server_migration_tests",
+ default=False,
+ help="Defines whether to run share servers migration tests. "
+ "Enable this option if the used driver supports it."),
cfg.StrOpt("image_with_share_tools",
default="manila-service-image-master",
@@ -260,6 +283,10 @@
default=1500,
help="Time to wait for share migration before "
"timing out (seconds)."),
+ cfg.IntOpt("share_server_migration_timeout",
+ default="1500",
+ help="Time to wait for share server migration before "
+ "timing out (seconds)."),
cfg.StrOpt("default_share_type_name",
help="Default share type name to use in tempest tests."),
cfg.StrOpt("backend_replication_type",
@@ -271,6 +298,11 @@
help="Default size in GB for shares created by share tests."),
cfg.BoolOpt("run_ipv6_tests",
default=False,
- help="Enable or disable running IPv6 tests."),
-
+ help="Enable or disable running IPv6 NFS scenario tests. "
+ "These tests validate that IPv6 export locations work, "
+ "and that access can be provided to IPv6 clients. When "
+ "you do not specify a storage_network, the tests will "
+ "attempt to create an IPv6 subnet on the project network "
+ "they create for ping and SSH to the client test VM "
+ "where data path testing is performed."),
]
diff --git a/manila_tempest_tests/services/share/json/shares_client.py b/manila_tempest_tests/services/share/json/shares_client.py
index b2eabb4..87d7e47 100644
--- a/manila_tempest_tests/services/share/json/shares_client.py
+++ b/manila_tempest_tests/services/share/json/shares_client.py
@@ -18,7 +18,6 @@
import six
from six.moves.urllib import parse as urlparse
-
from tempest import config
from tempest.lib.common import rest_client
from tempest.lib.common.utils import data_utils
@@ -26,6 +25,7 @@
from manila_tempest_tests import share_exceptions
+
CONF = config.CONF
@@ -262,7 +262,8 @@
(snapshot_name, status, self.build_timeout))
raise exceptions.TimeoutException(message)
- def wait_for_access_rule_status(self, share_id, rule_id, status):
+ def wait_for_access_rule_status(self, share_id, rule_id, status,
+ raise_rule_in_error_state=True):
"""Waits for an access rule to reach a given status."""
rule_status = "new"
start = int(time.time())
@@ -273,7 +274,7 @@
if rule["id"] in rule_id:
rule_status = rule['state']
break
- if 'error' in rule_status:
+ if 'error' in rule_status and raise_rule_in_error_state:
raise share_exceptions.AccessRuleBuildErrorException(
rule_id=rule_id)
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 5e2f8df..c1a0f3c 100644
--- a/manila_tempest_tests/services/share/v2/json/shares_client.py
+++ b/manila_tempest_tests/services/share/v2/json/shares_client.py
@@ -15,9 +15,9 @@
import json
import re
-import six
import time
+import six
from six.moves.urllib import parse
from tempest import config
from tempest.lib.common.utils import data_utils
@@ -578,7 +578,7 @@
time.sleep(self.build_interval)
body = self.get_snapshot(snapshot_id, version=version)
snapshot_status = body['status']
- if snapshot_status == status:
+ if snapshot_status in status:
return
if 'error' in snapshot_status:
raise (share_exceptions.
@@ -1522,7 +1522,7 @@
time.sleep(self.build_interval)
body = self.show_share_server(server_id)
server_status = body[status_attr]
- if server_status == status:
+ if server_status in status:
return
elif constants.STATUS_ERROR in server_status.lower():
raise share_exceptions.ShareServerBuildErrorException(
@@ -1654,20 +1654,23 @@
'share_id': share_id,
'availability_zone': availability_zone,
}
-
+ headers, extra_headers = utils.get_extra_headers(
+ version, constants.SHARE_REPLICA_GRADUATION_VERSION)
body = json.dumps({'share_replica': post_body})
resp, body = self.post(uri, body,
- headers=EXPERIMENTAL,
- extra_headers=True,
+ headers=headers,
+ extra_headers=extra_headers,
version=version)
self.expected_success(202, resp.status)
return self._parse_resp(body)
def get_share_replica(self, replica_id, version=LATEST_MICROVERSION):
"""Get the details of share_replica."""
+ headers, extra_headers = utils.get_extra_headers(
+ version, constants.SHARE_REPLICA_GRADUATION_VERSION)
resp, body = self.get("share-replicas/%s" % replica_id,
- headers=EXPERIMENTAL,
- extra_headers=True,
+ headers=headers,
+ extra_headers=extra_headers,
version=version)
self.expected_success(200, resp.status)
return self._parse_resp(body)
@@ -1676,8 +1679,10 @@
"""Get list of replicas."""
uri = "share-replicas/detail"
uri += ("?share_id=%s" % share_id) if share_id is not None else ''
- resp, body = self.get(uri, headers=EXPERIMENTAL,
- extra_headers=True, version=version)
+ headers, extra_headers = utils.get_extra_headers(
+ version, constants.SHARE_REPLICA_GRADUATION_VERSION)
+ resp, body = self.get(uri, headers=headers,
+ extra_headers=extra_headers, version=version)
self.expected_success(200, resp.status)
return self._parse_resp(body)
@@ -1686,17 +1691,21 @@
"""Get summary list of replicas."""
uri = "share-replicas"
uri += ("?share_id=%s" % share_id) if share_id is not None else ''
- resp, body = self.get(uri, headers=EXPERIMENTAL,
- extra_headers=True, version=version)
+ headers, extra_headers = utils.get_extra_headers(
+ version, constants.SHARE_REPLICA_GRADUATION_VERSION)
+ resp, body = self.get(uri, headers=headers,
+ extra_headers=extra_headers, version=version)
self.expected_success(200, resp.status)
return self._parse_resp(body)
def delete_share_replica(self, replica_id, version=LATEST_MICROVERSION):
"""Delete share_replica."""
uri = "share-replicas/%s" % replica_id
+ headers, extra_headers = utils.get_extra_headers(
+ version, constants.SHARE_REPLICA_GRADUATION_VERSION)
resp, body = self.delete(uri,
- headers=EXPERIMENTAL,
- extra_headers=True,
+ headers=headers,
+ extra_headers=extra_headers,
version=version)
self.expected_success(202, resp.status)
return body
@@ -1709,9 +1718,11 @@
'promote': None,
}
body = json.dumps(post_body)
+ headers, extra_headers = utils.get_extra_headers(
+ version, constants.SHARE_REPLICA_GRADUATION_VERSION)
resp, body = self.post(uri, body,
- headers=EXPERIMENTAL,
- extra_headers=True,
+ headers=headers,
+ extra_headers=extra_headers,
version=version)
self.expected_success(expected_status, resp.status)
return self._parse_resp(body)
@@ -1720,8 +1731,10 @@
expected_status=200,
version=LATEST_MICROVERSION):
uri = "share-replicas/%s/export-locations" % replica_id
- resp, body = self.get(uri, headers=EXPERIMENTAL,
- extra_headers=True, version=version)
+ headers, extra_headers = utils.get_extra_headers(
+ version, constants.SHARE_REPLICA_GRADUATION_VERSION)
+ resp, body = self.get(uri, headers=headers,
+ extra_headers=extra_headers, version=version)
self.expected_success(expected_status, resp.status)
return self._parse_resp(body)
@@ -1731,8 +1744,10 @@
version=LATEST_MICROVERSION):
uri = "share-replicas/%s/export-locations/%s" % (replica_id,
export_location_id)
- resp, body = self.get(uri, headers=EXPERIMENTAL,
- extra_headers=True, version=version)
+ headers, extra_headers = utils.get_extra_headers(
+ version, constants.SHARE_REPLICA_GRADUATION_VERSION)
+ resp, body = self.get(uri, headers=headers,
+ extra_headers=extra_headers, version=version)
self.expected_success(expected_status, resp.status)
return self._parse_resp(body)
@@ -1779,9 +1794,11 @@
}
}
body = json.dumps(post_body)
+ headers, extra_headers = utils.get_extra_headers(
+ version, constants.SHARE_REPLICA_GRADUATION_VERSION)
resp, body = self.post(uri, body,
- headers=EXPERIMENTAL,
- extra_headers=True,
+ headers=headers,
+ extra_headers=extra_headers,
version=version)
self.expected_success(202, resp.status)
return self._parse_resp(body)
@@ -1797,9 +1814,11 @@
}
}
body = json.dumps(post_body)
+ headers, extra_headers = utils.get_extra_headers(
+ version, constants.SHARE_REPLICA_GRADUATION_VERSION)
resp, body = self.post(uri, body,
- headers=EXPERIMENTAL,
- extra_headers=True,
+ headers=headers,
+ extra_headers=extra_headers,
version=version)
self.expected_success(202, resp.status)
return self._parse_resp(body)
@@ -1812,9 +1831,11 @@
'resync': None
}
body = json.dumps(post_body)
+ headers, extra_headers = utils.get_extra_headers(
+ version, constants.SHARE_REPLICA_GRADUATION_VERSION)
resp, body = self.post(uri, body,
- headers=EXPERIMENTAL,
- extra_headers=True,
+ headers=headers,
+ extra_headers=extra_headers,
version=version)
self.expected_success(expected_result, resp.status)
return self._parse_resp(body)
@@ -1827,9 +1848,11 @@
'force_delete': None
}
body = json.dumps(post_body)
+ headers, extra_headers = utils.get_extra_headers(
+ version, constants.SHARE_REPLICA_GRADUATION_VERSION)
resp, body = self.post(uri, body,
- headers=EXPERIMENTAL,
- extra_headers=True,
+ headers=headers,
+ extra_headers=extra_headers,
version=version)
self.expected_success(202, resp.status)
return self._parse_resp(body)
@@ -2084,3 +2107,90 @@
return body
###############
+
+ def share_server_migration_check(
+ self, share_server_id, host, writable=False,
+ preserve_snapshots=False, nondisruptive=False,
+ new_share_network_id=None, version=LATEST_MICROVERSION):
+ body = {
+ 'migration_check': {
+ 'host': host,
+ 'writable': writable,
+ 'preserve_snapshots': preserve_snapshots,
+ 'nondisruptive': nondisruptive,
+ 'new_share_network_id': new_share_network_id,
+ }
+ }
+
+ body = json.dumps(body)
+ resp, body = self.post('share-servers/%s/action' % share_server_id,
+ body, headers=EXPERIMENTAL, extra_headers=True,
+ version=version)
+ self.expected_success(200, resp.status)
+
+ return json.loads(body)
+
+ def share_server_migration_start(self, share_server_id, host,
+ writable=False, new_share_network_id=None,
+ preserve_snapshots=False,
+ nondisruptive=False,
+ version=LATEST_MICROVERSION):
+ body = {
+ 'migration_start': {
+ 'host': host,
+ 'writable': writable,
+ 'preserve_snapshots': preserve_snapshots,
+ 'nondisruptive': nondisruptive,
+ 'new_share_network_id': new_share_network_id,
+ }
+ }
+
+ body = json.dumps(body)
+ resp, body = self.post('share-servers/%s/action' % share_server_id,
+ body, headers=EXPERIMENTAL, extra_headers=True,
+ version=version)
+ self.expected_success(202, resp.status)
+
+ return body
+
+ def share_server_migration_complete(self, share_server_id,
+ version=LATEST_MICROVERSION):
+ body = {
+ 'migration_complete': None
+ }
+
+ body = json.dumps(body)
+ resp, body = self.post('share-servers/%s/action' % share_server_id,
+ body, headers=EXPERIMENTAL, extra_headers=True,
+ version=version)
+ self.expected_success(200, resp.status)
+
+ return body
+
+ def share_server_migration_cancel(self, share_server_id,
+ version=LATEST_MICROVERSION):
+ body = {
+ 'migration_cancel': None
+ }
+
+ body = json.dumps(body)
+ resp, body = self.post('share-servers/%s/action' % share_server_id,
+ body, headers=EXPERIMENTAL, extra_headers=True,
+ version=version)
+ self.expected_success(202, resp.status)
+
+ return body
+
+ def share_server_migration_get_progress(self, share_server_id,
+ version=LATEST_MICROVERSION):
+ body = {
+ 'migration_get_progress': None
+ }
+
+ body = json.dumps(body)
+ resp, body = self.post('share-servers/%s/action' % share_server_id,
+ body, headers=EXPERIMENTAL, extra_headers=True,
+ version=version)
+ self.expected_sucess(200, resp.status)
+
+ return json.loads(body)
diff --git a/manila_tempest_tests/share_exceptions.py b/manila_tempest_tests/share_exceptions.py
index 67b4fca..9466afe 100644
--- a/manila_tempest_tests/share_exceptions.py
+++ b/manila_tempest_tests/share_exceptions.py
@@ -80,3 +80,8 @@
class ShareServerBuildErrorException(exceptions.TempestException):
message = ("Share server %(server_id)s failed to build and is in ERROR "
"status")
+
+
+class ShareServerMigrationException(exceptions.TempestException):
+ message = ("Share server %(server_id)s failed to migrate and is in ERROR "
+ "status")
diff --git a/manila_tempest_tests/tests/api/admin/test_admin_actions.py b/manila_tempest_tests/tests/api/admin/test_admin_actions.py
index c6e21d7..57b97e3 100644
--- a/manila_tempest_tests/tests/api/admin/test_admin_actions.py
+++ b/manila_tempest_tests/tests/api/admin/test_admin_actions.py
@@ -14,11 +14,12 @@
# under the License.
import ddt
+from tempest import config
+from tempest.lib import decorators
import testtools
+from testtools import testcase as tc
from manila_tempest_tests.tests.api import base
-from tempest import config
-from testtools import testcase as tc
CONF = config.CONF
@@ -48,6 +49,7 @@
resource_id, s_type=resource_type, status="available")
self._wait_for_resource_status(resource_id, resource_type[:-1])
+ @decorators.idempotent_id('4f8c6ae9-0656-445f-a911-fbf98fe761d0')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@ddt.data("error", "available", "error_deleting", "deleting", "creating")
def test_reset_share_state(self, status):
@@ -55,6 +57,7 @@
self.shares_v2_client.wait_for_share_status(self.sh["id"], status)
self.addCleanup(self._reset_resource_available, self.sh["id"])
+ @decorators.idempotent_id('13075b2d-fe83-41bf-b6ef-99cfcc00257d')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@ddt.data("error", "available", "error_deleting", "deleting", "creating")
def test_reset_share_instance_state(self, status):
@@ -68,6 +71,7 @@
self.addCleanup(self._reset_resource_available,
share_instance_id, "share_instances")
+ @decorators.idempotent_id('3e16d990-fa19-45e9-893f-e0b7a90127bd')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipUnless(CONF.share.run_snapshot_tests,
"Snapshot tests are disabled.")
@@ -81,6 +85,7 @@
self.addCleanup(self._reset_resource_available,
snapshot["id"], "snapshots")
+ @decorators.idempotent_id('2e8fee75-6b7f-4b69-8f68-0646ce6a96e9')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_force_delete_share(self):
share = self.create_share(share_type_id=self.share_type_id)
@@ -96,6 +101,7 @@
self.shares_v2_client.force_delete(share["id"])
self.shares_v2_client.wait_for_resource_deletion(share_id=share["id"])
+ @decorators.idempotent_id('382fca90-746e-4ad1-a509-b82a643d4a03')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_force_delete_share_instance(self):
share = self.create_share(share_type_id=self.share_type_id,
@@ -120,6 +126,7 @@
self.shares_v2_client.wait_for_resource_deletion(
share_instance_id=instance["id"])
+ @decorators.idempotent_id('d5a48182-ecd7-463e-a31a-148c81d3c5ed')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipUnless(CONF.share.run_snapshot_tests,
"Snapshot tests are disabled.")
@@ -138,6 +145,7 @@
self.shares_v2_client.force_delete(sn["id"], s_type="snapshots")
self.shares_v2_client.wait_for_resource_deletion(snapshot_id=sn["id"])
+ @decorators.idempotent_id('49a576eb-733a-4299-aa6f-918fe7c67a6a')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@base.skip_if_microversion_lt("2.22")
def test_reset_share_task_state(self):
diff --git a/manila_tempest_tests/tests/api/admin/test_admin_actions_negative.py b/manila_tempest_tests/tests/api/admin/test_admin_actions_negative.py
index c74bd4e..dd64af5 100644
--- a/manila_tempest_tests/tests/api/admin/test_admin_actions_negative.py
+++ b/manila_tempest_tests/tests/api/admin/test_admin_actions_negative.py
@@ -15,6 +15,7 @@
import ddt
from tempest import config
+from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
import testtools
from testtools import testcase as tc
@@ -44,12 +45,14 @@
cls.sn = cls.create_snapshot_wait_for_active(
cls.sh["id"], client=cls.admin_client)
+ @decorators.idempotent_id('f730c395-a501-44cf-90d9-a3273771b895')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_reset_share_state_to_unacceptable_state(self):
self.assertRaises(lib_exc.BadRequest,
self.admin_client.reset_state,
self.sh["id"], status="fake")
+ @decorators.idempotent_id('3bfa9555-9c7e-45a2-b5bd-384329cb6fda')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_reset_share_instance_state_to_unacceptable_state(self):
self.assertRaises(
@@ -60,6 +63,7 @@
status="fake"
)
+ @decorators.idempotent_id('02e0d0d5-ac66-4d24-9aa7-568f75944a05')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipUnless(CONF.share.run_snapshot_tests,
"Snapshot tests are disabled.")
@@ -68,6 +72,7 @@
self.admin_client.reset_state,
self.sn["id"], s_type="snapshots", status="fake")
+ @decorators.idempotent_id('3b525c29-b657-493f-aa41-b17676a95fd2')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_try_reset_share_state_with_member(self):
# Even if member from another tenant, it should be unauthorized
@@ -75,6 +80,7 @@
self.member_client.reset_state,
self.sh["id"])
+ @decorators.idempotent_id('d4abddba-1c20-49e1-85b1-5452f0faceb0')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_try_reset_share_instance_state_with_member(self):
# Even if member from another tenant, it should be unauthorized
@@ -82,6 +88,7 @@
self.member_client.reset_state,
self.sh_instance["id"], s_type="share_instances")
+ @decorators.idempotent_id('48dfb1ec-6db6-4022-8a41-2eb2883e0988')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipUnless(CONF.share.run_snapshot_tests,
"Snapshot tests are disabled.")
@@ -91,6 +98,7 @@
self.member_client.reset_state,
self.sn["id"], s_type="snapshots")
+ @decorators.idempotent_id('7cd0b48e-2815-4f8c-8718-3c071ff9701f')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_try_force_delete_share_with_member(self):
# If a non-admin tries to do force_delete, it should be unauthorized
@@ -98,6 +106,7 @@
self.member_client.force_delete,
self.sh["id"])
+ @decorators.idempotent_id('257da3e0-9460-4d97-8a56-c86c0427cc64')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_try_force_delete_share_instance_with_member(self):
# If a non-admin tries to do force_delete, it should be unauthorized
@@ -105,6 +114,7 @@
self.member_client.force_delete,
self.sh_instance["id"], s_type="share_instances")
+ @decorators.idempotent_id('c9a1894f-d58f-4885-86ba-736e9ab8428a')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipUnless(CONF.share.run_snapshot_tests,
"Snapshot tests are disabled.")
@@ -114,6 +124,7 @@
self.member_client.force_delete,
self.sn["id"], s_type="snapshots")
+ @decorators.idempotent_id('821da7c8-3501-44ba-9ffe-45f485a6e573')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_try_get_share_instance_with_member(self):
# If a non-admin tries to get instance, it should be unauthorized
@@ -121,6 +132,7 @@
self.member_client.get_share_instance,
self.sh_instance["id"])
+ @decorators.idempotent_id('ab361521-adc9-4fe3-9699-a5ccc49b579b')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_try_get_instances_of_share_with_member(self):
# If a non-admin tries to list instances of given share, it should be
@@ -129,6 +141,7 @@
self.member_client.get_instances_of_share,
self.sh['id'])
+ @decorators.idempotent_id('d662457c-2b84-4f13-aee7-5ffafe2552f1')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@base.skip_if_microversion_lt("2.22")
def test_reset_task_state_invalid_state(self):
@@ -146,12 +159,14 @@
cls.admin_client = cls.admin_shares_v2_client
cls.member_client = cls.shares_v2_client
+ @decorators.idempotent_id('1c928920-1538-400a-ab28-c58dd75503c3')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_list_share_instance_with_member(self):
# If a non-admin tries to list instances, it should be unauthorized
self.assertRaises(lib_exc.Forbidden,
self.member_client.list_share_instances)
+ @decorators.idempotent_id('aba8638c-bfed-4c3e-994b-5309fcd912b2')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
@base.skip_if_microversion_lt("2.22")
def test_reset_task_state_share_not_found(self):
@@ -159,6 +174,7 @@
lib_exc.NotFound, self.admin_client.reset_task_state,
'fake_share', 'migration_error')
+ @decorators.idempotent_id('e31d2d7b-7202-4699-9423-72f710e72181')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
@testtools.skipUnless(CONF.share.run_snapshot_tests,
"Snapshot tests are disabled.")
@@ -168,11 +184,13 @@
"fake",
s_type="snapshots")
+ @decorators.idempotent_id('dedca5c1-151d-40f7-bb7f-8913d51c05a9')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_force_delete_nonexistent_share(self):
self.assertRaises(lib_exc.NotFound,
self.admin_client.force_delete, "fake")
+ @decorators.idempotent_id('7cbfc035-12ea-4e2c-8da1-baf261e45f03')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_force_delete_nonexistent_share_instance(self):
self.assertRaises(lib_exc.NotFound,
@@ -180,16 +198,19 @@
"fake",
s_type="share_instances")
+ @decorators.idempotent_id('17e7eb3c-dbe6-4667-b838-663211365d44')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_reset_nonexistent_share_state(self):
self.assertRaises(lib_exc.NotFound,
self.admin_client.reset_state, "fake")
+ @decorators.idempotent_id('26ce6f02-98eb-435a-9065-2e5bbcac87c5')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_reset_nonexistent_share_instance_state(self):
self.assertRaises(lib_exc.NotFound, self.admin_client.reset_state,
"fake", s_type="share_instances")
+ @decorators.idempotent_id('7e07f684-b68f-4b0e-89cc-05d70a67dd69')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
@testtools.skipUnless(CONF.share.run_snapshot_tests,
"Snapshot tests are disabled.")
@@ -197,6 +218,7 @@
self.assertRaises(lib_exc.NotFound, self.admin_client.reset_state,
"fake", s_type="snapshots")
+ @decorators.idempotent_id('59b09ad2-d405-4762-a253-d7b7cf56f0a5')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
@ddt.data('migrate_share', 'migration_complete', 'reset_task_state',
'migration_get_progress', 'migration_cancel')
diff --git a/manila_tempest_tests/tests/api/admin/test_export_locations.py b/manila_tempest_tests/tests/api/admin/test_export_locations.py
index 96a0d9d..dc1e2fa 100644
--- a/manila_tempest_tests/tests/api/admin/test_export_locations.py
+++ b/manila_tempest_tests/tests/api/admin/test_export_locations.py
@@ -18,6 +18,7 @@
from oslo_utils import uuidutils
import six
from tempest import config
+from tempest.lib import decorators
from testtools import testcase as tc
from manila_tempest_tests.tests.api import base
@@ -109,6 +110,7 @@
# it making assertion that it has proper date value.
timeutils.parse_strtime(time)
+ @decorators.idempotent_id('dfcb05af-369a-44c9-a06a-67d12a2a0917')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@utils.skip_if_microversion_not_supported('2.13')
def test_list_share_export_locations(self):
@@ -118,6 +120,7 @@
self._verify_export_location_structure(export_locations,
version='2.13')
+ @decorators.idempotent_id('032173d7-3ddf-4730-8524-d1a96a2a9e16')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@utils.skip_if_microversion_not_supported('2.14')
def test_list_share_export_locations_with_preferred_flag(self):
@@ -127,6 +130,7 @@
self._verify_export_location_structure(export_locations,
version='2.14')
+ @decorators.idempotent_id('814da2ce-2909-4b02-a92e-12bc1b640580')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_get_share_export_location(self):
export_locations = self.admin_client.list_share_export_locations(
@@ -137,6 +141,7 @@
self.share['id'], export_location['id'])
self._verify_export_location_structure(el, format='detail')
+ @decorators.idempotent_id('397969c6-7fc8-4bf8-86c7-300b96857c54')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_list_share_export_locations_by_member(self):
export_locations = self.member_client.list_share_export_locations(
@@ -144,6 +149,7 @@
self._verify_export_location_structure(export_locations, role='member')
+ @decorators.idempotent_id('66cef86f-5da8-4cb4-bc21-91f6c1e27cb5')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_get_share_export_location_by_member(self):
export_locations = self.admin_client.list_share_export_locations(
@@ -157,6 +163,7 @@
self._verify_export_location_structure(el, role='member',
format='detail')
+ @decorators.idempotent_id('06ea2636-1c9f-4889-8b5f-e10c2c2572cb')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@utils.skip_if_microversion_not_supported('2.13')
def test_list_share_instance_export_locations(self):
@@ -167,6 +174,7 @@
self._verify_export_location_structure(export_locations,
version='2.13')
+ @decorators.idempotent_id('b93e4cba-ea98-4b1c-90f8-e0a8763033a3')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@utils.skip_if_microversion_not_supported('2.14')
def test_list_share_instance_export_locations_with_preferred_flag(self):
@@ -177,6 +185,7 @@
self._verify_export_location_structure(export_locations,
version='2.14')
+ @decorators.idempotent_id('59421c43-293f-41fd-8ac6-e856deeceac9')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_get_share_instance_export_location(self):
for share_instance in self.share_instances:
@@ -188,6 +197,7 @@
share_instance['id'], el['id'])
self._verify_export_location_structure(el, format='detail')
+ @decorators.idempotent_id('581acd8d-b89d-4684-8310-b910b46acc7a')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_share_contains_all_export_locations_of_all_share_instances(self):
share_export_locations = self.admin_client.list_share_export_locations(
diff --git a/manila_tempest_tests/tests/api/admin/test_export_locations_negative.py b/manila_tempest_tests/tests/api/admin/test_export_locations_negative.py
index ef4f80b..065013d 100644
--- a/manila_tempest_tests/tests/api/admin/test_export_locations_negative.py
+++ b/manila_tempest_tests/tests/api/admin/test_export_locations_negative.py
@@ -14,6 +14,7 @@
# under the License.
from tempest import config
+from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
from testtools import testcase as tc
@@ -49,6 +50,7 @@
cls.share_instances = cls.admin_client.get_instances_of_share(
cls.share['id'])
+ @decorators.idempotent_id('8eac1355-f272-4913-8a49-1a8a9cb086bd')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_get_inexistent_share_export_location(self):
self.assertRaises(
@@ -58,6 +60,7 @@
"fake-inexistent-share-instance-id",
)
+ @decorators.idempotent_id('064a18dd-1a00-42f1-84c0-5a3e3b46fb39')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_get_inexistent_share_instance_export_location(self):
for share_instance in self.share_instances:
@@ -68,6 +71,7 @@
"fake-inexistent-share-instance-id",
)
+ @decorators.idempotent_id('6d0b9d1b-fc87-4b7f-add5-919b0ddcda90')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_list_share_instance_export_locations_as_member(self):
for share_instance in self.share_instances:
@@ -76,6 +80,7 @@
self.admin_member_client.list_share_instance_export_locations,
share_instance['id'])
+ @decorators.idempotent_id('abde4357-a26c-4adb-88a6-ece6b0e15b5e')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_get_share_instance_export_locations_as_member(self):
for share_instance in self.share_instances:
@@ -88,6 +93,7 @@
get_share_instance_export_location),
share_instance['id'], el['id'])
+ @decorators.idempotent_id('a3c3d16b-5f62-4089-8f86-efc660592986')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_list_share_export_locations_by_different_project_user(self):
self.assertRaises(
@@ -95,6 +101,7 @@
self.different_project_client.list_share_export_locations,
self.share['id'])
+ @decorators.idempotent_id('0f6823a5-3929-4025-9cd4-b5198b4384dd')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_get_share_export_location_by_different_project_user(self):
export_locations = self.admin_client.list_share_export_locations(
@@ -115,6 +122,7 @@
super(ExportLocationsAPIOnlyNegativeTest, cls).skip_checks()
utils.check_skip_if_microversion_lt("2.9")
+ @decorators.idempotent_id('4b5b4e89-0c80-4383-b272-62d5e0419d9a')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_get_export_locations_by_nonexistent_share(self):
self.assertRaises(
@@ -123,6 +131,7 @@
"fake-inexistent-share-id",
)
+ @decorators.idempotent_id('21ba5111-91a8-4ec3-86dc-689fc2fa90e6')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_get_export_locations_by_nonexistent_share_instance(self):
self.assertRaises(
diff --git a/manila_tempest_tests/tests/api/admin/test_migration.py b/manila_tempest_tests/tests/api/admin/test_migration.py
index 1bc67fb..25e7213 100644
--- a/manila_tempest_tests/tests/api/admin/test_migration.py
+++ b/manila_tempest_tests/tests/api/admin/test_migration.py
@@ -17,6 +17,7 @@
import ddt
from tempest import config
from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
import testtools
from testtools import testcase as tc
@@ -361,6 +362,7 @@
class MigrationCancelNFSTest(MigrationBase):
protocol = "nfs"
+ @decorators.idempotent_id('d39dfa1b-6e91-4efc-84f1-76f878b51f2a')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@base.skip_if_microversion_lt("2.29")
@ddt.data(True, False)
@@ -398,6 +400,7 @@
dest_pool, share, constants.TASK_STATE_MIGRATION_CANCELLED,
complete=False)
+ @decorators.idempotent_id('640dce56-2084-488d-8dea-456840ff397e')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@base.skip_if_microversion_lt("2.29")
@testtools.skipUnless(
@@ -433,24 +436,19 @@
class MigrationOppositeDriverModesNFSTest(MigrationBase):
protocol = "nfs"
+ @decorators.idempotent_id('d8cce50d-e8da-4fbc-8f94-0827bf277b6c')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@base.skip_if_microversion_lt("2.29")
@ddt.data(True, False)
def test_migration_opposite_driver_modes(self, force_host_assisted):
self._check_migration_enabled(force_host_assisted)
- share = self.create_share(self.protocol,
- share_type_id=self.share_type_id)
- share = self.shares_v2_client.get_share(share['id'])
- share, dest_pool = self._setup_migration(share, opposite=True)
-
if not CONF.share.multitenancy_enabled:
# If currently configured is DHSS=False,
# then we need it for DHSS=True
new_share_network_id = self.provide_share_network(
self.shares_v2_client,
self.networks_client,
- isolated_creds_client=None,
ignore_multitenancy_config=True,
)
else:
@@ -458,6 +456,12 @@
# then we must pass None for DHSS=False
new_share_network_id = None
+ share = self.create_share(self.protocol,
+ share_type_id=self.share_type_id,
+ cleanup_in_class=False)
+ share = self.shares_v2_client.get_share(share['id'])
+ share, dest_pool = self._setup_migration(share, opposite=True)
+
old_share_network_id = share['share_network_id']
old_share_type_id = share['share_type']
new_share_type_id = self.new_type_opposite['share_type']['id']
@@ -500,6 +504,7 @@
class MigrationTwoPhaseNFSTest(MigrationBase):
protocol = "nfs"
+ @decorators.idempotent_id('e6cf0e4d-bdf3-49c1-b6ba-56d1ad6c81d2')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@base.skip_if_microversion_lt("2.29")
@ddt.data(True, False)
@@ -551,6 +556,7 @@
class MigrationWithShareExtendingNFSTest(MigrationBase):
protocol = "nfs"
+ @decorators.idempotent_id('0e3d75e0-385a-4f7a-889f-2a3db79db8c2')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@base.skip_if_microversion_lt("2.29")
@testtools.skipUnless(
@@ -564,6 +570,7 @@
class MigrationWithShareShrinkingNFSTest(MigrationBase):
protocol = "nfs"
+ @decorators.idempotent_id('58c72e51-d217-48bc-8155-5a010912312e')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@base.skip_if_microversion_lt("2.29")
@testtools.skipUnless(
@@ -577,6 +584,7 @@
class MigrationOfShareWithSnapshotNFSTest(MigrationBase):
protocol = "nfs"
+ @decorators.idempotent_id('a95eb701-626a-4175-967b-4880d3716857')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@base.skip_if_microversion_lt("2.29")
@testtools.skipUnless(
@@ -618,6 +626,7 @@
class MigrationWithDifferentSnapshotSupportNFSTest(MigrationBase):
protocol = "nfs"
+ @decorators.idempotent_id('a18b3637-2070-4a1b-acd9-c392eb7963b5')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@base.skip_if_microversion_lt("2.29")
@testtools.skipUnless(CONF.share.run_snapshot_tests,
@@ -630,6 +639,7 @@
self._validate_share_migration_with_different_snapshot_capability_type(
force_host_assisted, True)
+ @decorators.idempotent_id('59313673-6576-4163-ab96-41bafcdad63a')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@base.skip_if_microversion_lt("2.29")
@testtools.skipUnless(CONF.share.run_snapshot_tests,
diff --git a/manila_tempest_tests/tests/api/admin/test_migration_negative.py b/manila_tempest_tests/tests/api/admin/test_migration_negative.py
index e8a22b6..12e3fb0 100644
--- a/manila_tempest_tests/tests/api/admin/test_migration_negative.py
+++ b/manila_tempest_tests/tests/api/admin/test_migration_negative.py
@@ -17,6 +17,7 @@
import ddt
from tempest import config
from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
import testtools
from testtools import testcase as tc
@@ -79,6 +80,7 @@
cleanup_in_class=True,
extra_specs=utils.get_configured_extra_specs(variation='invalid'))
+ @decorators.idempotent_id('8aa1f2a0-bc44-4df5-a556-161590e594a3')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@base.skip_if_microversion_lt("2.22")
def test_migration_cancel_invalid(self):
@@ -86,6 +88,7 @@
lib_exc.BadRequest, self.shares_v2_client.migration_cancel,
self.share['id'])
+ @decorators.idempotent_id('6d0dfb2e-51a0-4cb7-8c69-6135a49c6057')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@base.skip_if_microversion_lt("2.22")
def test_migration_get_progress_None(self):
@@ -96,6 +99,7 @@
lib_exc.BadRequest, self.shares_v2_client.migration_get_progress,
self.share['id'])
+ @decorators.idempotent_id('2ab1fc82-bc13-4c99-8324-c6b23530e8a4')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@base.skip_if_microversion_lt("2.22")
def test_migration_complete_invalid(self):
@@ -103,6 +107,7 @@
lib_exc.BadRequest, self.shares_v2_client.migration_complete,
self.share['id'])
+ @decorators.idempotent_id('8ef562b4-7704-4a78-973f-9bf8d2b6f6a6')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@base.skip_if_microversion_lt("2.22")
def test_migration_cancel_not_found(self):
@@ -110,6 +115,7 @@
lib_exc.NotFound, self.shares_v2_client.migration_cancel,
'invalid_share_id')
+ @decorators.idempotent_id('044c792b-63e0-42c3-9f44-dc2280e2af08')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@base.skip_if_microversion_lt("2.22")
def test_migration_get_progress_not_found(self):
@@ -117,6 +123,7 @@
lib_exc.NotFound, self.shares_v2_client.migration_get_progress,
'invalid_share_id')
+ @decorators.idempotent_id('a509871a-3f3a-4618-bb60-9661732dd371')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@base.skip_if_microversion_lt("2.22")
def test_migration_complete_not_found(self):
@@ -124,6 +131,7 @@
lib_exc.NotFound, self.shares_v2_client.migration_complete,
'invalid_share_id')
+ @decorators.idempotent_id('6276bea6-6939-4569-930f-218d99c0fa56')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@base.skip_if_microversion_lt("2.29")
@testtools.skipUnless(CONF.share.run_snapshot_tests,
@@ -138,6 +146,7 @@
self.shares_v2_client.wait_for_resource_deletion(snapshot_id=snap[
"id"])
+ @decorators.idempotent_id('78670c24-c4ee-45b5-b166-2d053c333144')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@base.skip_if_microversion_lt("2.29")
@ddt.data(True, False)
@@ -155,6 +164,7 @@
# NOTE(ganso): No need to assert, it is already waiting for correct
# status (migration_success).
+ @decorators.idempotent_id('af17204f-ffab-4ba8-8cb6-032e49216f67')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@base.skip_if_microversion_lt("2.29")
def test_migrate_share_host_invalid(self):
@@ -162,6 +172,7 @@
lib_exc.NotFound, self.shares_v2_client.migrate_share,
self.share['id'], 'invalid_host')
+ @decorators.idempotent_id('0558e9c4-0416-41d2-b28a-803d4b81521a')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@base.skip_if_microversion_lt("2.29")
@ddt.data({'writable': False, 'preserve_metadata': False,
@@ -183,6 +194,7 @@
preserve_metadata=preserve_metadata, nondisruptive=nondisruptive,
preserve_snapshots=preserve_snapshots)
+ @decorators.idempotent_id('ee57024c-d00e-4def-8eec-cbc62bae327f')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@base.skip_if_microversion_lt("2.29")
def test_migrate_share_change_type_no_valid_host(self):
@@ -201,6 +213,7 @@
self.share['id'], self.dest_pool,
constants.TASK_STATE_MIGRATION_ERROR)
+ @decorators.idempotent_id('e2bd0cca-c091-4785-a9dc-7f42d2bb95a5')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@base.skip_if_microversion_lt("2.29")
def test_migrate_share_not_found(self):
@@ -208,6 +221,7 @@
lib_exc.NotFound, self.shares_v2_client.migrate_share,
'invalid_share_id', self.dest_pool)
+ @decorators.idempotent_id('86b427a7-27c0-4cd5-8f52-9688b339980b')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@base.skip_if_microversion_lt("2.29")
def test_migrate_share_not_available(self):
@@ -223,6 +237,7 @@
self.shares_client.wait_for_share_status(self.share['id'],
constants.STATUS_AVAILABLE)
+ @decorators.idempotent_id('e8f1e491-697a-4941-bf51-4d37f0a93fa5')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@base.skip_if_microversion_lt("2.29")
def test_migrate_share_invalid_share_network(self):
@@ -231,6 +246,7 @@
self.share['id'], self.dest_pool,
new_share_network_id='invalid_net_id')
+ @decorators.idempotent_id('be262d44-2ca2-4b9c-be3a-5a6a98ed871b')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@base.skip_if_microversion_lt("2.29")
def test_migrate_share_invalid_share_type(self):
@@ -239,6 +255,7 @@
self.share['id'], self.dest_pool,
new_share_type_id='invalid_type_id')
+ @decorators.idempotent_id('16c72693-6f9e-4cb4-a166-c60accd3479b')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@base.skip_if_microversion_lt("2.29")
def test_migrate_share_opposite_type_share_network_invalid(self):
@@ -264,6 +281,7 @@
new_share_type_id=new_type_opposite['share_type']['id'],
new_share_network_id=new_share_network_id)
+ @decorators.idempotent_id('1f529b09-e404-4f0e-9423-bb4b117b5522')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@base.skip_if_microversion_lt("2.48")
def test_share_type_azs_share_migrate_unsupported_az(self):
@@ -277,6 +295,7 @@
self.share['id'], self.dest_pool,
new_share_type_id=new_share_type['share_type']['id'])
+ @decorators.idempotent_id('90cf0ae4-4251-4142-bfa8-41f67a9e5b23')
@testtools.skipUnless(CONF.share.run_driver_assisted_migration_tests,
"Driver-assisted migration tests are disabled.")
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@@ -284,6 +303,7 @@
def test_create_snapshot_during_share_migration(self):
self._test_share_actions_during_share_migration('create_snapshot', [])
+ @decorators.idempotent_id('20121039-bb11-45d8-9972-d2daff7a779c')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@base.skip_if_microversion_lt("2.29")
@ddt.data(('extend_share', [CONF.share.share_size + 2]),
@@ -301,6 +321,7 @@
if not property_to_evaluate[method_name]:
raise self.skipException(method_name + 'tests are disabled.')
+ @decorators.idempotent_id('6e83fc25-4e3e-49a7-93e8-db4e6b355a91')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@base.skip_if_microversion_lt("2.29")
def test_add_access_rule_during_migration(self):
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 79c9c19..cfa9baa 100644
--- a/manila_tempest_tests/tests/api/admin/test_multi_backend.py
+++ b/manila_tempest_tests/tests/api/admin/test_multi_backend.py
@@ -15,6 +15,7 @@
from tempest import config
from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
from testtools import testcase as tc
from manila_tempest_tests.tests.api import base
@@ -56,6 +57,7 @@
# Create shares using precreated share types
cls.shares = cls.create_shares(share_data_list)
+ @decorators.idempotent_id('888add9d-4ad0-4d88-a62f-af7ee1d9f9ab')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_share_backend_name_reporting(self):
# Share's 'host' should be like "hostname@backend_name"
@@ -63,6 +65,7 @@
get = self.shares_client.get_share(share['id'])
self.assertEqual(2, len(get["host"].split("@")))
+ @decorators.idempotent_id('691fbcef-6d8d-4ad9-b493-501bbb3dcf3c')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_share_share_type(self):
# Share type should be the same as provided with share creation
@@ -71,6 +74,7 @@
version="2.5")
self.assertEqual(self.sts[i]["name"], get["share_type"])
+ @decorators.idempotent_id('f25e0cb0-d656-4f16-a761-ec23992cd9e7')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_share_share_type_v_2_6(self):
# Share type should be the same as provided with share creation
@@ -80,6 +84,7 @@
self.assertEqual(self.sts[i]["id"], get["share_type"])
self.assertEqual(self.sts[i]["name"], get["share_type_name"])
+ @decorators.idempotent_id('bfa0c056-0a15-40e1-bdff-f1e10b95736c')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_share_backend_name_distinction(self):
# Different share backends should have different host records
diff --git a/manila_tempest_tests/tests/api/admin/test_quotas.py b/manila_tempest_tests/tests/api/admin/test_quotas.py
index 5dbab2a..25f43a4 100644
--- a/manila_tempest_tests/tests/api/admin/test_quotas.py
+++ b/manila_tempest_tests/tests/api/admin/test_quotas.py
@@ -16,6 +16,7 @@
import ddt
from tempest import config
from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
import testtools
from testtools import testcase as tc
@@ -39,15 +40,17 @@
msg = "Quota tests are disabled."
raise cls.skipException(msg)
super(SharesAdminQuotasTest, cls).resource_setup()
- cls.user_id = cls.shares_v2_client.user_id
- cls.tenant_id = cls.shares_v2_client.tenant_id
+ cls.client = cls.shares_v2_client
+ cls.user_id = cls.client.user_id
+ cls.tenant_id = cls.client.tenant_id
# create share type
cls.share_type = cls._create_share_type()
cls.share_type_id = cls.share_type['id']
+ @decorators.idempotent_id('f62c48e3-9736-4f0c-9f9b-f139f393ac0a')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_default_quotas(self):
- quotas = self.shares_v2_client.default_quotas(self.tenant_id)
+ quotas = self.client.default_quotas(self.tenant_id)
self.assertGreater(int(quotas["gigabytes"]), -2)
self.assertGreater(int(quotas["snapshot_gigabytes"]), -2)
self.assertGreater(int(quotas["shares"]), -2)
@@ -60,9 +63,10 @@
self.assertGreater(int(quotas["share_replicas"]), -2)
self.assertGreater(int(quotas["replica_gigabytes"]), -2)
+ @decorators.idempotent_id('1ff57cfa-cd8d-495f-86eb-9fead307428e')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_show_quotas(self):
- quotas = self.shares_v2_client.show_quotas(self.tenant_id)
+ quotas = self.client.show_quotas(self.tenant_id)
self.assertGreater(int(quotas["gigabytes"]), -2)
self.assertGreater(int(quotas["snapshot_gigabytes"]), -2)
self.assertGreater(int(quotas["shares"]), -2)
@@ -75,9 +79,10 @@
self.assertGreater(int(quotas["share_replicas"]), -2)
self.assertGreater(int(quotas["replica_gigabytes"]), -2)
+ @decorators.idempotent_id('9b96dd45-7c0d-41ee-88e4-600185f61358')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_show_quotas_for_user(self):
- quotas = self.shares_v2_client.show_quotas(
+ quotas = self.client.show_quotas(
self.tenant_id, self.user_id)
self.assertGreater(int(quotas["gigabytes"]), -2)
self.assertGreater(int(quotas["snapshot_gigabytes"]), -2)
@@ -91,30 +96,33 @@
self.assertGreater(int(quotas["share_replicas"]), -2)
self.assertGreater(int(quotas["replica_gigabytes"]), -2)
+ @decorators.idempotent_id('2e98a13e-b2ed-4977-bafe-47ea48b504f2')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@base.skip_if_microversion_not_supported(PRE_SHARE_GROUPS_MICROVERSION)
def test_show_sg_quotas_using_too_old_microversion(self):
- quotas = self.shares_v2_client.show_quotas(
+ quotas = self.client.show_quotas(
self.tenant_id, version=PRE_SHARE_GROUPS_MICROVERSION)
for key in ('share_groups', 'share_group_snapshots'):
self.assertNotIn(key, quotas)
+ @decorators.idempotent_id('b8bcbc04-68fb-4c8f-9f4c-a3b6c6b8911c')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@base.skip_if_microversion_not_supported(PRE_SHARE_GROUPS_MICROVERSION)
def test_show_sg_quotas_for_user_using_too_old_microversion(self):
- quotas = self.shares_v2_client.show_quotas(
+ quotas = self.client.show_quotas(
self.tenant_id, self.user_id,
version=PRE_SHARE_GROUPS_MICROVERSION)
for key in ('share_groups', 'share_group_snapshots'):
self.assertNotIn(key, quotas)
+ @decorators.idempotent_id('19fe431b-e83e-4c4e-acb8-018d7a470c8b')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@base.skip_if_microversion_not_supported(
PRE_SHARE_REPLICA_QUOTAS_MICROVERSION)
def test_show_replica_quotas_for_user_using_too_old_microversion(self):
- quotas = self.shares_v2_client.show_quotas(
+ quotas = self.client.show_quotas(
self.tenant_id, self.user_id,
version=PRE_SHARE_REPLICA_QUOTAS_MICROVERSION)
@@ -126,6 +134,7 @@
('name', False),
)
@ddt.unpack
+ @decorators.idempotent_id('836e1725-2853-4d54-b281-8173773d8527')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@base.skip_if_microversion_lt("2.39")
def test_show_share_type_quotas(self, share_type_key, is_st_public):
@@ -150,10 +159,10 @@
keys.append('replica_gigabytes')
# Get current project quotas
- p_quotas = self.shares_v2_client.show_quotas(self.tenant_id)
+ p_quotas = self.client.show_quotas(self.tenant_id)
- # Get current quotas
- st_quotas = self.shares_v2_client.show_quotas(
+ # Get current share type quotas
+ st_quotas = self.client.show_quotas(
self.tenant_id, share_type=share_type[share_type_key])
# Share type quotas have values equal to project's
@@ -169,13 +178,22 @@
@ddt.ddt
class SharesAdminQuotasUpdateTest(base.BaseSharesAdminTest):
+ # We want to force a fresh project for this test class, since we'll be
+ # manipulating project quotas - and any pre-existing projects may have
+ # resources, quotas and the like that might interfere with our test cases.
force_tenant_isolation = True
@classmethod
- def resource_setup(cls):
+ def skip_checks(cls):
+ super(SharesAdminQuotasUpdateTest, cls).skip_checks()
+ if not CONF.auth.use_dynamic_credentials:
+ raise cls.skipException('Dynamic credentials are required')
if not CONF.share.run_quota_tests:
msg = "Quota tests are disabled."
raise cls.skipException(msg)
+
+ @classmethod
+ def resource_setup(cls):
super(SharesAdminQuotasUpdateTest, cls).resource_setup()
# create share type
cls.share_type = cls._create_share_type()
@@ -183,13 +201,11 @@
# create share group type
cls.share_group_type = cls._create_share_group_type()
cls.share_group_type_id = cls.share_group_type['id']
+ cls.client = cls.shares_v2_client
+ cls.tenant_id = cls.client.tenant_id
+ cls.user_id = cls.client.user_id
- def setUp(self):
- super(self.__class__, self).setUp()
- self.client = self.get_client_with_isolated_creds(client_version='2')
- self.tenant_id = self.client.tenant_id
- self.user_id = self.client.user_id
-
+ @decorators.idempotent_id('da16e906-e8e6-4aa0-9fc1-76ed48cfd428')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_update_tenant_quota_shares(self):
# get current quotas
@@ -197,13 +213,15 @@
new_quota = int(quotas["shares"]) + 2
# set new quota for shares
- updated = self.client.update_quotas(self.tenant_id, shares=new_quota)
+ updated = self.update_quotas(self.tenant_id, shares=new_quota)
+
self.assertEqual(new_quota, int(updated["shares"]))
@ddt.data(
"share_groups",
"share_group_snapshots",
)
+ @decorators.idempotent_id('cb09de7e-94e9-401a-b82b-8b2de210f8b9')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@testtools.skipUnless(
CONF.share.run_share_group_tests, 'Share Group tests disabled.')
@@ -214,10 +232,11 @@
new_quota = int(quotas[quota_key]) + 2
# Set new quota
- updated = self.client.update_quotas(
- self.tenant_id, **{quota_key: new_quota})
+ updated = self.update_quotas(self.tenant_id, **{quota_key: new_quota})
+
self.assertEqual(new_quota, int(updated[quota_key]))
+ @decorators.idempotent_id('2c7f9e19-268d-4420-a046-a7faf21174a1')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_update_user_quota_shares(self):
# get current quotas
@@ -225,14 +244,17 @@
new_quota = int(quotas["shares"]) - 1
# set new quota for shares
- updated = self.client.update_quotas(
- self.tenant_id, self.user_id, shares=new_quota)
+ updated = self.update_quotas(self.tenant_id,
+ user_id=self.user_id,
+ shares=new_quota)
+
self.assertEqual(new_quota, int(updated["shares"]))
@ddt.data(
"share_groups",
"share_group_snapshots",
)
+ @decorators.idempotent_id('c32a716b-f971-4855-97ea-f30d4423d03d')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@testtools.skipUnless(
CONF.share.run_share_group_tests, 'Share Group tests disabled.')
@@ -243,8 +265,10 @@
new_quota = int(quotas[quota_key]) - 1
# Set new quota
- updated = self.client.update_quotas(
- self.tenant_id, self.user_id, **{quota_key: new_quota})
+ updated = self.update_quotas(self.tenant_id,
+ user_id=self.user_id,
+ **{quota_key: new_quota})
+
self.assertEqual(new_quota, int(updated[quota_key]))
@ddt.data(("share_replicas", False),
@@ -253,6 +277,7 @@
("replica_gigabytes", True),
)
@ddt.unpack
+ @decorators.idempotent_id('af16dc89-c93d-43de-8902-2c88c75f107f')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@base.skip_if_microversion_not_supported(SHARE_REPLICA_QUOTAS_MICROVERSION)
def test_update_user_quota_replica_related(self, quota_key, use_user_id):
@@ -268,8 +293,8 @@
kwargs.update({quota_key: new_quota})
# Set the new quota based on tenant or tenant and user_id
- updated = self.client.update_quotas(
- self.tenant_id, **kwargs)
+ updated = self.update_quotas(self.tenant_id, **kwargs)
+
self.assertEqual(new_quota, int(updated[quota_key]))
@ddt.data(
@@ -277,13 +302,14 @@
('name', False),
)
@ddt.unpack
+ @decorators.idempotent_id('155ea3de-b3b5-4aa0-be8b-eebcc19ce874')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@base.skip_if_microversion_lt("2.39")
def test_update_share_type_quota(self, share_type_key, is_st_public):
# Check if the used microversion supports 'share_replica' and
# 'replica_gigabytes' quotas
replica_quotas_supported = utils.share_replica_quotas_are_supported()
- share_type = self._create_share_type()
+ share_type = self._create_share_type(is_public=is_st_public)
# Get current quotas
quotas = self.client.show_quotas(
@@ -298,10 +324,14 @@
for q in quota_keys:
new_quota = int(quotas[q]) - 1
- # Set new quota
- updated = self.client.update_quotas(
- self.tenant_id, share_type=share_type[share_type_key],
- **{q: new_quota})
+ # Set new quota, cleanup isn't necessary, share type will be
+ # deleted when the test concludes, and that'll take care of
+ # share type quotas
+ updated = self.update_quotas(self.tenant_id,
+ share_type=share_type[share_type_key],
+ cleanup=False,
+ **{q: new_quota})
+
self.assertEqual(new_quota, int(updated[q]))
current_quotas = self.client.show_quotas(
@@ -310,6 +340,7 @@
for q in quota_keys:
self.assertEqual(int(quotas[q]) - 1, current_quotas[q])
+ @decorators.idempotent_id('78957d97-afad-4371-a21e-79641fff83f6')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_update_tenant_quota_snapshots(self):
# get current quotas
@@ -317,10 +348,11 @@
new_quota = int(quotas["snapshots"]) + 2
# set new quota for snapshots
- updated = self.client.update_quotas(
- self.tenant_id, snapshots=new_quota)
+ updated = self.update_quotas(self.tenant_id, snapshots=new_quota)
+
self.assertEqual(new_quota, int(updated["snapshots"]))
+ @decorators.idempotent_id('53f4fd79-39aa-42be-82ce-e423ebffe837')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_update_user_quota_snapshots(self):
# get current quotas
@@ -328,10 +360,13 @@
new_quota = int(quotas["snapshots"]) - 1
# set new quota for snapshots
- updated = self.client.update_quotas(
- self.tenant_id, self.user_id, snapshots=new_quota)
+ updated = self.update_quotas(self.tenant_id,
+ user_id=self.user_id,
+ snapshots=new_quota)
+
self.assertEqual(new_quota, int(updated["snapshots"]))
+ @decorators.idempotent_id('37ee5bd2-db07-4817-b71a-7c3e78634399')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_update_tenant_quota_gigabytes(self):
# get current quotas
@@ -341,10 +376,11 @@
gigabytes = int(custom["gigabytes"]) + 2
# set new quota for shares
- updated = self.client.update_quotas(
- self.tenant_id, gigabytes=gigabytes)
+ updated = self.update_quotas(self.tenant_id, gigabytes=gigabytes)
+
self.assertEqual(gigabytes, int(updated["gigabytes"]))
+ @decorators.idempotent_id('284a2e95-48a1-4f1b-b952-f734b1b6238a')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_update_tenant_quota_snapshot_gigabytes(self):
# get current quotas
@@ -354,12 +390,13 @@
snapshot_gigabytes = int(custom["snapshot_gigabytes"]) + 2
# set new quota for shares
- updated = self.client.update_quotas(
- self.tenant_id,
- snapshot_gigabytes=snapshot_gigabytes)
+ updated = self.update_quotas(self.tenant_id,
+ snapshot_gigabytes=snapshot_gigabytes)
+
self.assertEqual(snapshot_gigabytes,
int(updated["snapshot_gigabytes"]))
+ @decorators.idempotent_id('75977d53-f06b-41a2-8365-0ce549e4a51a')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_update_user_quota_gigabytes(self):
# get current quotas
@@ -369,10 +406,13 @@
gigabytes = int(custom["gigabytes"]) - 1
# set new quota for shares
- updated = self.client.update_quotas(
- self.tenant_id, self.user_id, gigabytes=gigabytes)
+ updated = self.update_quotas(self.tenant_id,
+ user_id=self.user_id,
+ gigabytes=gigabytes)
+
self.assertEqual(gigabytes, int(updated["gigabytes"]))
+ @decorators.idempotent_id('00a189fc-93ed-44c2-b9dc-1d9b6c26d005')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_update_user_quota_snapshot_gigabytes(self):
# get current quotas
@@ -382,12 +422,14 @@
snapshot_gigabytes = int(custom["snapshot_gigabytes"]) - 1
# set new quota for shares
- updated = self.client.update_quotas(
- self.tenant_id, self.user_id,
- snapshot_gigabytes=snapshot_gigabytes)
+ updated = self.update_quotas(self.tenant_id,
+ user_id=self.user_id,
+ snapshot_gigabytes=snapshot_gigabytes)
+
self.assertEqual(snapshot_gigabytes,
int(updated["snapshot_gigabytes"]))
+ @decorators.idempotent_id('da7f3179-f2f3-402e-82c2-e6855774a99a')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_update_tenant_quota_share_networks(self):
# get current quotas
@@ -395,10 +437,11 @@
new_quota = int(quotas["share_networks"]) + 2
# set new quota for share-networks
- updated = self.client.update_quotas(
- self.tenant_id, share_networks=new_quota)
+ updated = self.update_quotas(self.tenant_id, share_networks=new_quota)
+
self.assertEqual(new_quota, int(updated["share_networks"]))
+ @decorators.idempotent_id('f75f01a0-5921-44ab-b373-bb9e070f87eb')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_update_user_quota_share_networks(self):
# get current quotas
@@ -407,11 +450,13 @@
new_quota = int(quotas["share_networks"]) - 1
# set new quota for share-networks
- updated = self.client.update_quotas(
- self.tenant_id, self.user_id,
- share_networks=new_quota)
+ updated = self.update_quotas(self.tenant_id,
+ user_id=self.user_id,
+ share_networks=new_quota)
+
self.assertEqual(new_quota, int(updated["share_networks"]))
+ @decorators.idempotent_id('84e24c32-ee78-461e-ac1f-f9e4d99f88e2')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_reset_tenant_quotas(self):
# Get default_quotas
@@ -437,8 +482,8 @@
data["share_replicas"] = int(custom["share_replicas"]) + 2
data["replica_gigabytes"] = int(custom["replica_gigabytes"]) + 2
- # set new quota
- updated = self.client.update_quotas(self.tenant_id, **data)
+ # set new quota, turn off cleanup - we'll do it right below
+ updated = self.update_quotas(self.tenant_id, cleanup=False, **data)
self.assertEqual(data["shares"], int(updated["shares"]))
self.assertEqual(data["snapshots"], int(updated["snapshots"]))
self.assertEqual(data["gigabytes"], int(updated["gigabytes"]))
@@ -500,10 +545,11 @@
('name', False),
)
@ddt.unpack
+ @decorators.idempotent_id('15e57302-5a14-4be4-8720-95b639c2bfad')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@base.skip_if_microversion_lt("2.39")
def test_reset_share_type_quotas(self, share_type_key, is_st_public):
- share_type = self._create_share_type()
+ share_type = self._create_share_type(is_public=is_st_public)
quota_keys = ['shares', 'snapshots', 'gigabytes', 'snapshot_gigabytes']
# get default_quotas
@@ -519,8 +565,8 @@
quota_keys.append('share_replicas')
quota_keys.append('replica_gigabytes')
- # set new quota for project
- updated_p_quota = self.client.update_quotas(
+ # set new project quota
+ updated_p_quota = self.update_quotas(
self.tenant_id,
shares=int(default_quotas['shares']) + 5,
snapshots=int(default_quotas['snapshots']) + 5,
@@ -533,14 +579,15 @@
kwargs.update(self._get_new_replica_quota_values(
default_quotas, 3))
- # set new quota for project
- self.client.update_quotas(
+ # set share type quota for project, don't cleanup, we'll do that below
+ self.update_quotas(
self.tenant_id,
share_type=share_type[share_type_key],
shares=int(default_quotas['shares']) + 3,
snapshots=int(default_quotas['snapshots']) + 3,
gigabytes=int(default_quotas['gigabytes']) + 3,
snapshot_gigabytes=int(default_quotas['snapshot_gigabytes']) + 3,
+ cleanup=False,
**kwargs
)
@@ -559,172 +606,203 @@
self.assertNotEqual(default_quotas[key], current_st_quota[key])
self.assertEqual(current_p_quota[key], current_st_quota[key])
+ @decorators.idempotent_id('d4bba375-7111-4b93-b6dd-4f0532febc3e')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_unlimited_quota_for_shares(self):
- self.client.update_quotas(self.tenant_id, shares=-1)
+ self.update_quotas(self.tenant_id, shares=-1)
quotas = self.client.show_quotas(self.tenant_id)
self.assertEqual(-1, quotas.get('shares'))
+ @decorators.idempotent_id('756ffd0e-a476-49af-ac85-9bb4ce5e29b7')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_unlimited_user_quota_for_shares(self):
- self.client.update_quotas(
- self.tenant_id, self.user_id, shares=-1)
+ self.update_quotas(self.tenant_id, user_id=self.user_id, shares=-1)
quotas = self.client.show_quotas(self.tenant_id, self.user_id)
self.assertEqual(-1, quotas.get('shares'))
+ @decorators.idempotent_id('9779d166-09d3-4745-8acc-2243eadec3ea')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_unlimited_quota_for_snapshots(self):
- self.client.update_quotas(self.tenant_id, snapshots=-1)
+ self.update_quotas(self.tenant_id, snapshots=-1)
quotas = self.client.show_quotas(self.tenant_id)
self.assertEqual(-1, quotas.get('snapshots'))
+ @decorators.idempotent_id('245b3bf3-09ef-4b6d-8643-f156bf1bf23c')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_unlimited_user_quota_for_snapshots(self):
- self.client.update_quotas(
- self.tenant_id, self.user_id, snapshots=-1)
+ self.update_quotas(self.tenant_id, user_id=self.user_id, snapshots=-1)
quotas = self.client.show_quotas(self.tenant_id, self.user_id)
self.assertEqual(-1, quotas.get('snapshots'))
+ @decorators.idempotent_id('b6a94e87-091a-48dc-9b51-13d81541869c')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_unlimited_quota_for_gigabytes(self):
- self.client.update_quotas(self.tenant_id, gigabytes=-1)
+ self.update_quotas(self.tenant_id, gigabytes=-1)
quotas = self.client.show_quotas(self.tenant_id)
self.assertEqual(-1, quotas.get('gigabytes'))
+ @decorators.idempotent_id('0d044db4-ae5b-416d-aa51-098afb72cd6c')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_unlimited_quota_for_snapshot_gigabytes(self):
- self.client.update_quotas(
- self.tenant_id, snapshot_gigabytes=-1)
+ self.update_quotas(self.tenant_id, snapshot_gigabytes=-1)
quotas = self.client.show_quotas(self.tenant_id)
self.assertEqual(-1, quotas.get('snapshot_gigabytes'))
+ @decorators.idempotent_id('2de4b7cf-9189-413f-858b-860ecf5fd18b')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_unlimited_user_quota_for_gigabytes(self):
- self.client.update_quotas(
- self.tenant_id, self.user_id, gigabytes=-1)
+ self.update_quotas(self.tenant_id, user_id=self.user_id, gigabytes=-1)
quotas = self.client.show_quotas(self.tenant_id, self.user_id)
self.assertEqual(-1, quotas.get('gigabytes'))
+ @decorators.idempotent_id('cbe63027-1108-4779-9fd3-22f41f60d6bb')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_unlimited_user_quota_for_snapshot_gigabytes(self):
- self.client.update_quotas(
- self.tenant_id, self.user_id, snapshot_gigabytes=-1)
+ self.update_quotas(self.tenant_id,
+ user_id=self.user_id,
+ snapshot_gigabytes=-1)
quotas = self.client.show_quotas(self.tenant_id, self.user_id)
self.assertEqual(-1, quotas.get('snapshot_gigabytes'))
+ @decorators.idempotent_id('e35455f5-92db-4669-ac21-9daf170df248')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_unlimited_quota_for_share_networks(self):
- self.client.update_quotas(self.tenant_id, share_networks=-1)
+ self.update_quotas(self.tenant_id, share_networks=-1)
quotas = self.client.show_quotas(self.tenant_id)
self.assertEqual(-1, quotas.get('share_networks'))
+ @decorators.idempotent_id('66b04887-e611-4d4f-a40b-c8b14766b6af')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_unlimited_user_quota_for_share_networks(self):
- self.client.update_quotas(
- self.tenant_id, self.user_id, share_networks=-1)
+ self.update_quotas(self.tenant_id,
+ user_id=self.user_id,
+ share_networks=-1)
quotas = self.client.show_quotas(self.tenant_id, self.user_id)
self.assertEqual(-1, quotas.get('share_networks'))
+ @decorators.idempotent_id('7c2cd2d4-4352-4811-9e39-70f56e6297c2')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@testtools.skipUnless(
CONF.share.run_share_group_tests, 'Share Group tests disabled.')
@utils.skip_if_microversion_not_supported(SHARE_GROUPS_MICROVERSION)
def test_unlimited_quota_for_share_groups(self):
- self.client.update_quotas(self.tenant_id, share_groups=-1)
+ self.update_quotas(self.tenant_id, share_groups=-1)
quotas = self.client.show_quotas(self.tenant_id)
self.assertEqual(-1, quotas.get('share_groups'))
+ @decorators.idempotent_id('76d270d5-f314-47cb-9c3f-409f8ff12ce2')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@testtools.skipUnless(
CONF.share.run_share_group_tests, 'Share Group tests disabled.')
@utils.skip_if_microversion_not_supported(SHARE_GROUPS_MICROVERSION)
def test_unlimited_user_quota_for_share_group_snapshots(self):
- self.client.update_quotas(
- self.tenant_id, self.user_id, share_group_snapshots=-1)
+ self.update_quotas(self.tenant_id,
+ user_id=self.user_id,
+ share_group_snapshots=-1)
quotas = self.client.show_quotas(self.tenant_id, self.user_id)
self.assertEqual(-1, quotas.get('share_group_snapshots'))
@ddt.data("share_replicas", "replica_gigabytes")
+ @decorators.idempotent_id('15aa5df5-b2ae-4a3a-acb8-efbbc84581be')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@utils.skip_if_microversion_not_supported(
SHARE_REPLICA_QUOTAS_MICROVERSION)
def test_unlimited_quota_for_replica_quotas(self, quota_key):
kwargs = {quota_key: -1}
- self.client.update_quotas(self.tenant_id, **kwargs)
+ self.update_quotas(self.tenant_id, **kwargs)
quotas = self.client.show_quotas(self.tenant_id)
self.assertEqual(-1, quotas.get(quota_key))
@ddt.data("share_replicas", "replica_gigabytes")
+ @decorators.idempotent_id('84b99731-f748-44fe-a291-162d05da9e25')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@utils.skip_if_microversion_not_supported(
SHARE_REPLICA_QUOTAS_MICROVERSION)
def test_unlimited_user_quota_for_replica_quotas(self, quota_key):
kwargs = {quota_key: -1}
- self.client.update_quotas(self.tenant_id, self.user_id, **kwargs)
+ self.update_quotas(self.tenant_id, user_id=self.user_id, **kwargs)
quotas = self.client.show_quotas(self.tenant_id, self.user_id)
self.assertEqual(-1, quotas.get(quota_key))
@ddt.data(11, -1)
+ @decorators.idempotent_id('43f58705-3cad-46bc-816c-41e8fa55dd8d')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_update_user_quotas_bigger_than_project_quota(self, user_quota):
- self.client.update_quotas(self.tenant_id, shares=10)
- self.client.update_quotas(
- self.tenant_id, user_id=self.user_id, force=True,
- shares=user_quota)
+ self.update_quotas(self.tenant_id, shares=10)
+
+ self.update_quotas(self.tenant_id,
+ user_id=self.user_id,
+ force=True,
+ shares=user_quota)
@ddt.data(11, -1)
+ @decorators.idempotent_id('315cb76f-920d-4cb9-ac7d-16be8e95e1b2')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@base.skip_if_microversion_lt("2.39")
def test_update_share_type_quotas_bigger_than_project_quota(self, st_q):
share_type = self._create_share_type()
- self.client.update_quotas(self.tenant_id, shares=10)
- self.client.update_quotas(
- self.tenant_id, share_type=share_type['name'], force=True,
- shares=st_q)
+ self.update_quotas(self.tenant_id, shares=10)
+ # no need to cleanup share type quota, share type will be deleted at
+ # the end of the test
+ self.update_quotas(self.tenant_id,
+ share_type=share_type['name'],
+ force=True,
+ cleanup=False,
+ shares=st_q)
+
+ @decorators.idempotent_id('c95be1eb-6331-4c37-9fac-ed6c36270457')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@base.skip_if_microversion_lt("2.39")
def test_set_share_type_quota_bigger_than_users_quota(self):
share_type = self._create_share_type()
- self.client.update_quotas(self.tenant_id, force=False, shares=13)
- self.client.update_quotas(
- self.tenant_id, user_id=self.user_id, force=False, shares=11)
+
+ self.update_quotas(self.tenant_id, force=False, shares=13)
+
+ self.update_quotas(self.tenant_id,
+ user_id=self.user_id,
+ force=True,
+ shares=11)
# Share type quota does not depend on user's quota, so we should be
- # able to update it.
- self.client.update_quotas(
- self.tenant_id, share_type=share_type['name'], force=False,
- shares=12)
+ # able to update it. No need for cleanup, since the share type will
+ # be deleted when the test completes, cleaning up quotas and usages
+ self.update_quotas(self.tenant_id,
+ share_type=share_type['name'],
+ force=False,
+ cleanup=False,
+ shares=12)
+ @decorators.idempotent_id('4687eb25-17b3-4995-ace2-62f8bda29c57')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@base.skip_if_microversion_lt("2.39")
def test_quotas_usages(self):
@@ -733,12 +811,21 @@
for i in (1, 2))
# Set quotas for project, user and both share types
- self.client.update_quotas(self.tenant_id, shares=3, gigabytes=10)
- self.client.update_quotas(
- self.tenant_id, user_id=self.user_id, shares=2, gigabytes=7)
+ self.update_quotas(self.tenant_id, shares=3, gigabytes=10)
+
+ self.update_quotas(self.tenant_id,
+ user_id=self.user_id,
+ shares=2,
+ gigabytes=7)
+
for st in (st_1['id'], st_2['name']):
- self.client.update_quotas(
- self.tenant_id, share_type=st, shares=2, gigabytes=4)
+ # no need for cleanup, since share types will be deleted at the
+ # end of the test
+ self.update_quotas(self.tenant_id,
+ share_type=st,
+ shares=2,
+ gigabytes=4,
+ cleanup=False)
# Create share, 4Gb, st1 - ok
share_1 = self.create_share(
@@ -808,17 +895,21 @@
self._check_sgs_usages(p_quotas, sgs_in_use)
self._check_sgs_usages(u_quotas, sgs_in_use)
+ @decorators.idempotent_id('fe357398-12d4-4a63-b5ae-0d5091ba3442')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipUnless(
CONF.share.run_share_group_tests, 'Share Group tests disabled.')
@base.skip_if_microversion_lt(SHARE_GROUPS_MICROVERSION)
def test_share_group_quotas_usages(self):
# Set quotas for project (3 SG, 1 SGS) and user (2 SG, 1 SGS)
- self.client.update_quotas(
- self.tenant_id, share_groups=3, share_group_snapshots=1)
- self.client.update_quotas(
- self.tenant_id, user_id=self.user_id,
- share_groups=2, share_group_snapshots=1)
+ self.update_quotas(self.tenant_id,
+ share_groups=3,
+ share_group_snapshots=1)
+
+ self.update_quotas(self.tenant_id,
+ user_id=self.user_id,
+ share_groups=2,
+ share_group_snapshots=1)
# Check usages, they should be 0s
self._check_usages(0, 0)
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 ae5e227..e1e033f 100644
--- a/manila_tempest_tests/tests/api/admin/test_quotas_negative.py
+++ b/manila_tempest_tests/tests/api/admin/test_quotas_negative.py
@@ -14,13 +14,15 @@
# under the License.
import ddt
-import manila_tempest_tests.tests.api.test_replication_negative as rep_neg_test
from tempest import config
+from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
import testtools
from testtools import testcase as tc
from manila_tempest_tests.tests.api import base
+from manila_tempest_tests.tests.api import test_replication_negative as \
+ rep_neg_test
from manila_tempest_tests import utils
CONF = config.CONF
@@ -33,16 +35,26 @@
@ddt.ddt
class SharesAdminQuotasNegativeTest(base.BaseSharesAdminTest):
+ # We want to force some fresh projects for this test class, since we'll be
+ # manipulating project quotas - and any pre-existing projects may have
+ # resources, quotas and the like that might interfere with our test cases.
force_tenant_isolation = True
@classmethod
- def resource_setup(cls):
+ def skip_checks(cls):
+ super(SharesAdminQuotasNegativeTest, cls).skip_checks()
+ if not CONF.auth.use_dynamic_credentials:
+ raise cls.skipException('Dynamic credentials are required')
if not CONF.share.run_quota_tests:
msg = "Quota tests are disabled."
raise cls.skipException(msg)
+
+ @classmethod
+ def resource_setup(cls):
super(SharesAdminQuotasNegativeTest, cls).resource_setup()
- cls.user_id = cls.shares_client.user_id
- cls.tenant_id = cls.shares_client.tenant_id
+ cls.client = cls.shares_v2_client
+ cls.user_id = cls.client.user_id
+ cls.tenant_id = cls.client.tenant_id
# create share type
cls.share_type = cls._create_share_type()
cls.share_type_id = cls.share_type['id']
@@ -50,16 +62,17 @@
cls.share_group_type = cls._create_share_group_type()
cls.share_group_type_id = cls.share_group_type['id']
+ @decorators.idempotent_id('c7174059-7172-4cc8-9121-aefe509ef14c')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_get_quotas_with_empty_tenant_id(self):
self.assertRaises(lib_exc.NotFound,
- self.shares_client.show_quotas, "")
+ self.client.show_quotas, "")
+ @decorators.idempotent_id('0fbcbfad-fdb5-42d6-b005-041dc4ddea64')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_reset_quotas_with_empty_tenant_id(self):
- client = self.get_client_with_isolated_creds()
self.assertRaises(lib_exc.NotFound,
- client.reset_quotas, "")
+ self.client.reset_quotas, "")
@ddt.data(
{"shares": -2},
@@ -68,48 +81,50 @@
{"snapshot_gigabytes": -2},
{"share_networks": -2},
)
+ @decorators.idempotent_id('07d3e69a-7cda-4ca7-9fea-c32f6830fdd3')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_update_quota_with_wrong_data(self, kwargs):
# -1 is acceptable value as unlimited
- client = self.get_client_with_isolated_creds()
- self.assertRaises(
- lib_exc.BadRequest,
- client.update_quotas, client.tenant_id, **kwargs)
+ self.assertRaises(lib_exc.BadRequest,
+ self.update_quotas,
+ self.tenant_id,
+ **kwargs)
@ddt.data(
{"share_groups": -2},
{"share_group_snapshots": -2},
)
+ @decorators.idempotent_id('b11c5d5f-2b58-4a5f-8469-b22ea51709c0')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
@testtools.skipUnless(
CONF.share.run_share_group_tests, 'Share Group tests disabled.')
@utils.skip_if_microversion_not_supported(SHARE_GROUPS_MICROVERSION)
def test_update_sg_quota_with_wrong_data(self, kwargs):
# -1 is acceptable value as unlimited
- client = self.get_client_with_isolated_creds(client_version='2')
- self.assertRaises(
- lib_exc.BadRequest,
- client.update_quotas, client.tenant_id, **kwargs)
+ self.assertRaises(lib_exc.BadRequest,
+ self.update_quotas,
+ self.tenant_id,
+ **kwargs)
@ddt.data(
{"share_replicas": -2},
{"replica_gigabytes": -2},
)
+ @decorators.idempotent_id('d070ccc6-6685-4f49-a8e5-9b891790881e')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
@utils.skip_if_microversion_not_supported(
SHARE_REPLICA_QUOTAS_MICROVERSION)
def test_update_replica_quotas_wrong_data(self, kwargs):
# -1 is acceptable value as unlimited
+ self.assertRaises(lib_exc.BadRequest,
+ self.update_quotas,
+ self.tenant_id,
+ **kwargs)
- client = self.get_client_with_isolated_creds(client_version='2')
- self.assertRaises(
- lib_exc.BadRequest,
- client.update_quotas, client.tenant_id, **kwargs)
-
+ @decorators.idempotent_id('75d39eda-a2b5-4271-a61d-9e2c86370b3e')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_create_share_with_size_bigger_than_quota(self):
- quotas = self.shares_client.show_quotas(
- self.shares_client.tenant_id)
+ quotas = self.client.show_quotas(self.tenant_id)
overquota = int(quotas['gigabytes']) + 2
# try schedule share with size, bigger than gigabytes quota
@@ -117,120 +132,116 @@
self.create_share,
size=overquota)
+ @decorators.idempotent_id('37dd40a8-375e-454b-8b80-229cb0eecb01')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
@testtools.skipUnless(
CONF.share.run_share_group_tests, 'Share Group tests disabled.')
@utils.skip_if_microversion_not_supported(SHARE_GROUPS_MICROVERSION)
def test_create_share_group_with_exceeding_quota_limit(self):
- client = self.get_client_with_isolated_creds(client_version='2')
- client.update_quotas(client.tenant_id, share_groups=0)
+ self.update_quotas(self.tenant_id, share_groups=0)
# Try schedule share group creation
- self.assertRaises(
- lib_exc.OverLimit,
- self.create_share_group,
- share_group_type_id=self.share_group_type_id,
- share_type_ids=[self.share_type_id],
- client=client,
- cleanup_in_class=False)
+ self.assertRaises(lib_exc.OverLimit,
+ self.create_share_group,
+ share_group_type_id=self.share_group_type_id,
+ share_type_ids=[self.share_type_id],
+ cleanup_in_class=False)
+ @decorators.idempotent_id('e039535c-dc4e-497a-ac09-30b3395ba95b')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_set_user_quota_shares_bigger_than_tenant_quota(self):
- client = self.get_client_with_isolated_creds()
# get current quotas for tenant
- tenant_quotas = client.show_quotas(client.tenant_id)
+ tenant_quotas = self.client.show_quotas(self.tenant_id)
# try set user quota for shares bigger than tenant quota
bigger_value = int(tenant_quotas["shares"]) + 2
self.assertRaises(lib_exc.BadRequest,
- client.update_quotas,
- client.tenant_id,
- client.user_id,
+ self.update_quotas,
+ self.tenant_id,
+ user_id=self.user_id,
force=False,
shares=bigger_value)
+ @decorators.idempotent_id('57495588-d645-402e-9b89-0ab63a58ce3e')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_set_user_quota_snaps_bigger_than_tenant_quota(self):
- client = self.get_client_with_isolated_creds()
# get current quotas for tenant
- tenant_quotas = client.show_quotas(client.tenant_id)
+ tenant_quotas = self.client.show_quotas(self.tenant_id)
# try set user quota for snapshots bigger than tenant quota
bigger_value = int(tenant_quotas["snapshots"]) + 2
self.assertRaises(lib_exc.BadRequest,
- client.update_quotas,
- client.tenant_id,
- client.user_id,
+ self.update_quotas,
+ self.tenant_id,
+ user_id=self.user_id,
force=False,
snapshots=bigger_value)
+ @decorators.idempotent_id('6187050f-f262-48cf-bdd6-32982f860fba')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_set_user_quota_gigabytes_bigger_than_tenant_quota(self):
- client = self.get_client_with_isolated_creds()
# get current quotas for tenant
- tenant_quotas = client.show_quotas(client.tenant_id)
+ tenant_quotas = self.client.show_quotas(self.tenant_id)
# try set user quota for gigabytes bigger than tenant quota
bigger_value = int(tenant_quotas["gigabytes"]) + 2
self.assertRaises(lib_exc.BadRequest,
- client.update_quotas,
- client.tenant_id,
- client.user_id,
+ self.update_quotas,
+ self.tenant_id,
+ user_id=self.user_id,
force=False,
gigabytes=bigger_value)
+ @decorators.idempotent_id('8eb4aed8-c239-49d3-aee1-d63d043aa3d1')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_set_user_quota_snap_gigabytes_bigger_than_tenant_quota(self):
- client = self.get_client_with_isolated_creds()
-
# get current quotas for tenant
- tenant_quotas = client.show_quotas(client.tenant_id)
+ tenant_quotas = self.client.show_quotas(self.tenant_id)
# try set user quota for snapshot gigabytes bigger than tenant quota
bigger_value = int(tenant_quotas["snapshot_gigabytes"]) + 2
self.assertRaises(lib_exc.BadRequest,
- client.update_quotas,
- client.tenant_id,
- client.user_id,
+ self.update_quotas,
+ self.tenant_id,
+ user_id=self.user_id,
force=False,
snapshot_gigabytes=bigger_value)
+ @decorators.idempotent_id('a272a24b-21a6-4f6c-917c-cbe103203a11')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_set_user_quota_share_networks_bigger_than_tenant_quota(self):
- client = self.get_client_with_isolated_creds()
# get current quotas for tenant
- tenant_quotas = client.show_quotas(client.tenant_id)
+ tenant_quotas = self.client.show_quotas(self.tenant_id)
# try set user quota for share_networks bigger than tenant quota
bigger_value = int(tenant_quotas["share_networks"]) + 2
self.assertRaises(lib_exc.BadRequest,
- client.update_quotas,
- client.tenant_id,
- client.user_id,
+ self.update_quotas,
+ self.tenant_id,
+ user_id=self.user_id,
force=False,
share_networks=bigger_value)
@ddt.data("share_replicas", "replica_gigabytes")
+ @decorators.idempotent_id('40dabf7d-98da-48a9-bb62-285098d5acb4')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
@utils.skip_if_microversion_not_supported(
SHARE_REPLICA_QUOTAS_MICROVERSION)
def test_try_set_user_quota_replicas_bigger_than_tenant_quota(self, key):
- client = self.get_client_with_isolated_creds(client_version='2')
-
# get current quotas for tenant
- tenant_quotas = client.show_quotas(client.tenant_id)
+ tenant_quotas = self.client.show_quotas(self.tenant_id)
# try set user quota for snapshots bigger than tenant quota
bigger_value = int(tenant_quotas[key]) + 2
kwargs = {key: bigger_value}
self.assertRaises(lib_exc.BadRequest,
- client.update_quotas,
- client.tenant_id,
- client.user_id,
+ self.update_quotas,
+ self.tenant_id,
+ user_id=self.user_id,
force=False,
**kwargs)
@@ -249,174 +260,161 @@
('os-quota-sets', '2.7', 'update_quotas'),
)
@ddt.unpack
+ @decorators.idempotent_id('ed38ab0a-694c-48ea-bce5-5c264f485d5b')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
@base.skip_if_microversion_not_supported("2.7")
def test_show_quotas_with_wrong_versions(self, url, version, method_name):
- self.assertRaises(
- lib_exc.NotFound,
- getattr(self.shares_v2_client, method_name),
- self.shares_v2_client.tenant_id,
- version=version, url=url,
- )
+ self.assertRaises(lib_exc.NotFound,
+ getattr(self.client, method_name),
+ self.tenant_id,
+ version=version,
+ url=url)
+ @decorators.idempotent_id('50af5d8c-0b30-4e8d-93bf-bb975db58516')
@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,
- )
+ self.assertRaises(lib_exc.NotFound,
+ self.client.detail_quotas,
+ self.tenant_id,
+ version=version,
+ url=url)
@ddt.data('show', 'reset', 'update')
+ @decorators.idempotent_id('cf45eb7d-7330-4b2d-8214-e4149eb4a398')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
@base.skip_if_microversion_lt("2.39")
def test_share_type_quotas_using_nonexistent_share_type(self, op):
- client = self.get_client_with_isolated_creds(client_version='2')
kwargs = {"share_type": "fake_nonexistent_share_type"}
if op == 'update':
- tenant_quotas = client.show_quotas(client.tenant_id)
+ tenant_quotas = self.client.show_quotas(self.tenant_id)
kwargs['shares'] = tenant_quotas['shares']
- self.assertRaises(
- lib_exc.NotFound,
- getattr(client, op + '_quotas'),
- client.tenant_id,
- **kwargs)
+ self.assertRaises(lib_exc.NotFound,
+ getattr(self.client, op + '_quotas'),
+ self.tenant_id,
+ **kwargs)
@ddt.data('id', 'name')
+ @decorators.idempotent_id('2ba641a1-100b-417e-80e2-d3f717fd3c7c')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
@base.skip_if_microversion_lt("2.39")
def test_try_update_share_type_quota_for_share_networks(self, key):
- client = self.get_client_with_isolated_creds(client_version='2')
share_type = self._create_share_type()
- tenant_quotas = client.show_quotas(client.tenant_id)
+ tenant_quotas = self.client.show_quotas(self.tenant_id)
# Try to set 'share_networks' quota for share type
- self.assertRaises(
- lib_exc.BadRequest,
- client.update_quotas,
- client.tenant_id,
- share_type=share_type[key],
- share_networks=int(tenant_quotas["share_networks"]),
- )
+ self.assertRaises(lib_exc.BadRequest,
+ self.update_quotas,
+ self.tenant_id,
+ share_type=share_type[key],
+ share_networks=int(tenant_quotas["share_networks"]))
@ddt.data('share_groups', 'share_group_snapshots')
+ @decorators.idempotent_id('5eb6ce15-1172-4bcb-9c7b-91543bf714e8')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
@base.skip_if_microversion_lt(SHARE_GROUPS_MICROVERSION)
def test_try_update_share_type_quota_for_share_groups(self, quota_name):
- client = self.get_client_with_isolated_creds(client_version='2')
share_type = self._create_share_type()
- tenant_quotas = client.show_quotas(client.tenant_id)
+ tenant_quotas = self.client.show_quotas(self.tenant_id)
- self.assertRaises(
- lib_exc.BadRequest,
- client.update_quotas,
- client.tenant_id,
- share_type=share_type["name"],
- **{quota_name: int(tenant_quotas[quota_name])}
- )
+ self.assertRaises(lib_exc.BadRequest,
+ self.update_quotas,
+ self.tenant_id,
+ share_type=share_type["name"],
+ **{quota_name: int(tenant_quotas[quota_name])})
@ddt.data('share_groups', 'share_group_snapshots')
+ @decorators.idempotent_id('1b504c74-2ce9-40f6-87fb-9e643b1b5906')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
@base.skip_if_microversion_not_supported(PRE_SHARE_GROUPS_MICROVERSION)
@base.skip_if_microversion_not_supported(SHARE_GROUPS_MICROVERSION)
def test_share_group_quotas_using_too_old_microversion(self, quota_key):
- client = self.get_client_with_isolated_creds(client_version='2')
- tenant_quotas = client.show_quotas(
- client.tenant_id, version=SHARE_GROUPS_MICROVERSION)
+ tenant_quotas = self.client.show_quotas(
+ self.tenant_id, version=SHARE_GROUPS_MICROVERSION)
kwargs = {
"version": PRE_SHARE_GROUPS_MICROVERSION,
quota_key: tenant_quotas[quota_key],
}
- self.assertRaises(
- lib_exc.BadRequest,
- client.update_quotas,
- client.tenant_id,
- **kwargs)
+ self.assertRaises(lib_exc.BadRequest,
+ self.client.update_quotas,
+ self.tenant_id,
+ **kwargs)
@ddt.data("share_replicas", "replica_gigabytes")
+ @decorators.idempotent_id('66f22d42-37bc-4f9b-8e0b-a679341e1e88')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
@base.skip_if_microversion_not_supported(SHARE_REPLICA_QUOTAS_MICROVERSION)
def test_share_replica_quotas_using_too_old_microversion(self, quota_key):
- client = self.get_client_with_isolated_creds(client_version='2')
- tenant_quotas = client.show_quotas(
- client.tenant_id, version=SHARE_REPLICA_QUOTAS_MICROVERSION)
+ tenant_quotas = self.client.show_quotas(
+ self.tenant_id, version=SHARE_REPLICA_QUOTAS_MICROVERSION)
kwargs = {
"version": PRE_SHARE_REPLICA_QUOTAS_MICROVERSION,
quota_key: tenant_quotas[quota_key],
}
- self.assertRaises(
- lib_exc.BadRequest,
- client.update_quotas,
- client.tenant_id,
- **kwargs)
+ self.assertRaises(lib_exc.BadRequest,
+ self.update_quotas,
+ self.tenant_id,
+ **kwargs)
@ddt.data('show', 'reset', 'update')
+ @decorators.idempotent_id('acc609c2-f314-4540-984c-33e93d048f6c')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
@base.skip_if_microversion_lt("2.38")
def test_share_type_quotas_using_too_old_microversion(self, op):
- client = self.get_client_with_isolated_creds(client_version='2')
share_type = self._create_share_type()
kwargs = {"version": "2.38", "share_type": share_type["name"]}
if op == 'update':
- tenant_quotas = client.show_quotas(client.tenant_id)
+ tenant_quotas = self.client.show_quotas(self.tenant_id)
kwargs['shares'] = tenant_quotas['shares']
- self.assertRaises(
- lib_exc.BadRequest,
- getattr(client, op + '_quotas'),
- client.tenant_id,
- **kwargs)
+ self.assertRaises(lib_exc.BadRequest,
+ getattr(self.client, op + '_quotas'),
+ self.tenant_id,
+ **kwargs)
@ddt.data('show', 'reset', 'update')
+ @decorators.idempotent_id('719768d1-d313-40e9-9127-c5777840ecbd')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
@base.skip_if_microversion_lt("2.39")
def test_quotas_providing_share_type_and_user_id(self, op):
- client = self.get_client_with_isolated_creds(client_version='2')
share_type = self._create_share_type()
- kwargs = {"share_type": share_type["name"], "user_id": client.user_id}
+ kwargs = {"share_type": share_type["name"], "user_id": self.user_id}
if op == 'update':
- tenant_quotas = client.show_quotas(client.tenant_id)
+ tenant_quotas = self.client.show_quotas(self.tenant_id)
kwargs['shares'] = tenant_quotas['shares']
- self.assertRaises(
- lib_exc.BadRequest,
- getattr(client, op + '_quotas'),
- client.tenant_id,
- **kwargs)
+ self.assertRaises(lib_exc.BadRequest,
+ getattr(self.client, op + '_quotas'),
+ self.tenant_id,
+ **kwargs)
@ddt.data(11, -1)
+ @decorators.idempotent_id('82256511-aa46-4b99-a6e5-8b400534e96d')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
@base.skip_if_microversion_lt("2.39")
def test_update_share_type_quotas_bigger_than_project_quota(self, st_q):
- client = self.get_client_with_isolated_creds(client_version='2')
share_type = self._create_share_type()
- client.update_quotas(client.tenant_id, shares=10)
+ self.update_quotas(self.tenant_id, shares=10)
- self.assertRaises(
- lib_exc.BadRequest,
- client.update_quotas,
- client.tenant_id,
- share_type=share_type['name'],
- force=False,
- shares=st_q)
+ self.assertRaises(lib_exc.BadRequest,
+ self.update_quotas,
+ self.tenant_id,
+ share_type=share_type['name'],
+ force=False,
+ shares=st_q)
+ @decorators.idempotent_id('6396daab-ba73-4140-8a0a-8eef0a01804d')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_create_share_over_quota_limit(self):
- original_quota = self.shares_v2_client.show_quotas(
- self.tenant_id)
self.create_share(share_type_id=self.share_type_id)
- self.shares_v2_client.update_quotas(self.tenant_id, shares=1)
- updated_quota = self.shares_v2_client.show_quotas(self.tenant_id)
- self.addCleanup(self.shares_v2_client.update_quotas,
- self.tenant_id, shares=original_quota['shares'])
+
+ updated_quota = self.update_quotas(self.tenant_id, shares=1)
self.assertEqual(1, updated_quota['shares'])
self.assertRaises(lib_exc.OverLimit,
@@ -427,36 +425,41 @@
@ddt.ddt
class ReplicaQuotasNegativeTest(rep_neg_test.ReplicationNegativeBase):
+ # We want to force some fresh projects for this test class, since we'll be
+ # manipulating project quotas - and any pre-existing projects may have
+ # resources, quotas and the like that might interfere with our test cases.
+ force_tenant_isolation = True
+
+ @classmethod
+ def resource_setup(cls):
+ super(ReplicaQuotasNegativeTest, cls).resource_setup()
+ cls.client = cls.shares_v2_client
+ cls.user_id = cls.client.user_id
+ cls.tenant_id = cls.client.tenant_id
+
@classmethod
def skip_checks(cls):
super(ReplicaQuotasNegativeTest, cls).skip_checks()
+ if not CONF.auth.use_dynamic_credentials:
+ raise cls.skipException('Dynamic credentials are required')
if not CONF.share.run_quota_tests:
msg = "Quota tests are disabled."
raise cls.skipException(msg)
-
utils.check_skip_if_microversion_lt(SHARE_REPLICA_QUOTAS_MICROVERSION)
def _modify_quotas_for_test(self, quota_key, new_limit):
kwargs = {quota_key: new_limit}
- # Get the original quota values
- original_quota = self.admin_client.show_quotas(self.tenant_id)
-
# Update the current quotas
- self.admin_client.update_quotas(self.tenant_id, **kwargs)
-
- # Save the previous value
- old_quota_values = {quota_key: original_quota[quota_key]}
+ self.update_quotas(self.tenant_id, client=self.admin_client, **kwargs)
# Get the updated quotas and add a cleanup
updated_quota = self.admin_client.show_quotas(self.tenant_id)
- self.addCleanup(self.admin_client.update_quotas,
- self.tenant_id,
- **old_quota_values)
# Make sure that the new value was properly set
self.assertEqual(new_limit, updated_quota[quota_key])
+ @decorators.idempotent_id('ad19eaa5-bacd-4bc5-9592-622b0c856cdd')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@ddt.data(('share_replicas', 2), ('replica_gigabytes', None))
@ddt.unpack
@@ -478,6 +481,7 @@
self.share1['id'],
availability_zone=self.replica_zone)
+ @decorators.idempotent_id('0006f1ff-69c0-40b7-8437-55cc0a08a195')
@testtools.skipUnless(
CONF.share.run_extend_tests,
"Share extend tests are disabled.")
@@ -493,6 +497,6 @@
# Make sure that the request to create a third one will fail
self.assertRaises(lib_exc.OverLimit,
- self.shares_v2_client.extend_share,
+ self.client.extend_share,
self.share1['id'],
new_size)
diff --git a/manila_tempest_tests/tests/api/admin/test_replication.py b/manila_tempest_tests/tests/api/admin/test_replication.py
index 60f97a7..a7bbad2 100644
--- a/manila_tempest_tests/tests/api/admin/test_replication.py
+++ b/manila_tempest_tests/tests/api/admin/test_replication.py
@@ -13,7 +13,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+import ddt
from tempest import config
+from tempest.lib import decorators
from testtools import testcase as tc
from manila_tempest_tests.common import constants
@@ -23,8 +25,10 @@
CONF = config.CONF
_MIN_SUPPORTED_MICROVERSION = '2.11'
+LATEST_MICROVERSION = CONF.share.max_api_microversion
+@ddt.ddt
class ReplicationAdminTest(base.BaseSharesMixedTest):
@classmethod
@@ -50,7 +54,7 @@
)
extra_specs = {"replication_type": cls.replication_type}
- cls.share_type = cls._create_share_type(extra_specs)
+ cls.share_type = cls._create_share_type(specs=extra_specs)
cls.share_type_id = cls.share_type['id']
cls.sn_id = None
if cls.multitenancy_enabled:
@@ -77,9 +81,15 @@
return [replica['id'] for replica in replica_list
if replica['replica_state'] == r_state]
+ @decorators.idempotent_id('0213cdfd-6a0f-4f24-a154-69796888a64a')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
- def test_promote_out_of_sync_share_replica(self):
+ @ddt.data(
+ *set([constants.MIN_SHARE_REPLICATION_VERSION,
+ constants.SHARE_REPLICA_GRADUATION_VERSION,
+ LATEST_MICROVERSION]))
+ def test_promote_out_of_sync_share_replica(self, version):
"""Test promote 'out_of_sync' share replica to active state."""
+ self.skip_if_microversion_not_supported(version)
if (self.replication_type
not in constants.REPLICATION_PROMOTION_CHOICES):
msg = "Option backend_replication_type should be one of (%s)!"
@@ -89,13 +99,13 @@
share_type_id=self.share_type_id, client=self.admin_client,
availability_zone=self.share_zone, share_network_id=self.sn_id)
original_replica = self.admin_client.list_share_replicas(
- share_id=share['id'])[0]
+ share_id=share['id'], version=version)[0]
# NOTE(Yogi1): Cleanup needs to be disabled for replica that is
# being promoted since it will become the 'primary'/'active' replica.
replica = self.create_share_replica(
share["id"], self.replica_zone, cleanup=False,
- client=self.admin_client)
+ client=self.admin_client, version=version)
# Wait for replica state to update after creation
self.admin_client.wait_for_share_replica_status(
replica['id'], constants.REPLICATION_STATE_IN_SYNC,
@@ -103,7 +113,7 @@
# List replicas
replica_list = self.admin_client.list_share_replicas(
- share_id=share['id'])
+ share_id=share['id'], version=version)
# Check if there is only 1 'active' replica before promotion.
active_replicas = self._filter_share_replica_list(
@@ -112,82 +122,116 @@
# Set replica_state to 'out_of_sync'
self.admin_client.reset_share_replica_state(
- replica['id'], constants.REPLICATION_STATE_OUT_OF_SYNC)
+ replica['id'], constants.REPLICATION_STATE_OUT_OF_SYNC,
+ version=version)
self.admin_client.wait_for_share_replica_status(
replica['id'], constants.REPLICATION_STATE_OUT_OF_SYNC,
status_attr='replica_state')
# Promote 'out_of_sync' replica to 'active' state.
- self.promote_share_replica(replica['id'], self.admin_client)
+ self.promote_share_replica(replica['id'], self.admin_client,
+ version=version)
# Original replica will need to be cleaned up before the promoted
# replica can be deleted.
self.addCleanup(self.delete_share_replica, original_replica['id'])
# Check if there is still only 1 'active' replica after promotion.
replica_list = self.admin_client.list_share_replicas(
- share_id=self.share["id"])
+ share_id=self.share["id"], version=version)
new_active_replicas = self._filter_share_replica_list(
replica_list, constants.REPLICATION_STATE_ACTIVE)
self.assertEqual(1, len(new_active_replicas))
+ @decorators.idempotent_id('22a199b7-f4f6-4ede-b09f-8047a9d01cad')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
- def test_force_delete_share_replica(self):
+ @ddt.data(
+ *set([constants.MIN_SHARE_REPLICATION_VERSION,
+ constants.SHARE_REPLICA_GRADUATION_VERSION,
+ LATEST_MICROVERSION]))
+ def test_force_delete_share_replica(self, version):
"""Test force deleting a replica that is in 'error_deleting' status."""
+ self.skip_if_microversion_not_supported(version)
replica = self.create_share_replica(self.share['id'],
self.replica_zone,
cleanup_in_class=False,
- client=self.admin_client)
+ client=self.admin_client,
+ version=version)
self.admin_client.reset_share_replica_status(
- replica['id'], constants.STATUS_ERROR_DELETING)
+ replica['id'], constants.STATUS_ERROR_DELETING, version=version)
self.admin_client.wait_for_share_replica_status(
replica['id'], constants.STATUS_ERROR_DELETING)
- self.admin_client.force_delete_share_replica(replica['id'])
+ self.admin_client.force_delete_share_replica(replica['id'],
+ version=version)
self.admin_client.wait_for_resource_deletion(replica_id=replica['id'])
+ @decorators.idempotent_id('16bd90f0-c478-4a99-8633-b18703ff56fa')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
- def test_reset_share_replica_status(self):
+ @ddt.data(
+ *set([constants.MIN_SHARE_REPLICATION_VERSION,
+ constants.SHARE_REPLICA_GRADUATION_VERSION,
+ LATEST_MICROVERSION]))
+ def test_reset_share_replica_status(self, version):
"""Test resetting a replica's 'status' attribute."""
+ self.skip_if_microversion_not_supported(version)
replica = self.create_share_replica(self.share['id'],
self.replica_zone,
cleanup_in_class=False,
- client=self.admin_client)
+ client=self.admin_client,
+ version=version)
self.admin_client.reset_share_replica_status(replica['id'],
- constants.STATUS_ERROR)
+ constants.STATUS_ERROR,
+ version=version)
self.admin_client.wait_for_share_replica_status(
replica['id'], constants.STATUS_ERROR)
+ @decorators.idempotent_id('258844da-a853-42b6-87db-b16e616018c6')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
- def test_reset_share_replica_state(self):
+ @ddt.data(
+ *set([constants.MIN_SHARE_REPLICATION_VERSION,
+ constants.SHARE_REPLICA_GRADUATION_VERSION,
+ LATEST_MICROVERSION]))
+ def test_reset_share_replica_state(self, version):
"""Test resetting a replica's 'replica_state' attribute."""
+ self.skip_if_microversion_not_supported(version)
replica = self.create_share_replica(self.share['id'],
self.replica_zone,
cleanup_in_class=False,
- client=self.admin_client)
+ client=self.admin_client,
+ version=version)
self.admin_client.reset_share_replica_state(replica['id'],
- constants.STATUS_ERROR)
+ constants.STATUS_ERROR,
+ version=version)
self.admin_client.wait_for_share_replica_status(
replica['id'], constants.STATUS_ERROR, status_attr='replica_state')
+ @decorators.idempotent_id('2969565a-85e8-4c61-9dfb-cc7f7ca9f6dd')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
- def test_resync_share_replica(self):
+ @ddt.data(
+ *set([constants.MIN_SHARE_REPLICATION_VERSION,
+ constants.SHARE_REPLICA_GRADUATION_VERSION,
+ LATEST_MICROVERSION]))
+ def test_resync_share_replica(self, version):
"""Test resyncing a replica."""
+ self.skip_if_microversion_not_supported(version)
replica = self.create_share_replica(self.share['id'],
self.replica_zone,
cleanup_in_class=False,
- client=self.admin_client)
+ client=self.admin_client,
+ version=version)
self.admin_client.wait_for_share_replica_status(
replica['id'], constants.REPLICATION_STATE_IN_SYNC,
status_attr='replica_state')
# Set replica_state to 'out_of_sync'.
self.admin_client.reset_share_replica_state(
- replica['id'], constants.REPLICATION_STATE_OUT_OF_SYNC)
+ replica['id'], constants.REPLICATION_STATE_OUT_OF_SYNC,
+ version=version)
self.admin_client.wait_for_share_replica_status(
replica['id'], constants.REPLICATION_STATE_OUT_OF_SYNC,
status_attr='replica_state')
# Attempt resync
- self.admin_client.resync_share_replica(replica['id'])
+ self.admin_client.resync_share_replica(replica['id'], version=version)
self.admin_client.wait_for_share_replica_status(
replica['id'], constants.REPLICATION_STATE_IN_SYNC,
status_attr='replica_state')
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 8264798..5ceb818 100644
--- a/manila_tempest_tests/tests/api/admin/test_replication_actions.py
+++ b/manila_tempest_tests/tests/api/admin/test_replication_actions.py
@@ -11,6 +11,7 @@
# under the License.
from tempest import config
+from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
import testtools
from testtools import testcase as tc
@@ -53,7 +54,7 @@
# create share type
extra_specs = {"replication_type": cls.replication_type}
- cls.share_type = cls._create_share_type(extra_specs)
+ cls.share_type = cls._create_share_type(specs=extra_specs)
cls.share_type_id = cls.share_type['id']
cls.sn_id = None
@@ -76,6 +77,7 @@
cls.replica = cls.admin_client.list_share_replicas(
share_id=cls.share['id'])[0]
+ @decorators.idempotent_id('b39f319e-2515-42c0-85c4-21c2fb2123bf')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipUnless(CONF.share.run_extend_tests,
'Extend share tests are disabled.')
@@ -88,6 +90,7 @@
share = self.admin_client.get_share(self.share["id"])
self.assertEqual(new_size, int(share["size"]))
+ @decorators.idempotent_id('743bfb8e-a314-4e8e-92b5-079bd3eae72d')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipUnless(CONF.share.run_shrink_tests,
'Shrink share tests are disabled.')
@@ -99,6 +102,7 @@
shrink_share = self.admin_client.get_share(self.share["id"])
self.assertEqual(new_size, int(shrink_share["size"]))
+ @decorators.idempotent_id('84150cd6-2777-4806-8aa3-51359f16816e')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@testtools.skipUnless(CONF.share.run_manage_unmanage_tests,
'Manage/Unmanage Tests are disabled.')
@@ -135,6 +139,7 @@
self.create_share_replica(managed_share['id'], self.replica_zone,
cleanup=True, client=self.admin_client)
+ @decorators.idempotent_id('cbbe2650-47bb-456b-8b41-74c66270ea97')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipUnless(CONF.share.run_manage_unmanage_tests,
'Manage/Unmanage Tests are disabled.')
@@ -148,6 +153,7 @@
self.admin_client.unmanage_share,
share_id=self.share['id'])
+ @decorators.idempotent_id('796fb2a8-1ac3-4eee-b12e-da511eb52e87')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@testtools.skipUnless(CONF.share.run_manage_unmanage_tests,
'Manage/Unmanage Tests are disabled.')
@@ -161,6 +167,7 @@
self.admin_client.unmanage_share(share['id'])
self.admin_client.wait_for_resource_deletion(share_id=share['id'])
+ @decorators.idempotent_id('93220873-c6c4-40f7-840d-d0ff02e7cd7e')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipUnless(CONF.share.run_manage_unmanage_snapshot_tests,
'Manage/Unmanage Snapshot Tests are disabled.')
@@ -176,6 +183,7 @@
provider_location="127.0.0.1:/fake_provider_location/"
"manila_share_9dc61f49_fbc8_48d7_9337_2f9593d9")
+ @decorators.idempotent_id('0b0cd350-8691-477b-adb1-5e79b92e3759')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipUnless(CONF.share.run_manage_unmanage_snapshot_tests,
'Manage/Unmanage Snapshot Tests are disabled.')
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 6adf9c8..1d0b873 100644
--- a/manila_tempest_tests/tests/api/admin/test_scheduler_stats.py
+++ b/manila_tempest_tests/tests/api/admin/test_scheduler_stats.py
@@ -15,6 +15,7 @@
import ddt
from tempest import config
from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
from testtools import testcase as tc
from manila_tempest_tests.tests.api import base
@@ -45,6 +46,7 @@
super(SchedulerStatsAdminTest, cls).resource_setup()
cls.admin_client = cls.shares_v2_client
+ @decorators.idempotent_id('dab6d654-7d1c-4bc0-8017-1c4c072b49a1')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_pool_list(self):
@@ -58,6 +60,7 @@
actual_keys = set(pool.keys())
self.assertTrue(actual_keys.issuperset(required_keys))
+ @decorators.idempotent_id('8f4582c4-df82-4b64-be79-a8c6fdc58eac')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_pool_list_with_filters(self):
@@ -87,6 +90,7 @@
for k, v in search_opts.items():
self.assertEqual(v[1:-1], filtered_pool_list[0][k])
+ @decorators.idempotent_id('1c2f1b0f-c509-4676-8335-bb6b10debea2')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_pool_list_with_filters_negative(self):
@@ -103,6 +107,7 @@
# Ensure we got no pools
self.assertEmpty(pool_list)
+ @decorators.idempotent_id('b6fdd156-3923-495a-ab01-f94bfb5d7040')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_pool_list_detail(self):
@@ -116,6 +121,7 @@
actual_keys = set(pool.keys())
self.assertTrue(actual_keys.issuperset(required_keys))
+ @decorators.idempotent_id('071a1e47-959e-47df-ad19-335064bb25ff')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_pool_list_detail_with_filters(self):
@@ -145,6 +151,7 @@
for k, v in search_opts.items():
self.assertEqual(v[1:-1], filtered_pool_list[0][k])
+ @decorators.idempotent_id('56f04711-7b57-4d2a-a4f3-96c82845208e')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_pool_list_detail_with_filters_negative(self):
@@ -161,6 +168,7 @@
# Ensure we got no pools
self.assertEmpty(pool_list)
+ @decorators.idempotent_id('f027fb62-1ec3-4f52-a782-e9dd9db34fda')
@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"))
@@ -186,6 +194,7 @@
self.assertIn("pool", pool_keys)
self.assertIs(detail, "capabilities" in pool_keys)
+ @decorators.idempotent_id('31cb2c99-3abf-4dce-8e66-7fd30b168300')
@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"))
diff --git a/manila_tempest_tests/tests/api/admin/test_security_services.py b/manila_tempest_tests/tests/api/admin/test_security_services.py
index 3b29e26..bb3c103 100644
--- a/manila_tempest_tests/tests/api/admin/test_security_services.py
+++ b/manila_tempest_tests/tests/api/admin/test_security_services.py
@@ -13,6 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest.lib import decorators
from testtools import testcase as tc
from manila_tempest_tests.tests.api import base
@@ -46,6 +47,7 @@
'kerberos',
**ss_kerberos_data)
+ @decorators.idempotent_id('6f843a0a-21da-4a83-ae3b-3831f99b3678')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_list_security_services_all_tenants(self):
listed = self.shares_client.list_security_services(
@@ -57,6 +59,7 @@
keys = ["name", "id", "status", "type", ]
[self.assertIn(key, s_s.keys()) for s_s in listed for key in keys]
+ @decorators.idempotent_id('fe515fa7-0275-4190-adc7-5321e1047dad')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_list_security_services_invalid_filters(self):
listed = self.shares_client.list_security_services(
diff --git a/manila_tempest_tests/tests/api/admin/test_services.py b/manila_tempest_tests/tests/api/admin/test_services.py
index bda4bb4..7e70dc2 100644
--- a/manila_tempest_tests/tests/api/admin/test_services.py
+++ b/manila_tempest_tests/tests/api/admin/test_services.py
@@ -14,6 +14,7 @@
# under the License.
import ddt
+from tempest.lib import decorators
from testtools import testcase as tc
from manila_tempest_tests.tests.api import base
@@ -26,6 +27,7 @@
super(ServicesAdminTest, self).setUp()
self.services = self.shares_client.list_services()
+ @decorators.idempotent_id('74cd12ab-a1f5-40fb-9110-d9035b4b20c5')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@ddt.data('shares_client', 'shares_v2_client')
def test_list_services(self, client_name):
@@ -35,6 +37,7 @@
for service in services:
self.assertIsNotNone(service['id'])
+ @decorators.idempotent_id('e80f4b89-7280-47eb-9cbf-01a09e04c2d8')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@ddt.data('shares_client', 'shares_v2_client')
def test_get_services_by_host_name(self, client_name):
@@ -45,6 +48,7 @@
for service in services:
self.assertEqual(host, service["host"])
+ @decorators.idempotent_id('1dd4d799-b900-4476-9e51-ad9db6ee4435')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@ddt.data('shares_client', 'shares_v2_client')
def test_get_services_by_binary_name(self, client_name):
@@ -55,6 +59,7 @@
for service in services:
self.assertEqual(binary, service["binary"])
+ @decorators.idempotent_id('d12ea678-025f-46b4-95c5-3a03b3e440d7')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@ddt.data('shares_client', 'shares_v2_client')
def test_get_services_by_availability_zone(self, client_name):
@@ -65,6 +70,7 @@
for service in services:
self.assertEqual(zone, service["zone"])
+ @decorators.idempotent_id('e82921a7-6c98-4c9c-a47b-34a0badc3b59')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@ddt.data('shares_client', 'shares_v2_client')
def test_get_services_by_status(self, client_name):
@@ -75,6 +81,7 @@
for service in services:
self.assertEqual(status, service["status"])
+ @decorators.idempotent_id('c30234f0-1331-4560-93a7-cbda7d00eb53')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@ddt.data('shares_client', 'shares_v2_client')
def test_get_services_by_state(self, client_name):
@@ -85,6 +92,7 @@
for service in services:
self.assertEqual(state, service["state"])
+ @decorators.idempotent_id('b77c4bc4-57d5-4181-9e95-e230ab682b32')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@ddt.data('shares_client', 'shares_v2_client')
def test_get_services_by_all_filters(self, client_name):
diff --git a/manila_tempest_tests/tests/api/admin/test_services_negative.py b/manila_tempest_tests/tests/api/admin/test_services_negative.py
index 04ff803..d74c609 100644
--- a/manila_tempest_tests/tests/api/admin/test_services_negative.py
+++ b/manila_tempest_tests/tests/api/admin/test_services_negative.py
@@ -14,6 +14,7 @@
# under the License.
import ddt
+from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
from testtools import testcase as tc
@@ -29,11 +30,13 @@
cls.admin_client = cls.admin_shares_v2_client
cls.member_client = cls.shares_v2_client
+ @decorators.idempotent_id('59ab1a7d-817d-42e5-a1b9-adfc2912e08c')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_list_services_with_non_admin_user(self):
self.assertRaises(lib_exc.Forbidden,
self.member_client.list_services)
+ @decorators.idempotent_id('04f59090-069d-4cae-b028-e004ff29126c')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_get_service_by_invalid_params(self):
# All services are expected if send the request with invalid parameter
@@ -54,36 +57,42 @@
key=lambda service: service['id']),
msg)
+ @decorators.idempotent_id('386dc131-39f9-4d5f-af87-edf76e3d0e71')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_get_service_by_invalid_host(self):
params = {'host': 'fake_host'}
services_fake = self.admin_client.list_services(params)
self.assertEqual(0, len(services_fake))
+ @decorators.idempotent_id('766461b0-e89a-4113-8229-24c4d11d585a')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_get_service_by_invalid_binary(self):
params = {'binary': 'fake_binary'}
services_fake = self.admin_client.list_services(params)
self.assertEqual(0, len(services_fake))
+ @decorators.idempotent_id('ac570fde-690d-4448-9cce-ce35e0a14b88')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_get_service_by_invalid_zone(self):
params = {'zone': 'fake_zone'}
services_fake = self.admin_client.list_services(params)
self.assertEqual(0, len(services_fake))
+ @decorators.idempotent_id('da0fef1d-c4d3-4c33-a836-5f836e85df69')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_get_service_by_invalid_status(self):
params = {'status': 'fake_status'}
services_fake = self.admin_client.list_services(params)
self.assertEqual(0, len(services_fake))
+ @decorators.idempotent_id('41936575-3a96-455b-8069-7f6563abf0e2')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_get_service_by_invalid_state(self):
params = {'state': 'fake_state'}
services_fake = self.admin_client.list_services(params)
self.assertEqual(0, len(services_fake))
+ @decorators.idempotent_id('3c72227b-7fa1-4294-bdf4-413ec4c324e5')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
@ddt.data(
('os-services', '2.7'),
diff --git a/manila_tempest_tests/tests/api/admin/test_share_group_types.py b/manila_tempest_tests/tests/api/admin/test_share_group_types.py
index d05c079..3666079 100644
--- a/manila_tempest_tests/tests/api/admin/test_share_group_types.py
+++ b/manila_tempest_tests/tests/api/admin/test_share_group_types.py
@@ -13,16 +13,19 @@
# License for the specific language governing permissions and limitations
# under the License.
-import ddt
import itertools
+
+import ddt
from tempest import config
from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
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
LATEST_MICROVERSION = CONF.share.max_api_microversion
@@ -54,6 +57,7 @@
share_type = cls.create_share_type(name, extra_specs=extra_specs)
cls.share_type2 = share_type['share_type']
+ @decorators.idempotent_id('e2ba1754-cecc-4178-ad39-eefbb59e4d6d')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@ddt.data(
*itertools.product(('id', 'name'), set(
@@ -93,6 +97,7 @@
self.shares_v2_client.wait_for_resource_deletion(
share_group_type_id=sg_type_r['id'])
+ @decorators.idempotent_id('65cf04d6-0620-4e0d-96f2-456946e8a552')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@ddt.data('id', 'name')
def test_create_share_group_type_multiple_share_types_min(self, st_key):
@@ -109,6 +114,7 @@
set(sg_type['share_types']),
'Share types not applied correctly.')
+ @decorators.idempotent_id('6e103b7b-cd01-4edb-91e7-a16681781b36')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_create_share_group_type_with_one_spec_min(self):
name = data_utils.rand_name("tempest-manila")
@@ -123,6 +129,7 @@
self.assertDictMatch(group_specs, sg_type['group_specs'])
+ @decorators.idempotent_id('ec459ebb-5c45-4d4f-95f0-3bbf2974366c')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_create_share_group_type_with_multiple_specs_min(self):
name = data_utils.rand_name("tempest-manila")
@@ -137,6 +144,7 @@
self.assertDictMatch(group_specs, sg_type['group_specs'])
+ @decorators.idempotent_id('15b44580-a34d-4e0d-a77b-0e76b45d6199')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@ddt.data(
*set([constants.MIN_SHARE_GROUP_MICROVERSION,
@@ -166,6 +174,7 @@
self.assertEqual('value3', sg_type['group_specs']['key1'])
self.assertEqual(group_specs['key2'], sg_type['group_specs']['key2'])
+ @decorators.idempotent_id('3ed054c5-d0ab-4a73-b704-994eb7f9c46c')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_update_all_share_group_type_specs_min(self):
name = data_utils.rand_name("tempest-manila")
@@ -190,6 +199,7 @@
self.assertIn(k, sg_type['group_specs'])
self.assertEqual(v, sg_type['group_specs'][k])
+ @decorators.idempotent_id('efddee69-ca23-4681-8247-94ded81c4c3a')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@ddt.data(
*set([constants.MIN_SHARE_GROUP_MICROVERSION,
@@ -218,6 +228,7 @@
self.assertDictMatch(group_specs, sg_type['group_specs'])
+ @decorators.idempotent_id('c2d34b42-e3ec-404e-8b7a-0fe9b1560507')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@ddt.data(
*set([constants.MIN_SHARE_GROUP_MICROVERSION,
@@ -278,6 +289,7 @@
sgt_id, version=version)
self.assertEmpty(access)
+ @decorators.idempotent_id('b8b20a96-cecc-4677-8a77-aae3b93e5b96')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@ddt.data(*set(('2.45', '2.46', LATEST_MICROVERSION)))
def test_share_group_type_create_show_list_with_is_default_key(self,
diff --git a/manila_tempest_tests/tests/api/admin/test_share_group_types_negative.py b/manila_tempest_tests/tests/api/admin/test_share_group_types_negative.py
index 3cb5ed7..30ab384 100644
--- a/manila_tempest_tests/tests/api/admin/test_share_group_types_negative.py
+++ b/manila_tempest_tests/tests/api/admin/test_share_group_types_negative.py
@@ -12,6 +12,7 @@
from tempest import config
from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
from testtools import testcase as tc
@@ -45,6 +46,7 @@
share_types=[cls.share_type['share_type']['id']],
client=cls.admin_shares_v2_client)
+ @decorators.idempotent_id('1f8e3f98-4df7-4383-94d6-4ad058ef79c1')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_create_share_group_type_without_name(self):
self.assertRaises(
@@ -53,6 +55,7 @@
name=None,
share_types=data_utils.rand_name("fake"))
+ @decorators.idempotent_id('6c95f5b7-6e30-4e1e-b0fc-a0f05cf2982d')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_create_share_group_type_with_nonexistent_share_type(self):
self.assertRaises(
@@ -61,6 +64,7 @@
name=data_utils.rand_name("sgt_name_should_have_not_been_created"),
share_types=data_utils.rand_name("fake"))
+ @decorators.idempotent_id('ce6ba41b-4207-4866-8f70-7a89f64b4cd4')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_create_share_group_type_with_empty_name(self):
self.assertRaises(
@@ -68,6 +72,7 @@
self.create_share_group_type, '',
client=self.admin_shares_v2_client)
+ @decorators.idempotent_id('77159ec6-adb7-4d35-9d4b-039d322f7852')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_create_share_group_type_with_too_big_name(self):
self.assertRaises(
@@ -75,6 +80,7 @@
self.create_share_group_type,
"x" * 256, client=self.admin_shares_v2_client)
+ @decorators.idempotent_id('43ac388d-05e8-45d5-b633-631cc1f290af')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_create_share_group_type_with_wrong_value_for_group_specs(self):
self.assertRaises(
@@ -84,6 +90,7 @@
share_types=[self.share_type['share_type']['id']],
group_specs="expecting_error_code_400")
+ @decorators.idempotent_id('8fb8bd73-0219-460d-993e-bff7ddec29e8')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_get_share_group_type_using_nonexistent_id(self):
self.assertRaises(
@@ -91,6 +98,7 @@
self.admin_shares_v2_client.get_share_group_type,
data_utils.rand_name("fake"))
+ @decorators.idempotent_id('76b5c302-f492-45b4-b464-7be6efd373be')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_delete_share_group_type_using_nonexistent_id(self):
self.assertRaises(
@@ -98,6 +106,7 @@
self.admin_shares_v2_client.delete_share_group_type,
data_utils.rand_name("fake"))
+ @decorators.idempotent_id('081183cb-0f1c-4b67-8552-909935dc0be2')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_create_duplicate_of_share_group_type(self):
unique_name = data_utils.rand_name("unique_sgt_name")
@@ -119,6 +128,7 @@
self.admin_shares_v2_client.delete_share_group_type(sg_type['id'])
self.assertEqual(2, len(list_of_ids))
+ @decorators.idempotent_id('6c30989d-2e8a-48d3-809a-556dddae51bd')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_add_project_access_to_public_share_group_type(self):
self.assertRaises(
@@ -127,6 +137,7 @@
self.share_group_type["id"],
self.admin_shares_v2_client.tenant_id)
+ @decorators.idempotent_id('3375a1f8-7828-4cbe-89d7-fe11fcf30b21')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_remove_project_access_from_public_share_group_type(self):
self.assertRaises(
@@ -135,6 +146,7 @@
self.share_group_type["id"],
self.admin_shares_v2_client.tenant_id)
+ @decorators.idempotent_id('68e3d7f9-fdc0-44a2-ae84-a72eba314e19')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_add_project_access_to_nonexistent_share_group_type(self):
self.assertRaises(
@@ -143,6 +155,7 @@
data_utils.rand_name("fake"),
self.admin_shares_v2_client.tenant_id)
+ @decorators.idempotent_id('94f0c902-ab12-435e-abd5-e09a892db82a')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_remove_project_access_from_nonexistent_share_group_type(self):
self.assertRaises(
diff --git a/manila_tempest_tests/tests/api/admin/test_share_groups.py b/manila_tempest_tests/tests/api/admin/test_share_groups.py
index c7b3a42..e88d5ce 100644
--- a/manila_tempest_tests/tests/api/admin/test_share_groups.py
+++ b/manila_tempest_tests/tests/api/admin/test_share_groups.py
@@ -16,6 +16,8 @@
import ddt
from tempest import config
from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
+from tempest.lib import exceptions
import testtools
from testtools import testcase as tc
@@ -58,6 +60,7 @@
version=constants.MIN_SHARE_GROUP_MICROVERSION)
cls.sg_type_id = cls.sg_type['id']
+ @decorators.idempotent_id('79eaa86f-4c8f-49fd-acb2-ec051aa6bf93')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@ddt.data(
*set([constants.MIN_SHARE_GROUP_MICROVERSION,
@@ -95,6 +98,7 @@
'Expected %s, got %s' % (
share_group['id'], expected_share_types, actual_share_types))
+ @decorators.idempotent_id('ff6c17af-03ba-4506-923d-b6c229492d0e')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_create_share_group_with_multiple_share_types_min(self):
share_group = self.create_share_group(
@@ -128,6 +132,7 @@
'Expected %s, got %s' % (
share_group['id'], expected_share_types, actual_share_types))
+ @decorators.idempotent_id('99f0471c-e978-42ac-b50b-848b16692eab')
@testtools.skipUnless(
CONF.share.default_share_type_name, "Only if defaults are defined.")
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@@ -136,10 +141,13 @@
constants.SHARE_GROUPS_GRADUATION_VERSION, LATEST_MICROVERSION]))
def test_default_share_group_type_applied(self, version):
self.skip_if_microversion_not_supported(version)
-
- default_type = self.shares_v2_client.get_default_share_group_type(
- version=version
- )
+ try:
+ default_type = self.shares_v2_client.get_default_share_group_type(
+ version=version
+ )
+ except exceptions.NotFound:
+ msg = "There is no default share group type"
+ raise self.skipException(msg)
default_share_types = default_type['share_types']
share_group = self.create_share_group(
@@ -163,6 +171,7 @@
'Expected %s, got %s' % (
share_group['id'], expected_sg_type, actual_sg_type))
+ @decorators.idempotent_id('8ca1f0a0-2a36-4adb-af6b-6741b00307c5')
@testtools.skipUnless(
CONF.share.multitenancy_enabled, "Only for multitenancy.")
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@@ -197,6 +206,7 @@
self.assertEqual(
orig_sg['share_server_id'], new_sg['share_server_id'])
+ @decorators.idempotent_id('93fd4a97-a25a-4a17-b5ae-c8894c1adfc5')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_create_sg_with_sg_type_but_without_any_group_specs(self):
# Create share group type not specifying any group specs
diff --git a/manila_tempest_tests/tests/api/admin/test_share_groups_negative.py b/manila_tempest_tests/tests/api/admin/test_share_groups_negative.py
index 8a226c4..dd66559 100644
--- a/manila_tempest_tests/tests/api/admin/test_share_groups_negative.py
+++ b/manila_tempest_tests/tests/api/admin/test_share_groups_negative.py
@@ -15,6 +15,7 @@
from tempest import config
from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
from testtools import testcase as tc
from manila_tempest_tests.common import constants
@@ -36,6 +37,7 @@
utils.check_skip_if_microversion_lt(
constants.MIN_SHARE_GROUP_MICROVERSION)
+ @decorators.idempotent_id('b90537b7-634d-4fca-b451-770fbcca7927')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_create_share_group_with_wrong_consistent_snapshot_spec(self):
# Create valid share type for share group type
diff --git a/manila_tempest_tests/tests/api/admin/test_share_instances.py b/manila_tempest_tests/tests/api/admin/test_share_instances.py
index 4474ffd..14cdbab 100644
--- a/manila_tempest_tests/tests/api/admin/test_share_instances.py
+++ b/manila_tempest_tests/tests/api/admin/test_share_instances.py
@@ -14,6 +14,7 @@
# under the License.
import ddt
+from tempest.lib import decorators
from testtools import testcase as tc
from manila_tempest_tests.tests.api import base
@@ -32,6 +33,7 @@
# create share
cls.share = cls.create_share(share_type_id=cls.share_type_id)
+ @decorators.idempotent_id('b5211759-17ab-4806-a58c-c65bc8a06087')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_get_instances_of_share_v2_3(self):
"""Test that we get only the 1 share instance back for the share."""
@@ -50,6 +52,7 @@
self.share['id'],
si['share_id']))
+ @decorators.idempotent_id('b2d8ccba-5973-4e72-b3df-52555ce40b4f')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_list_share_instances_v2_3(self):
"""Test that we list the share instance back."""
@@ -62,6 +65,7 @@
msg = 'Share instance for share %s was not found.' % self.share['id']
self.assertIn(self.share['id'], share_ids, msg)
+ @decorators.idempotent_id('d4b2544a-96ce-41ed-8b8e-e46ceef91462')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@ddt.data('2.3', '2.9', '2.10', '2.30', '2.54')
def test_get_share_instance(self, version):
@@ -99,6 +103,7 @@
si['id'], expected_keys, actual_keys))
@ddt.data('path', 'id')
+ @decorators.idempotent_id('c27b415d-341c-42f0-a269-2c94f69fbee1')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@base.skip_if_microversion_lt("2.35")
def test_list_share_instances_with_export_location_path_and_id(
diff --git a/manila_tempest_tests/tests/api/admin/test_share_instances_negative.py b/manila_tempest_tests/tests/api/admin/test_share_instances_negative.py
index 36f9558..ebf8364 100644
--- a/manila_tempest_tests/tests/api/admin/test_share_instances_negative.py
+++ b/manila_tempest_tests/tests/api/admin/test_share_instances_negative.py
@@ -11,6 +11,7 @@
# under the License.
import ddt
+from tempest.lib import decorators
from testtools import testcase as tc
from manila_tempest_tests.tests.api import base
@@ -28,6 +29,7 @@
# create share
cls.share = cls.create_share(share_type_id=cls.share_type_id)
+ @decorators.idempotent_id('babe885e-a8ab-439d-8b95-e5422983a942')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@base.skip_if_microversion_not_supported("2.34")
@ddt.data('path', 'id')
@@ -44,6 +46,7 @@
self.assertGreater(len(share_instances), 0)
+ @decorators.idempotent_id('ce0d045c-e418-42fa-86e4-ead493fc0663')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@base.skip_if_microversion_lt("2.35")
@ddt.data('path', 'id')
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 f5fd840..09bbdb7 100644
--- a/manila_tempest_tests/tests/api/admin/test_share_manage.py
+++ b/manila_tempest_tests/tests/api/admin/test_share_manage.py
@@ -16,13 +16,14 @@
import ddt
from tempest import config
from tempest.lib.common.utils import data_utils
-
+from tempest.lib import decorators
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
@@ -84,10 +85,14 @@
share_ids = [si['share_id'] for si in share_instance_list]
self.assertNotIn(share['id'], share_ids)
+ export_path = share['export_locations'][0]
+ if utils.is_microversion_ge(version, "2.8"):
+ export_path = share['export_locations'][0]['path']
+
# Manage share
manage_params = {
'service_host': share['host'],
- 'export_path': share['export_locations'][0],
+ 'export_path': export_path,
'protocol': share['share_proto'],
'share_type_id': self.st['share_type']['id'],
'name': name,
@@ -142,21 +147,25 @@
self._delete_share_server_and_wait(
managed_share['share_server_id'])
+ @decorators.idempotent_id('15b654d0-34ed-4154-9f5f-b96d2e4e9d1c')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@base.skip_if_microversion_not_supported("2.5")
def test_manage_with_os_share_manage_url(self):
self._test_manage(version="2.5")
+ @decorators.idempotent_id('8c0beefb-19da-441e-b73f-d90eb8000ff3')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@base.skip_if_microversion_not_supported("2.8")
def test_manage_with_is_public_True(self):
self._test_manage(is_public=True, version="2.8")
+ @decorators.idempotent_id('da7b7a4f-6693-4460-bdb7-1f8d42032bc6')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@base.skip_if_microversion_not_supported("2.16")
def test_manage_show_user_id(self):
self._test_manage(version="2.16")
+ @decorators.idempotent_id('24ec7840-0174-484f-8b3a-8c6f162bf576')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
def test_manage(self):
self._test_manage(check_manage=True)
diff --git a/manila_tempest_tests/tests/api/admin/test_share_manage_negative.py b/manila_tempest_tests/tests/api/admin/test_share_manage_negative.py
index de7e1bf..cc97dd6 100644
--- a/manila_tempest_tests/tests/api/admin/test_share_manage_negative.py
+++ b/manila_tempest_tests/tests/api/admin/test_share_manage_negative.py
@@ -15,6 +15,7 @@
from tempest import config
from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
import testtools
from testtools import testcase as tc
@@ -90,6 +91,7 @@
return valid_params
+ @decorators.idempotent_id('8267161e-4f55-44eb-9af5-30d1a3fb2606')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_manage_invalid_param_raises_exception(self):
# Try to manage share with invalid parameters, it should not succeed
@@ -140,6 +142,7 @@
self._delete_share_server_and_wait(
managed_share['share_server_id'])
+ @decorators.idempotent_id('01b36343-c503-4c14-bb74-71f131ae96b6')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_manage_invalid_param_manage_error(self):
# Try to manage share with invalid parameters, it should not succeed.
@@ -184,6 +187,7 @@
self._delete_share_server_and_wait(
managed_share['share_server_id'])
+ @decorators.idempotent_id('832b1c4d-e6f2-4a75-9ea5-d99f780db743')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_manage_share_duplicate(self):
share = self._create_share_for_manage()
@@ -216,6 +220,7 @@
self._delete_share_server_and_wait(
managed_share['share_server_id'])
+ @decorators.idempotent_id('c2f28981-5758-46e8-9d90-5c3269461d94')
@testtools.skipUnless(CONF.share.multitenancy_enabled,
'Multitenancy tests are disabled.')
@utils.skip_if_microversion_not_supported("2.49")
@@ -244,6 +249,7 @@
self._delete_share_server_and_wait(
managed_share['share_server_id'])
+ @decorators.idempotent_id('162b6b96-e801-40f4-b111-7e533cf8b943')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_delete_share_in_manage_error(self):
share = self._create_share_for_manage()
@@ -280,6 +286,7 @@
self._delete_share_server_and_wait(
managed_share['share_server_id'])
+ @decorators.idempotent_id('7cad4763-8f78-46a5-aeeb-6ca174284d3d')
@testtools.skipUnless(CONF.share.run_snapshot_tests,
'Snapshot tests are disabled.')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@@ -300,6 +307,7 @@
self._delete_snapshot_and_wait(snap)
self._delete_share_and_wait(share)
+ @decorators.idempotent_id('f71bcb3c-836e-4e9e-972a-50debeb8c285')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_unmanage_share_transitional_state(self):
# A share in transitional state cannot be unmanaged
@@ -319,6 +327,7 @@
# cleanup
self._reset_state_and_delete_share(share)
+ @decorators.idempotent_id('916ca8e2-5635-4cc9-8ab6-36b7b53ecd0a')
@testtools.skipUnless(CONF.share.multitenancy_enabled,
'Multitenancy tests are disabled.')
@utils.skip_if_microversion_not_supported("2.48")
diff --git a/manila_tempest_tests/tests/api/admin/test_share_networks.py b/manila_tempest_tests/tests/api/admin/test_share_networks.py
index e66e503..2ff9533 100644
--- a/manila_tempest_tests/tests/api/admin/test_share_networks.py
+++ b/manila_tempest_tests/tests/api/admin/test_share_networks.py
@@ -13,15 +13,15 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest.lib import decorators
from testtools import testcase as tc
from manila_tempest_tests.tests.api import base
from manila_tempest_tests.tests.api import test_share_networks
-class ShareNetworkAdminTest(
- base.BaseSharesAdminTest,
- test_share_networks.ShareNetworkListMixin):
+class ShareNetworkAdminTest(base.BaseSharesMixedTest,
+ test_share_networks.ShareNetworkListMixin):
@classmethod
def resource_setup(cls):
@@ -49,8 +49,6 @@
cls.sn_with_ldap_ss["id"],
cls.ss_ldap["id"])
- cls.isolated_client = cls.get_client_with_isolated_creds(
- type_of_creds='alt')
cls.data_sn_with_kerberos_ss = {
'name': 'sn_with_kerberos_ss',
'created_at': '2003-03-03',
@@ -64,30 +62,33 @@
'description': 'fake description',
}
- cls.ss_kerberos = cls.isolated_client.create_security_service(
+ cls.ss_kerberos = cls.alt_shares_v2_client.create_security_service(
ss_type='kerberos',
**cls.data_sn_with_ldap_ss)
- cls.sn_with_kerberos_ss = cls.isolated_client.create_share_network(
- cleanup_in_class=True,
- **cls.data_sn_with_kerberos_ss)
+ cls.sn_with_kerberos_ss = (
+ cls.alt_shares_v2_client.create_share_network(
+ cleanup_in_class=True, **cls.data_sn_with_kerberos_ss)
+ )
- cls.isolated_client.add_sec_service_to_share_network(
+ cls.alt_shares_v2_client.add_sec_service_to_share_network(
cls.sn_with_kerberos_ss["id"],
cls.ss_kerberos["id"])
+ @decorators.idempotent_id('983fb22d-3057-402f-8988-62ce41a557fb')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_list_share_networks_all_tenants(self):
- listed = self.shares_client.list_share_networks_with_detail(
+ listed = self.admin_shares_v2_client.list_share_networks_with_detail(
{'all_tenants': 1})
self.assertTrue(any(self.sn_with_ldap_ss['id'] == sn['id']
for sn in listed))
self.assertTrue(any(self.sn_with_kerberos_ss['id'] == sn['id']
for sn in listed))
+ @decorators.idempotent_id('36c26b6b-8984-4255-959b-74f6ef46c37b')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_list_share_networks_filter_by_project_id(self):
- listed = self.shares_client.list_share_networks_with_detail(
+ listed = self.admin_shares_v2_client.list_share_networks_with_detail(
{'project_id': self.sn_with_kerberos_ss['project_id']})
self.assertTrue(any(self.sn_with_kerberos_ss['id'] == sn['id']
for sn in listed))
diff --git a/manila_tempest_tests/tests/api/admin/test_share_servers.py b/manila_tempest_tests/tests/api/admin/test_share_servers.py
index c49b0d9..b5fe72c 100644
--- a/manila_tempest_tests/tests/api/admin/test_share_servers.py
+++ b/manila_tempest_tests/tests/api/admin/test_share_servers.py
@@ -18,6 +18,7 @@
import ddt
import six
from tempest import config
+from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
import testtools
from testtools import testcase as tc
@@ -45,14 +46,17 @@
# create share type
cls.share_type = cls._create_share_type()
cls.share_type_id = cls.share_type['id']
- # create share
- cls.share = cls.create_share(share_type_id=cls.share_type_id)
+ # create share in this new share network
+ cls.share = cls.create_share(
+ share_type_id=cls.share_type_id)
cls.share_network = cls.shares_v2_client.get_share_network(
cls.shares_v2_client.share_network_id)
+
if not cls.share_network["name"]:
sn_id = cls.share_network["id"]
cls.share_network = cls.shares_v2_client.update_share_network(
sn_id, name="sn_%s" % sn_id)
+
cls.sn_name_and_id = [
cls.share_network["name"],
cls.share_network["id"],
@@ -66,6 +70,7 @@
cls.date_re = re.compile("^([0-9]{4}-[0-9]{2}-[0-9]{2}[A-Z]{1}"
"[0-9]{2}:[0-9]{2}:[0-9]{2}).*$")
+ @decorators.idempotent_id('3f821248-2c05-4323-a95f-a0216a537b0a')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_list_share_servers_without_filters(self):
servers = self.shares_v2_client.list_share_servers()
@@ -96,6 +101,7 @@
# Server we used is present.
any(s["share_network_name"] in self.sn_name_and_id for s in servers)
+ @decorators.idempotent_id('515e3332-cce9-4a28-ad2e-96dbb2cc672e')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_list_share_servers_with_host_filter(self):
# Get list of share servers and remember 'host' name
@@ -121,6 +127,7 @@
for server in servers:
self.assertEqual(server["host"], host)
+ @decorators.idempotent_id('77a5c1c5-db2f-4ff6-872c-ed73a575acd0')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_list_share_servers_with_status_filter(self):
search_opts = {"status": "active"}
@@ -132,6 +139,7 @@
for server in servers:
self.assertEqual(server["status"], "active")
+ @decorators.idempotent_id('ed671cbb-7732-4966-9f1e-b997b8aa05ff')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_list_share_servers_with_project_id_filter(self):
search_opts = {"project_id": self.share_network["project_id"]}
@@ -142,6 +150,7 @@
self.assertEqual(server["project_id"],
self.share_network["project_id"])
+ @decorators.idempotent_id('70064129-df97-4dba-9482-2819558111ec')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_list_share_servers_with_share_network_name_filter(self):
search_opts = {"share_network": self.share_network["name"]}
@@ -152,6 +161,7 @@
self.assertEqual(server["share_network_name"],
self.share_network["name"])
+ @decorators.idempotent_id('f64e8024-eb42-4a4c-be6b-97d35633a019')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_list_share_servers_with_share_network_id_filter(self):
search_opts = {"share_network": self.share_network["id"]}
@@ -162,6 +172,7 @@
self.assertIn(server["share_network_name"],
self.sn_name_and_id)
+ @decorators.idempotent_id('e1af24f4-bf63-467d-a857-3a402fa9b65b')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_show_share_server(self):
share = self.shares_v2_client.get_share(self.share["id"])
@@ -200,6 +211,7 @@
# 'backend_details' should be a dict
self.assertIsInstance(server["backend_details"], dict)
+ @decorators.idempotent_id('782d8f5f-2c02-44dd-8d43-e06b651a71be')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_show_share_server_details(self):
share = self.shares_v2_client.get_share(self.share['id'])
@@ -211,6 +223,7 @@
self.assertIsInstance(k, six.string_types)
self.assertIsInstance(v, six.string_types)
+ @decorators.idempotent_id('2fdf8d29-3ab8-4424-b684-6253f45b9666')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@ddt.data(True, False)
@testtools.skipIf(CONF.share.share_network_id != "",
@@ -222,6 +235,7 @@
# TODO(vponomaryov): attach security-services too. If any exist from
# donor share-network.
new_sn = self.create_share_network(
+ add_security_services=True,
neutron_net_id=self.share_net_info['neutron_net_id'],
neutron_subnet_id=self.share_net_info['neutron_subnet_id'])
@@ -276,6 +290,7 @@
self.shares_v2_client.wait_for_resource_deletion(
sn_id=new_sn["id"])
+ @decorators.idempotent_id('960d49c5-f8d6-42be-aaf4-b7890a55df03')
@testtools.skipIf(CONF.share.share_network_id != "",
"This test is not suitable for pre-existing "
"share_network.")
@@ -285,6 +300,7 @@
# Get network and subnet from existing share_network and reuse it
# to be able to delete share_server after test ends.
new_sn = self.create_share_network(
+ add_security_services=True,
neutron_net_id=self.share_net_info['neutron_net_id'],
neutron_subnet_id=self.share_net_info['neutron_subnet_id'])
share = self.create_share(
diff --git a/manila_tempest_tests/tests/api/admin/test_share_servers_manage.py b/manila_tempest_tests/tests/api/admin/test_share_servers_manage.py
index 7b037b3..fa9966e 100644
--- a/manila_tempest_tests/tests/api/admin/test_share_servers_manage.py
+++ b/manila_tempest_tests/tests/api/admin/test_share_servers_manage.py
@@ -16,6 +16,7 @@
import ddt
from tempest import config
from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
import testtools
from testtools import testcase as tc
@@ -53,6 +54,7 @@
cleanup_in_class=True,
extra_specs=cls.extra_specs)
+ @decorators.idempotent_id('2bbe564d-d314-474b-8060-ada30581d0cd')
@testtools.skipIf(CONF.share.share_network_id != "",
"This test is not suitable for pre-existing "
"share_network.")
diff --git a/manila_tempest_tests/tests/api/admin/test_share_servers_manage_negative.py b/manila_tempest_tests/tests/api/admin/test_share_servers_manage_negative.py
index e3a5608..0b04511 100644
--- a/manila_tempest_tests/tests/api/admin/test_share_servers_manage_negative.py
+++ b/manila_tempest_tests/tests/api/admin/test_share_servers_manage_negative.py
@@ -16,6 +16,7 @@
import ddt
from tempest import config
from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
import testtools
from testtools import testcase as tc
@@ -81,6 +82,7 @@
('share_network_subnet_id', 'invalid_share_network_subnet_id'),
)
@ddt.unpack
+ @decorators.idempotent_id('60b94091-f35d-42ac-a25a-ca1f7e66bb44')
@testtools.skipIf(CONF.share.share_network_id != "",
"This test is not suitable for pre-existing "
"share_network.")
@@ -131,6 +133,7 @@
# delete share server
self._delete_share_server_and_wait(managed_share_server['id'])
+ @decorators.idempotent_id('0f21aebe-e983-4112-a494-b287293112d2')
@testtools.skipIf(CONF.share.share_network_id != "",
"This test is not suitable for pre-existing "
"share_network.")
@@ -172,6 +175,7 @@
# delete share server
self._delete_share_server_and_wait(share['share_server_id'])
+ @decorators.idempotent_id('84f9a808-8bff-4652-8877-4c9f0dfeed8a')
@testtools.skipIf(CONF.share.share_network_id != "",
"This test is not suitable for pre-existing "
"share_network.")
@@ -213,6 +217,7 @@
# delete share server
self._delete_share_server_and_wait(share['share_server_id'])
+ @decorators.idempotent_id('fbe6cf2d-3e33-40d8-b420-b785d3cb7559')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_share_server_reset_state_invalid_state(self):
@@ -232,6 +237,7 @@
# delete share
self._delete_share_and_wait(share)
+ @decorators.idempotent_id('c0a13fc4-9f30-483a-b473-0f0ce533f645')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_unmanage_share_server_with_share(self):
@@ -250,6 +256,7 @@
# delete share
self._delete_share_and_wait(share)
+ @decorators.idempotent_id('d2feb338-5c78-4370-b5ba-c8b16df63b43')
@testtools.skipIf(CONF.share.share_network_id != "",
"This test is not suitable for pre-existing "
"share_network.")
@@ -299,6 +306,7 @@
# delete share server
self._delete_share_server_and_wait(managed_share_server['id'])
+ @decorators.idempotent_id('30606085-4b01-4489-a18c-22e67ed0e221')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_manage_share_server_double_manage(self):
diff --git a/manila_tempest_tests/tests/api/admin/test_share_servers_migration.py b/manila_tempest_tests/tests/api/admin/test_share_servers_migration.py
new file mode 100644
index 0000000..e162b17
--- /dev/null
+++ b/manila_tempest_tests/tests/api/admin/test_share_servers_migration.py
@@ -0,0 +1,408 @@
+# Copyright 2020 NetApp 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 decorators
+from tempest.lib import exceptions
+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
+
+
+class MigrationShareServerBase(base.BaseSharesAdminTest):
+ protocol = None
+
+ @classmethod
+ def skip_checks(cls):
+ super(MigrationShareServerBase, cls).skip_checks()
+ if cls.protocol not in CONF.share.enable_protocols:
+ raise cls.skipException('%s tests are disabled.' % cls.protocol)
+ if not CONF.share.multitenancy_enabled:
+ raise cls.skipException('Multitenancy tests are disabled.')
+ if not CONF.share.run_share_server_migration_tests:
+ raise cls.skipException(
+ 'Share server migration tests are disabled.')
+ utils.check_skip_if_microversion_lt('2.57')
+
+ @classmethod
+ def resource_setup(cls):
+ super(MigrationShareServerBase, cls).resource_setup()
+ cls.all_hosts = cls.shares_v2_client.list_pools(detail=True)
+ cls.backends = set()
+ for pool in cls.all_hosts['pools']:
+ if pool['capabilities'].get('driver_handles_share_servers'):
+ cls.backends.add(pool['name'].split('#')[0])
+
+ if len(cls.backends) < 2:
+ msg = ("Could not find the necessary backends. At least two"
+ " are needed to run the tests of share server migration")
+ raise cls.skipException(msg)
+
+ # create share type (generic)
+ cls.share_type = cls._create_share_type()
+
+ # create two non routable IPs to be used in NFS access rulesi
+ cls.access_rules_ip_rw = utils.rand_ip()
+ cls.access_rules_ip_ro = utils.rand_ip()
+
+ def _setup_migration(self, share):
+ """Initial share server migration setup."""
+
+ share = self.shares_v2_client.get_share(share['id'])
+ server_id = share['share_server_id']
+
+ # (andrer) Verify if have at least one backend compatible with
+ # the specified share server.
+ dest_host, compatible = (
+ self._choose_compatible_backend_for_share_server(server_id))
+
+ snapshot = False
+ if (compatible['supported_capabilities']['preserve_snapshots'] and
+ share['snapshot_support']):
+ snapshot = self.create_snapshot_wait_for_active(
+ share['id'], cleanup_in_class=False)['id']
+
+ # (andrer) Check the share export locations.
+ old_exports = self.shares_v2_client.list_share_export_locations(
+ share['id'])
+ self.assertNotEmpty(old_exports)
+ old_exports = [x['path'] for x in old_exports
+ if x['is_admin_only'] is False]
+ self.assertNotEmpty(old_exports)
+
+ # (andrer) Create the access rules, considering NFS and CIFS
+ # protocols.
+ access_rules = self._get_access_rule_data_for_protocols()
+ for rule in access_rules:
+ self.shares_v2_client.create_access_rule(
+ share['id'], access_type=rule.get('access_type'),
+ access_to=rule.get('access_to'),
+ access_level=rule.get('access_level')
+ )
+ self.shares_v2_client.wait_for_share_status(
+ share['id'], constants.RULE_STATE_ACTIVE,
+ status_attr='access_rules_status')
+
+ share = self.shares_v2_client.get_share(share['id'])
+
+ return share, server_id, dest_host, snapshot
+
+ def _validate_state_of_resources(self, share, expected_status,
+ snapshot_id):
+ """Validates the share and snapshot status."""
+ statuses = ((expected_status,)
+ if not isinstance(expected_status, (tuple, list, set))
+ else expected_status)
+
+ share = self.shares_v2_client.get_share(share['id'])
+ self.assertIn(share['status'], statuses)
+
+ if snapshot_id:
+ snapshot = self.shares_v2_client.get_snapshot(snapshot_id)
+ self.assertIn(snapshot['status'], statuses)
+
+ def _validate_share_server_migration_complete(
+ self, share, dest_host, dest_server_id, snapshot_id=None,
+ share_network_id=None, version=CONF.share.max_api_microversion):
+ """Validates the share server migration complete. """
+
+ # Check the export locations
+ new_exports = self.shares_v2_client.list_share_export_locations(
+ share['id'], version=version)
+ self.assertNotEmpty(new_exports)
+ new_exports = [x['path'] for x in new_exports if
+ x['is_admin_only'] is False]
+ self.assertNotEmpty(new_exports)
+
+ # Check the share host, share_network, share_server and status.
+ share = self.shares_v2_client.get_share(share['id'])
+ self.assertEqual(share['host'].split('#')[0], dest_host)
+ self.assertEqual(share_network_id, share['share_network_id'])
+ self.assertEqual(dest_server_id, share['share_server_id'])
+ self.assertEqual(share['status'], constants.STATUS_AVAILABLE)
+
+ # Check the snapshot status if possible.
+ if snapshot_id:
+ self.shares_v2_client.wait_for_snapshot_status(
+ snapshot_id, constants.STATUS_AVAILABLE)
+
+ # Check the share server destination status.
+ dest_server = self.shares_v2_client.show_share_server(dest_server_id)
+ self.assertIn(dest_server['task_state'],
+ constants.TASK_STATE_MIGRATION_SUCCESS)
+
+ # Check if the access rules are in the share.
+ rules = self.shares_v2_client.list_access_rules(share['id'])
+ if self.protocol == 'cifs':
+ expected_rules = [{
+ 'state': constants.RULE_STATE_ACTIVE,
+ 'access_to': CONF.share.username_for_user_rules,
+ 'access_type': 'user',
+ 'access_level': 'rw',
+ }]
+ elif self.protocol == 'nfs':
+ expected_rules = [{
+ 'state': constants.RULE_STATE_ACTIVE,
+ 'access_to': self.access_rules_ip_rw,
+ 'access_type': 'ip',
+ 'access_level': 'rw',
+ }, {
+ 'state': constants.RULE_STATE_ACTIVE,
+ 'access_to': self.access_rules_ip_ro,
+ 'access_type': 'ip',
+ 'access_level': 'ro',
+ }]
+
+ filtered_rules = [{'state': rule['state'],
+ 'access_to': rule['access_to'],
+ 'access_level': rule['access_level'],
+ 'access_type': rule['access_type']}
+ for rule in rules]
+
+ for r in expected_rules:
+ self.assertIn(r, filtered_rules)
+ self.assertEqual(len(expected_rules), len(filtered_rules))
+
+ @classmethod
+ def _choose_compatible_backend_for_share_server(self, server_id):
+ """Choose a compatible host for the share server migration."""
+ for backend in self.backends:
+ # This try is necessary since if you try migrate the share server
+ # using the same backend and share network will raise an exception.
+ try:
+ compatibility = (
+ self.admin_shares_v2_client.share_server_migration_check(
+ share_server_id=server_id, host=backend))
+ except exceptions.Conflict or exceptions.ServerFault:
+ continue
+ if compatibility['compatible']:
+ return backend, compatibility
+
+ raise self.skipException(
+ "Not found compatible host for the share server migration.")
+
+ def _choose_incompatible_backend_for_share_server(self, server_id):
+ """Choose a not compatible host for the share server migration."""
+ for backend in self.backends:
+ # This try is necessary since if you try migrate the share server
+ # using the same backend and share network will raise an exception.
+ try:
+ compatibility = (
+ self.admin_shares_v2_client.share_server_migration_check(
+ share_server_id=server_id, host=backend))
+ except exceptions.Conflict or exceptions.ServerFault:
+ continue
+ if not compatibility['compatible']:
+ return backend, compatibility
+
+ raise self.skipException(
+ "None of the hosts available are incompatible to perform a"
+ " negative share server migration test.")
+
+ def _get_share_server_destination_for_migration(self, src_server_id):
+ """Find the destination share server chosen for the migration."""
+ params = {'source_share_server_id': src_server_id,
+ 'status': constants.STATUS_SERVER_MIGRATING_TO}
+ dest_server = self.admin_shares_v2_client.list_share_servers(
+ search_opts=params)
+ dest_server_id = dest_server[0]['id'] if dest_server else None
+
+ return dest_server_id
+
+ def _get_access_rule_data_for_protocols(self):
+ """Return fake data for access rules based on configured protocol."""
+ if self.protocol == 'nfs':
+ return [{
+ 'access_type': 'ip',
+ 'access_to': self.access_rules_ip_rw,
+ 'access_level': 'rw',
+ }, {
+ 'access_type': 'ip',
+ 'access_to': self.access_rules_ip_ro,
+ 'access_level': 'ro',
+ }]
+ elif self.protocol == 'cifs':
+ return [{
+ 'access_type': 'user',
+ 'access_to': CONF.share.username_for_user_rules,
+ 'access_level': 'rw',
+ }]
+ else:
+ message = "Unrecognized protocol and access rules configuration"
+ raise self.skipException(message)
+
+
+@ddt.ddt
+class ShareServerMigrationBasicNFS(MigrationShareServerBase):
+ protocol = "nfs"
+
+ @decorators.idempotent_id('5b84bcb6-17d8-4073-8e02-53b54aee6f8b')
+ @tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
+ def test_share_server_migration_cancel(self):
+ """Test the share server migration cancel."""
+ share_network_id = self.provide_share_network(
+ self.shares_v2_client, self.networks_client)
+ share = self.create_share(share_protocol=self.protocol,
+ share_type_id=self.share_type['id'],
+ share_network_id=share_network_id,
+ cleanup_in_class=False)
+ share = self.shares_v2_client.get_share(share['id'])
+
+ # Initial migration setup.
+ share, src_server_id, dest_host, snapshot_id = self._setup_migration(
+ share)
+
+ preserve_snapshots = True if snapshot_id else False
+
+ # Start share server migration.
+ self.shares_v2_client.share_server_migration_start(
+ src_server_id, dest_host, preserve_snapshots=preserve_snapshots)
+
+ expected_state = constants.TASK_STATE_MIGRATION_DRIVER_PHASE1_DONE
+ self.shares_v2_client.wait_for_share_server_status(
+ src_server_id, expected_state, status_attr='task_state')
+ # Get for the destination share server.
+ dest_server_id = self._get_share_server_destination_for_migration(
+ src_server_id)
+
+ dest_server = self.shares_v2_client.show_share_server(dest_server_id)
+ self.assertEqual(dest_host, dest_server['host'])
+ self.assertEqual(share_network_id, dest_server['share_network_id'])
+
+ # Validate the share instances status.
+ share_status = constants.STATUS_SERVER_MIGRATING
+ self._validate_state_of_resources(share, share_status, snapshot_id)
+
+ # Cancel the share server migration.
+ self.shares_v2_client.share_server_migration_cancel(src_server_id)
+
+ # Wait for the migration cancelled status.
+ expected_state = constants.TASK_STATE_MIGRATION_CANCELLED
+ self.shares_v2_client.wait_for_share_server_status(
+ src_server_id, expected_state, status_attr='task_state')
+
+ # After the cancel operation, we need to validate again the resources.
+ expected_status = constants.STATUS_AVAILABLE
+ self._validate_state_of_resources(share, expected_status, snapshot_id)
+
+ @decorators.idempotent_id('99e439a8-a716-4205-bf5b-af50128cb908')
+ @tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
+ @ddt.data(False, True)
+ def test_share_server_migration_complete(self, new_share_network):
+ """Test the share server migration complete."""
+ share_network_id = self.provide_share_network(
+ self.shares_v2_client, self.networks_client)
+ dest_share_network_id = share_network_id
+ if new_share_network:
+ src_share_network = self.shares_v2_client.get_share_network(
+ share_network_id)
+ share_net_info = (
+ utils.share_network_get_default_subnet(src_share_network))
+ dest_share_network_id = self.create_share_network(
+ neutron_net_id=share_net_info['neutron_net_id'],
+ neutron_subnet_id=share_net_info['neutron_subnet_id'],
+ cleanup_in_class=False)['id']
+
+ share = self.create_share(share_protocol=self.protocol,
+ share_type_id=self.share_type['id'],
+ share_network_id=share_network_id,
+ cleanup_in_class=False)
+ share = self.shares_v2_client.get_share(share['id'])
+
+ # Initial migration setup.
+ share, src_server_id, dest_host, snapshot_id = self._setup_migration(
+ share)
+
+ preserve_snapshots = True if snapshot_id else False
+
+ # Start share server migration.
+ self.shares_v2_client.share_server_migration_start(
+ src_server_id, dest_host,
+ new_share_network_id=dest_share_network_id,
+ preserve_snapshots=preserve_snapshots)
+
+ expected_state = constants.TASK_STATE_MIGRATION_DRIVER_PHASE1_DONE
+ self.shares_v2_client.wait_for_share_server_status(
+ src_server_id, expected_state, status_attr='task_state')
+ # Get for the destination share server.
+ dest_server_id = self._get_share_server_destination_for_migration(
+ src_server_id)
+
+ dest_server = self.shares_v2_client.show_share_server(dest_server_id)
+ self.assertEqual(dest_host, dest_server['host'])
+ self.assertEqual(dest_share_network_id,
+ dest_server['share_network_id'])
+
+ expected_status = constants.STATUS_SERVER_MIGRATING
+ self._validate_state_of_resources(share, expected_status, snapshot_id)
+
+ # Share server migration complete.
+ self.shares_v2_client.share_server_migration_complete(src_server_id)
+
+ # It's necessary wait for the destination server went to active status.
+ expected_status = constants.SERVER_STATE_ACTIVE
+ self.shares_v2_client.wait_for_share_server_status(
+ dest_server_id, expected_status)
+
+ # Check if the source server went to inactive status if it exists.
+ try:
+ src_server = self.shares_v2_client.show_share_server(src_server_id)
+ except exceptions.NotFound:
+ src_server = None
+
+ if src_server:
+ self.assertEqual(
+ src_server['status'], constants.SERVER_STATE_INACTIVE)
+
+ # Validate the share server migration complete.
+ share = self.shares_v2_client.get_share(share['id'])
+ self._validate_share_server_migration_complete(
+ share, dest_host, dest_server_id, snapshot_id=snapshot_id,
+ share_network_id=dest_share_network_id)
+
+ @decorators.idempotent_id('52e154eb-2d39-45af-b5c1-49ea569ab804')
+ @tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
+ @ddt.data(True, False)
+ def test_share_server_migration_check(self, compatible):
+ """The share server migration check compatibility tests."""
+ share = self.create_share(share_protocol=self.protocol,
+ share_type_id=self.share_type['id'],
+ cleanup_in_class=False)
+ share = self.shares_v2_client.get_share(share['id'])
+ # Find a backend compatible or not for the share server
+ # check compatibility operation.
+ if compatible:
+ dest_host, result = (
+ self._choose_compatible_backend_for_share_server(
+ server_id=share['share_server_id']))
+ self.assertTrue(result['compatible'])
+ self.assertEqual(result['requested_capabilities']['host'],
+ dest_host)
+ else:
+ dest_host, result = (
+ self._choose_incompatible_backend_for_share_server(
+ server_id=share['share_server_id']))
+ self.assertFalse(result['compatible'])
+ self.assertEqual(result['requested_capabilities'].get('host'),
+ dest_host)
+
+
+class ShareServerMigrationBasicCIFS(ShareServerMigrationBasicNFS):
+ protocol = "cifs"
diff --git a/manila_tempest_tests/tests/api/admin/test_share_servers_migration_negative.py b/manila_tempest_tests/tests/api/admin/test_share_servers_migration_negative.py
new file mode 100644
index 0000000..3b39a61
--- /dev/null
+++ b/manila_tempest_tests/tests/api/admin/test_share_servers_migration_negative.py
@@ -0,0 +1,392 @@
+# Copyright 2020 NetApp 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.
+
+from tempest import config
+from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
+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.admin import test_share_servers_migration
+from manila_tempest_tests.tests.api import base
+
+CONF = config.CONF
+
+
+class MigrationShareServerNegative(
+ test_share_servers_migration.MigrationShareServerBase):
+ protocol = None
+
+ @classmethod
+ def _setup_migration(cls, cleanup_in_class=True):
+ """Setup migration for negative tests."""
+ extra_specs = {
+ 'driver_handles_share_servers': CONF.share.multitenancy_enabled}
+ if CONF.share.capability_snapshot_support:
+ extra_specs['snapshot_support'] = True
+ share_type = cls.create_share_type(
+ name=data_utils.rand_name("tempest-share-type"),
+ extra_specs=extra_specs,
+ cleanup_in_class=cleanup_in_class)
+ share = cls.create_share(share_protocol=cls.protocol,
+ share_type_id=share_type['share_type']['id'],
+ cleanup_in_class=cleanup_in_class)
+ share = cls.shares_v2_client.get_share(share['id'])
+ share_server_id = share['share_server_id']
+ dest_host, compatible = (
+ cls._choose_compatible_backend_for_share_server(share_server_id))
+
+ return share, share_server_id, dest_host
+
+
+class ShareServerMigrationInvalidParametersNFS(MigrationShareServerNegative):
+ """Tests related to share server not found."""
+ protocol = "nfs"
+
+ @classmethod
+ def resource_setup(cls):
+ super(ShareServerMigrationInvalidParametersNFS, cls).resource_setup()
+ cls.fake_server_id = 'fake_server_id'
+ cls.fake_host = 'fake_host@fake_backend'
+
+ @decorators.idempotent_id('1be6ec2a-3118-4033-9cdb-ea6d199d97f4')
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+ def test_share_server_invalid_server_migration_check(self):
+ """Not found share server in migration check."""
+ self.assertRaises(lib_exc.NotFound,
+ self.shares_v2_client.share_server_migration_check,
+ self.fake_server_id,
+ self.fake_host)
+
+ @decorators.idempotent_id('2aeffcfa-4e68-40e4-8a75-03b017503501')
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+ def test_share_server_invalid_server_migration_cancel(self):
+ """Not found share server in migration cancel."""
+ self.assertRaises(lib_exc.NotFound,
+ self.shares_v2_client.share_server_migration_cancel,
+ self.fake_server_id)
+
+ @decorators.idempotent_id('52d23980-80e7-40de-8dba-1bb1382ef995')
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+ def test_share_server_invalid_server_migration_start(self):
+ """Not found share server in migration start."""
+ self.assertRaises(lib_exc.NotFound,
+ self.shares_v2_client.share_server_migration_start,
+ self.fake_server_id,
+ self.fake_host)
+
+ @decorators.idempotent_id('47795631-eb50-424b-9fac-d2ee832cd01c')
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+ def test_share_server_invalid_server_migration_get_progress(self):
+ """Not found share server in migration get progress."""
+ self.assertRaises(
+ lib_exc.BadRequest,
+ self.shares_v2_client.share_server_migration_get_progress,
+ self.fake_server_id)
+
+ @decorators.idempotent_id('3b464298-a4e4-417b-92d6-acfbd30ac45b')
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+ def test_share_server_invalid_server_migration_complete(self):
+ """Not found share server in migration complete."""
+ self.assertRaises(
+ lib_exc.NotFound,
+ self.shares_v2_client.share_server_migration_complete,
+ self.fake_server_id)
+
+ @decorators.idempotent_id('2d25cf84-0b5c-4a9f-ae20-9bec09bb6914')
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+ def test_share_server_invalid_host_migration_start(self):
+ """Invalid host in migration start."""
+ share = self.create_share(
+ share_protocol=self.protocol,
+ share_type_id=self.share_type['id'])
+ share = self.shares_v2_client.get_share(share['id'])
+ share_server_id = share['share_server_id']
+ self.assertRaises(lib_exc.NotFound,
+ self.shares_v2_client.share_server_migration_start,
+ share_server_id,
+ self.fake_host)
+
+ @decorators.idempotent_id('e7e2c19c-a0ed-41ab-b666-b2beae4a690c')
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+ def test_share_server_invalid_host_migration_check(self):
+ """Invalid host in migration check."""
+ share = self.create_share(
+ share_protocol=self.protocol,
+ share_type_id=self.share_type['id'])
+ share = self.shares_v2_client.get_share(share['id'])
+ share_server_id = share['share_server_id']
+ self.assertRaises(lib_exc.NotFound,
+ self.shares_v2_client.share_server_migration_check,
+ share_server_id,
+ self.fake_host)
+
+ @decorators.idempotent_id('f0d7a055-3b46-4d2b-9b96-1d719bd323e8')
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+ def test_share_server_invalid_share_network_migration_start(self):
+ """Invalid host in migration start."""
+ share = self.create_share(
+ share_protocol=self.protocol,
+ share_type_id=self.share_type['id'])
+ share = self.shares_v2_client.get_share(share['id'])
+ share_server_id = share['share_server_id']
+ dest_host, _ = self._choose_compatible_backend_for_share_server(
+ share_server_id)
+ self.assertRaises(lib_exc.BadRequest,
+ self.shares_v2_client.share_server_migration_start,
+ share_server_id,
+ dest_host,
+ new_share_network_id='fake_share_net_id')
+
+ @decorators.idempotent_id('2617e714-7a8e-49a4-8109-beab3ea6527f')
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+ def test_share_server_invalid_share_network_migration_check(self):
+ """Invalid host in migration check."""
+ share = self.create_share(
+ share_protocol=self.protocol,
+ share_type_id=self.share_type['id'])
+ share = self.shares_v2_client.get_share(share['id'])
+ share_server_id = share['share_server_id']
+ dest_host, _ = self._choose_compatible_backend_for_share_server(
+ share_server_id)
+ self.assertRaises(lib_exc.BadRequest,
+ self.shares_v2_client.share_server_migration_check,
+ share_server_id,
+ self.fake_host,
+ new_share_network_id='fake_share_net_id')
+
+
+class ShareServerErrorStatusOperationNFS(MigrationShareServerNegative):
+ protocol = "nfs"
+
+ @classmethod
+ def resource_setup(cls):
+ super(ShareServerErrorStatusOperationNFS, cls).resource_setup()
+ cls.share = cls.create_share(
+ share_protocol=cls.protocol,
+ share_type_id=cls.share_type['id'])
+ cls.share = cls.shares_v2_client.get_share(cls.share['id'])
+ cls.share_server_id = cls.share['share_server_id']
+ cls.dest_host, _ = cls._choose_compatible_backend_for_share_server(
+ cls.share_server_id)
+ cls.shares_v2_client.share_server_reset_state(
+ cls.share_server_id, status=constants.STATUS_ERROR)
+
+ @decorators.idempotent_id('1f8d75c1-aa3c-465a-b2dd-9ad33933944f')
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+ def test_share_server_invalid_operation_migration_check(self):
+ """Share server migration check invalid operation."""
+ self.assertRaises(lib_exc.Conflict,
+ self.shares_v2_client.share_server_migration_check,
+ self.share_server_id,
+ self.dest_host)
+
+ @decorators.idempotent_id('c256c5f5-b4d1-47b7-a1f4-af21f19ce600')
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+ def test_share_server_invalid_operation_migration_start(self):
+ """Share server migration start invalid operation."""
+ self.assertRaises(lib_exc.Conflict,
+ self.shares_v2_client.share_server_migration_start,
+ self.share_server_id,
+ self.dest_host)
+
+ @decorators.idempotent_id('d2830fe4-8d13-40d2-b987-18d414bb6196')
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+ def test_share_server_invalid_operation_migration_get_progress(self):
+ """Share server migration get progress invalid operation."""
+ self.assertRaises(
+ lib_exc.BadRequest,
+ self.shares_v2_client.share_server_migration_get_progress,
+ self.share_server_id)
+
+ @decorators.idempotent_id('245f39d7-bcbc-4711-afd7-651a5535a880')
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+ def test_share_server_invalid_operation_migration_cancel(self):
+ """Share server migration cancel invalid operation."""
+ self.assertRaises(lib_exc.BadRequest,
+ self.shares_v2_client.share_server_migration_cancel,
+ self.share_server_id)
+
+ @decorators.idempotent_id('3db45440-2c70-4fa4-b5eb-75e3cb0204f8')
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+ def test_share_server_invalid_operation_migration_complete(self):
+ """Share server migration complete invalid operation."""
+ self.assertRaises(
+ lib_exc.BadRequest,
+ self.shares_v2_client.share_server_migration_complete,
+ self.share_server_id)
+
+
+class ShareServerMigrationStartNegativesNFS(MigrationShareServerNegative):
+ protocol = "nfs"
+
+ @classmethod
+ def resource_setup(cls):
+ super(ShareServerMigrationStartNegativesNFS, cls).resource_setup()
+ cls.share, cls.server_id, cls.dest_host = cls._setup_migration()
+ cls.shares_v2_client.share_server_migration_start(
+ cls.server_id, cls.dest_host)
+
+ @classmethod
+ def resource_cleanup(cls):
+ states = [constants.TASK_STATE_MIGRATION_DRIVER_IN_PROGRESS,
+ constants.TASK_STATE_MIGRATION_DRIVER_PHASE1_DONE]
+ cls.shares_v2_client.wait_for_share_server_status(
+ cls.server_id, status=states, status_attr="task_state")
+ cls.shares_v2_client.share_server_migration_cancel(cls.server_id)
+ cls.shares_v2_client.wait_for_share_status(cls.share['id'],
+ status="available")
+ super(ShareServerMigrationStartNegativesNFS, cls).resource_cleanup()
+
+ @decorators.idempotent_id('5b904db3-fc36-4c35-a8ef-cf6b80315388')
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+ def test_share_server_migration_start_try_create_snapshot(self):
+ """Try create snap during a server migration."""
+ if not CONF.share.capability_snapshot_support:
+ raise self.skipException(
+ 'Snapshot tests are disabled or unsupported.')
+ self.assertRaises(
+ lib_exc.BadRequest,
+ self.shares_v2_client.create_snapshot,
+ self.share['id']
+ )
+
+ @decorators.idempotent_id('93882b54-78d4-4c4e-95b5-993de0cdb25d')
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+ def test_share_server_migration_start_try_create_access_rule(self):
+ """Try create access rule during a server migration."""
+ self.assertRaises(
+ lib_exc.BadRequest,
+ self.shares_v2_client.create_access_rule,
+ self.share['id']
+ )
+
+ @decorators.idempotent_id('7c74a4a8-61b2-4c55-bc4b-02eac73d2c6e')
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+ def test_share_server_migration_start_try_delete_share_network(self):
+ """Try delete share network during a server migration."""
+ self.assertRaises(
+ lib_exc.Conflict,
+ self.shares_v2_client.delete_share_network,
+ self.share['share_network_id']
+ )
+
+
+class ShareServerMigrationStartInvalidStatesNFS(MigrationShareServerNegative):
+ protocol = "nfs"
+
+ @decorators.idempotent_id('bcec0503-b2a9-4514-bf3f-a30d55f41e78')
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+ def test_share_server_migration_start_invalid_network(self):
+ """Try server migration start with invalid network."""
+ share, share_server_id, dest_host = self._setup_migration(
+ cleanup_in_class=False)
+ azs = self.get_availability_zones()
+ if len(azs) < 2:
+ raise self.skipException(
+ "Could not find the necessary azs. At least two azs are "
+ "needed to run this test.")
+
+ # In this test we'll attempt to start a migration to a share
+ # network that isn't available in the destination back ends's
+ # availability zone.
+ dest_host_az = self.get_availability_zones(backends=[dest_host])
+
+ if dest_host_az[0] != share['availability_zone']:
+ share_network_az = share['availability_zone']
+ else:
+ for az in azs:
+ if az != dest_host_az:
+ share_network_az = az
+ break
+
+ share_network = self.create_share_network(
+ client=self.shares_v2_client, cleanup_in_class=False,
+ availability_zone=share_network_az)
+ self.assertRaises(
+ lib_exc.Conflict,
+ self.shares_v2_client.share_server_migration_start,
+ share_server_id,
+ dest_host,
+ new_share_network_id=share_network['id'])
+
+ @decorators.idempotent_id('11374277-efcf-4992-ad94-c8f4a393d41b')
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+ def test_share_server_migration_start_invalid_share_state(self):
+ """Try server migration start with invalid share state."""
+ share, share_server_id, dest_host = self._setup_migration(
+ cleanup_in_class=False)
+ self.shares_v2_client.reset_state(share['id'], status='error')
+
+ self.assertRaises(
+ lib_exc.Conflict,
+ self.shares_v2_client.share_server_migration_start,
+ share_server_id,
+ dest_host
+ )
+
+ @decorators.idempotent_id('ebe8da5b-ee9c-48c7-a7e4-9e71839f813f')
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+ def test_share_server_migration_start_with_share_replica(self):
+ """Try server migration start with share replica."""
+ if not CONF.share.backend_replication_type or (
+ not CONF.share.run_replication_tests):
+ raise self.skipException(
+ 'Share replica tests are disabled or unsupported.')
+ extra_specs = {
+ 'driver_handles_share_servers': CONF.share.multitenancy_enabled,
+ 'replication_type': CONF.share.backend_replication_type
+ }
+ share_type = self.shares_v2_client.create_share_type(
+ name=data_utils.rand_name("tempest-share-type"),
+ extra_specs=extra_specs,
+ cleanup_in_class=False)
+ share = self.create_share(share_type_id=share_type['share_type']['id'],
+ share_protocol=self.protocol,
+ cleanup_in_class=False)
+ share = self.shares_v2_client.get_share(share['id'])
+ share_server_id = share['share_server_id']
+ dest_host, _ = self._choose_compatible_backend_for_share_server(
+ share_server_id)
+ self.create_share_replica(
+ share['id'],
+ cleanup_in_class=False)
+ self.assertRaises(
+ lib_exc.Conflict,
+ self.shares_v2_client.share_server_migration_start,
+ share_server_id,
+ dest_host
+ )
+
+
+class ShareServerMigrationInvalidParametersCIFS(
+ ShareServerMigrationInvalidParametersNFS):
+ protocol = "cifs"
+
+
+class ShareServerErrorStatusOperationCIFS(ShareServerErrorStatusOperationNFS):
+ protocol = "cifs"
+
+
+class ShareServerMigrationStartNegativesCIFS(
+ ShareServerMigrationStartNegativesNFS):
+ protocol = "cifs"
+
+
+class ShareServerMigrationInvalidStatesCIFS(
+ ShareServerMigrationStartInvalidStatesNFS):
+ protocol = "cifs"
diff --git a/manila_tempest_tests/tests/api/admin/test_share_servers_negative.py b/manila_tempest_tests/tests/api/admin/test_share_servers_negative.py
index e281914..8f2110d 100644
--- a/manila_tempest_tests/tests/api/admin/test_share_servers_negative.py
+++ b/manila_tempest_tests/tests/api/admin/test_share_servers_negative.py
@@ -14,6 +14,7 @@
# under the License.
from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
from testtools import testcase as tc
@@ -28,65 +29,76 @@
cls.admin_client = cls.admin_shares_v2_client
cls.member_client = cls.shares_v2_client
+ @decorators.idempotent_id('6d55516f-9018-4372-8310-f725c4562961')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_list_share_servers_with_member(self):
self.assertRaises(lib_exc.Forbidden,
self.member_client.list_share_servers)
+ @decorators.idempotent_id('d9021f06-c146-4e76-852e-8a1ebb3fa92e')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_show_share_server_with_member(self):
self.assertRaises(lib_exc.Forbidden,
self.member_client.show_share_server,
'fake_id')
+ @decorators.idempotent_id('16b6f911-487e-4c25-9241-75de2dbfc8ff')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_show_share_server_details_with_member(self):
self.assertRaises(lib_exc.Forbidden,
self.member_client.show_share_server_details,
'fake_id')
+ @decorators.idempotent_id('f7580ef6-f7bb-4b52-ba45-82d2d2d66dbe')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_show_share_server_with_inexistent_id(self):
self.assertRaises(lib_exc.NotFound,
self.admin_client.show_share_server,
'fake_id')
+ @decorators.idempotent_id('368c5404-483e-4eee-bb80-86206d153ea2')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_show_share_server_details_with_inexistent_id(self):
self.assertRaises(lib_exc.NotFound,
self.admin_client.show_share_server_details,
'fake_id')
+ @decorators.idempotent_id('664b5201-7ba9-4e33-9534-5307fc003e44')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_list_share_servers_with_wrong_filter_key(self):
search_opts = {'fake_filter_key': 'ACTIVE'}
servers = self.admin_client.list_share_servers(search_opts)
self.assertEqual(0, len(servers))
+ @decorators.idempotent_id('dcf169c9-1238-40cb-8a5c-ca6aca9d4d6b')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_list_share_servers_with_wrong_filter_value(self):
search_opts = {'host': 123}
servers = self.admin_client.list_share_servers(search_opts)
self.assertEqual(0, len(servers))
+ @decorators.idempotent_id('3e5d6007-5214-4fa2-bd33-dfd3bead67bf')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_list_share_servers_with_fake_status(self):
search_opts = {"status": data_utils.rand_name("fake_status")}
servers = self.admin_client.list_share_servers(search_opts)
self.assertEqual(0, len(servers))
+ @decorators.idempotent_id('e893b32a-124f-4e5c-a425-58c8a4eac4a5')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_list_share_servers_with_fake_host(self):
search_opts = {"host": data_utils.rand_name("fake_host")}
servers = self.admin_client.list_share_servers(search_opts)
self.assertEqual(0, len(servers))
+ @decorators.idempotent_id('2f1162a8-bb52-4e2a-abc0-68d16f769e4f')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_list_share_servers_with_fake_project(self):
search_opts = {"project_id": data_utils.rand_name("fake_project_id")}
servers = self.admin_client.list_share_servers(search_opts)
self.assertEqual(0, len(servers))
+ @decorators.idempotent_id('ca23f385-56b2-4c02-9797-d88c3b7fb981')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_list_share_servers_with_fake_share_network(self):
search_opts = {
@@ -95,12 +107,14 @@
servers = self.admin_client.list_share_servers(search_opts)
self.assertEqual(0, len(servers))
+ @decorators.idempotent_id('0acb9107-18b2-4e9d-8432-37fd0d4c79b3')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_delete_share_server_with_nonexistent_id(self):
self.assertRaises(lib_exc.NotFound,
self.admin_client.delete_share_server,
"fake_nonexistent_share_server_id")
+ @decorators.idempotent_id('65e12bf7-2ec6-4a5b-971b-b1ecb67b77b7')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_delete_share_server_with_member(self):
self.assertRaises(lib_exc.Forbidden,
diff --git a/manila_tempest_tests/tests/api/admin/test_share_snapshot_instances.py b/manila_tempest_tests/tests/api/admin/test_share_snapshot_instances.py
index b8b859f..d09b25f 100644
--- a/manila_tempest_tests/tests/api/admin/test_share_snapshot_instances.py
+++ b/manila_tempest_tests/tests/api/admin/test_share_snapshot_instances.py
@@ -15,6 +15,7 @@
import ddt
from tempest import config
+from tempest.lib import decorators
from testtools import testcase as tc
from manila_tempest_tests.tests.api import base
@@ -46,6 +47,7 @@
cls.snapshot = cls.shares_v2_client.get_snapshot(snap['id'])
@ddt.data(True, False)
+ @decorators.idempotent_id('bcb29129-9713-4481-8e74-97682c62f218')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_list_snapshot_instances_by_snapshot(self, detail):
"""Test that we get only the 1 snapshot instance from snapshot."""
@@ -78,6 +80,7 @@
self.assertIn(key, expected_keys)
self.assertEqual(len(expected_keys), len(si))
+ @decorators.idempotent_id('1d0bd333-300d-4af2-81eb-176b550f2c36')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_list_snapshot_instances(self):
"""Test that we get at least the snapshot instance."""
@@ -89,6 +92,7 @@
self.snapshot['id'])
self.assertIn(self.snapshot['id'], snapshot_ids, msg)
+ @decorators.idempotent_id('d21bf82d-2b3b-4061-8db5-502b7376a44d')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_get_snapshot_instance(self):
instances = self.shares_v2_client.list_snapshot_instances(
@@ -110,6 +114,7 @@
self.assertEqual(self.snapshot['provider_location'],
instance_detail['provider_location'])
+ @decorators.idempotent_id('c7724848-4e17-4d28-801d-2ec77dfcf502')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_reset_snapshot_instance_status_and_delete(self):
"""Test resetting a snapshot instance's status attribute."""
diff --git a/manila_tempest_tests/tests/api/admin/test_share_snapshot_instances_negative.py b/manila_tempest_tests/tests/api/admin/test_share_snapshot_instances_negative.py
index 17d9bcc..730ce8b 100644
--- a/manila_tempest_tests/tests/api/admin/test_share_snapshot_instances_negative.py
+++ b/manila_tempest_tests/tests/api/admin/test_share_snapshot_instances_negative.py
@@ -14,6 +14,7 @@
# under the License.
from tempest import config
+from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
from testtools import testcase as tc
@@ -47,6 +48,7 @@
cls.snapshot = cls.create_snapshot_wait_for_active(
cls.share["id"], client=cls.admin_client)
+ @decorators.idempotent_id('6e371aac-ff8b-4eac-abc9-b8d777448ff3')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_list_snapshot_instances_with_snapshot_by_non_admin(self):
self.assertRaises(
@@ -54,6 +56,7 @@
self.member_client.list_snapshot_instances,
snapshot_id=self.snapshot['id'])
+ @decorators.idempotent_id('d80331e4-8738-46c7-b726-1e716acef738')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_get_snapshot_instance_by_non_admin(self):
instances = self.admin_client.list_snapshot_instances(
@@ -63,6 +66,7 @@
self.member_client.get_snapshot_instance,
instance_id=instances[0]['id'])
+ @decorators.idempotent_id('666a6caf-31b0-45d9-808c-e590250cffd4')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_reset_snapshot_instance_status_by_non_admin(self):
instances = self.admin_client.list_snapshot_instances(
@@ -90,12 +94,14 @@
cls.admin_client = cls.admin_shares_v2_client
cls.member_client = cls.shares_v2_client
+ @decorators.idempotent_id('abded04d-40c0-4eb9-b2be-58b4efb16244')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_get_snapshot_instance_with_non_existent_instance(self):
self.assertRaises(lib_exc.NotFound,
self.admin_client.get_snapshot_instance,
instance_id="nonexistent_instance")
+ @decorators.idempotent_id('1609702b-de87-4d12-9a9c-78077d4676f3')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_list_snapshot_instances_by_non_admin(self):
self.assertRaises(
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 a4a093b..370e014 100644
--- a/manila_tempest_tests/tests/api/admin/test_share_types.py
+++ b/manila_tempest_tests/tests/api/admin/test_share_types.py
@@ -16,6 +16,7 @@
import ddt
from tempest import config
from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
from testtools import testcase as tc
@@ -30,6 +31,7 @@
@ddt.ddt
class ShareTypesAdminTest(base.BaseSharesAdminTest):
+ @decorators.idempotent_id('34000fb9-b595-4a10-8306-7465f9ebc45d')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_share_type_create_delete(self):
name = data_utils.rand_name("tempest-manila")
@@ -66,6 +68,7 @@
else:
self.assertNotIn('description', share_type)
+ @decorators.idempotent_id('228d8bab-0b31-433e-956f-9db9877e6573')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@ddt.data('2.0', '2.6', '2.7', '2.40', '2.41')
def test_share_type_create_get(self, version):
@@ -99,6 +102,7 @@
self.assertDictMatch(get["volume_type"], get["share_type"])
@base.skip_if_microversion_lt("2.50")
+ @decorators.idempotent_id('a9af19e1-e789-4c4f-a39b-dd8df6ed00b1')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@ddt.data(
('2.50', data_utils.rand_name("type_updated"),
@@ -147,6 +151,7 @@
updated_st["share_type"]["share_type_access:is_public"])
@base.skip_if_microversion_lt("2.50")
+ @decorators.idempotent_id('9019dc61-b2b1-472d-9b15-a3986439d4c3')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@ddt.data(
('2.50', None, '', None),
@@ -176,6 +181,7 @@
self._verify_description(None, updated_st['share_type'], version)
+ @decorators.idempotent_id('5cc4c2e5-d2a4-4bfc-9208-3455ac551f20')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@ddt.data('2.0', '2.6', '2.7', '2.40', '2.41')
def test_share_type_create_list(self, version):
@@ -208,6 +214,7 @@
for i in range(len(sts)):
self.assertDictMatch(sts[i], vts[i])
+ @decorators.idempotent_id('4e2ad320-9f3d-4797-a3ad-bf800bcd1831')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_get_share_with_share_type(self):
@@ -238,6 +245,7 @@
self.assertEqual(st_create["share_type"]["id"], get["share_type"])
self.assertEqual(shr_type_name, get["share_type_name"])
+ @decorators.idempotent_id('d2261a27-d4a4-4237-9fad-f6fd8f27783a')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_private_share_type_access(self):
name = data_utils.rand_name("tempest-manila")
@@ -286,6 +294,7 @@
access = self.shares_v2_client.list_access_to_share_type(st_id)
self.assertEmpty(access)
+ @decorators.idempotent_id('90dca5c5-f28e-4f16-90ed-78f5d725664e')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@ddt.data(*set(('2.45', '2.46', LATEST_MICROVERSION)))
def test_share_type_create_show_list_with_is_default_key(self, version):
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 f4c21b8..1855713 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
@@ -18,6 +18,7 @@
import ddt
from tempest import config
from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
from testtools import testcase as tc
from manila_tempest_tests.tests.api import base
@@ -46,6 +47,7 @@
cls.shares_client.create_share_type_extra_specs(
cls.st_id, cls.custom_extra_specs)
+ @decorators.idempotent_id('d4cae104-838b-4248-8c9c-125165710786')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_get_one_share_type_extra_spec(self):
es_get_one = self.shares_client.get_share_type_extra_spec(
@@ -53,6 +55,7 @@
self.assertEqual({"key1": self.custom_extra_specs["key1"]}, es_get_one)
+ @decorators.idempotent_id('508ceb85-5456-4db9-b33f-00620d7baea1')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_get_all_share_type_extra_specs(self):
es_get_all = self.shares_client.get_share_type_extra_specs(self.st_id)
@@ -79,6 +82,7 @@
self.shares_client.create_share_type_extra_specs(
self.st_id, self.custom_extra_specs)
+ @decorators.idempotent_id('baba776b-1b05-42ca-a002-bff1f8f14e13')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_update_one_share_type_extra_spec(self):
self.custom_extra_specs["key1"] = "fake_value1_updated"
@@ -93,6 +97,7 @@
expected_extra_specs.update(self.required_extra_specs)
self.assertEqual(self.custom_extra_specs, get)
+ @decorators.idempotent_id('374e7ff5-0d26-4778-bbb5-4ffd28521ad9')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_update_all_share_type_extra_specs(self):
self.custom_extra_specs["key2"] = "value2_updated"
@@ -107,6 +112,7 @@
expected_extra_specs.update(self.required_extra_specs)
self.assertEqual(self.custom_extra_specs, get)
+ @decorators.idempotent_id('129db0ce-9a4f-4a40-994f-e492174e0661')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_delete_one_share_type_extra_spec(self):
# Delete one extra spec for share type
@@ -117,6 +123,7 @@
self.assertNotIn('key1', get)
+ @decorators.idempotent_id('1b9f501d-8f34-46d0-b318-83bdfed571ec')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@ddt.data(*set(['2.24', LATEST_MICROVERSION]))
def test_delete_snapshot_support_extra_spec(self, version):
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 262e387..8d2893c 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
@@ -16,6 +16,7 @@
import ddt
from tempest import config
from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
from testtools import testcase as tc
@@ -37,6 +38,7 @@
extra_specs=extra_specs,
client=self.admin_shares_v2_client)["share_type"]
+ @decorators.idempotent_id('195c1cc6-249a-4f82-b420-4901d2557b3a')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_create_extra_specs_with_user(self):
st = self._create_share_type()
@@ -46,6 +48,7 @@
st["id"],
self.add_extra_specs_to_dict({"key": "new_value"}))
+ @decorators.idempotent_id('dc883ec3-1bae-4ed7-8bf5-2cdc7027e37b')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_list_extra_specs_with_user(self):
st = self._create_share_type()
@@ -54,6 +57,7 @@
self.shares_v2_client.get_share_type_extra_specs,
st["id"])
+ @decorators.idempotent_id('1d3e687e-b2fb-4b96-8428-324ff881eea2')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_get_extra_spec_with_user(self):
st = self._create_share_type()
@@ -62,6 +66,7 @@
self.shares_v2_client.get_share_type_extra_spec,
st["id"], "key")
+ @decorators.idempotent_id('4c9505d9-d4ef-42fa-8410-8ab88ec0c852')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_get_extra_specs_with_user(self):
st = self._create_share_type()
@@ -70,6 +75,7 @@
self.shares_v2_client.get_share_type_extra_specs,
st["id"])
+ @decorators.idempotent_id('36c5ada4-9efd-4f6a-b58d-24f08a2433ce')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_read_extra_specs_on_share_type_with_user(self):
st = self._create_share_type()
@@ -88,6 +94,7 @@
'Incorrect extra specs visible to non-admin user; '
'expected %s, got %s' % (expected_keys, actual_keys))
+ @decorators.idempotent_id('62a9b77a-f796-4bd9-baf9-7c24b3f55560')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_update_extra_spec_with_user(self):
st = self._create_share_type()
@@ -96,6 +103,7 @@
self.shares_v2_client.update_share_type_extra_spec,
st["id"], "key", "new_value")
+ @decorators.idempotent_id('207cec3c-8ed9-4d6d-8fc8-3aecaacdff93')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_update_extra_specs_with_user(self):
st = self._create_share_type()
@@ -104,6 +112,7 @@
self.shares_v2_client.update_share_type_extra_specs,
st["id"], {"key": "new_value"})
+ @decorators.idempotent_id('3f43c5d0-23c5-4b76-98c7-a3f9adb33c89')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_delete_extra_specs_with_user(self):
st = self._create_share_type()
@@ -112,6 +121,7 @@
self.shares_v2_client.delete_share_type_extra_spec,
st["id"], "key")
+ @decorators.idempotent_id('d82a7bcc-1dc5-4ef8-87cd-f8dff1574adc')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_set_too_long_key(self):
too_big_key = "k" * 256
@@ -122,6 +132,7 @@
st["id"],
self.add_extra_specs_to_dict({too_big_key: "value"}))
+ @decorators.idempotent_id('210faa88-8f2f-45f5-9bcf-54ce81d03788')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_set_too_long_value_with_creation(self):
too_big_value = "v" * 256
@@ -132,6 +143,7 @@
st["id"],
self.add_extra_specs_to_dict({"key": too_big_value}))
+ @decorators.idempotent_id('890dceaa-22c4-4d2c-99ca-16ac8cdda33c')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_set_too_long_value_with_update(self):
too_big_value = "v" * 256
@@ -145,6 +157,7 @@
st["id"],
self.add_extra_specs_to_dict({"key": too_big_value}))
+ @decorators.idempotent_id('c512437e-6cfd-4545-859f-554955bd0fc9')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_set_too_long_value_with_update_of_one_key(self):
too_big_value = "v" * 256
@@ -157,12 +170,14 @@
self.admin_shares_v2_client.update_share_type_extra_spec,
st["id"], "key", too_big_value)
+ @decorators.idempotent_id('938115f7-512e-49c3-a16a-a6498d6069bb')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_list_es_with_empty_shr_type_id(self):
self.assertRaises(
lib_exc.NotFound,
self.admin_shares_v2_client.get_share_type_extra_specs, "")
+ @decorators.idempotent_id('65c3c528-008f-43f5-b367-8bd77cfab4a7')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_list_es_with_invalid_shr_type_id(self):
self.assertRaises(
@@ -170,6 +185,7 @@
self.admin_shares_v2_client.get_share_type_extra_specs,
data_utils.rand_name("fake"))
+ @decorators.idempotent_id('430e0bed-9073-4822-8d0b-a3c55a8dfa31')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_create_es_with_empty_shr_type_id(self):
self.assertRaises(
@@ -177,6 +193,7 @@
self.admin_shares_v2_client.create_share_type_extra_specs,
"", {"key1": "value1", })
+ @decorators.idempotent_id('7b43025d-b014-460f-9c9d-1004433fb798')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_create_es_with_invalid_shr_type_id(self):
self.assertRaises(
@@ -184,6 +201,7 @@
self.admin_shares_v2_client.create_share_type_extra_specs,
data_utils.rand_name("fake"), {"key1": "value1", })
+ @decorators.idempotent_id('7b9bee14-5ca5-4110-a56a-b3030b6b3948')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_create_es_with_empty_specs(self):
st = self._create_share_type()
@@ -192,6 +210,7 @@
self.admin_shares_v2_client.create_share_type_extra_specs,
st["id"], "")
+ @decorators.idempotent_id('7f199925-44d2-4d92-bedc-2636c07621fb')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_create_es_with_invalid_specs(self):
st = self._create_share_type()
@@ -200,6 +219,7 @@
self.admin_shares_v2_client.create_share_type_extra_specs,
st["id"], {"": "value_with_empty_key"})
+ @decorators.idempotent_id('51241ed9-350b-4218-bfb0-c446d660d70b')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_get_extra_spec_with_empty_key(self):
st = self._create_share_type()
@@ -208,6 +228,7 @@
self.admin_shares_v2_client.get_share_type_extra_spec,
st["id"], "")
+ @decorators.idempotent_id('271d825b-2c57-429a-8dca-2cb9dd140dd0')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_get_extra_spec_with_invalid_key(self):
st = self._create_share_type()
@@ -216,6 +237,7 @@
self.admin_shares_v2_client.get_share_type_extra_spec,
st["id"], data_utils.rand_name("fake"))
+ @decorators.idempotent_id('cf07e7bc-cd3a-4c85-a848-786a60ba1f7d')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_get_extra_specs_with_empty_shr_type_id(self):
self.assertRaises(
@@ -223,6 +245,7 @@
self.admin_shares_v2_client.get_share_type_extra_specs,
"")
+ @decorators.idempotent_id('dfe6e34b-c86a-4cf6-9bf3-19de3a886b67')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_get_extra_specs_with_invalid_shr_type_id(self):
self.assertRaises(
@@ -230,6 +253,7 @@
self.admin_shares_v2_client.get_share_type_extra_specs,
data_utils.rand_name("fake"))
+ @decorators.idempotent_id('0b8f6b51-0583-4b59-a851-9189db657a05')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_delete_es_key_with_empty_shr_type_id(self):
self.assertRaises(
@@ -237,6 +261,7 @@
self.admin_shares_v2_client.delete_share_type_extra_spec,
"", "key", )
+ @decorators.idempotent_id('9aa8fb2a-28a5-44b7-848b-9b49e1e9d670')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_delete_es_key_with_invalid_shr_type_id(self):
self.assertRaises(
@@ -244,6 +269,7 @@
self.admin_shares_v2_client.delete_share_type_extra_spec,
data_utils.rand_name("fake"), "key", )
+ @decorators.idempotent_id('cd68d020-24d2-4f68-8691-782b4815c1b0')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_delete_with_invalid_key(self):
st = self._create_share_type()
@@ -252,6 +278,7 @@
self.admin_shares_v2_client.delete_share_type_extra_spec,
st["id"], data_utils.rand_name("fake"))
+ @decorators.idempotent_id('1ed5cbc9-21a8-45b7-8069-b7c0aaeede21')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_update_spec_with_empty_shr_type_id(self):
self.assertRaises(
@@ -259,6 +286,7 @@
self.admin_shares_v2_client.update_share_type_extra_spec,
"", "key", "new_value")
+ @decorators.idempotent_id('704087fa-0397-4d9d-98b7-f9b081f64c86')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_update_spec_with_invalid_shr_type_id(self):
self.assertRaises(
@@ -266,6 +294,7 @@
self.admin_shares_v2_client.update_share_type_extra_spec,
data_utils.rand_name("fake"), "key", "new_value")
+ @decorators.idempotent_id('eab96e92-9b95-44b0-89a2-e907a103039d')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_update_spec_with_empty_key(self):
st = self._create_share_type()
@@ -274,6 +303,7 @@
self.admin_shares_v2_client.update_share_type_extra_spec,
st["id"], "", "new_value")
+ @decorators.idempotent_id('70af1a8a-ab3e-4c8b-862d-8a36c2d47cb3')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_update_with_invalid_shr_type_id(self):
self.assertRaises(
@@ -281,6 +311,7 @@
self.admin_shares_v2_client.update_share_type_extra_specs,
data_utils.rand_name("fake"), {"key": "new_value"})
+ @decorators.idempotent_id('d2595594-eaad-43dc-b847-0a009a17d854')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_update_with_invalid_specs(self):
st = self._create_share_type()
@@ -289,6 +320,7 @@
self.admin_shares_v2_client.update_share_type_extra_specs,
st["id"], {"": "new_value"})
+ @decorators.idempotent_id('6849eada-89a8-4009-a91d-87367621f9aa')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_delete_spec_driver_handles_share_servers(self):
st = self._create_share_type()
@@ -300,6 +332,7 @@
st["id"],
"driver_handles_share_servers")
+ @decorators.idempotent_id('6ea50e81-2c93-4258-8358-6f8d354a339a')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
@ddt.data('2.0', '2.23')
def test_try_delete_required_spec_snapshot_support_version(self, 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 c828d37..2018a70 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
@@ -15,6 +15,7 @@
import ddt
from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
from testtools import testcase as tc
@@ -32,12 +33,14 @@
extra_specs=extra_specs,
client=self.admin_shares_v2_client)["share_type"]
+ @decorators.idempotent_id('0efe4ed6-9318-4174-aef7-fca4b6aa6444')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_create_share_with_nonexistent_share_type(self):
self.assertRaises(lib_exc.NotFound,
self.admin_shares_v2_client.create_share,
share_type_id=data_utils.rand_name("fake"))
+ @decorators.idempotent_id('a1cd6c4f-4dc4-4f45-813b-f1cd3527c614')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_create_share_type_with_empty_name(self):
self.assertRaises(
@@ -45,6 +48,7 @@
self.create_share_type, '',
client=self.admin_shares_v2_client)
+ @decorators.idempotent_id('ca59430b-d1fb-4e8f-b1e3-6ab6a6b40984')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_create_share_type_with_too_big_name(self):
self.assertRaises(lib_exc.BadRequest,
@@ -52,6 +56,7 @@
"x" * 256,
client=self.admin_shares_v2_client)
+ @decorators.idempotent_id('42f7777a-7ee4-4622-80f8-8726b467c4db')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
@ddt.data('2.0', '2.6', '2.40')
def test_create_share_type_with_description_in_wrong_version(
@@ -64,18 +69,21 @@
version=version,
client=self.admin_shares_v2_client)
+ @decorators.idempotent_id('43b0ef5a-3a05-4f74-a08e-57efebb7e66e')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_get_share_type_by_nonexistent_id(self):
self.assertRaises(lib_exc.NotFound,
self.admin_shares_v2_client.get_share_type,
data_utils.rand_name("fake"))
+ @decorators.idempotent_id('27e00ad7-edc8-4d50-b53e-4da41dd8a5d3')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_delete_share_type_by_nonexistent_id(self):
self.assertRaises(lib_exc.NotFound,
self.admin_shares_v2_client.delete_share_type,
data_utils.rand_name("fake"))
+ @decorators.idempotent_id('1f481bab-5205-49ee-bf01-b1848a32f9ee')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_create_duplicate_of_share_type(self):
st = self._create_share_type()
@@ -85,6 +93,7 @@
extra_specs=self.add_extra_specs_to_dict(),
client=self.admin_shares_v2_client)
+ @decorators.idempotent_id('c13f54eb-17a4-4403-be87-f6a3ca18de6e')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_add_share_type_allowed_for_public(self):
st = self._create_share_type()
@@ -93,6 +102,7 @@
st["id"],
self.admin_shares_v2_client.tenant_id)
+ @decorators.idempotent_id('bf1d68fb-b954-4b3b-af54-115f3b67b3b3')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_remove_share_type_allowed_for_public(self):
st = self._create_share_type()
@@ -102,6 +112,7 @@
st["id"],
self.admin_shares_v2_client.tenant_id)
+ @decorators.idempotent_id('3d9a7e9d-2b64-422e-b8b6-88c3088564f6')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_add_share_type_by_nonexistent_id(self):
self.assertRaises(lib_exc.NotFound,
@@ -109,6 +120,7 @@
data_utils.rand_name("fake"),
self.admin_shares_v2_client.tenant_id)
+ @decorators.idempotent_id('13d5c3cd-15cd-4c2e-ace6-46889cf9e0e2')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_remove_share_type_by_nonexistent_id(self):
self.assertRaises(
@@ -116,3 +128,35 @@
self.admin_shares_v2_client.remove_access_from_share_type,
data_utils.rand_name("fake"),
self.admin_shares_v2_client.tenant_id)
+
+ @decorators.idempotent_id('0fd53c51-e1ba-4392-9f4c-5d3bdd157163')
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_BACKEND)
+ def test_create_share_with_non_allowed_share_type(self):
+ # Create a private share type
+ name = data_utils.rand_name('share-type')
+ share_type = self.create_share_type(
+ client=self.admin_shares_v2_client,
+ name=name, is_public=False,
+ extra_specs=self.add_extra_specs_to_dict())['share_type']
+
+ # The share type should not be listed without access
+ share_type_list = (
+ self.admin_shares_v2_client.list_share_types()['share_types'])
+ self.assertFalse(
+ any(share_type['id'] in st['id'] for st in share_type_list))
+
+ # List projects that have access for share type - none expected
+ access = self.admin_shares_v2_client.list_access_to_share_type(
+ share_type['id'])
+ self.assertEmpty(access)
+
+ # Although the share type should not be found on alt project,
+ # try to create a share with it by using the share type name
+ self.assertRaises(lib_exc.NotFound,
+ self.alt_shares_v2_client.create_share,
+ share_type_id=share_type['name'])
+
+ # The share should not be listed
+ share_list = self.alt_shares_v2_client.list_shares(detailed=True)
+ self.assertFalse(
+ any(share_type['id'] in s['share_type'] for s in share_list))
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 dfadd7a..d6b9d22 100644
--- a/manila_tempest_tests/tests/api/admin/test_shares_actions.py
+++ b/manila_tempest_tests/tests/api/admin/test_shares_actions.py
@@ -16,6 +16,7 @@
import ddt
from tempest import config
from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
import testtools
from testtools import testcase as tc
@@ -36,7 +37,7 @@
# create share type for share filtering purposes
specs = {"storage_protocol": CONF.share.capability_storage_protocol}
- cls.share_type = cls._create_share_type(specs)
+ cls.share_type = cls._create_share_type(specs=specs)
cls.share_type_id = cls.share_type['id']
# create share
@@ -80,6 +81,7 @@
share_type_id=cls.share_type_id,
))
+ @decorators.idempotent_id('5f61f5dd-891e-478f-b102-803096820882')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_get_share(self):
@@ -107,6 +109,7 @@
CONF.share.share_size, share["size"])
self.assertEqual(CONF.share.share_size, int(share["size"]), msg)
+ @decorators.idempotent_id('60d34573-8452-47ab-9455-0067bdd3ed9c')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_list_shares(self):
@@ -123,6 +126,7 @@
msg = "expected id lists %s times in share list" % (len(gen))
self.assertEqual(1, len(gen), msg)
+ @decorators.idempotent_id('85f9438d-d3f6-4f3a-8134-e89915373df3')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_list_shares_with_detail(self):
@@ -143,6 +147,7 @@
msg = "expected id lists %s times in share list" % (len(gen))
self.assertEqual(1, len(gen), msg)
+ @decorators.idempotent_id('47dad08b-0c36-428f-8ab9-5eba92ffc995')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_list_shares_with_detail_filter_by_metadata(self):
filters = {'metadata': self.metadata}
@@ -158,6 +163,7 @@
if CONF.share.capability_create_share_from_snapshot_support:
self.assertFalse(self.shares[1]['id'] in [s['id'] for s in shares])
+ @decorators.idempotent_id('d884c91e-88f5-4e42-83d9-ec3b440af893')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_list_shares_with_detail_filter_by_extra_specs(self):
filters = {
@@ -191,6 +197,7 @@
extra_specs = self.shares_client.get_share_type_extra_specs(st_id)
self.assertDictContainsSubset(filters["extra_specs"], extra_specs)
+ @decorators.idempotent_id('76fbe8ba-f1d3-4446-b9b8-55617762a2c7')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_list_shares_with_detail_filter_by_share_type_id(self):
filters = {'share_type_id': self.share_type_id}
@@ -221,6 +228,7 @@
for share in self.shares:
self.assertIn(share['id'], share_ids)
+ @decorators.idempotent_id('04afc330-78ee-494f-a660-7670c877a440')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_list_shares_with_detail_filter_by_host(self):
base_share = self.shares_client.get_share(self.shares[0]['id'])
@@ -237,6 +245,7 @@
@base.skip_if_microversion_lt("2.35")
@ddt.data(('path', True), ('id', True), ('path', False), ('id', False))
@ddt.unpack
+ @decorators.idempotent_id('a27e5e3f-451f-4200-af38-99a562ccbe86')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_list_shares_or_with_detail_filter_by_export_location(
self, export_location_type, enable_detail):
@@ -260,6 +269,7 @@
self.assertEqual(1, len(shares))
self.assertEqual(self.shares[0]['id'], shares[0]['id'])
+ @decorators.idempotent_id('4582de51-1dcd-4c44-b550-eca9a9685038')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipIf(
not CONF.share.multitenancy_enabled, "Only for multitenancy.")
@@ -276,6 +286,7 @@
self.assertEqual(
filters['share_network_id'], share['share_network_id'])
+ @decorators.idempotent_id('645aebc4-55ac-406d-b7ab-5614c4fc12e6')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipUnless(
CONF.share.capability_create_share_from_snapshot_support,
@@ -292,6 +303,7 @@
self.assertEqual(filters['snapshot_id'], share['snapshot_id'])
self.assertFalse(self.shares[0]['id'] in [s['id'] for s in shares])
+ @decorators.idempotent_id('87659cee-4692-412a-9bfe-06fc97d30ba0')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_list_shares_with_detail_with_asc_sorting(self):
filters = {'sort_key': 'created_at', 'sort_dir': 'asc'}
@@ -304,6 +316,7 @@
sorted_list = [share['created_at'] for share in shares]
self.assertEqual(sorted(sorted_list), sorted_list)
+ @decorators.idempotent_id('631f4226-f1ea-47b1-a472-8f12da2d05c4')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_list_shares_with_detail_filter_by_existed_name(self):
# list shares by name, at least one share is expected
@@ -311,6 +324,7 @@
shares = self.shares_client.list_shares_with_detail(params)
self.assertEqual(self.share_name, shares[0]["name"])
+ @decorators.idempotent_id('d0dae9e5-a826-48e4-b7b7-24b08ad5a7cb')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_list_shares_with_detail_filter_by_fake_name(self):
# list shares by fake name, no shares are expected
@@ -318,6 +332,7 @@
shares = self.shares_client.list_shares_with_detail(params)
self.assertEqual(0, len(shares))
+ @decorators.idempotent_id('8eac9b63-666f-4c52-8c5f-58b1fdf201e2')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_list_shares_with_detail_filter_by_active_status(self):
# list shares by active status, at least one share is expected
@@ -327,6 +342,7 @@
for share in shares:
self.assertEqual(params["status"], share["status"])
+ @decorators.idempotent_id('e94f41c0-f6c4-4d77-b4f9-2c796c27e348')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_list_shares_with_detail_filter_by_fake_status(self):
# list shares by fake status, no shares are expected
@@ -334,6 +350,7 @@
shares = self.shares_client.list_shares_with_detail(params)
self.assertEqual(0, len(shares))
+ @decorators.idempotent_id('d24a438e-4622-48ac-993e-a30d04746745')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipUnless(CONF.share.run_snapshot_tests,
"Snapshot tests are disabled.")
@@ -364,6 +381,7 @@
get["share_id"]))
self.assertEqual(self.shares[0]["id"], get["share_id"], msg)
+ @decorators.idempotent_id('9fae88a5-dd95-40ba-96e2-ac3694cf455f')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipUnless(CONF.share.run_snapshot_tests,
"Snapshot tests are disabled.")
@@ -381,6 +399,7 @@
msg = "expected id lists %s times in share list" % (len(gen))
self.assertEqual(1, len(gen), msg)
+ @decorators.idempotent_id('84013334-5985-4067-8b54-4c633f6022f3')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipUnless(CONF.share.run_snapshot_tests,
"Snapshot tests are disabled.")
diff --git a/manila_tempest_tests/tests/api/admin/test_snapshot_export_locations.py b/manila_tempest_tests/tests/api/admin/test_snapshot_export_locations.py
index a7b8641..0d27e21 100644
--- a/manila_tempest_tests/tests/api/admin/test_snapshot_export_locations.py
+++ b/manila_tempest_tests/tests/api/admin/test_snapshot_export_locations.py
@@ -17,6 +17,7 @@
from oslo_utils import uuidutils
import six
from tempest import config
+from tempest.lib import decorators
from testtools import testcase as tc
from manila_tempest_tests.tests.api import base
@@ -95,6 +96,7 @@
self.assertTrue(uuidutils.is_uuid_like(
export_location['share_snapshot_instance_id']))
+ @decorators.idempotent_id('18287f50-0e12-463d-906f-5c7cba256288')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_list_snapshot_export_location(self):
export_locations = (
@@ -104,6 +106,7 @@
for el in export_locations:
self._verify_export_location_structure(el)
+ @decorators.idempotent_id('6272b60b-31a1-41c1-86f5-af28926898e6')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_get_snapshot_export_location(self):
export_locations = (
@@ -115,6 +118,7 @@
self.snapshot['id'], export_location['id'])
self._verify_export_location_structure(el, detail=True)
+ @decorators.idempotent_id('03be6418-5ba3-4919-a798-89d7e5ffb925')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_get_snapshot_instance_export_location(self):
for snapshot_instance in self.snapshot_instances:
@@ -126,6 +130,7 @@
snapshot_instance['id'], el['id'])
self._verify_export_location_structure(el, detail=True)
+ @decorators.idempotent_id('cdf444ea-95a3-4f7b-ae48-6b027a6b9529')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_snapshot_contains_all_export_locations_of_all_snapshot_instances(
self):
diff --git a/manila_tempest_tests/tests/api/admin/test_snapshot_export_locations_negative.py b/manila_tempest_tests/tests/api/admin/test_snapshot_export_locations_negative.py
index 9d48254..2c3a8c7 100644
--- a/manila_tempest_tests/tests/api/admin/test_snapshot_export_locations_negative.py
+++ b/manila_tempest_tests/tests/api/admin/test_snapshot_export_locations_negative.py
@@ -14,6 +14,7 @@
# under the License.
from tempest import config
+from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
from testtools import testcase as tc
@@ -39,7 +40,7 @@
def setup_clients(cls):
super(SnapshotExportLocationsNegativeTest, cls).setup_clients()
cls.admin_client = cls.admin_shares_v2_client
- cls.isolated_client = cls.alt_shares_v2_client
+ cls.different_project_client = cls.alt_shares_v2_client
@classmethod
def resource_setup(cls):
@@ -56,6 +57,7 @@
cls.snapshot_instances = cls.admin_client.list_snapshot_instances(
snapshot_id=cls.snapshot['id'])
+ @decorators.idempotent_id('53f0f184-7398-4e7a-ac21-fa432570db7f')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_get_inexistent_snapshot_export_location(self):
self.assertRaises(
@@ -65,16 +67,18 @@
"fake-inexistent-snapshot-export-location-id",
)
+ @decorators.idempotent_id('43229517-bf93-4be7-9f89-a69034d2f03c')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
- def test_list_snapshot_export_locations_by_member(self):
+ def test_list_snapshot_export_locations_by_different_project_user(self):
self.assertRaises(
lib_exc.NotFound,
- self.isolated_client.list_snapshot_export_locations,
+ self.different_project_client.list_snapshot_export_locations,
self.snapshot['id']
)
+ @decorators.idempotent_id('66839514-796a-4ee9-a8ed-7614521d01d5')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
- def test_get_snapshot_export_location_by_member(self):
+ def test_get_snapshot_export_location_by_different_project_user(self):
export_locations = (
self.admin_client.list_snapshot_export_locations(
self.snapshot['id']))
@@ -84,11 +88,11 @@
continue
self.assertRaises(
lib_exc.NotFound,
- self.isolated_client.get_snapshot_export_location,
+ self.different_project_client.get_snapshot_export_location,
self.snapshot['id'],
- export_location['id']
- )
+ export_location['id'])
+ @decorators.idempotent_id('52e0b807-7b29-4795-960a-518bcadc1503')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_get_inexistent_snapshot_instance_export_location(self):
for snapshot_instance in self.snapshot_instances:
@@ -99,6 +103,7 @@
"fake-inexistent-snapshot-export-location-id",
)
+ @decorators.idempotent_id('3f4e2a0e-1522-47fb-b770-9d7a0651dde2')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_get_snapshot_instance_export_location_by_member(self):
for snapshot_instance in self.snapshot_instances:
@@ -108,7 +113,8 @@
for el in export_locations:
self.assertRaises(
lib_exc.Forbidden,
- self.isolated_client.get_snapshot_instance_export_location,
+ (self.different_project_client.
+ get_snapshot_instance_export_location),
snapshot_instance['id'], el['id'],
)
@@ -129,8 +135,11 @@
def setup_clients(cls):
super(SnapshotExportLocationsAPIOnlyNegativeTest, cls).setup_clients()
cls.admin_client = cls.admin_shares_v2_client
- cls.isolated_client = cls.alt_shares_v2_client
+ # admin_member_client is a regular user in admin's project
+ cls.admin_member_client = (
+ cls.admin_project_member_client.shares_v2_client)
+ @decorators.idempotent_id('37901216-b574-4786-9b1d-9b1ccdf123d2')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_list_export_locations_by_nonexistent_snapshot(self):
self.assertRaises(
@@ -139,6 +148,7 @@
"fake-inexistent-snapshot-id",
)
+ @decorators.idempotent_id('c2aa3770-c061-4b49-83ac-ab29773c2e0c')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_list_export_locations_by_nonexistent_snapshot_instance(self):
self.assertRaises(
@@ -147,11 +157,12 @@
"fake-inexistent-snapshot-instance-id",
)
+ @decorators.idempotent_id('74d5d46d-8161-4e17-acbc-812248d6d694')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_list_inexistent_snapshot_instance_export_locations_by_member(
self):
self.assertRaises(
lib_exc.Forbidden,
- self.isolated_client.list_snapshot_instance_export_locations,
+ self.admin_member_client.list_snapshot_instance_export_locations,
"fake-inexistent-snapshot-instance-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 5c57aa9..8e97887 100644
--- a/manila_tempest_tests/tests/api/admin/test_snapshot_manage.py
+++ b/manila_tempest_tests/tests/api/admin/test_snapshot_manage.py
@@ -16,14 +16,15 @@
import ddt
from tempest import config
from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
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
@@ -130,6 +131,7 @@
self.shares_v2_client.get_snapshot,
get_snapshot['id'])
+ @decorators.idempotent_id('5fb65a19-fb73-4b5a-9210-010f93e0304f')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@ddt.data('2.12', '2.16', CONF.share.max_api_microversion)
def test_manage_different_versions(self, version):
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 287654e..68ed242 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
@@ -16,6 +16,7 @@
import six
from tempest import config
from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
import testtools
from testtools import testcase as tc
@@ -64,6 +65,7 @@
share_protocol=cls.protocol
)
+ @decorators.idempotent_id('df7ac126-2c13-4902-b9c0-d103c71680ee')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_manage_not_found(self):
# Manage non-existing snapshot fails
@@ -74,6 +76,7 @@
'fake-provider-location',
)
+ @decorators.idempotent_id('645a88f7-1eec-49a2-a232-757dc2112dd8')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_manage_already_exists(self):
# Manage already existing snapshot fails
@@ -95,6 +98,7 @@
# Delete snapshot
self._delete_snapshot_and_wait(snap)
+ @decorators.idempotent_id('e94706f4-9c72-41f1-9ed4-09eb93d0b36f')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_manage_invalid_provider_location(self):
# Manage a snapshot with wrong provider location fails
@@ -133,6 +137,7 @@
)
self._delete_snapshot_and_wait(managed_snap)
+ @decorators.idempotent_id('d0049626-a524-4c8a-a58a-006ae2cdfea5')
@testtools.skipUnless(CONF.share.multitenancy_enabled,
'Multitenancy tests are disabled.')
@utils.skip_if_microversion_not_supported("2.48")
diff --git a/manila_tempest_tests/tests/api/admin/test_user_messages.py b/manila_tempest_tests/tests/api/admin/test_user_messages.py
index 83c5e37..80c992c 100644
--- a/manila_tempest_tests/tests/api/admin/test_user_messages.py
+++ b/manila_tempest_tests/tests/api/admin/test_user_messages.py
@@ -52,6 +52,7 @@
self.message = self.create_user_message()
@decorators.attr(type=[base.TAG_POSITIVE, base.TAG_API])
+ @decorators.idempotent_id('37127e11-7aa7-46b2-ab05-e3bf36d94fd8')
def test_list_messages(self):
body = self.shares_v2_client.list_messages()
self.assertIsInstance(body, list)
@@ -60,6 +61,7 @@
self.assertEqual(set(MESSAGE_KEYS), set(message.keys()))
@decorators.attr(type=[base.TAG_POSITIVE, base.TAG_API])
+ @decorators.idempotent_id('ff938d3e-9cdd-470a-b091-d389be7be755')
def test_list_messages_sorted_and_paginated(self):
self.create_user_message()
self.create_user_message()
@@ -77,6 +79,7 @@
self.assertEqual(ids, sorted(ids))
@decorators.attr(type=[base.TAG_POSITIVE, base.TAG_API])
+ @decorators.idempotent_id('292b0a2c-f066-48a6-9492-8dede87ee7b4')
def test_list_messages_filtered(self):
self.create_user_message()
params = {'resource_id': self.message['resource_id']}
@@ -86,6 +89,7 @@
self.assertEqual([self.message['id']], ids)
@decorators.attr(type=[base.TAG_POSITIVE, base.TAG_API])
+ @decorators.idempotent_id('a92971c5-a72a-4de2-8e9b-dc612b798a7a')
def test_show_message(self):
self.addCleanup(self.shares_v2_client.delete_message,
self.message['id'])
@@ -110,6 +114,7 @@
self.assertEqual(set(MESSAGE_KEYS), set(message.keys()))
@decorators.attr(type=[base.TAG_POSITIVE, base.TAG_API])
+ @decorators.idempotent_id('88b2db98-8e33-4552-9225-c19a3b6f18e0')
def test_delete_message(self):
self.shares_v2_client.delete_message(self.message['id'])
self.shares_v2_client.wait_for_resource_deletion(
@@ -117,6 +122,7 @@
@decorators.attr(type=[base.TAG_POSITIVE, base.TAG_API])
@base.skip_if_microversion_not_supported(QUERY_BY_TIMESTAMP_MICROVERSION)
+ @decorators.idempotent_id('2ed0c40e-cdaa-471b-97d4-5ebe3fb040e9')
def test_list_messages_with_since_and_before_filters(self):
new_message = self.create_user_message()
created_at_1 = timeutils.parse_strtime(self.message['created_at'])
diff --git a/manila_tempest_tests/tests/api/admin/test_user_messages_negative.py b/manila_tempest_tests/tests/api/admin/test_user_messages_negative.py
index cf592e4..d8fcd5d 100644
--- a/manila_tempest_tests/tests/api/admin/test_user_messages_negative.py
+++ b/manila_tempest_tests/tests/api/admin/test_user_messages_negative.py
@@ -24,7 +24,7 @@
QUERY_BY_TIMESTAMP_MICROVERSION = '2.52'
-class UserMessageNegativeTest(base.BaseSharesAdminTest):
+class UserMessageNegativeTest(base.BaseSharesMixedTest):
@classmethod
def skip_checks(cls):
@@ -36,28 +36,28 @@
self.message = self.create_user_message()
@decorators.attr(type=[base.TAG_NEGATIVE, base.TAG_API])
+ @decorators.idempotent_id('cb6c0dbd-a3cb-404b-a358-7cec3596aff4')
def test_show_message_of_other_tenants(self):
- isolated_client = self.get_client_with_isolated_creds(
- type_of_creds='alt', client_version='2')
self.assertRaises(lib_exc.NotFound,
- isolated_client.get_message,
+ self.alt_shares_v2_client.get_message,
self.message['id'])
@decorators.attr(type=[base.TAG_NEGATIVE, base.TAG_API])
+ @decorators.idempotent_id('f493a1f9-43e1-4a85-a673-8520d5a81f68')
def test_show_nonexistent_message(self):
self.assertRaises(lib_exc.NotFound,
self.shares_v2_client.get_message,
six.text_type(uuidutils.generate_uuid()))
@decorators.attr(type=[base.TAG_NEGATIVE, base.TAG_API])
+ @decorators.idempotent_id('2f5be1aa-974b-4f6a-ae3a-084578e64f82')
def test_delete_message_of_other_tenants(self):
- isolated_client = self.get_client_with_isolated_creds(
- type_of_creds='alt', client_version='2')
self.assertRaises(lib_exc.NotFound,
- isolated_client.delete_message,
+ self.alt_shares_v2_client.delete_message,
self.message['id'])
@decorators.attr(type=[base.TAG_NEGATIVE, base.TAG_API])
+ @decorators.idempotent_id('9029cc9f-b904-4e58-b268-adf7a93cc1f1')
def test_delete_nonexistent_message(self):
self.assertRaises(lib_exc.NotFound,
self.shares_v2_client.delete_message,
@@ -65,6 +65,7 @@
@decorators.attr(type=[base.TAG_NEGATIVE, base.TAG_API])
@base.skip_if_microversion_not_supported(QUERY_BY_TIMESTAMP_MICROVERSION)
+ @decorators.idempotent_id('03e80563-1a36-408e-baa8-0e3ed46f7a0a')
def test_list_messages_with_invalid_time_format(self):
params_key = ['created_since', 'created_before']
for key in params_key:
diff --git a/manila_tempest_tests/tests/api/base.py b/manila_tempest_tests/tests/api/base.py
old mode 100644
new mode 100755
index 671ccf3..fe4616e
--- a/manila_tempest_tests/tests/api/base.py
+++ b/manila_tempest_tests/tests/api/base.py
@@ -14,18 +14,13 @@
# under the License.
import copy
-import inspect
import re
import traceback
-from oslo_concurrency import lockutils
from oslo_log import log
import six
-from tempest.common import credentials_factory as common_creds
-
from tempest import config
from tempest.lib.common import cred_client
-from tempest.lib.common import dynamic_creds
from tempest.lib.common.utils import data_utils
from tempest.lib import exceptions
from tempest import test
@@ -35,6 +30,7 @@
from manila_tempest_tests import share_exceptions
from manila_tempest_tests import utils
+
CONF = config.CONF
LOG = log.getLogger(__name__)
@@ -97,26 +93,6 @@
return True # Suppress error if any
-def network_synchronized(f):
-
- def wrapped_func(self, *args, **kwargs):
- with_isolated_creds = True if len(args) > 2 else False
- no_lock_required = kwargs.get(
- "isolated_creds_client", with_isolated_creds)
- if no_lock_required:
- # Usage of not reusable network. No need in lock.
- return f(self, *args, **kwargs)
-
- # Use lock assuming reusage of common network.
- @lockutils.synchronized("manila_network_lock", external=True)
- def source_func(self, *args, **kwargs):
- return f(self, *args, **kwargs)
-
- return source_func(self, *args, **kwargs)
-
- return wrapped_func
-
-
skip_if_microversion_not_supported = utils.skip_if_microversion_not_supported
skip_if_microversion_lt = utils.skip_if_microversion_lt
@@ -134,12 +110,6 @@
# Will be cleaned up in tearDown method
method_resources = []
- # Will be cleaned up in resource_cleanup
- class_isolated_creds = []
-
- # Will be cleaned up in tearDown method
- method_isolated_creds = []
-
# NOTE(andreaf) Override the client manager class to be used, so that
# a stable class is used, which includes plugin registered services as well
client_manager = clients.Clients
@@ -157,103 +127,6 @@
microversion)
@classmethod
- def _get_dynamic_creds(cls, name, network_resources=None):
- identity_version = CONF.identity.auth_version
- if identity_version == 'v3':
- identity_uri = CONF.identity.uri_v3
- identity_admin_endpoint_type = CONF.identity.v3_endpoint_type
- elif identity_version == 'v2':
- identity_uri = CONF.identity.uri
- identity_admin_endpoint_type = CONF.identity.v2_admin_endpoint_type
-
- return dynamic_creds.DynamicCredentialProvider(
- identity_version=identity_version,
- name=name,
- network_resources=network_resources,
- credentials_domain=CONF.auth.default_credentials_domain_name,
- admin_role=CONF.identity.admin_role,
- admin_creds=common_creds.get_configured_admin_credentials(),
- identity_admin_domain_scope=CONF.identity.admin_domain_scope,
- identity_admin_role=CONF.identity.admin_role,
- extra_roles=None,
- neutron_available=CONF.service_available.neutron,
- create_networks=(
- CONF.share.create_networks_when_multitenancy_enabled),
- project_network_cidr=CONF.network.project_network_cidr,
- project_network_mask_bits=CONF.network.project_network_mask_bits,
- public_network_id=CONF.network.public_network_id,
- resource_prefix='tempest',
- identity_admin_endpoint_type=identity_admin_endpoint_type,
- identity_uri=identity_uri)
-
- @classmethod
- def get_client_with_isolated_creds(cls,
- name=None,
- type_of_creds="admin",
- cleanup_in_class=False,
- client_version='1'):
- """Creates isolated creds.
-
- :param name: name, will be used for naming ic and related stuff
- :param type_of_creds: admin, alt or primary
- :param cleanup_in_class: defines place where to delete
- :returns: SharesClient -- shares client with isolated creds.
- :returns: To client added dict attr 'creds' with
- :returns: key elements 'tenant' and 'user'.
- """
- if name is None:
- # Get name of test method
- name = inspect.stack()[1][3]
- if len(name) > 32:
- name = name[0:32]
-
- # Choose type of isolated creds
- ic = cls._get_dynamic_creds(name)
- if "admin" in type_of_creds:
- creds = ic.get_admin_creds().credentials
- elif "alt" in type_of_creds:
- creds = ic.get_alt_creds().credentials
- else:
- creds = ic.get_credentials(type_of_creds).credentials
- ic.type_of_creds = type_of_creds
-
- # create client with isolated creds
- os = clients.Clients(creds)
- if client_version == '1':
- client = os.share_v1.SharesClient()
- elif client_version == '2':
- client = os.share_v2.SharesV2Client()
-
- # Set place where will be deleted isolated creds
- ic_res = {
- "method": ic.clear_creds,
- "deleted": False,
- }
- if cleanup_in_class:
- cls.class_isolated_creds.insert(0, ic_res)
- else:
- cls.method_isolated_creds.insert(0, ic_res)
-
- # Provide share network
- if CONF.share.multitenancy_enabled:
- if (not CONF.service_available.neutron and
- CONF.share.create_networks_when_multitenancy_enabled):
- raise cls.skipException("Neutron support is required")
- nc = os.network.NetworksClient()
- share_network_id = cls.provide_share_network(client, nc, ic)
- client.share_network_id = share_network_id
- resource = {
- "type": "share_network",
- "id": client.share_network_id,
- "client": client,
- }
- if cleanup_in_class:
- cls.class_resources.insert(0, resource)
- else:
- cls.method_resources.insert(0, resource)
- return client
-
- @classmethod
def skip_checks(cls):
super(BaseSharesTest, cls).skip_checks()
if not CONF.service_available.manila:
@@ -269,6 +142,24 @@
raise cls.skipException(msg)
@classmethod
+ def setup_credentials(cls):
+ # This call is used to tell the credential allocator to create
+ # network resources for this test case. NOTE: it must go before the
+ # super call, to override decisions in the base classes.
+ network_resources = {}
+ if (CONF.share.multitenancy_enabled and
+ CONF.share.create_networks_when_multitenancy_enabled):
+ # We're testing a DHSS=True driver, and manila is configured with
+ # NeutronNetworkPlugin (or a derivative) that supports creating
+ # share networks with project neutron networks, so lets ask for
+ # neutron network resources to be created with test credentials
+ network_resources.update({'network': True,
+ 'subnet': True,
+ 'router': True})
+ cls.set_network_resources(**network_resources)
+ super(BaseSharesTest, cls).setup_credentials()
+
+ @classmethod
def setup_clients(cls):
super(BaseSharesTest, cls).setup_clients()
os = getattr(cls, 'os_%s' % cls.credentials[0])
@@ -276,160 +167,187 @@
cls.shares_client = os.share_v1.SharesClient()
cls.shares_v2_client = os.share_v2.SharesV2Client()
# Initialise network clients for test credentials
+ cls.networks_client = None
+ cls.subnets_client = None
if CONF.service_available.neutron:
cls.networks_client = os.network.NetworksClient()
cls.subnets_client = os.network.SubnetsClient()
- else:
- cls.networks_client = None
- cls.subnets_client = None
- if CONF.identity.auth_version == 'v3':
- project_id = os.auth_provider.auth_data[1]['project']['id']
- else:
- project_id = os.auth_provider.auth_data[1]['token']['tenant']['id']
- cls.tenant_id = project_id
- cls.user_id = os.auth_provider.auth_data[1]['user']['id']
-
+ # If DHSS=True, create a share network and set it in the client
+ # for easy access.
if CONF.share.multitenancy_enabled:
if (not CONF.service_available.neutron and
CONF.share.create_networks_when_multitenancy_enabled):
- raise cls.skipException("Neutron support is required")
+ raise cls.skipException(
+ "Neutron support is required when "
+ "CONF.share.create_networks_when_multitenancy_enabled "
+ "is set to True")
share_network_id = cls.provide_share_network(
- cls.shares_v2_client, cls.networks_client)
+ cls.shares_client, cls.networks_client)
cls.shares_client.share_network_id = share_network_id
cls.shares_v2_client.share_network_id = share_network_id
- resource = {
- "type": "share_network",
- "id": share_network_id,
- "client": cls.shares_v2_client,
- }
- cls.class_resources.insert(0, resource)
def setUp(self):
super(BaseSharesTest, self).setUp()
- self.addCleanup(self.clear_isolated_creds)
self.addCleanup(self.clear_resources)
verify_test_has_appropriate_tags(self)
@classmethod
def resource_cleanup(cls):
cls.clear_resources(cls.class_resources)
- cls.clear_isolated_creds(cls.class_isolated_creds)
super(BaseSharesTest, cls).resource_cleanup()
@classmethod
- @network_synchronized
- def provide_share_network(cls, shares_client, networks_client,
- isolated_creds_client=None,
- ignore_multitenancy_config=False):
- """Used for finding/creating share network for multitenant driver.
+ def provide_and_associate_security_services(
+ cls, shares_client, share_network_id, cleanup_in_class=True):
+ """Creates a security service and associates to a share network.
- This method creates/gets entity share-network for one tenant. This
- share-network will be used for creation of service vm.
+ This method creates security services based on the Multiopt
+ defined in tempest configuration named security_service. When this
+ configuration is not provided, the method will return None.
+ After the security service creation, this method also associates
+ the security service to a share network.
- :param shares_client: shares client, which requires share-network
- :param networks_client: network client from same tenant as shares
- :param isolated_creds_client: DynamicCredentialProvider instance
- If provided, then its networking will be used if needed.
- If not provided, then common network will be used if needed.
- :param ignore_multitenancy_config: provide a share network regardless
- of 'multitenancy_enabled' configuration value.
- :returns: str -- share network id for shares_client tenant
- :returns: None -- if single-tenant driver used
+ :param shares_client: shares client, which requires the provisioning
+ :param share_network_id: id of the share network to associate the
+ security service
+ :param cleanup_in_class: if the security service and the association
+ will be removed in the method teardown or class teardown
+ :returns: None -- if the security service configuration is not
+ defined
"""
- sc = shares_client
- search_word = "reusable"
- sn_name = "autogenerated_by_tempest_%s" % search_word
+ ss_configs = CONF.share.security_service
+ if not ss_configs:
+ return
+
+ for ss_config in ss_configs:
+ ss_name = "ss_autogenerated_by_tempest_%s" % (
+ ss_config.get("ss_type"))
+
+ ss_params = {
+ "name": ss_name,
+ "dns_ip": ss_config.get("ss_dns_ip"),
+ "server": ss_config.get("ss_server"),
+ "domain": ss_config.get("ss_domain"),
+ "user": ss_config.get("ss_user"),
+ "password": ss_config.get("ss_password")
+ }
+ ss_type = ss_config.get("ss_type")
+ security_service = cls.create_security_service(
+ ss_type,
+ client=shares_client,
+ cleanup_in_class=cleanup_in_class,
+ **ss_params)
+
+ cls.add_sec_service_to_share_network(
+ shares_client, share_network_id,
+ security_service["id"],
+ cleanup_in_class=cleanup_in_class)
+
+ @classmethod
+ def add_sec_service_to_share_network(
+ cls, client, share_network_id,
+ security_service_id, cleanup_in_class=True):
+ """Associates a security service to a share network.
+
+ This method associates a security service provided by
+ the security service configuration with a specific
+ share network.
+
+ :param share_network_id: the share network id to be
+ associate with a given security service
+ :param security_service_id: the security service id
+ to be associate with a given share network
+ :param cleanup_in_class: if the resources will be
+ dissociate in the method teardown or class teardown
+ """
+
+ client.add_sec_service_to_share_network(
+ share_network_id,
+ security_service_id)
+ resource = {
+ "type": "dissociate_security_service",
+ "id": security_service_id,
+ "extra_params": {
+ "share_network_id": share_network_id
+ },
+ "client": client,
+ }
+
+ if cleanup_in_class:
+ cls.class_resources.insert(0, resource)
+ else:
+ cls.method_resources.insert(0, resource)
+
+ @classmethod
+ def provide_share_network(cls, shares_client, networks_client,
+ ignore_multitenancy_config=False):
+ """Get or create share network for DHSS=True drivers
+
+ When testing DHSS=True (multitenancy_enabled) drivers, shares must
+ be requested on share networks.
+ :returns: str -- share network id for shares_client tenant
+ :returns: None -- if single-tenant driver (DHSS=False) is used
+ """
if (not ignore_multitenancy_config and
not CONF.share.multitenancy_enabled):
- # Assumed usage of a single-tenant driver
- share_network_id = None
- else:
- if sc.share_network_id:
- # Share-network already exists, use it
- share_network_id = sc.share_network_id
- elif not CONF.share.create_networks_when_multitenancy_enabled:
- share_network_id = None
+ # Assumed usage of a single-tenant driver (DHSS=False)
+ return None
- # Try get suitable share-network
- share_networks = sc.list_share_networks_with_detail()
- for sn in share_networks:
- net_info = (
- utils.share_network_get_default_subnet(sn)
- if utils.share_network_subnets_are_supported() else sn)
- if net_info is None:
- continue
- if(net_info["neutron_net_id"] is None and
- net_info["neutron_subnet_id"] is None and
- sn["name"] and search_word in sn["name"]):
- share_network_id = sn["id"]
- break
+ if shares_client.share_network_id:
+ # Share-network already exists, use it
+ return shares_client.share_network_id
- # Create new share-network if one was not found
- if share_network_id is None:
- sn_desc = "This share-network was created by tempest"
- sn = sc.create_share_network(name=sn_name,
- description=sn_desc)
- share_network_id = sn["id"]
- else:
- net_id = subnet_id = share_network_id = None
+ sn_name = "autogenerated_by_tempest"
+ sn_desc = "This share-network was created by tempest"
- if not isolated_creds_client:
- # Search for networks, created in previous runs
- service_net_name = "share-service"
- networks = networks_client.list_networks()
- if "networks" in networks.keys():
- networks = networks["networks"]
- for network in networks:
- if (service_net_name in network["name"] and
- sc.tenant_id == network['tenant_id']):
- net_id = network["id"]
- if len(network["subnets"]) > 0:
- subnet_id = network["subnets"][0]
- break
+ if not CONF.share.create_networks_when_multitenancy_enabled:
+ # We need a new share network, but don't need to associate
+ # any neutron networks to it - this configuration is used
+ # when manila is configured with "StandaloneNetworkPlugin"
+ # or "NeutronSingleNetworkPlugin" where all tenants share
+ # a single backend network where shares are exported.
+ sn = cls.create_share_network(cleanup_in_class=True,
+ client=shares_client,
+ add_security_services=True,
+ name=sn_name,
+ description=sn_desc)
+ return sn['id']
- # Create suitable network
- if net_id is None or subnet_id is None:
- ic = cls._get_dynamic_creds(service_net_name)
- net_data = ic._create_network_resources(sc.tenant_id)
- network, subnet, router = net_data
- net_id = network["id"]
- subnet_id = subnet["id"]
+ # Retrieve non-public network list owned by the tenant
+ filters = {'project_id': shares_client.tenant_id,
+ 'shared': False}
+ tenant_networks = (
+ networks_client.list_networks(**filters).get('networks', [])
+ )
+ tenant_networks_with_subnet = (
+ [n for n in tenant_networks if n['subnets']]
+ )
- # Try get suitable share-network
- share_networks = sc.list_share_networks_with_detail()
- for sn in share_networks:
- net_info = (
- utils.share_network_get_default_subnet(sn)
- if utils.share_network_subnets_are_supported()
- else sn)
- if net_info is None:
- continue
- if (net_id == net_info["neutron_net_id"] and
- subnet_id == net_info["neutron_subnet_id"] and
- sn["name"] and search_word in sn["name"]):
- share_network_id = sn["id"]
- break
- else:
- sn_name = "autogenerated_by_tempest_for_isolated_creds"
- # Use precreated network and subnet from isolated creds
- net_id = isolated_creds_client.get_credentials(
- isolated_creds_client.type_of_creds).network['id']
- subnet_id = isolated_creds_client.get_credentials(
- isolated_creds_client.type_of_creds).subnet['id']
+ if not tenant_networks_with_subnet:
+ # This can only occur if using tempest's pre-provisioned
+ # credentials and not allocating networks to them
+ raise cls.skipException(
+ "Test credentials must provide at least one "
+ "non-shared project network with a valid subnet when "
+ "CONF.share.create_networks_when_multitenancy_enabled is "
+ "set to True.")
- # Create suitable share-network
- if share_network_id is None:
- sn_desc = "This share-network was created by tempest"
- sn = sc.create_share_network(name=sn_name,
- description=sn_desc,
- neutron_net_id=net_id,
- neutron_subnet_id=subnet_id)
- share_network_id = sn["id"]
+ net_id = tenant_networks_with_subnet[0]['id']
+ subnet_id = tenant_networks_with_subnet[0]['subnets'][0]
- return share_network_id
+ # Create suitable share-network
+ sn = cls.create_share_network(cleanup_in_class=True,
+ client=shares_client,
+ add_security_services=True,
+ name=sn_name,
+ description=sn_desc,
+ neutron_net_id=net_id,
+ neutron_subnet_id=subnet_id)
+
+ return sn['id']
@classmethod
def _create_share(cls, share_protocol=None, size=None, name=None,
@@ -759,11 +677,13 @@
return rep_domain, pools_in_rep_domain
@classmethod
- def create_share_replica(cls, share_id, availability_zone, client=None,
- cleanup_in_class=False, cleanup=True):
+ def create_share_replica(cls, share_id, availability_zone=None,
+ client=None, cleanup_in_class=False,
+ cleanup=True,
+ version=CONF.share.max_api_microversion):
client = client or cls.shares_v2_client
replica = client.create_share_replica(
- share_id, availability_zone=availability_zone)
+ share_id, availability_zone=availability_zone, version=version)
resource = {
"type": "share_replica",
"id": replica["id"],
@@ -781,18 +701,20 @@
return replica
@classmethod
- def delete_share_replica(cls, replica_id, client=None):
+ def delete_share_replica(cls, replica_id, client=None,
+ version=CONF.share.max_api_microversion):
client = client or cls.shares_v2_client
try:
- client.delete_share_replica(replica_id)
+ client.delete_share_replica(replica_id, version=version)
client.wait_for_resource_deletion(replica_id=replica_id)
except exceptions.NotFound:
pass
@classmethod
- def promote_share_replica(cls, replica_id, client=None):
+ def promote_share_replica(cls, replica_id, client=None,
+ version=CONF.share.max_api_microversion):
client = client or cls.shares_v2_client
- replica = client.promote_share_replica(replica_id)
+ replica = client.promote_share_replica(replica_id, version=version)
client.wait_for_share_replica_status(
replica["id"],
constants.REPLICATION_STATE_ACTIVE,
@@ -820,7 +742,8 @@
access_to = "client3.com"
elif protocol in CONF.share.enable_cephx_rules_for_protocols:
access_type = "cephx"
- access_to = "eve"
+ access_to = data_utils.rand_name(
+ cls.__class__.__name__ + '-cephx-id')
else:
message = "Unrecognized protocol and access rules configuration."
raise cls.skipException(message)
@@ -829,7 +752,9 @@
@classmethod
def create_share_network(cls, client=None,
- cleanup_in_class=False, **kwargs):
+ cleanup_in_class=False,
+ add_security_services=True, **kwargs):
+
if client is None:
client = cls.shares_client
share_network = client.create_share_network(**kwargs)
@@ -838,15 +763,23 @@
"id": share_network["id"],
"client": client,
}
+
if cleanup_in_class:
cls.class_resources.insert(0, resource)
else:
cls.method_resources.insert(0, resource)
+
+ if add_security_services:
+ cls.provide_and_associate_security_services(
+ client, share_network["id"], cleanup_in_class=cleanup_in_class)
+
return share_network
@classmethod
- def create_share_network_subnet(cls, client=None,
- cleanup_in_class=False, **kwargs):
+ def create_share_network_subnet(cls,
+ client=None,
+ cleanup_in_class=False,
+ **kwargs):
if client is None:
client = cls.shares_v2_client
share_network_subnet = client.create_subnet(**kwargs)
@@ -908,6 +841,23 @@
is_public, description)
return share_type
+ @classmethod
+ def update_quotas(cls, project_id, user_id=None, cleanup=True,
+ client=None, **kwargs):
+ client = client or cls.shares_v2_client
+ updated_quotas = client.update_quotas(project_id,
+ user_id=user_id,
+ **kwargs)
+ resource = {
+ "type": "quotas",
+ "id": project_id,
+ "client": client,
+ "user_id": user_id,
+ }
+ if cleanup:
+ cls.method_resources.insert(0, resource)
+ return updated_quotas
+
@staticmethod
def add_extra_specs_to_dict(extra_specs=None):
"""Add any required extra-specs to share type dictionary"""
@@ -935,18 +885,6 @@
return extra_specs_dict
@classmethod
- def clear_isolated_creds(cls, creds=None):
- if creds is None:
- creds = cls.method_isolated_creds
- for ic in creds:
- if "deleted" not in ic.keys():
- ic["deleted"] = False
- if not ic["deleted"]:
- with handle_cleanup_exceptions():
- ic["method"]()
- ic["deleted"] = True
-
- @classmethod
def clear_share_replicas(cls, share_id, client=None):
client = client or cls.shares_v2_client
share_replicas = client.list_share_replicas(
@@ -997,6 +935,11 @@
res_id != CONF.share.share_network_id):
client.delete_share_network(res_id)
client.wait_for_resource_deletion(sn_id=res_id)
+ elif res["type"] == "dissociate_security_service":
+ sn_id = res["extra_params"]["share_network_id"]
+ client.remove_sec_service_from_share_network(
+ sn_id=sn_id, ss_id=res_id
+ )
elif res["type"] == "security_service":
client.delete_security_service(res_id)
client.wait_for_resource_deletion(ss_id=res_id)
@@ -1024,6 +967,9 @@
client.wait_for_resource_deletion(
share_network_subnet_id=res_id,
sn_id=sn_id)
+ elif res["type"] == "quotas":
+ user_id = res.get('user_id')
+ client.reset_quotas(res_id, user_id=user_id)
else:
LOG.warning("Provided unsupported resource type for "
"cleanup '%s'. Skipping.", res["type"])
@@ -1130,6 +1076,7 @@
share_type_name = data_utils.rand_name("share-type")
bogus_type = self.create_share_type(
+ client=self.admin_shares_v2_client,
name=share_type_name,
extra_specs=extra_specs)['share_type']
@@ -1140,6 +1087,25 @@
self.shares_v2_client.wait_for_share_status(share['id'], "error")
return self.shares_v2_client.wait_for_message(share['id'])
+ def allow_access(self, share_id, client=None, access_type=None,
+ access_level='rw', access_to=None, status='active',
+ raise_rule_in_error_state=True, cleanup=True):
+
+ client = client or self.shares_v2_client
+ a_type, a_to = self._get_access_rule_data_from_config()
+ access_type = access_type or a_type
+ access_to = access_to or a_to
+
+ rule = client.create_access_rule(share_id, access_type, access_to,
+ access_level)
+ client.wait_for_access_rule_status(share_id, rule['id'], status,
+ raise_rule_in_error_state)
+ if cleanup:
+ self.addCleanup(client.wait_for_resource_deletion,
+ rule_id=rule['id'], share_id=share_id)
+ self.addCleanup(client.delete_access_rule, share_id, rule['id'])
+ return rule
+
class BaseSharesAltTest(BaseSharesTest):
"""Base test case class for all Shares Alt API tests."""
@@ -1157,11 +1123,11 @@
cls.admin_shares_v2_client = cls.os_admin.share_v2.SharesV2Client()
@classmethod
- def _create_share_type(cls, specs=None):
+ def _create_share_type(cls, is_public=True, specs=None):
name = data_utils.rand_name("unique_st_name")
extra_specs = cls.add_extra_specs_to_dict(specs)
return cls.create_share_type(
- name, extra_specs=extra_specs,
+ name, extra_specs=extra_specs, is_public=is_public,
client=cls.admin_shares_v2_client)['share_type']
@classmethod
@@ -1310,12 +1276,6 @@
cls.alt_shares_v2_client, cls.os_alt.networks_client)
cls.alt_shares_client.share_network_id = alt_share_network_id
cls.alt_shares_v2_client.share_network_id = alt_share_network_id
- resource = {
- "type": "share_network",
- "id": alt_share_network_id,
- "client": cls.alt_shares_v2_client,
- }
- cls.class_resources.insert(0, resource)
@classmethod
def create_user_and_get_client(cls, project=None):
@@ -1355,11 +1315,11 @@
return os
@classmethod
- def _create_share_type(cls, specs=None):
+ def _create_share_type(cls, is_public=True, specs=None):
name = data_utils.rand_name("unique_st_name")
extra_specs = cls.add_extra_specs_to_dict(specs)
return cls.create_share_type(
- name, extra_specs=extra_specs,
+ name, extra_specs=extra_specs, is_public=is_public,
client=cls.admin_shares_v2_client)['share_type']
@classmethod
diff --git a/manila_tempest_tests/tests/api/test_access_rules_metadata.py b/manila_tempest_tests/tests/api/test_access_rules_metadata.py
index 1c2db41..bb6f7cd 100644
--- a/manila_tempest_tests/tests/api/test_access_rules_metadata.py
+++ b/manila_tempest_tests/tests/api/test_access_rules_metadata.py
@@ -15,6 +15,7 @@
import ddt
from tempest import config
+from tempest.lib import decorators
from testtools import testcase as tc
from manila_tempest_tests.common import constants
@@ -76,6 +77,7 @@
cls.share["id"], cls.access_type,
cls.access_to[cls.access_type].pop(), 'rw', metadata=cls.md1)
+ @decorators.idempotent_id('4c8e0236-2e7b-4337-be3c-17b51a738644')
@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"}
@@ -102,6 +104,7 @@
self.shares_v2_client.wait_for_resource_deletion(
rule_id=access["id"], share_id=self.share["id"])
+ @decorators.idempotent_id('8c294d7d-0702-49ce-b964-0945ec323370')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_update_metadata_by_key(self):
md2 = {"key7": "value7", "key2": "value6_new"}
@@ -116,6 +119,7 @@
self.md1.update(md2)
self.assertEqual(self.md1, get_access['metadata'])
+ @decorators.idempotent_id('c97cc976-2c2f-4db3-ba07-cd04af29c9f4')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_list_access_filter_by_metadata(self):
data = {"key3": "v3", "key4": "value4"}
diff --git a/manila_tempest_tests/tests/api/test_access_rules_metadata_negative.py b/manila_tempest_tests/tests/api/test_access_rules_metadata_negative.py
index 4383a84..2c11a26 100644
--- a/manila_tempest_tests/tests/api/test_access_rules_metadata_negative.py
+++ b/manila_tempest_tests/tests/api/test_access_rules_metadata_negative.py
@@ -15,6 +15,7 @@
import ddt
from tempest import config
+from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
from testtools import testcase as tc
@@ -67,6 +68,7 @@
cls.share["id"], cls.access_type, cls.access_to,
'rw', metadata={u"key1": u"value1"})
+ @decorators.idempotent_id('d2d41db8-ae00-4641-a5ec-499cee1877f1')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@ddt.data({'data': {"": "value"}}, {'data': {"k" * 256: "value"}},
{'data': {"key": "x" * 1024}})
@@ -76,6 +78,7 @@
self.shares_v2_client.update_access_metadata,
self.access["id"], data)
+ @decorators.idempotent_id('53dc2752-687d-4895-bc9e-518c3bed29d0')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_try_delete_unexisting_access_metadata(self):
self.assertRaises(lib_exc.NotFound,
diff --git a/manila_tempest_tests/tests/api/test_availability_zones.py b/manila_tempest_tests/tests/api/test_availability_zones.py
index 0d87036..842d9e1 100644
--- a/manila_tempest_tests/tests/api/test_availability_zones.py
+++ b/manila_tempest_tests/tests/api/test_availability_zones.py
@@ -13,6 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest.lib import decorators
from testtools import testcase as tc
from manila_tempest_tests.tests.api import base
@@ -28,6 +29,7 @@
for key in keys:
self.assertIn(key, az)
+ @decorators.idempotent_id('202f20d3-1afa-40ea-a5e6-8b7bda40e6cf')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_list_availability_zones_legacy_url_api_v1(self):
# NOTE(vponomaryov): remove this test with removal of availability zone
@@ -35,6 +37,7 @@
azs = self.shares_client.list_availability_zones()
self._list_availability_zones_assertions(azs)
+ @decorators.idempotent_id('7054f2f4-bc77-4d60-82a6-2f23b93d281e')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@base.skip_if_microversion_not_supported("2.6")
def test_list_availability_zones_legacy_url_api_v2(self):
@@ -44,6 +47,7 @@
url='os-availability-zone', version='2.6')
self._list_availability_zones_assertions(azs)
+ @decorators.idempotent_id('4caadb86-2988-4adb-b705-aece99235c1e')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@base.skip_if_microversion_not_supported("2.7")
def test_list_availability_zones(self):
diff --git a/manila_tempest_tests/tests/api/test_availability_zones_negative.py b/manila_tempest_tests/tests/api/test_availability_zones_negative.py
index 95aa2d7..825dc54 100644
--- a/manila_tempest_tests/tests/api/test_availability_zones_negative.py
+++ b/manila_tempest_tests/tests/api/test_availability_zones_negative.py
@@ -13,6 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
from testtools import testcase as tc
@@ -27,6 +28,7 @@
super(AvailabilityZonesNegativeTest, cls).skip_checks()
utils.check_skip_if_microversion_not_supported('2.7')
+ @decorators.idempotent_id('050fa9fb-4cc8-4064-9e91-bb169fca03db')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_list_availability_zones_api_not_found_with_legacy_url(self):
# NOTE(vponomaryov): remove this test with removal of availability zone
@@ -38,6 +40,7 @@
version='2.7',
)
+ @decorators.idempotent_id('133ffc40-bff1-491a-a230-189cddd66e29')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_list_availability_zones_api_not_found(self):
self.assertRaises(
diff --git a/manila_tempest_tests/tests/api/test_extensions.py b/manila_tempest_tests/tests/api/test_extensions.py
index d60b861..bf866e3 100644
--- a/manila_tempest_tests/tests/api/test_extensions.py
+++ b/manila_tempest_tests/tests/api/test_extensions.py
@@ -13,6 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest.lib import decorators
from testtools import testcase as tc
from manila_tempest_tests.tests.api import base
@@ -20,6 +21,7 @@
class ExtensionsTest(base.BaseSharesTest):
+ @decorators.idempotent_id('befd2105-c9f6-4eca-a693-9900eb0fb37a')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_extensions(self):
diff --git a/manila_tempest_tests/tests/api/test_limits.py b/manila_tempest_tests/tests/api/test_limits.py
index 5f1f33d..c5d500f 100644
--- a/manila_tempest_tests/tests/api/test_limits.py
+++ b/manila_tempest_tests/tests/api/test_limits.py
@@ -13,6 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest.lib import decorators
from testtools import testcase as tc
from manila_tempest_tests.tests.api import base
@@ -20,6 +21,7 @@
class ShareLimitsTest(base.BaseSharesTest):
+ @decorators.idempotent_id('239903d2-f1cb-4bec-b456-d57456308244')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_limits_keys(self):
@@ -44,6 +46,7 @@
]
[self.assertIn(key, limits["absolute"].keys()) for key in abs_keys]
+ @decorators.idempotent_id('fea1a10e-6bcb-46eb-bbba-f6f0a8d4f377')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_limits_values(self):
diff --git a/manila_tempest_tests/tests/api/test_metadata.py b/manila_tempest_tests/tests/api/test_metadata.py
index bcea697..00e5e5d 100644
--- a/manila_tempest_tests/tests/api/test_metadata.py
+++ b/manila_tempest_tests/tests/api/test_metadata.py
@@ -13,6 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest.lib import decorators
from testtools import testcase as tc
from manila_tempest_tests.tests.api import base
@@ -30,6 +31,7 @@
# create share
cls.share = cls.create_share(share_type_id=cls.share_type_id)
+ @decorators.idempotent_id('9070249f-6e94-4a38-a036-08debee547c3')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_set_metadata_in_share_creation(self):
@@ -46,6 +48,7 @@
# verify metadata
self.assertEqual(md, metadata)
+ @decorators.idempotent_id('2725ab8e-cc04-4032-9393-74726ba43eb7')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_set_get_delete_metadata(self):
@@ -72,6 +75,7 @@
get_metadata = self.shares_client.get_metadata(share["id"])
self.assertEqual({}, get_metadata)
+ @decorators.idempotent_id('c94851f4-2559-4712-9297-9912db1da7ff')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_set_and_update_metadata_by_key(self):
@@ -94,6 +98,7 @@
# verify metadata
self.assertEqual(md2, get_md)
+ @decorators.idempotent_id('698ba406-493f-4c69-a093-273676fed438')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_set_metadata_min_size_key(self):
data = {"k": "value"}
@@ -103,6 +108,7 @@
body_get = self.shares_client.get_metadata(self.share["id"])
self.assertEqual(data['k'], body_get.get('k'))
+ @decorators.idempotent_id('34c5bd96-ced7-42ef-a114-570cc63cf81d')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_set_metadata_max_size_key(self):
max_key = "k" * 255
@@ -114,6 +120,7 @@
self.assertIn(max_key, body_get)
self.assertEqual(data[max_key], body_get.get(max_key))
+ @decorators.idempotent_id('c776ab40-f75e-4d9f-abcf-a8f628a25991')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_set_metadata_min_size_value(self):
data = {"key": "v"}
@@ -123,6 +130,7 @@
body_get = self.shares_client.get_metadata(self.share["id"])
self.assertEqual(data['key'], body_get['key'])
+ @decorators.idempotent_id('759ec4ab-2537-44ad-852b-1af85c6ca933')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_set_metadata_max_size_value(self):
max_value = "v" * 1023
@@ -133,6 +141,7 @@
body_get = self.shares_client.get_metadata(self.share["id"])
self.assertEqual(data['key'], body_get['key'])
+ @decorators.idempotent_id('c5ca19ba-3595-414a-8ff9-fbc88cd801ba')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_upd_metadata_min_size_key(self):
data = {"k": "value"}
@@ -142,6 +151,7 @@
body_get = self.shares_client.get_metadata(self.share["id"])
self.assertEqual(data, body_get)
+ @decorators.idempotent_id('5eff5619-b7cd-42f1-85e0-47d3d47098dd')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_upd_metadata_max_size_key(self):
max_key = "k" * 255
@@ -152,6 +162,7 @@
body_get = self.shares_client.get_metadata(self.share["id"])
self.assertEqual(data, body_get)
+ @decorators.idempotent_id('44a572f1-6b5c-49d0-8f2e-1583ec3428d8')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_upd_metadata_min_size_value(self):
data = {"key": "v"}
@@ -161,6 +172,7 @@
body_get = self.shares_client.get_metadata(self.share["id"])
self.assertEqual(data, body_get)
+ @decorators.idempotent_id('694d95e1-ba8c-49fc-a888-6f9f0d51d77d')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_upd_metadata_max_size_value(self):
max_value = "v" * 1023
diff --git a/manila_tempest_tests/tests/api/test_metadata_negative.py b/manila_tempest_tests/tests/api/test_metadata_negative.py
index dd3b330..efed9f3 100644
--- a/manila_tempest_tests/tests/api/test_metadata_negative.py
+++ b/manila_tempest_tests/tests/api/test_metadata_negative.py
@@ -14,6 +14,7 @@
# under the License.
import ddt
+from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
from testtools import testcase as tc
@@ -23,6 +24,7 @@
@ddt.ddt
class SharesMetadataAPIOnlyNegativeTest(base.BaseSharesTest):
+ @decorators.idempotent_id('22aecf50-0d98-4b97-82b8-599559f7692f')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
@ddt.data(True, False)
def test_try_set_metadata_to_unexisting_share(self, is_v2_client):
@@ -32,6 +34,7 @@
client.set_metadata,
"wrong_share_id", md)
+ @decorators.idempotent_id('7df0acd7-03f8-45c4-8c72-eb6932af70b1')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
@ddt.data(True, False)
def test_try_update_all_metadata_for_unexisting_share(self, is_v2_client):
@@ -54,18 +57,21 @@
# create share
cls.share = cls.create_share(share_type_id=cls.share_type_id)
+ @decorators.idempotent_id('0cb7f160-4fa4-4d30-8a46-373ddae5844d')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_try_set_metadata_with_empty_key(self):
self.assertRaises(lib_exc.BadRequest,
self.shares_client.set_metadata,
self.share["id"], {"": "value"})
+ @decorators.idempotent_id('759ca34d-1c87-43f3-8da2-8e1d373049ac')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_try_upd_metadata_with_empty_key(self):
self.assertRaises(lib_exc.BadRequest,
self.shares_client.update_all_metadata,
self.share["id"], {"": "value"})
+ @decorators.idempotent_id('94c7ebb3-14c3-4ff1-9839-ae3acb318cd0')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_try_set_metadata_with_too_big_key(self):
too_big_key = "x" * 256
@@ -74,6 +80,7 @@
self.shares_client.set_metadata,
self.share["id"], md)
+ @decorators.idempotent_id('33ef3047-6ca3-4547-a681-b52314382dcb')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_try_upd_metadata_with_too_big_key(self):
too_big_key = "x" * 256
@@ -82,6 +89,7 @@
self.shares_client.update_all_metadata,
self.share["id"], md)
+ @decorators.idempotent_id('1114970a-1b45-4c56-b20a-e13e1764e3c4')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_try_set_metadata_with_too_big_value(self):
too_big_value = "x" * 1024
@@ -90,6 +98,7 @@
self.shares_client.set_metadata,
self.share["id"], md)
+ @decorators.idempotent_id('c2eddcf0-cf81-4f9f-b06d-c9165ab8553e')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_try_upd_metadata_with_too_big_value(self):
too_big_value = "x" * 1024
@@ -98,12 +107,14 @@
self.shares_client.update_all_metadata,
self.share["id"], md)
+ @decorators.idempotent_id('14df3262-5a2b-4de4-b335-422329b22b07')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_try_delete_unexisting_metadata(self):
self.assertRaises(lib_exc.NotFound,
self.shares_client.delete_metadata,
self.share["id"], "wrong_key")
+ @decorators.idempotent_id('c6c70d55-7ed0-439f-ae34-f19af55361f6')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@ddt.data(("foo.xml", False), ("foo.json", False),
("foo.xml", True), ("foo.json", True))
diff --git a/manila_tempest_tests/tests/api/test_microversions.py b/manila_tempest_tests/tests/api/test_microversions.py
index d62d35b..b314ff8 100644
--- a/manila_tempest_tests/tests/api/test_microversions.py
+++ b/manila_tempest_tests/tests/api/test_microversions.py
@@ -15,6 +15,7 @@
# under the License.
from tempest import config
+from tempest.lib import decorators
from testtools import testcase as tc
from manila_tempest_tests.tests.api import base
@@ -33,6 +34,7 @@
Sends HTTP GET requests to the version API to validate microversions.
"""
+ @decorators.idempotent_id('1b20943e-a398-49dd-a69d-513ce6ea01b4')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_microversions_root_version(self):
@@ -55,6 +57,7 @@
self.assertEqual(_MIN_API_VERSION, v2.get('min_version'))
self.assertNotIn(v2.get('version'), [None, ''])
+ @decorators.idempotent_id('6ccaae5f-2382-45a5-a844-6d31837beba8')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_microversions_v1_no_version(self):
@@ -73,6 +76,7 @@
self.assertEqual('', version_list[0].get('min_version'))
self.assertEqual('', version_list[0].get('version'))
+ @decorators.idempotent_id('7b7e4ddf-08bb-4764-a94f-5f377da3b2cb')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_microversions_v1_with_version(self):
@@ -91,6 +95,7 @@
self.assertEqual('', version_list[0].get('min_version'))
self.assertEqual('', version_list[0].get('version'))
+ @decorators.idempotent_id('9a8bd7fd-f9d0-4fc6-8e1c-0178d87ec7c1')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_microversions_v2_no_version(self):
@@ -110,6 +115,7 @@
self.assertEqual(_MIN_API_VERSION, version_list[0].get('min_version'))
self.assertNotIn(version_list[0].get('version'), [None, ''])
+ @decorators.idempotent_id('101574fd-9d47-4bd6-97f6-cde219f089ca')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_microversions_v2_min_version(self):
@@ -129,6 +135,7 @@
self.assertEqual(_MIN_API_VERSION, version_list[0].get('min_version'))
self.assertNotIn(version_list[0].get('version'), [None, ''])
+ @decorators.idempotent_id('e0766a36-b57c-46f8-b474-a38b74f3b9ed')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_microversions_v2_max_version(self):
@@ -148,6 +155,7 @@
self.assertEqual(_MIN_API_VERSION, version_list[0].get('min_version'))
self.assertNotIn(version_list[0].get('version'), [None, ''])
+ @decorators.idempotent_id('038ff428-edde-43ff-ae29-1b18676b61d5')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_microversions_v2_invalid_version(self):
@@ -156,6 +164,7 @@
self.assertEqual(400, resp.status)
+ @decorators.idempotent_id('0d82fc0b-d24d-4d07-ab43-bd0895ec0c4c')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_microversions_v2_unacceptable_version(self):
diff --git a/manila_tempest_tests/tests/api/test_quotas.py b/manila_tempest_tests/tests/api/test_quotas.py
index 32152e0..958cb63 100644
--- a/manila_tempest_tests/tests/api/test_quotas.py
+++ b/manila_tempest_tests/tests/api/test_quotas.py
@@ -13,13 +13,16 @@
# License for the specific language governing permissions and limitations
# under the License.
-import ddt
import itertools
-from manila_tempest_tests import utils
+
+import ddt
from tempest import config
+from tempest.lib import decorators
from testtools import testcase as tc
from manila_tempest_tests.tests.api import base
+from manila_tempest_tests import utils
+
CONF = config.CONF
PRE_SHARE_REPLICAS_MICROVERSION = "2.52"
@@ -35,9 +38,10 @@
msg = "Quota tests are disabled."
raise cls.skipException(msg)
super(SharesQuotasTest, cls).resource_setup()
- cls.user_id = cls.shares_v2_client.user_id or cls.user_id
- cls.tenant_id = cls.shares_v2_client.tenant_id or cls.tenant_id
+ cls.user_id = cls.shares_v2_client.user_id
+ cls.tenant_id = cls.shares_v2_client.tenant_id
+ @decorators.idempotent_id('a4649f11-41d0-4e73-ab5a-1466f2339b2f')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@ddt.data('shares_client', 'shares_v2_client')
def test_default_quotas(self, client_name):
@@ -52,6 +56,7 @@
self.assertGreater(int(quotas["share_replicas"]), -2)
self.assertGreater(int(quotas["replica_gigabytes"]), -2)
+ @decorators.idempotent_id('19525293-2b32-48c3-a7cd-cab279ac4631')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@ddt.data('shares_client', 'shares_v2_client')
def test_show_quotas(self, client_name):
@@ -66,6 +71,7 @@
self.assertGreater(int(quotas["share_replicas"]), -2)
self.assertGreater(int(quotas["replica_gigabytes"]), -2)
+ @decorators.idempotent_id('1e670af7-9734-42a8-97b7-3080526f3aca')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@ddt.data('shares_client', 'shares_v2_client')
def test_show_quotas_for_user(self, client_name):
@@ -86,6 +92,7 @@
["2.25", "2.53", CONF.share.max_api_microversion]), (True, False))
)
@ddt.unpack
+ @decorators.idempotent_id('795614f6-4a18-47d5-b817-0b294e9d4c48')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_show_quotas_detail(self, microversion, with_user):
self.skip_if_microversion_not_supported(microversion)
@@ -106,6 +113,7 @@
self.assertIn(inner, outer_keys)
self.assertGreater(int(quotas[outer][inner]), -2)
+ @decorators.idempotent_id('7bd5ac42-9fcb-477f-a253-02cde2bde661')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@base.skip_if_microversion_not_supported(PRE_SHARE_REPLICAS_MICROVERSION)
def test_quota_detail_2_52_no_share_replica_quotas(self):
diff --git a/manila_tempest_tests/tests/api/test_quotas_negative.py b/manila_tempest_tests/tests/api/test_quotas_negative.py
index 2e850fb..6b6f1b2 100644
--- a/manila_tempest_tests/tests/api/test_quotas_negative.py
+++ b/manila_tempest_tests/tests/api/test_quotas_negative.py
@@ -15,6 +15,7 @@
import ddt
from tempest import config
+from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
from testtools import testcase as tc
@@ -33,17 +34,20 @@
raise cls.skipException(msg)
super(SharesQuotasNegativeTest, cls).resource_setup()
+ @decorators.idempotent_id('d0dfe81d-8e8c-4847-a55f-95ba8a3d922c')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_get_quotas_with_empty_tenant_id(self):
self.assertRaises(lib_exc.NotFound,
self.shares_v2_client.show_quotas, "")
+ @decorators.idempotent_id('e7dbc580-1857-4f88-8886-988dc2f2c7b9')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_reset_quotas_with_user(self):
self.assertRaises(lib_exc.Forbidden,
self.shares_v2_client.reset_quotas,
self.shares_v2_client.tenant_id)
+ @decorators.idempotent_id('f1c8e16f-5406-4389-a29c-547cca8a56e0')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_update_quotas_with_user(self):
self.assertRaises(lib_exc.Forbidden,
@@ -52,6 +56,7 @@
shares=9)
@ddt.data("2.6", "2.7", "2.24")
+ @decorators.idempotent_id('0f0033b3-357e-42e6-9c94-cac650e1cd50')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_get_quotas_detail_with_wrong_version(self, microversion):
self.assertRaises(lib_exc.NotFound,
diff --git a/manila_tempest_tests/tests/api/test_replication.py b/manila_tempest_tests/tests/api/test_replication.py
index 08f73d1..5eb5e2a 100644
--- a/manila_tempest_tests/tests/api/test_replication.py
+++ b/manila_tempest_tests/tests/api/test_replication.py
@@ -15,6 +15,7 @@
from tempest import config
from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
import testtools
from testtools import testcase as tc
@@ -151,6 +152,7 @@
raise self.skipException(
msg % ','.join(constants.REPLICATION_PROMOTION_CHOICES))
+ @decorators.idempotent_id('8858617f-292d-4e5c-9e15-794b7f1b2e3c')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
def test_add_delete_share_replica(self):
# Create the replica
@@ -159,6 +161,7 @@
# Delete the replica
self.delete_share_replica(share_replica["id"])
+ @decorators.idempotent_id('58c3faf4-6c97-4fec-9a9b-7cff0d2035cd')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@testtools.skipIf(
not CONF.share.multitenancy_enabled, "Only for multitenancy.")
@@ -181,6 +184,7 @@
# Delete subnet
self.shares_v2_client.delete_subnet(self.sn_id, subnet['id'])
+ @decorators.idempotent_id('00e12b41-b95d-494a-99be-e584aae10f5c')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
def test_add_access_rule_create_replica_delete_rule(self):
# Add access rule to the share
@@ -204,6 +208,7 @@
self.shares_v2_client.wait_for_resource_deletion(
rule_id=rule["id"], share_id=self.shares[0]['id'])
+ @decorators.idempotent_id('3af3f19a-1195-464e-870b-1a3918914f1b')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
def test_create_replica_add_access_rule_delete_replica(self):
access_type, access_to = self._get_access_rule_data_from_config()
@@ -221,6 +226,7 @@
# Delete the replica
self.delete_share_replica(share_replica["id"])
+ @decorators.idempotent_id('a542c179-ea41-4bc0-bd80-e06eaddf5253')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@testtools.skipUnless(CONF.share.run_multiple_share_replicas_tests,
'Multiple share replicas tests are disabled.')
@@ -252,6 +258,7 @@
self.assertIn(share_replica1["id"], replica_ids)
self.assertIn(share_replica2["id"], replica_ids)
+ @decorators.idempotent_id('98b7c1d6-02e8-425a-b697-db2d2671fa11')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
def test_promote_in_sync_share_replica(self):
# Test promote 'in_sync' share_replica to 'active' state
@@ -261,6 +268,7 @@
share["id"])[0]
self._verify_in_sync_replica_promotion(share, original_replica)
+ @decorators.idempotent_id('3af912f4-b5d7-4241-b2b3-bdf12ff398a4')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
def test_add_rule_promote_share_replica_verify_rule(self):
# Verify the access rule stays intact after share replica promotion
@@ -285,6 +293,7 @@
self.assertEqual(access_to, rules_list[0]["access_to"])
self.assertEqual('ro', rules_list[0]["access_level"])
+ @decorators.idempotent_id('7904e3c7-e6d0-472d-b9c9-c0772b4f9f1b')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@base.skip_if_microversion_not_supported("2.48")
def test_share_type_azs_share_replicas(self):
@@ -307,6 +316,7 @@
self.assertIn(share['availability_zone'], self.zones)
self.assertIn(replica['availability_zone'], self.zones)
+ @decorators.idempotent_id('b5ade58b-cb81-47eb-966b-28e6d85b5568')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
def test_promote_and_promote_back(self):
# Test promote back and forth between 2 share replicas
@@ -345,6 +355,7 @@
new_replica['id'], constants.REPLICATION_STATE_IN_SYNC,
status_attr='replica_state')
+ @decorators.idempotent_id('1452156b-75a5-4f3c-a921-834732a03b0a')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_active_replication_state(self):
# Verify the replica_state of first instance is set to active.
@@ -439,6 +450,7 @@
replica['id'], len(replica_id_list))
self.assertEqual(1, len(replica_id_list), msg)
+ @decorators.idempotent_id('abe0e49d-0b94-4b81-a220-ab047712492d')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_show_share_replica(self):
replica = self.shares_v2_client.get_share_replica(self.replica1["id"])
@@ -450,6 +462,7 @@
'expected %s, got %s.' % (replica["id"],
detail_keys, actual_keys))
+ @decorators.idempotent_id('f5225fb7-fcbe-4825-bf5b-0e11c2d26e03')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_detail_list_share_replicas_for_share(self):
# List replicas for share
@@ -462,6 +475,7 @@
# Verify keys
self._validate_replica_list(replica_list)
+ @decorators.idempotent_id('e39aeb5d-fe4b-4896-8615-e6e7290bcb56')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_detail_list_share_replicas_for_all_shares(self):
# List replicas for all available shares
@@ -474,6 +488,7 @@
# Verify keys
self._validate_replica_list(replica_list)
+ @decorators.idempotent_id('8d11848a-7766-41e5-af09-6121e5bad447')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_summary_list_share_replicas_for_all_shares(self):
# List replicas
diff --git a/manila_tempest_tests/tests/api/test_replication_export_locations.py b/manila_tempest_tests/tests/api/test_replication_export_locations.py
index a99ee55..55ea475 100644
--- a/manila_tempest_tests/tests/api/test_replication_export_locations.py
+++ b/manila_tempest_tests/tests/api/test_replication_export_locations.py
@@ -13,6 +13,7 @@
import ddt
from tempest import config
from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
import testtools
from testtools import testcase as tc
@@ -118,6 +119,7 @@
for export in expected_exports:
self.assertIn(export['path'], share_export_paths)
+ @decorators.idempotent_id('da22cfb8-7dd8-4bf1-87fc-a1f7b51ebf8e')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@ddt.data(*set(['2.46', '2.47', LATEST_MICROVERSION]))
def test_replicated_share_export_locations(self, version):
@@ -135,6 +137,7 @@
primary_replica_exports,
share_exports, version)
+ @decorators.idempotent_id('58430f57-c6eb-44e2-9583-eecb1dd10594')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@ddt.data(*set(['2.46', '2.47', LATEST_MICROVERSION]))
@testtools.skipUnless(
@@ -184,6 +187,7 @@
# Delete the secondary (the 'active' replica before promotion)
self.delete_share_replica(primary_replica['id'])
+ @decorators.idempotent_id('10ab6304-a1cd-4e60-90e3-7f9358b8808a')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@utils.skip_if_microversion_not_supported('2.47')
def test_replica_export_locations(self):
diff --git a/manila_tempest_tests/tests/api/test_replication_export_locations_negative.py b/manila_tempest_tests/tests/api/test_replication_export_locations_negative.py
index 3d18fae..eb0530c 100644
--- a/manila_tempest_tests/tests/api/test_replication_export_locations_negative.py
+++ b/manila_tempest_tests/tests/api/test_replication_export_locations_negative.py
@@ -12,6 +12,7 @@
from tempest import config
from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
import testtools
from testtools import testcase as tc
@@ -63,6 +64,7 @@
cls.share_zone = cls.zones[0]
cls.replica_zone = cls.zones[-1]
+ @decorators.idempotent_id('7a6318c2-71e9-45d2-aafe-5dcc0810a14a')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@utils.skip_if_microversion_not_supported('2.47')
@testtools.skipUnless(
@@ -85,6 +87,7 @@
self.shares_v2_client.get_share_export_location,
share['id'], export['id'])
+ @decorators.idempotent_id('f1b89548-4da7-4ce1-a3c0-363a6c1ea726')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@utils.skip_if_microversion_not_supported('2.47')
def test_get_replica_export_location_for_non_replica(self):
@@ -101,6 +104,7 @@
self.shares_v2_client.list_share_replica_export_locations,
instance['id'])
+ @decorators.idempotent_id('f60d7eec-ec29-4767-985f-ff8c9e771cae')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
@utils.skip_if_microversion_not_supported('2.47')
def test_list_replica_export_locations_for_invalid_replica(self):
@@ -110,6 +114,7 @@
self.shares_v2_client.list_share_replica_export_locations,
'invalid-replica-id')
+ @decorators.idempotent_id('29ec890e-e324-4487-b2e3-f87642b6a58d')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@utils.skip_if_microversion_not_supported('2.47')
def test_get_replica_export_location_for_invalid_export_id(self):
diff --git a/manila_tempest_tests/tests/api/test_replication_negative.py b/manila_tempest_tests/tests/api/test_replication_negative.py
index 3215641..c437737 100644
--- a/manila_tempest_tests/tests/api/test_replication_negative.py
+++ b/manila_tempest_tests/tests/api/test_replication_negative.py
@@ -15,6 +15,7 @@
from tempest import config
from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
import testtools
from testtools import testcase as tc
@@ -52,7 +53,7 @@
# create share type
extra_specs = {"replication_type": cls.replication_type}
- cls.share_type = cls._create_share_type(extra_specs)
+ cls.share_type = cls._create_share_type(specs=extra_specs)
cls.share_type_id = cls.share_type['id']
cls.sn_id = None
if cls.multitenancy_enabled:
@@ -89,6 +90,7 @@
raise self.skipException(
msg % ','.join(constants.REPLICATION_PROMOTION_CHOICES))
+ @decorators.idempotent_id('90c5947d-b857-406c-b7dc-7010cbee6482')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_try_add_replica_to_share_with_no_replication_share_type(self):
# Create share without replication type
@@ -103,6 +105,7 @@
share['id'],
self.replica_zone)
+ @decorators.idempotent_id('d14ba73e-4f13-451e-86d5-ffeb188e51b7')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_add_replica_to_share_with_error_state(self):
# Set "error" state
@@ -116,12 +119,14 @@
self.share1['id'],
self.replica_zone)
+ @decorators.idempotent_id('94b41c28-e7a9-4f19-9315-4a57210141af')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_try_delete_last_active_replica(self):
self.assertRaises(lib_exc.BadRequest,
self.shares_v2_client.delete_share_replica,
self.instance_id1)
+ @decorators.idempotent_id('6fbf984d-4efa-41d7-88bf-11ef2f078c02')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_try_delete_share_having_replica(self):
self.create_share_replica(self.share1["id"], self.replica_zone,
@@ -130,6 +135,7 @@
self.shares_v2_client.delete_share,
self.share1["id"])
+ @decorators.idempotent_id('b9c2e57b-f1ae-475c-9d0b-df75dbe93b61')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_promote_out_of_sync_share_replica(self):
# Test promoting an out_of_sync share_replica to active state
@@ -148,6 +154,7 @@
self.shares_v2_client.promote_share_replica,
replica['id'])
+ @decorators.idempotent_id('e525c3d0-9f45-489f-8e78-ed9e3ac540f7')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_promote_active_share_replica(self):
# Test promote active share_replica
@@ -157,6 +164,7 @@
self.shares_v2_client.promote_share_replica(self.instance_id1,
expected_status=200)
+ @decorators.idempotent_id('37dc3f7e-5a36-4020-ae1b-3c5e6771f024')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_promote_share_replica_for_writable_share_type(self):
# Test promote active share_replica for writable share
@@ -174,6 +182,7 @@
# Try promoting the replica
self.shares_v2_client.promote_share_replica(replica['id'])
+ @decorators.idempotent_id('600a13d2-5cf0-482e-97af-9f598b55a407')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_add_access_rule_share_replica_error_status(self):
access_type, access_to = self._get_access_rule_data_from_config()
@@ -190,6 +199,7 @@
self.admin_client.create_access_rule,
self.share1["id"], access_type, access_to, 'ro')
+ @decorators.idempotent_id('91b93b71-4048-412b-bb42-0fe88edfb987')
@testtools.skipUnless(CONF.share.run_host_assisted_migration_tests or
CONF.share.run_driver_assisted_migration_tests,
"Share migration tests are disabled.")
@@ -211,6 +221,7 @@
lib_exc.Conflict, self.admin_client.migrate_share,
self.share1['id'], dest_host)
+ @decorators.idempotent_id('bf01bcfc-57cb-4e56-957f-8aa9f1b9be1b')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@base.skip_if_microversion_lt("2.48")
def test_try_add_replica_share_type_azs_unsupported_az(self):
@@ -224,6 +235,7 @@
self.share1['id'],
self.replica_zone)
+ @decorators.idempotent_id('97fc5ab3-c6e2-4da4-ae45-08d458a5ba0c')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipIf(
not CONF.share.multitenancy_enabled, "Only for multitenancy.")
@@ -255,12 +267,14 @@
utils.check_skip_if_microversion_lt(_MIN_SUPPORTED_MICROVERSION)
+ @decorators.idempotent_id('72395c9b-4432-4a8b-84b4-60303e6bc962')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_get_replica_by_nonexistent_id(self):
self.assertRaises(lib_exc.NotFound,
self.shares_v2_client.get_share_replica,
data_utils.rand_uuid())
+ @decorators.idempotent_id('41d45772-e021-4404-a991-85f7a6e6431b')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_delete_replica_by_nonexistent_id(self):
self.assertRaises(lib_exc.NotFound,
diff --git a/manila_tempest_tests/tests/api/test_replication_snapshots.py b/manila_tempest_tests/tests/api/test_replication_snapshots.py
index 591b3fd..a812679 100644
--- a/manila_tempest_tests/tests/api/test_replication_snapshots.py
+++ b/manila_tempest_tests/tests/api/test_replication_snapshots.py
@@ -14,6 +14,7 @@
# under the License.
from tempest import config
+from tempest.lib import decorators
import testtools
from testtools import testcase as tc
@@ -53,7 +54,7 @@
# create share type
extra_specs = {"replication_type": cls.replication_type}
- cls.share_type = cls._create_share_type(extra_specs)
+ cls.share_type = cls._create_share_type(specs=extra_specs)
cls.share_type_id = cls.share_type['id']
cls.sn_id = None
if cls.multitenancy_enabled:
@@ -66,6 +67,7 @@
cls.share_zone = cls.zones[0]
cls.replica_zone = cls.zones[-1]
+ @decorators.idempotent_id('67fce02a-1d46-4186-8260-69e30b26195d')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
def test_snapshot_after_share_replica(self):
"""Test the snapshot for replicated share.
@@ -100,6 +102,7 @@
snapshot_id=snapshot['id'],
share_network_id=self.sn_id)
+ @decorators.idempotent_id('ced8920b-6e3a-4bb4-9b3d-86e54377fcb7')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
def test_snapshot_before_share_replica(self):
"""Test the snapshot for replicated share.
@@ -138,6 +141,7 @@
snapshot_id=snapshot['id'],
share_network_id=self.sn_id)
+ @decorators.idempotent_id('a5372844-69ad-40e1-bbf3-265eb66af123')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
def test_snapshot_before_and_after_share_replica(self):
"""Test the snapshot for replicated share.
@@ -187,6 +191,7 @@
snapshot_id=snapshot2['id'],
share_network_id=self.sn_id)
+ @decorators.idempotent_id('b4cd376b-1eb8-4780-801a-64b0c3bee1e4')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
def test_delete_snapshot_after_adding_replica(self):
"""Verify the snapshot delete.
@@ -208,6 +213,7 @@
self.shares_v2_client.wait_for_resource_deletion(
snapshot_id=snapshot["id"])
+ @decorators.idempotent_id('913056a7-d897-4a1b-a7be-b2b2cf5d9572')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@testtools.skipUnless(
CONF.share.capability_create_share_from_snapshot_support,
diff --git a/manila_tempest_tests/tests/api/test_revert_to_snapshot.py b/manila_tempest_tests/tests/api/test_revert_to_snapshot.py
index ea9e5dd..6a915c6 100644
--- a/manila_tempest_tests/tests/api/test_revert_to_snapshot.py
+++ b/manila_tempest_tests/tests/api/test_revert_to_snapshot.py
@@ -14,9 +14,9 @@
# under the License.
import ddt
-
from tempest import config
from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
from testtools import testcase as tc
from manila_tempest_tests.common import constants
@@ -24,6 +24,7 @@
from manila_tempest_tests.tests.api import base
from manila_tempest_tests import utils
+
CONF = config.CONF
@@ -101,6 +102,7 @@
cls.shares_v2_client.share_network_id)
cls.sn_id = cls.share_network['id']
+ @decorators.idempotent_id('196f2bc5-e13a-4730-ac51-61e339068a06')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@ddt.data(
*{constants.REVERT_TO_SNAPSHOT_MICROVERSION,
@@ -116,6 +118,7 @@
self.shares_v2_client.wait_for_share_status(self.share['id'],
constants.STATUS_AVAILABLE)
+ @decorators.idempotent_id('09bd9942-7ef9-4d24-b2dd-f83bdda27b50')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@ddt.data(
*{constants.REVERT_TO_SNAPSHOT_MICROVERSION,
@@ -137,6 +140,7 @@
self.shares_v2_client.wait_for_share_status(self.share['id'],
constants.STATUS_AVAILABLE)
+ @decorators.idempotent_id('146de138-d351-49dc-a13a-5cdbed40b9ac')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@tc.skipUnless(CONF.share.run_replication_tests,
'Replication tests are disabled.')
diff --git a/manila_tempest_tests/tests/api/test_revert_to_snapshot_negative.py b/manila_tempest_tests/tests/api/test_revert_to_snapshot_negative.py
index 34b0530..bc01f00 100644
--- a/manila_tempest_tests/tests/api/test_revert_to_snapshot_negative.py
+++ b/manila_tempest_tests/tests/api/test_revert_to_snapshot_negative.py
@@ -14,9 +14,9 @@
# under the License.
import ddt
-
from tempest import config
from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
from tempest.lib import exceptions
from testtools import testcase as tc
@@ -24,6 +24,7 @@
from manila_tempest_tests.tests.api import base
from manila_tempest_tests import utils
+
CONF = config.CONF
@@ -73,6 +74,7 @@
cls.share = cls.create_share(share_type_id=cls.st_id)
cls.share2 = cls.create_share(share_type_id=cls.st_id)
+ @decorators.idempotent_id('21dd8561-8913-42a2-a95c-74b536964c94')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@ddt.data(
*{constants.REVERT_TO_SNAPSHOT_MICROVERSION,
@@ -90,6 +92,7 @@
snapshot1['id'],
version=version)
+ @decorators.idempotent_id('7360ee16-ac7d-46ce-9c81-251d64fb7434')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@ddt.data(
*{constants.REVERT_TO_SNAPSHOT_MICROVERSION,
@@ -109,6 +112,7 @@
snapshot['id'],
version=version)
+ @decorators.idempotent_id('108a451e-a8e9-450f-8f75-53883d58c6be')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@ddt.data(
*{constants.REVERT_TO_SNAPSHOT_MICROVERSION,
@@ -133,6 +137,7 @@
snapshot['id'],
version=version)
+ @decorators.idempotent_id('29024057-dbbd-4cf6-a796-207dfbd4c3ff')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@ddt.data(
*{constants.REVERT_TO_SNAPSHOT_MICROVERSION,
@@ -145,6 +150,7 @@
self.share['id'],
version=version)
+ @decorators.idempotent_id('ef706fad-5ac4-41dc-af81-5aa0331560cf')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@ddt.data(
*{constants.REVERT_TO_SNAPSHOT_MICROVERSION,
diff --git a/manila_tempest_tests/tests/api/test_rules.py b/manila_tempest_tests/tests/api/test_rules.py
index 7867bb4..71bdd06 100644
--- a/manila_tempest_tests/tests/api/test_rules.py
+++ b/manila_tempest_tests/tests/api/test_rules.py
@@ -13,10 +13,11 @@
# License for the specific language governing permissions and limitations
# under the License.
+import itertools
import ddt
-import itertools
from tempest import config
+from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
import testtools
from testtools import testcase as tc
@@ -24,6 +25,7 @@
from manila_tempest_tests.tests.api import base
from manila_tempest_tests import utils
+
CONF = config.CONF
LATEST_MICROVERSION = CONF.share.max_api_microversion
@@ -101,6 +103,7 @@
cls.access_type = "ip"
cls.access_to = "2.2.2.2"
+ @decorators.idempotent_id('3390df2d-f6f8-4634-a562-87c1be994f6a')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@ddt.data(*itertools.chain(
itertools.product({'1.0', '2.9', '2.37', LATEST_MICROVERSION}, {4}),
@@ -155,6 +158,7 @@
self.shares_v2_client.wait_for_resource_deletion(
rule_id=rule["id"], share_id=self.share['id'], version=version)
+ @decorators.idempotent_id('5d25168a-d646-443e-8cf1-3151eb7887f5')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@ddt.data(*itertools.chain(
itertools.product({'1.0', '2.9', '2.37', LATEST_MICROVERSION}, {4}),
@@ -207,6 +211,7 @@
self.shares_v2_client.wait_for_resource_deletion(
rule_id=rule["id"], share_id=self.share['id'], version=version)
+ @decorators.idempotent_id('187a4fb0-ba1d-45b9-83c9-f0272e7e6f3e')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@testtools.skipIf(
"nfs" not in CONF.share.enable_ro_access_level_for_protocols,
@@ -220,6 +225,7 @@
class ShareIpRulesForCIFSTest(ShareIpRulesForNFSTest):
protocol = "cifs"
+ @decorators.idempotent_id('8fa0a15f-c04c-4521-91e7-020943bede8a')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@testtools.skipIf(
"cifs" not in CONF.share.enable_ro_access_level_for_protocols,
@@ -257,6 +263,7 @@
cls.access_type = "user"
cls.access_to = CONF.share.username_for_user_rules
+ @decorators.idempotent_id('1f87565f-c3d9-448d-b89a-387d6c2fdae6')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@ddt.data(*set(['1.0', '2.9', '2.27', '2.28', LATEST_MICROVERSION]))
def test_create_delete_user_rule(self, version):
@@ -302,6 +309,7 @@
self.shares_v2_client.wait_for_resource_deletion(
rule_id=rule["id"], share_id=self.share['id'], version=version)
+ @decorators.idempotent_id('ccb08342-b7ef-4dda-84ba-8de9879d8862')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@testtools.skipIf(
"nfs" not in CONF.share.enable_ro_access_level_for_protocols,
@@ -315,6 +323,7 @@
class ShareUserRulesForCIFSTest(ShareUserRulesForNFSTest):
protocol = "cifs"
+ @decorators.idempotent_id('ee11084d-6c1d-4856-8044-9aa9e6c670fb')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@testtools.skipIf(
"cifs" not in CONF.share.enable_ro_access_level_for_protocols,
@@ -353,6 +362,7 @@
# certificate that it possesses.
cls.access_to = "client1.com"
+ @decorators.idempotent_id('775ebc55-4a4d-4012-a030-2eeb7b6d2ce8')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@ddt.data(*set(['1.0', '2.9', '2.27', '2.28', LATEST_MICROVERSION]))
def test_create_delete_cert_rule(self, version):
@@ -398,6 +408,7 @@
self.shares_v2_client.wait_for_resource_deletion(
rule_id=rule["id"], share_id=self.share['id'], version=version)
+ @decorators.idempotent_id('cdd93d8e-7255-4ed4-8ef0-929a62bb302c')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@testtools.skipIf(
"glusterfs" not in CONF.share.enable_ro_access_level_for_protocols,
@@ -473,6 +484,7 @@
# Provide access to a client identified by a cephx auth id.
cls.access_to = "bob"
+ @decorators.idempotent_id('4e636fd2-26ef-4b63-96eb-77860a8b6cdf')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@ddt.data(*itertools.product(
set(['2.13', '2.27', '2.28', LATEST_MICROVERSION]),
@@ -495,6 +507,32 @@
self.shares_v2_client.wait_for_resource_deletion(
rule_id=rule["id"], share_id=self.share['id'])
+ @decorators.idempotent_id('ad907303-a439-4fcb-8845-fe91ecab7dc2')
+ @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+ def test_different_users_in_same_tenant_can_use_same_cephx_id(self):
+ # Grant access to the share
+ access1 = self.shares_v2_client.create_access_rule(
+ self.share['id'], self.access_type, self.access_to, 'rw')
+ self.shares_v2_client.wait_for_access_rule_status(
+ self.share['id'], access1['id'], 'active')
+
+ # Create a new user in the current project
+ project = self.os_admin.projects_client.show_project(
+ self.shares_v2_client.tenant_id)['project']
+ user_client = self.create_user_and_get_client(project)
+
+ # Create second share by the new user
+ share2 = self.create_share(client=user_client.shares_v2_client,
+ share_protocol=self.protocol,
+ share_type_id=self.share_type_id)
+
+ # Grant access to the second share using the same cephx ID that was
+ # used in access1
+ access2 = user_client.shares_v2_client.create_access_rule(
+ share2['id'], self.access_type, self.access_to, 'rw')
+ user_client.shares_v2_client.wait_for_access_rule_status(
+ share2['id'], access2['id'], 'active')
+
@ddt.ddt
class ShareRulesTest(base.BaseSharesMixedTest):
@@ -530,6 +568,7 @@
cls.share_type_id = cls.share_type['id']
cls.share = cls.create_share(share_type_id=cls.share_type_id)
+ @decorators.idempotent_id('c52e95cc-d6ea-4d02-9b52-cd7c1913dfff')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@ddt.data(*set(
['1.0', '2.9', '2.27', '2.28', '2.45', LATEST_MICROVERSION]))
@@ -623,6 +662,7 @@
self.shares_v2_client.wait_for_resource_deletion(
rule_id=rule["id"], share_id=self.share['id'], version=version)
+ @decorators.idempotent_id('b77bcbda-9754-48f0-9be6-79341ad1af64')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@ddt.data(*set(['1.0', '2.9', '2.27', '2.28', LATEST_MICROVERSION]))
def test_access_rules_deleted_if_share_deleted(self, version):
diff --git a/manila_tempest_tests/tests/api/test_rules_negative.py b/manila_tempest_tests/tests/api/test_rules_negative.py
index e532f7e..63ffb91 100644
--- a/manila_tempest_tests/tests/api/test_rules_negative.py
+++ b/manila_tempest_tests/tests/api/test_rules_negative.py
@@ -15,6 +15,7 @@
import ddt
from tempest import config
+from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
import testtools
from testtools import testcase as tc
@@ -54,6 +55,7 @@
# create snapshot
cls.snap = cls.create_snapshot_wait_for_active(cls.share["id"])
+ @decorators.idempotent_id('16781b45-d2bb-4891-aa97-c28c0769d5bd')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@ddt.data('1.2.3.256',
'1.1.1.-',
@@ -73,6 +75,7 @@
getattr(self, client_name).create_access_rule,
self.share["id"], "ip", ip_address)
+ @decorators.idempotent_id('e891deff-23d9-4872-911c-bd9b43dc797f')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@ddt.data('shares_client', 'shares_v2_client')
def test_create_access_rule_with_wrong_level(self, client_name):
@@ -83,6 +86,7 @@
'2.2.2.2',
'su')
+ @decorators.idempotent_id('efd594aa-dd24-427e-acdf-10d124afb572')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@ddt.data('1.0', '2.9', LATEST_MICROVERSION)
def test_create_duplicate_of_ip_rule(self, version):
@@ -132,6 +136,7 @@
self.shares_v2_client.wait_for_resource_deletion(
rule_id=rule["id"], share_id=self.share["id"], version=version)
+ @decorators.idempotent_id('63932d1d-a60a-4af7-ba3b-7cf6c68aaee9')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@ddt.data("10.20.30.40", "fd8c:b029:bba6:ac54::1",
"fd2c:b029:bba6:df54::1/128", "10.10.30.40/32")
@@ -165,6 +170,7 @@
self.shares_v2_client.create_access_rule,
self.share["id"], "ip", access_to)
+ @decorators.idempotent_id('d2856c7d-9417-416d-8d08-e68376ee5b2e')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_add_access_rule_on_share_with_no_host(self):
access_type, access_to = self._get_access_rule_data_from_config()
@@ -211,6 +217,7 @@
# create snapshot
cls.snap = cls.create_snapshot_wait_for_active(cls.share["id"])
+ @decorators.idempotent_id('d6148911-3a0c-4e1f-afdb-fcf203fe4a5b')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@ddt.data('shares_client', 'shares_v2_client')
def test_create_access_rule_user_with_wrong_input_2(self, client_name):
@@ -219,6 +226,7 @@
self.share["id"], "user",
"try+")
+ @decorators.idempotent_id('a4d8358d-dec0-4c2a-a544-182816a0ba6f')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@ddt.data('shares_client', 'shares_v2_client')
def test_create_access_rule_user_with_empty_key(self, client_name):
@@ -226,6 +234,7 @@
getattr(self, client_name).create_access_rule,
self.share["id"], "user", "")
+ @decorators.idempotent_id('f5252e86-4767-48ad-8be5-43e12c93df79')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@ddt.data('shares_client', 'shares_v2_client')
def test_create_access_rule_user_with_too_little_key(self, client_name):
@@ -233,6 +242,7 @@
getattr(self, client_name).create_access_rule,
self.share["id"], "user", "abc")
+ @decorators.idempotent_id('f8f4d3ee-82b8-4d37-917d-a0cd72073df4')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@ddt.data('shares_client', 'shares_v2_client')
def test_create_access_rule_user_with_too_big_key(self, client_name):
@@ -240,6 +250,7 @@
getattr(self, client_name).create_access_rule,
self.share["id"], "user", "a" * 256)
+ @decorators.idempotent_id('21724a99-0790-49d5-a069-d1df43782965')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@ddt.data('shares_client', 'shares_v2_client')
def test_create_access_rule_user_with_wrong_input_1(self, client_name):
@@ -248,6 +259,7 @@
self.share["id"], "user",
"try+")
+ @decorators.idempotent_id('bc62ce96-36fe-4c9b-b6b9-4d5a661c8035')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@ddt.data('shares_client', 'shares_v2_client')
@testtools.skipUnless(CONF.share.run_snapshot_tests,
@@ -259,6 +271,7 @@
access_type="user",
access_to="fakeuser")
+ @decorators.idempotent_id('04d5b25f-b335-4574-82b0-f607c8b3bf25')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@ddt.data('shares_client', 'shares_v2_client')
def test_create_access_rule_user_with_wrong_share_id(self, client_name):
@@ -268,6 +281,7 @@
access_type="user",
access_to="fakeuser")
+ @decorators.idempotent_id('301bdbd5-4398-4320-b334-7370995369e9')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@ddt.data('shares_client', 'shares_v2_client')
def test_create_access_rule_with_wrong_level(self, client_name):
@@ -305,6 +319,7 @@
# create snapshot
cls.snap = cls.create_snapshot_wait_for_active(cls.share["id"])
+ @decorators.idempotent_id('a16d53d5-50d4-4015-912f-2850c5d62690')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@ddt.data('shares_client', 'shares_v2_client')
def test_create_access_rule_cert_with_empty_common_name(self, client_name):
@@ -312,6 +327,7 @@
getattr(self, client_name).create_access_rule,
self.share["id"], "cert", "")
+ @decorators.idempotent_id('7b5383d8-5bcd-47aa-955b-ed3757a5bdb4')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@ddt.data('shares_client', 'shares_v2_client')
def test_create_access_rule_cert_with_whitespace_common_name(self,
@@ -320,6 +336,7 @@
getattr(self, client_name).create_access_rule,
self.share["id"], "cert", " ")
+ @decorators.idempotent_id('1c25c134-92b4-4875-a061-88d394e28bcc')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@ddt.data('shares_client', 'shares_v2_client')
def test_create_access_rule_cert_with_too_big_common_name(self,
@@ -329,6 +346,7 @@
getattr(self, client_name).create_access_rule,
self.share["id"], "cert", "a" * 65)
+ @decorators.idempotent_id('dd85d5cd-aa83-4f44-8572-bd7e68a84fb2')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipUnless(CONF.share.run_snapshot_tests,
"Snapshot tests are disabled.")
@@ -340,6 +358,7 @@
access_type="cert",
access_to="fakeclient1.com")
+ @decorators.idempotent_id('eb47a511-7688-4689-a2ad-54ba85b39b07')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@ddt.data('shares_client', 'shares_v2_client')
def test_create_access_rule_cert_with_wrong_share_id(self, client_name):
@@ -371,6 +390,7 @@
cls.access_type = "cephx"
cls.access_to = "david"
+ @decorators.idempotent_id('7b33c073-353e-4952-97dc-c3948a3cd037')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@ddt.data('jane.doe', u"bj\u00F6rn")
def test_create_access_rule_cephx_with_invalid_cephx_id(self, access_to):
@@ -378,6 +398,7 @@
self.shares_v2_client.create_access_rule,
self.share["id"], self.access_type, access_to)
+ @decorators.idempotent_id('dd8be44c-c7e8-42fe-b81c-095a1c66730c')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_create_access_rule_cephx_with_wrong_level(self):
self.assertRaises(lib_exc.BadRequest,
@@ -385,6 +406,61 @@
self.share["id"], self.access_type, self.access_to,
access_level="su")
+ @decorators.idempotent_id('4ffed391-d7cc-481b-bb74-9f3406ddd75f')
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+ def test_different_tenants_cannot_use_same_cephx_id(self):
+ # Grant access to the share
+ self.allow_access(self.share['id'], access_to=self.access_to)
+
+ # Create second share by the new user
+ share2 = self.create_share(client=self.alt_shares_v2_client,
+ share_protocol=self.protocol,
+ share_type_id=self.share_type_id)
+
+ # Try grant access to the second share using the same cephx id as used
+ # on the first share.
+ # Rule must be set to "error" status.
+ self.allow_access(share2['id'], client=self.alt_shares_v2_client,
+ access_to=self.access_to, status='error',
+ raise_rule_in_error_state=False)
+
+ share_alt_updated = self.alt_shares_v2_client.get_share(
+ share2['id'])
+ self.assertEqual('error', share_alt_updated['access_rules_status'])
+
+ @decorators.idempotent_id('1a9f46f0-d4e1-40ac-8726-aedd0320d583')
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API)
+ def test_can_apply_new_cephx_rules_when_one_is_in_error_state(self):
+ # Create share on "primary" tenant
+ share_primary = self.create_share()
+ # Add access rule to "Joe" by "primary" user
+ self.allow_access(share_primary['id'], access_to='Joe')
+
+ # Create share on "alt" tenant
+ share_alt = self.create_share(client=self.alt_shares_v2_client)
+ # Add access rule to "Joe" by "alt" user.
+ # Rule must be set to "error" status.
+ rule1 = self.allow_access(share_alt['id'],
+ client=self.alt_shares_v2_client,
+ access_to='Joe',
+ status='error',
+ raise_rule_in_error_state=False,
+ cleanup=False)
+
+ # Share's "access_rules_status" must be in "error" status
+ share_alt_updated = self.alt_shares_v2_client.get_share(
+ share_alt['id'])
+ self.assertEqual('error', share_alt_updated['access_rules_status'])
+
+ # Add second access rule to different client by "alt" user.
+ self.allow_access(share_alt['id'], client=self.alt_shares_v2_client)
+
+ # Check share's access_rules_status has transitioned to "active" status
+ self.alt_shares_v2_client.delete_access_rule(
+ share_alt['id'], rule1['id'])
+ self.alt_shares_v2_client.wait_for_share_status(
+ share_alt['id'], 'active', status_attr='access_rules_status')
+
@ddt.ddt
class ShareRulesNegativeTest(base.BaseSharesMixedTest):
@@ -412,6 +488,7 @@
# create snapshot
cls.snap = cls.create_snapshot_wait_for_active(cls.share["id"])
+ @decorators.idempotent_id('84da9231-5c4b-4615-8500-8fc6d30ff7ea')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@ddt.data('shares_client', 'shares_v2_client')
def test_delete_access_rule_with_wrong_id(self, client_name):
@@ -419,6 +496,7 @@
getattr(self, client_name).delete_access_rule,
self.share["id"], "wrong_rule_id")
+ @decorators.idempotent_id('13f9329f-12db-467d-9268-a9cca75997d9')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@ddt.data('shares_client', 'shares_v2_client')
def test_create_access_rule_ip_with_wrong_type(self, client_name):
@@ -426,6 +504,7 @@
getattr(self, client_name).create_access_rule,
self.share["id"], "wrong_type", "1.2.3.4")
+ @decorators.idempotent_id('fd6ede10-97d6-4ee8-a661-c516b7421c91')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@ddt.data('shares_client', 'shares_v2_client')
@testtools.skipUnless(CONF.share.run_snapshot_tests,
@@ -439,6 +518,7 @@
@ddt.ddt
class ShareRulesAPIOnlyNegativeTest(base.BaseSharesTest):
+ @decorators.idempotent_id('01279461-3ccc-49b2-a615-d7984dd0db8c')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
@ddt.data('shares_client', 'shares_v2_client')
def test_create_access_rule_ip_with_wrong_share_id(self, client_name):
diff --git a/manila_tempest_tests/tests/api/test_scheduler_stats_negative.py b/manila_tempest_tests/tests/api/test_scheduler_stats_negative.py
index c7dc3f0..2423bc1 100644
--- a/manila_tempest_tests/tests/api/test_scheduler_stats_negative.py
+++ b/manila_tempest_tests/tests/api/test_scheduler_stats_negative.py
@@ -13,6 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
from testtools import testcase as tc
@@ -21,11 +22,13 @@
class SchedulerStatsNegativeTest(base.BaseSharesTest):
+ @decorators.idempotent_id('33db76eb-7501-43f9-8c4f-8e6e35519a4d')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_list_pools_with_user(self):
self.assertRaises(lib_exc.Forbidden,
self.shares_client.list_pools)
+ @decorators.idempotent_id('f89136cf-34a1-475b-8514-3114f9f159a5')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_list_pools_detailed_with_user(self):
self.assertRaises(lib_exc.Forbidden,
diff --git a/manila_tempest_tests/tests/api/test_security_services.py b/manila_tempest_tests/tests/api/test_security_services.py
index 3bc0eeb..b300973 100644
--- a/manila_tempest_tests/tests/api/test_security_services.py
+++ b/manila_tempest_tests/tests/api/test_security_services.py
@@ -17,6 +17,7 @@
from oslo_log import log
import six
from tempest import config
+from tempest.lib import decorators
import testtools
from testtools import testcase as tc
@@ -31,6 +32,7 @@
@ddt.ddt
class SecurityServiceListMixin(object):
+ @decorators.idempotent_id('f6f5657c-a93c-49ed-86e3-b351a92734d5')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_list_security_services(self):
listed = self.shares_client.list_security_services()
@@ -42,6 +44,7 @@
keys = ["name", "id", "status", "type", ]
[self.assertIn(key, s_s.keys()) for s_s in listed for key in keys]
+ @decorators.idempotent_id('22b22937-7436-458c-ac22-8ff19feab253')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@ddt.data(*set(['1.0', '2.42', '2.44', LATEST_MICROVERSION]))
def test_list_security_services_with_detail(self, version):
@@ -68,6 +71,7 @@
for ss in listed:
self.assertEqual(with_ou, 'ou' in ss.keys())
+ @decorators.idempotent_id('88f62835-0aee-4bed-a37f-ffd99430da8a')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@testtools.skipIf(
not CONF.share.multitenancy_enabled, "Only for multitenancy.")
@@ -77,6 +81,7 @@
fresh_sn = []
for i in range(2):
sn = self.create_share_network(
+ add_security_services=False,
neutron_net_id=sn["neutron_net_id"],
neutron_subnet_id=sn["neutron_subnet_id"])
fresh_sn.append(sn)
@@ -94,6 +99,7 @@
keys = ["name", "id", "status", "type", ]
[self.assertIn(key, s_s.keys()) for s_s in listed for key in keys]
+ @decorators.idempotent_id('f055faad-dd36-4eed-9b50-61280931dea2')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_list_security_services_detailed_filter_by_ss_attributes(self):
search_opts = {
@@ -150,6 +156,7 @@
self.ss_kerberos = self.create_security_service(
'kerberos', **ss_kerberos_data)
+ @decorators.idempotent_id('70927e29-4a6a-431a-bbc1-76bc419e0579')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_create_delete_security_service(self):
data = self.generate_security_service_data()
@@ -160,6 +167,7 @@
self.assertEqual(ss_name, ss["type"])
self.shares_client.delete_security_service(ss["id"])
+ @decorators.idempotent_id('bb052be4-0176-4613-b7d5-e12bef391ddb')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@ddt.data(*set(['1.0', '2.43', '2.44', LATEST_MICROVERSION]))
def test_get_security_service(self, version):
@@ -181,6 +189,7 @@
self.assertDictContainsSubset(data, get)
self.assertEqual(with_ou, 'ou' in get)
+ @decorators.idempotent_id('84d47747-13c8-4ab9-9fc4-a43fbb29ad18')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_update_security_service(self):
data = self.generate_security_service_data()
@@ -205,6 +214,7 @@
self.assertDictContainsSubset(upd_data_ou, updated_ou)
self.assertDictContainsSubset(upd_data_ou, get_ou)
+ @decorators.idempotent_id('c3c04992-da11-4677-9098-eff3f4231a4b')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipIf(
not CONF.share.multitenancy_enabled, "Only for multitenancy.")
@@ -244,6 +254,7 @@
ss["id"], **update_data)
self.assertDictContainsSubset(update_data, updated)
+ @decorators.idempotent_id('8d9af272-df89-470d-9ff8-92ba774c9fff')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_list_security_services_filter_by_invalid_opt(self):
listed = self.shares_client.list_security_services(
@@ -252,6 +263,7 @@
self.assertTrue(any(self.ss_kerberos['id'] == ss['id']
for ss in listed))
+ @decorators.idempotent_id('d501710e-4710-4c13-a373-75ed6ababb13')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_try_list_security_services_all_tenants(self):
listed = self.shares_client.list_security_services(
diff --git a/manila_tempest_tests/tests/api/test_security_services_mapping.py b/manila_tempest_tests/tests/api/test_security_services_mapping.py
index 8025bf7..db0a8b7 100644
--- a/manila_tempest_tests/tests/api/test_security_services_mapping.py
+++ b/manila_tempest_tests/tests/api/test_security_services_mapping.py
@@ -13,6 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempest.lib import decorators
from testtools import testcase as tc
from manila_tempest_tests.tests.api import base
@@ -31,7 +32,9 @@
# create share network
data = self.generate_share_network_data()
- self.sn = self.create_share_network(client=self.cl, **data)
+ self.sn = self.create_share_network(client=self.cl,
+ add_security_services=False,
+ **data)
self.assertDictContainsSubset(data, self.sn)
# create security service
@@ -43,6 +46,7 @@
# Add security service to share network
self.cl.add_sec_service_to_share_network(self.sn["id"], self.ss["id"])
+ @decorators.idempotent_id('e8c5b4d5-7ad2-4aa7-bab0-b454a2e150e9')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_map_ss_to_sn_and_list(self):
@@ -52,6 +56,7 @@
for key in ["status", "id", "name"]:
self.assertIn(self.ss[key], ls[0][key])
+ @decorators.idempotent_id('9dd352b2-6d47-4cab-aa61-52d8081f67a2')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_map_ss_to_sn_and_delete(self):
@@ -59,6 +64,7 @@
self.cl.remove_sec_service_from_share_network(
self.sn["id"], self.ss["id"])
+ @decorators.idempotent_id('2b0bd5cc-eb35-430f-acfd-f80a2e467667')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_remap_ss_to_sn(self):
diff --git a/manila_tempest_tests/tests/api/test_security_services_mapping_negative.py b/manila_tempest_tests/tests/api/test_security_services_mapping_negative.py
index 744e5ac..f504e5c 100644
--- a/manila_tempest_tests/tests/api/test_security_services_mapping_negative.py
+++ b/manila_tempest_tests/tests/api/test_security_services_mapping_negative.py
@@ -16,6 +16,7 @@
from oslo_log import log
import six
from tempest import config
+from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
import testtools
from testtools import testcase as tc
@@ -42,6 +43,7 @@
cls.share_type = cls._create_share_type()
cls.share_type_id = cls.share_type['id']
+ @decorators.idempotent_id('e3d17444-8ed4-445e-bc65-c748dbc5d21f')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_add_sec_service_twice_to_share_network(self):
self.cl.add_sec_service_to_share_network(self.sn["id"], self.ss["id"])
@@ -49,54 +51,63 @@
self.cl.add_sec_service_to_share_network,
self.sn["id"], self.ss["id"])
+ @decorators.idempotent_id('3f7af51f-3afa-495c-94b7-e9d29f06cf1d')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_add_nonexistant_sec_service_to_share_network(self):
self.assertRaises(lib_exc.NotFound,
self.cl.add_sec_service_to_share_network,
self.sn["id"], "wrong_ss_id")
+ @decorators.idempotent_id('85dd5693-a89c-4d05-9416-0e11fbba23f5')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_add_empty_sec_service_id_to_share_network(self):
self.assertRaises(lib_exc.NotFound,
self.cl.add_sec_service_to_share_network,
self.sn["id"], "")
+ @decorators.idempotent_id('d9af5086-ace9-4be3-8119-e765699c0c91')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_add_sec_service_to_nonexistant_share_network(self):
self.assertRaises(lib_exc.NotFound,
self.cl.add_sec_service_to_share_network,
"wrong_sn_id", self.ss["id"])
+ @decorators.idempotent_id('7272426d-ab58-4efb-a490-0c78c07fa7fe')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_add_sec_service_to_share_network_with_empty_id(self):
self.assertRaises(lib_exc.NotFound,
self.cl.add_sec_service_to_share_network,
"", self.ss["id"])
+ @decorators.idempotent_id('f87aefa6-9681-477d-a118-603883849f4f')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_list_sec_services_for_nonexistant_share_network(self):
self.assertRaises(lib_exc.NotFound,
self.cl.list_sec_services_for_share_network,
"wrong_id")
+ @decorators.idempotent_id('7f8d7527-2d62-478a-ab19-213156777612')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_delete_nonexistant_sec_service_from_share_network(self):
self.assertRaises(lib_exc.NotFound,
self.cl.remove_sec_service_from_share_network,
self.sn["id"], "wrong_id")
+ @decorators.idempotent_id('be1c9c79-efa1-471e-920b-da4733ad383e')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_delete_sec_service_from_nonexistant_share_network(self):
self.assertRaises(lib_exc.NotFound,
self.cl.remove_sec_service_from_share_network,
"wrong_id", self.ss["id"])
+ @decorators.idempotent_id('c7c2f66f-81f8-4984-b807-2b9520105a33')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_delete_nonexistant_ss_from_nonexistant_sn(self):
self.assertRaises(lib_exc.NotFound,
self.cl.remove_sec_service_from_share_network,
"wrong_id", "wrong_id")
+ @decorators.idempotent_id('eb66a8f7-b549-4cf1-8719-30844fb151b6')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipIf(
not CONF.share.multitenancy_enabled, "Only for multitenancy.")
@@ -130,6 +141,7 @@
fresh_sn["id"],
self.ss["id"])
+ @decorators.idempotent_id('6a15c8ff-eba3-40e5-8fa1-6eab52338672')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_map_two_ss_with_same_type_to_sn(self):
# create share network
@@ -155,6 +167,7 @@
self.cl.add_sec_service_to_share_network,
sn["id"], security_services[1]["id"])
+ @decorators.idempotent_id('d422a15a-1f4c-4531-a092-9216b90c4179')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_delete_ss_that_assigned_to_sn(self):
# create share network
diff --git a/manila_tempest_tests/tests/api/test_security_services_negative.py b/manila_tempest_tests/tests/api/test_security_services_negative.py
index fe06416..3539634 100644
--- a/manila_tempest_tests/tests/api/test_security_services_negative.py
+++ b/manila_tempest_tests/tests/api/test_security_services_negative.py
@@ -16,6 +16,7 @@
from oslo_log import log
import six
from tempest import config
+from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
import testtools
from testtools import testcase as tc
@@ -35,51 +36,60 @@
cls.share_type = cls._create_share_type()
cls.share_type_id = cls.share_type['id']
+ @decorators.idempotent_id('f5cdf074-f5d4-4d9e-990b-c3d9385dfc2b')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_create_security_service_with_empty_type(self):
self.assertRaises(lib_exc.BadRequest,
self.shares_client.create_security_service, "")
+ @decorators.idempotent_id('6a7efebc-989a-42b3-a971-c28af1e209f5')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_create_security_service_with_wrong_type(self):
self.assertRaises(lib_exc.BadRequest,
self.shares_client.create_security_service,
"wrong_type")
+ @decorators.idempotent_id('2935de41-40b1-4907-8ab5-f4921f670bfd')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_get_security_service_without_id(self):
self.assertRaises(lib_exc.NotFound,
self.shares_client.get_security_service, "")
+ @decorators.idempotent_id('34e923a4-e5b4-4375-88b4-8bb05e8f010d')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_get_security_service_with_wrong_id(self):
self.assertRaises(lib_exc.NotFound,
self.shares_client.get_security_service,
"wrong_id")
+ @decorators.idempotent_id('887e0c2c-6658-442d-92e7-3b0c86a2dfcd')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_delete_security_service_without_id(self):
self.assertRaises(lib_exc.NotFound,
self.shares_client.delete_security_service, "")
+ @decorators.idempotent_id('c94eb229-5caf-4e81-b8a9-d73c0b63a93b')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_delete_security_service_with_wrong_type(self):
self.assertRaises(lib_exc.NotFound,
self.shares_client.delete_security_service,
"wrong_id")
+ @decorators.idempotent_id('60e51b95-af7f-463d-8d8e-6bca4ed3bec8')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_update_nonexistant_security_service(self):
self.assertRaises(lib_exc.NotFound,
self.shares_client.update_security_service,
"wrong_id", name="name")
+ @decorators.idempotent_id('e4554b3b-bc74-4204-8596-d502149bb408')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_update_security_service_with_empty_id(self):
self.assertRaises(lib_exc.NotFound,
self.shares_client.update_security_service,
"", name="name")
+ @decorators.idempotent_id('ab62240a-219c-4fa7-b1ca-08f91bec76f0')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipIf(
not CONF.share.multitenancy_enabled, "Only for multitenancy.")
@@ -116,6 +126,7 @@
ss["id"],
user="new_user")
+ @decorators.idempotent_id('288dbf42-ee22-4445-8363-7ebb1c3d89c9')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_get_deleted_security_service(self):
data = self.generate_security_service_data()
diff --git a/manila_tempest_tests/tests/api/test_share_group_actions.py b/manila_tempest_tests/tests/api/test_share_group_actions.py
index c1f4e6f..3b2325a 100644
--- a/manila_tempest_tests/tests/api/test_share_group_actions.py
+++ b/manila_tempest_tests/tests/api/test_share_group_actions.py
@@ -17,6 +17,7 @@
import ddt
from tempest import config
from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
from testtools import testcase as tc
from manila_tempest_tests.common import constants
@@ -103,6 +104,7 @@
description=cls.sg_snap_desc,
)
+ @decorators.idempotent_id('1e359389-09a7-4235-84c9-7b5c83632fff')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@ddt.data(
*set([constants.MIN_SHARE_GROUP_MICROVERSION,
@@ -128,6 +130,7 @@
self.assertEqual(self.share_group_name, share_group["name"])
self.assertEqual(self.share_group_desc, share_group["description"])
+ @decorators.idempotent_id('45b77673-b1bb-43a1-b4b7-41351930adbd')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_get_share_min_supported_sg_microversion(self):
@@ -155,6 +158,7 @@
self.assertEqual(self.share_size, int(share["size"]))
self.assertEqual(self.share_group["id"], share["share_group_id"])
+ @decorators.idempotent_id('04fcd695-c5f8-4de7-ab09-131424e6bdfb')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@ddt.data(
*set([constants.MIN_SHARE_GROUP_MICROVERSION,
@@ -185,6 +189,7 @@
msg = ("Expected id %s exactly once in share group list" % sg_id)
self.assertEqual(1, len(gen), msg)
+ @decorators.idempotent_id('16986c21-ecbc-429e-ab3d-8d1596a3eac4')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@ddt.data(
*set([constants.MIN_SHARE_GROUP_MICROVERSION, '2.36',
@@ -220,6 +225,7 @@
group_id)
self.assertEqual(1, len(gen), msg)
+ @decorators.idempotent_id('e72be2f9-56db-467f-89d7-0dddbf7e37e9')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_filter_shares_by_share_group_id_min(self):
shares = self.shares_v2_client.list_shares(
@@ -243,6 +249,7 @@
'Share %s expected in returned list, but got %s' % (
self.shares[0]['id'], share_ids))
+ @decorators.idempotent_id('5d2ca4f5-04da-4528-af47-ec980b95e884')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@ddt.data(
*set([constants.MIN_SHARE_GROUP_MICROVERSION,
@@ -273,6 +280,7 @@
self.assertEqual(self.sg_snap_name, sg_snapshot["name"])
self.assertEqual(self.sg_snap_desc, sg_snapshot["description"])
+ @decorators.idempotent_id('67e8c099-f1c1-4972-9c51-bb7bfe1d7994')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_get_share_group_snapshot_members_min(self):
sg_snapshot = self.shares_v2_client.get_share_group_snapshot(
@@ -297,6 +305,7 @@
if share['id'] == member['share_id']:
self.assertEqual(share['size'], member['size'])
+ @decorators.idempotent_id('650c5fa7-11f2-48bd-b012-fc2e32b6f446')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@ddt.data(
*set([constants.MIN_SHARE_GROUP_MICROVERSION,
@@ -401,6 +410,7 @@
version=version,
)
+ @decorators.idempotent_id('7f0a07ce-afdd-4c51-a29c-d8fe6cb5f6a5')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@ddt.data(
*set([constants.MIN_SHARE_GROUP_MICROVERSION,
@@ -440,6 +450,7 @@
# going to be reused
self._rollback_share_group_update(version)
+ @decorators.idempotent_id('611b1555-df09-499b-8aef-e8261e3f6863')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@ddt.data(
*set([constants.MIN_SHARE_GROUP_MICROVERSION,
diff --git a/manila_tempest_tests/tests/api/test_share_groups.py b/manila_tempest_tests/tests/api/test_share_groups.py
index 5b2ae9f..4c655e9 100644
--- a/manila_tempest_tests/tests/api/test_share_groups.py
+++ b/manila_tempest_tests/tests/api/test_share_groups.py
@@ -15,6 +15,7 @@
import ddt
from tempest import config
+from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
from testtools import testcase as tc
@@ -49,6 +50,7 @@
cls.share_group_type = cls._create_share_group_type()
cls.share_group_type_id = cls.share_group_type['id']
+ @decorators.idempotent_id('809d5e3d-5a4b-458a-a985-853d59800da5')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_create_populate_delete_share_group_min(self):
# Create a share group
@@ -93,6 +95,7 @@
self.assertRaises(
lib_exc.NotFound, self.shares_client.get_share, share['id'])
+ @decorators.idempotent_id('cf7984af-1e1d-4eaf-bf9a-d8ddf5cebd01')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_create_delete_empty_share_group_snapshot_min(self):
# Create base share group
@@ -133,6 +136,7 @@
sg_snapshot['id'],
version=constants.MIN_SHARE_GROUP_MICROVERSION)
+ @decorators.idempotent_id('727d9c69-4c3b-4375-a91b-8b3efd349976')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_create_share_group_from_empty_share_group_snapshot_min(self):
# Create base share group
@@ -193,6 +197,7 @@
msg)
@base.skip_if_microversion_lt("2.34")
+ @decorators.idempotent_id('14fd6d88-87ff-4af2-ad17-f95dbd8dcd61')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@ddt.data(
'sg', 'sg_and_share', 'none',
diff --git a/manila_tempest_tests/tests/api/test_share_groups_negative.py b/manila_tempest_tests/tests/api/test_share_groups_negative.py
index a0a6b4b..bfe07c6 100644
--- a/manila_tempest_tests/tests/api/test_share_groups_negative.py
+++ b/manila_tempest_tests/tests/api/test_share_groups_negative.py
@@ -15,14 +15,15 @@
from tempest import config
from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
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
@@ -78,6 +79,7 @@
description=cls.sg_snap_desc
)
+ @decorators.idempotent_id('7ce3fb52-1bec-42b1-9b4f-671c8465764b')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_create_sg_with_invalid_source_sg_snapshot_id_value_min(self):
self.assertRaises(
@@ -87,6 +89,7 @@
cleanup_in_class=False,
version=constants.MIN_SHARE_GROUP_MICROVERSION)
+ @decorators.idempotent_id('43c7a454-06b4-4c6e-8aaf-34709db64e28')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_create_sg_with_nonexistent_source_sg_snapshot_id_value_min(self):
self.assertRaises(
@@ -96,6 +99,7 @@
cleanup_in_class=False,
version=constants.MIN_SHARE_GROUP_MICROVERSION)
+ @decorators.idempotent_id('aae1b1db-ea04-4a53-88ad-e5ee648fe938')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_create_sg_with_invalid_share_network_id_value_min(self):
self.assertRaises(
@@ -105,6 +109,7 @@
cleanup_in_class=False,
version=constants.MIN_SHARE_GROUP_MICROVERSION)
+ @decorators.idempotent_id('ea817e28-08b9-40c1-bbab-a8820ec564ac')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_create_group_with_nonexistent_share_network_id_value_min(self):
self.assertRaises(
@@ -114,6 +119,7 @@
cleanup_in_class=False,
version=constants.MIN_SHARE_GROUP_MICROVERSION)
+ @decorators.idempotent_id('8bc89858-61de-49f3-868c-394841a93503')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_create_sg_with_invalid_share_type_id_value_min(self):
self.assertRaises(
@@ -123,6 +129,7 @@
cleanup_in_class=False,
version=constants.MIN_SHARE_GROUP_MICROVERSION)
+ @decorators.idempotent_id('97183b15-d150-4c6b-b812-734c2500afe7')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_create_sg_with_nonexistent_share_type_id_value_min(self):
self.assertRaises(
@@ -132,6 +139,7 @@
cleanup_in_class=False,
version=constants.MIN_SHARE_GROUP_MICROVERSION)
+ @decorators.idempotent_id('25a829e2-be7d-4a4d-881e-bc0634515985')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_create_sg_snapshot_with_invalid_sg_id_value_min(self):
self.assertRaises(
@@ -141,6 +149,7 @@
cleanup_in_class=False,
version=constants.MIN_SHARE_GROUP_MICROVERSION)
+ @decorators.idempotent_id('16ad5a77-0ef7-4906-8e14-56703c2c9d71')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_create_sg_snapshot_with_nonexistent_sg_id_value_min(self):
self.assertRaises(
@@ -150,6 +159,7 @@
cleanup_in_class=False,
version=constants.MIN_SHARE_GROUP_MICROVERSION)
+ @decorators.idempotent_id('d486a184-1160-4664-ad9b-6f8974685343')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_get_sg_with_invalid_id_min(self):
self.assertRaises(
@@ -158,6 +168,7 @@
"invalid_share_group_id",
version=constants.MIN_SHARE_GROUP_MICROVERSION)
+ @decorators.idempotent_id('7a5dcec1-27cc-4bfe-a166-d8c1832a4dc7')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_get_sg_without_passing_group_id_min(self):
self.assertRaises(
@@ -165,6 +176,7 @@
self.shares_v2_client.get_share_group,
'', version=constants.MIN_SHARE_GROUP_MICROVERSION)
+ @decorators.idempotent_id('9127933a-1960-415e-bf21-8bcb5720e371')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_update_sg_with_invalid_id_min(self):
self.assertRaises(
@@ -175,6 +187,7 @@
description='new_description',
version=constants.MIN_SHARE_GROUP_MICROVERSION)
+ @decorators.idempotent_id('bf8f9865-a906-4d55-b233-fec57cf43b66')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_delete_sg_with_invalid_id_min(self):
self.assertRaises(
@@ -183,6 +196,7 @@
"invalid_share_group_id",
version=constants.MIN_SHARE_GROUP_MICROVERSION)
+ @decorators.idempotent_id('16431501-800f-4695-bae6-6a4c715c2fbf')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_delete_sg_without_passing_sg_id_min(self):
self.assertRaises(
@@ -190,6 +204,7 @@
self.shares_v2_client.delete_share_group,
'', version=constants.MIN_SHARE_GROUP_MICROVERSION)
+ @decorators.idempotent_id('18fe2dee-4a07-484e-8f0f-bbc238500dc3')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_delete_sg_in_use_by_sg_snapshot_min(self):
self.assertRaises(
@@ -198,6 +213,7 @@
self.share_group['id'],
version=constants.MIN_SHARE_GROUP_MICROVERSION)
+ @decorators.idempotent_id('d2a58f10-cc86-498d-a5e0-1468d4345852')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_delete_share_in_use_by_sg_snapshot_min(self):
params = {'share_group_id': self.share['share_group_id']}
@@ -208,6 +224,7 @@
params=params,
version=constants.MIN_SHARE_GROUP_MICROVERSION)
+ @decorators.idempotent_id('c2225b19-d5f5-4d15-bb9a-de63bfce6760')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_delete_sg_containing_a_share_min(self):
self.assertRaises(
@@ -222,6 +239,7 @@
version=constants.MIN_SHARE_GROUP_MICROVERSION)
self.assertEqual('available', sg['status'])
+ @decorators.idempotent_id('edd329b8-7188-481f-9445-8f6d913538fa')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_filter_shares_on_invalid_group_id_min(self):
shares = self.shares_v2_client.list_shares(
@@ -231,6 +249,7 @@
)
self.assertEqual(0, len(shares), 'Incorrect number of shares returned')
+ @decorators.idempotent_id('5dc10968-cbff-46d9-a1aa-bafccc7a1905')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_filter_shares_on_nonexistent_group_id_min(self):
shares = self.shares_v2_client.list_shares(
@@ -240,6 +259,7 @@
)
self.assertEqual(0, len(shares), 'Incorrect number of shares returned')
+ @decorators.idempotent_id('f805f683-fe05-4534-9f40-a74be42ff82b')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_filter_shares_on_empty_share_group_id_min(self):
share_group = self.create_share_group(
@@ -257,6 +277,7 @@
)
self.assertEqual(0, len(shares), 'Incorrect number of shares returned')
+ @decorators.idempotent_id('8fc20c22-082f-4851-bcc3-d2f3af57f027')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_create_sg_with_nonexistent_az_min(self):
self.assertRaises(
@@ -270,6 +291,7 @@
version=constants.MIN_SHARE_GROUP_MICROVERSION)
@base.skip_if_microversion_lt("2.34")
+ @decorators.idempotent_id('64527564-9cd6-42db-8897-910f4fc1a151')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_create_sg_and_share_with_different_azs(self):
azs = self.shares_v2_client.list_availability_zones()
diff --git a/manila_tempest_tests/tests/api/test_share_network_subnets.py b/manila_tempest_tests/tests/api/test_share_network_subnets.py
index 5c90fd1..8387968 100644
--- a/manila_tempest_tests/tests/api/test_share_network_subnets.py
+++ b/manila_tempest_tests/tests/api/test_share_network_subnets.py
@@ -15,6 +15,7 @@
import ddt
from tempest import config
+from tempest.lib import decorators
import testtools
from testtools import testcase as tc
@@ -45,6 +46,7 @@
cls.share_network = cls.create_share_network()
cls.share_network_id = cls.share_network['id']
+ @decorators.idempotent_id('3e1e4da7-049f-404e-8673-142695a9a785')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_create_delete_subnet(self):
share_network = self.shares_v2_client.create_share_network()
@@ -82,6 +84,7 @@
# Delete the subnets
self.shares_v2_client.delete_subnet(share_network['id'], created['id'])
+ @decorators.idempotent_id('51c6836a-c6d2-4b80-a992-cf91f9a4332b')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_show_share_network_subnet(self):
share_network = self.create_share_network()
@@ -107,6 +110,7 @@
self.shares_v2_client.delete_subnet(share_network['id'],
created['id'])
+ @decorators.idempotent_id('89ed6115-eb1d-4a7e-a0a3-9b4a239fadc1')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipIf(
not CONF.share.multitenancy_enabled, "Only for multitenancy.")
@@ -174,6 +178,7 @@
# Delete the subnets
self.shares_v2_client.delete_subnet(share_network['id'], subnet['id'])
+ @decorators.idempotent_id('043fbe02-466d-4344-8e2f-f02cb65132cb')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipIf(
not CONF.share.multitenancy_enabled, "Only for multitenancy.")
diff --git a/manila_tempest_tests/tests/api/test_share_network_subnets_negative.py b/manila_tempest_tests/tests/api/test_share_network_subnets_negative.py
index 4836e74..a374f4e 100644
--- a/manila_tempest_tests/tests/api/test_share_network_subnets_negative.py
+++ b/manila_tempest_tests/tests/api/test_share_network_subnets_negative.py
@@ -14,8 +14,8 @@
# under the License.
import ddt
-
from tempest import config
+from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
import testtools
from testtools import testcase as tc
@@ -24,6 +24,7 @@
from manila_tempest_tests.tests.api import base
from manila_tempest_tests import utils
+
CONF = config.CONF
@@ -46,6 +47,7 @@
cls.az = cls.shares_v2_client.list_availability_zones()[0]
cls.az_name = cls.az['name']
+ @decorators.idempotent_id('d20b6105-22d1-4fc0-8468-45dd019240c0')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_add_share_network_subnet_share_network_not_found(self):
data = self.generate_subnet_data()
@@ -54,6 +56,7 @@
'fake_inexistent_id',
**data)
+ @decorators.idempotent_id('68264ac2-57e5-47ea-aa71-198c020be975')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_add_share_network_subnet_az_not_found(self):
data = {'availability_zone': 'non-existent-az'}
@@ -62,6 +65,7 @@
self.shares_v2_client.create_subnet,
self.share_network_id, **data)
+ @decorators.idempotent_id('13f397bf-5e3a-42b0-b4f9-9cd2dbbb0955')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
@ddt.data(True, False)
def test_add_share_network_subnet_in_same_az_exists(self, is_default):
@@ -79,6 +83,7 @@
self.shares_v2_client.create_subnet,
share_network['id'], **data)
+ @decorators.idempotent_id('36e991c1-f09b-47dc-adc9-3da388b14612')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_add_share_network_subnet_missing_parameters(self):
# Generate subnet data
@@ -90,6 +95,7 @@
self.shares_v2_client.create_subnet,
self.share_network_id, **data)
+ @decorators.idempotent_id('11e76b07-f3e3-401f-9469-256b93a768e6')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_show_subnet_share_network_not_found(self):
self.assertRaises(lib_exc.NotFound,
@@ -97,6 +103,7 @@
'fake-subnet',
'fake-sn')
+ @decorators.idempotent_id('22d4528b-39ae-4f97-b1b2-1b9d65146c97')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_show_subnet_not_found(self):
self.assertRaises(lib_exc.NotFound,
@@ -104,6 +111,7 @@
'fake-subnet',
self.share_network_id)
+ @decorators.idempotent_id('9dfc6ba3-c7be-4a6d-b104-ce77d2337bb3')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_get_deleted_subnet(self):
# Generate subnet data
@@ -130,6 +138,7 @@
subnet['id'],
self.share_network['id'])
+ @decorators.idempotent_id('bf9d63c4-37fb-4646-add7-905b196316f1')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipIf(not CONF.share.multitenancy_enabled,
'Can run only with drivers that do handle share servers '
@@ -202,6 +211,7 @@
self.shares_v2_client.delete_subnet(share_network_id,
subnet['id'])
+ @decorators.idempotent_id('5088edfe-2800-4dec-a982-42c864bba954')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipIf(not CONF.share.multitenancy_enabled,
'Can run only with drivers that do handle share servers '
@@ -271,6 +281,7 @@
self.shares_v2_client.delete_subnet(share_network_id,
subnet['id'])
+ @decorators.idempotent_id('1025b69b-f1fd-4e44-b749-33779545ffe8')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_delete_subnet_share_network_not_found(self):
self.assertRaises(lib_exc.NotFound,
@@ -278,6 +289,7 @@
'fake-sn',
'fake-subnet')
+ @decorators.idempotent_id('a5bdc817-0c34-4856-9732-f561e6ab5a83')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_delete_subnet_not_found(self):
self.assertRaises(lib_exc.NotFound,
diff --git a/manila_tempest_tests/tests/api/test_share_networks.py b/manila_tempest_tests/tests/api/test_share_networks.py
index b7cd0bf..db07591 100644
--- a/manila_tempest_tests/tests/api/test_share_networks.py
+++ b/manila_tempest_tests/tests/api/test_share_networks.py
@@ -14,6 +14,7 @@
# under the License.
from tempest import config
+from tempest.lib import decorators
import testtools
from testtools import testcase as tc
@@ -25,6 +26,7 @@
class ShareNetworkListMixin(object):
+ @decorators.idempotent_id('41c635b1-d9ef-4c05-9100-5e4b0034b523')
@tc.attr("gate", "smoke", )
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_list_share_networks(self):
@@ -35,6 +37,7 @@
keys = ["name", "id"]
[self.assertIn(key, sn.keys()) for sn in listed for key in keys]
+ @decorators.idempotent_id('18fe9031-cefc-4df3-bbb0-6541f5fda12b')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_try_list_share_networks_all_tenants(self):
listed = self.shares_client.list_share_networks_with_detail(
@@ -45,6 +48,7 @@
keys = ["name", "id"]
[self.assertIn(key, sn.keys()) for sn in listed for key in keys]
+ @decorators.idempotent_id('caf6635a-ecb8-4981-9776-11dcfdf3cdbc')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_try_list_share_networks_project_id(self):
listed = self.shares_client.list_share_networks_with_detail(
@@ -55,6 +59,7 @@
keys = ["name", "id"]
[self.assertIn(key, sn.keys()) for sn in listed for key in keys]
+ @decorators.idempotent_id('285c7a91-1703-42a5-86c8-2463edde60e2')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_list_share_networks_with_detail(self):
listed = self.shares_v2_client.list_share_networks_with_detail()
@@ -91,6 +96,7 @@
[self.assertIn(key, sn.keys()) for sn in listed for key in keys]
+ @decorators.idempotent_id('6d13a090-0855-40c0-85b1-424f6878c6ce')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_list_share_networks_filter_by_ss(self):
listed = self.shares_client.list_share_networks_with_detail(
@@ -103,6 +109,7 @@
self.assertTrue(any(ss['id'] == self.ss_ldap['id']
for ss in ss_list))
+ @decorators.idempotent_id('bff1356e-70aa-4bbe-b398-cb4dadd8fcb1')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
@base.skip_if_microversion_lt("2.36")
def test_list_share_networks_like_filter(self):
@@ -119,6 +126,7 @@
self.assertTrue(all(value in sn[key] for key, value in
valid_filter_opts.items()))
+ @decorators.idempotent_id('27490442-60f8-4514-a10a-194a400b48bb')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_list_share_networks_all_filter_opts(self):
valid_filter_opts = {
@@ -204,6 +212,7 @@
cls.sn_with_kerberos_ss["id"],
cls.ss_kerberos["id"])
+ @decorators.idempotent_id('b998a594-f630-475d-b46f-e4143caf61fb')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_create_delete_share_network(self):
# generate data for share network
@@ -216,6 +225,7 @@
# Delete share_network
self.shares_client.delete_share_network(created["id"])
+ @decorators.idempotent_id('55990ec2-37f0-483f-9c67-76fd6f377cc1')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_get_share_network(self):
get = self.shares_client.get_share_network(self.sn_with_ldap_ss["id"])
@@ -224,6 +234,7 @@
del data['created_at']
self.assertDictContainsSubset(data, get)
+ @decorators.idempotent_id('1837fdd3-8068-4e88-bc50-9224498f84c0')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_update_share_network(self):
update_data = self.generate_share_network_data()
@@ -232,6 +243,7 @@
**update_data)
self.assertDictContainsSubset(update_data, updated)
+ @decorators.idempotent_id('198a5c08-3aaf-4623-9720-95d33ebe3376')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipIf(
not CONF.share.multitenancy_enabled, "Only for multitenancy.")
@@ -246,6 +258,7 @@
self.shares_client.share_network_id, **update_dict)
self.assertDictContainsSubset(update_dict, updated)
+ @decorators.idempotent_id('7595a844-a28e-476c-89f1-4d3193ce9d5b')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_recreate_share_network(self):
# generate data for share network
@@ -265,6 +278,7 @@
# Delete second share network
self.shares_client.delete_share_network(sn2["id"])
+ @decorators.idempotent_id('be5f4f60-493e-47ea-a5bd-f16dfaa98c5c')
@tc.attr(base.TAG_POSITIVE, base.TAG_API)
def test_create_two_share_networks_with_same_net_and_subnet(self):
# generate data for share network
@@ -278,6 +292,7 @@
sn2 = self.create_share_network(**data)
self.assertDictContainsSubset(data, sn2)
+ @decorators.idempotent_id('50bac743-7ca9-409b-827f-f277da67e32e')
@testtools.skipUnless(CONF.share.create_networks_when_multitenancy_enabled,
"Only for setups with network creation.")
@testtools.skipUnless(CONF.share.multitenancy_enabled,
@@ -301,6 +316,7 @@
self.assertEqual(subnet_details['subnet']['gateway_ip'],
share_net_info['gateway'])
+ @decorators.idempotent_id('2dbf91da-04ae-4f9f-a7b9-0299c6b2e02c')
@testtools.skipUnless(CONF.share.create_networks_when_multitenancy_enabled,
"Only for setups with network creation.")
@testtools.skipUnless(CONF.share.multitenancy_enabled,
diff --git a/manila_tempest_tests/tests/api/test_share_networks_negative.py b/manila_tempest_tests/tests/api/test_share_networks_negative.py
index 0308ebc..0d9cbec 100644
--- a/manila_tempest_tests/tests/api/test_share_networks_negative.py
+++ b/manila_tempest_tests/tests/api/test_share_networks_negative.py
@@ -14,6 +14,7 @@
# under the License.
from tempest import config
+from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
import testtools
from testtools import testcase as tc
@@ -32,38 +33,45 @@
cls.share_type = cls._create_share_type()
cls.share_type_id = cls.share_type['id']
+ @decorators.idempotent_id('66289664-bf01-40dd-a76d-fd2c953bbceb')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_get_share_network_without_id(self):
self.assertRaises(lib_exc.NotFound,
self.shares_client.get_share_network, "")
+ @decorators.idempotent_id('80397850-2f64-48b3-b19b-79c4ac0bd58f')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_get_share_network_with_wrong_id(self):
self.assertRaises(lib_exc.NotFound,
self.shares_client.get_share_network, "wrong_id")
+ @decorators.idempotent_id('fe6ac194-5003-404c-b372-7515a58ff969')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_delete_share_network_without_id(self):
self.assertRaises(lib_exc.NotFound,
self.shares_client.delete_share_network, "")
+ @decorators.idempotent_id('7e22e8b9-a1ce-480c-89b3-b4edd807285a')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_delete_share_network_with_wrong_type(self):
self.assertRaises(lib_exc.NotFound,
self.shares_client.delete_share_network, "wrong_id")
+ @decorators.idempotent_id('a7c55dbe-c23e-403f-b8aa-4aa1128f32a4')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_update_nonexistant_share_network(self):
self.assertRaises(lib_exc.NotFound,
self.shares_client.update_share_network,
"wrong_id", name="name")
+ @decorators.idempotent_id('984349ca-df7d-4f85-a45f-948189debb65')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_update_share_network_with_empty_id(self):
self.assertRaises(lib_exc.NotFound,
self.shares_client.update_share_network,
"", name="name")
+ @decorators.idempotent_id('211b64b4-4c2b-4b6b-b011-725f40a37b03')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipIf(
not CONF.share.multitenancy_enabled, "Only for multitenancy.")
@@ -76,6 +84,7 @@
self.shares_client.share_network_id,
neutron_net_id="new_net_id")
+ @decorators.idempotent_id('9166b81c-d6ab-4592-bcf7-9410250e30dd')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_get_deleted_share_network(self):
data = self.generate_share_network_data()
@@ -89,6 +98,7 @@
self.shares_client.get_security_service,
sn["id"])
+ @decorators.idempotent_id('0d104b72-aab5-48b5-87f8-847d2155faa9')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_list_share_networks_wrong_created_since_value(self):
self.assertRaises(
@@ -96,6 +106,7 @@
self.shares_client.list_share_networks_with_detail,
params={'created_since': '2014-10-23T08:31:58.000000'})
+ @decorators.idempotent_id('c96dacaf-4cea-4fe9-bbd7-c9b1001f5495')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_list_share_networks_wrong_created_before_value(self):
self.assertRaises(
@@ -103,6 +114,7 @@
self.shares_client.list_share_networks_with_detail,
params={'created_before': '2014-10-23T08:31:58.000000'})
+ @decorators.idempotent_id('6e4912fd-ae85-4a43-81e8-e5b340099b64')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipIf(not CONF.share.multitenancy_enabled,
'Can run only with drivers that do handle share servers '
@@ -129,6 +141,7 @@
lib_exc.Conflict,
self.shares_client.delete_share_network, new_sn['id'])
+ @decorators.idempotent_id('4e71de31-1064-40da-948d-a72063fbd647')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@base.skip_if_microversion_not_supported("2.35")
def test_list_shares_with_like_filter_not_exist(self):
@@ -143,6 +156,7 @@
self.assertEqual(0, len(share_networks))
@base.skip_if_microversion_lt("2.51")
+ @decorators.idempotent_id('8a995305-ede9-4002-a9cd-f24ff4d71f63')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_delete_share_network_contains_more_than_one_subnet(self):
share_network = self.create_share_network()
@@ -171,6 +185,7 @@
self.assertIsNone(default_subnet['availability_zone'])
@base.skip_if_microversion_lt("2.51")
+ @decorators.idempotent_id('d84c3c5c-5913-42d4-9a66-0d5a78295adb')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_create_share_network_inexistent_az(self):
self.assertRaises(
diff --git a/manila_tempest_tests/tests/api/test_share_type_availability_zones.py b/manila_tempest_tests/tests/api/test_share_type_availability_zones.py
index 177cb8c..da77d5f 100644
--- a/manila_tempest_tests/tests/api/test_share_type_availability_zones.py
+++ b/manila_tempest_tests/tests/api/test_share_type_availability_zones.py
@@ -13,6 +13,7 @@
import ddt
from tempest import config
from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
import testtools
from manila_tempest_tests.tests.api import base
@@ -46,6 +47,7 @@
cls.valid_azs_spec = ', '.join(cls.valid_azs)
cls.invalid_azs_spec = ', '.join(cls.invalid_azs)
+ @decorators.idempotent_id('23005fad-59e1-4a4b-994c-7377e34b4ec6')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@ddt.data('az1, az2, az 3 ', 'az1,az2,az 3', 'az1 ,az2, az 3')
def test_share_type_azs_create_and_get_share_type(self, spec):
@@ -64,6 +66,7 @@
self.assertEqual(
'az1,az2,az 3', share_type['extra_specs']['availability_zones'])
+ @decorators.idempotent_id('545f1742-39dc-4bfb-8a81-6ec941b58fef')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@ddt.data('az1', 'az2', 'az 3', 'az1, az 3', 'az 3, az1',
'az2, az 3, az1')
@@ -90,6 +93,7 @@
self.assertIn(share_type_in_specific_azs['id'], share_type_ids)
self.assertIn(share_type_no_az_spec['id'], share_type_ids)
+ @decorators.idempotent_id('00a3e4ab-00a5-4683-a773-166353a69f28')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_share_type_azs_old_version_api_ignores_spec(self):
"""< v2.48, configuring share type AZs shouldn't fail share creation"""
@@ -110,6 +114,7 @@
# regardless of the 'availability_zones' extra-spec
self.assertIn(share['availability_zone'], self.valid_azs)
+ @decorators.idempotent_id('3399c706-5dcb-41b2-9701-4550bf4f81cb')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@ddt.data(True, False)
def test_share_type_azs_shares_az_in_create_req(self, specify_az):
@@ -127,6 +132,7 @@
else:
self.assertIn(share['availability_zone'], self.valid_azs)
+ @decorators.idempotent_id('fa5618ad-c452-41bd-8dc3-cc85abd6cee5')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@ddt.data(True, False)
def test_share_type_azs_share_groups_az_in_create_req(self, specify_az):
diff --git a/manila_tempest_tests/tests/api/test_share_type_availability_zones_negative.py b/manila_tempest_tests/tests/api/test_share_type_availability_zones_negative.py
index e756d1a..b98a98d 100644
--- a/manila_tempest_tests/tests/api/test_share_type_availability_zones_negative.py
+++ b/manila_tempest_tests/tests/api/test_share_type_availability_zones_negative.py
@@ -11,6 +11,7 @@
# under the License.
import ddt
from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
from testtools import testcase as tc
@@ -42,6 +43,7 @@
cls.valid_azs_spec = ', '.join(cls.valid_azs)
cls.invalid_azs_spec = ', '.join(cls.invalid_azs)
+ @decorators.idempotent_id('7a23af8d-a995-43ac-a381-2cd5c5f57f39')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@ddt.data('az1, az2, az 3, ', 'az1,,az 3', ',az2, az 3')
def test_share_type_azs_create_with_invalid_az_spec(self, spec):
@@ -56,6 +58,7 @@
extra_specs=extra_specs,
client=self.admin_shares_v2_client)
+ @decorators.idempotent_id('78f1afba-6087-415c-aaa1-a880ae341bfc')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_share_type_azs_filter_by_invalid_azs_extra_spec(self):
self.admin_shares_v2_client.update_share_type_extra_spec(
@@ -73,6 +76,7 @@
self.assertNotIn(self.share_type_id, share_type_ids)
self.assertIn(share_type_no_az_spec['id'], share_type_ids)
+ @decorators.idempotent_id('9285d7d5-cb40-462d-998c-891f0f934fdd')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_share_type_azs_shares_unsupported_az(self):
"""Test using an AZ not supported by the share type."""
@@ -84,6 +88,7 @@
availability_zone=self.valid_azs[0],
cleanup_in_class=False)
+ @decorators.idempotent_id('5712abae-52a5-46ec-8850-46e732b18b06')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_share_type_azs_share_groups_unsupported(self):
self.admin_shares_v2_client.update_share_type_extra_spec(
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 7ba6f86..95cc41f 100644
--- a/manila_tempest_tests/tests/api/test_share_types_negative.py
+++ b/manila_tempest_tests/tests/api/test_share_types_negative.py
@@ -13,15 +13,18 @@
# License for the specific language governing permissions and limitations
# under the License.
-import ddt
import random
+
+import ddt
from tempest import config
from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
from testtools import testcase as tc
from manila_tempest_tests.tests.api import base
+
CONF = config.CONF
LATEST_MICROVERSION = CONF.share.max_api_microversion
@@ -45,6 +48,7 @@
cls.st = cls._create_share_type()
cls.st2 = cls._create_share_type()
+ @decorators.idempotent_id('d6a6ac4d-6582-408d-ba55-6f5128eb940e')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_create_share_type_with_user(self):
self.assertRaises(lib_exc.Forbidden,
@@ -52,12 +56,14 @@
data_utils.rand_name("used_user_creds"),
client=self.shares_client)
+ @decorators.idempotent_id('857c664f-e634-4865-ba05-bdcd4336725d')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_delete_share_type_with_user(self):
self.assertRaises(lib_exc.Forbidden,
self.shares_client.delete_share_type,
self.st["id"])
+ @decorators.idempotent_id('06203276-f6a3-4a07-a014-8749763395d6')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_add_access_to_share_type_with_user(self):
self.assertRaises(lib_exc.Forbidden,
@@ -65,6 +71,7 @@
self.st['id'],
self.shares_client.tenant_id)
+ @decorators.idempotent_id('08b2d093-2ad8-46aa-8112-81d50547f36d')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_try_remove_access_from_share_type_with_user(self):
self.assertRaises(lib_exc.Forbidden,
@@ -73,6 +80,7 @@
self.shares_client.tenant_id)
@base.skip_if_microversion_lt("2.50")
+ @decorators.idempotent_id('4a22945c-8988-43a1-88c9-eb86e6abcd8e')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
@ddt.data(
('2.50', '', None, None),
@@ -93,6 +101,7 @@
version)
@base.skip_if_microversion_lt("2.50")
+ @decorators.idempotent_id('7193465a-ed8e-44d5-9ca9-4e8a3c5958e0')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
@ddt.data('2.50', LATEST_MICROVERSION)
def test_share_type_update_conflict(self, version):
diff --git a/manila_tempest_tests/tests/api/test_shares.py b/manila_tempest_tests/tests/api/test_shares.py
index 49af8e2..48461b1 100644
--- a/manila_tempest_tests/tests/api/test_shares.py
+++ b/manila_tempest_tests/tests/api/test_shares.py
@@ -14,6 +14,7 @@
# under the License.
from tempest import config
+from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
import testtools
from testtools import testcase as tc
@@ -41,6 +42,7 @@
cls.share = cls.create_share(cls.protocol,
share_type_id=cls.share_type_id)
+ @decorators.idempotent_id('21ad41fb-04cf-493c-bc2f-66c80220898b')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
def test_create_get_delete_share(self):
@@ -110,6 +112,16 @@
detailed_elements.add('progress')
self.assertTrue(detailed_elements.issubset(share.keys()), msg)
+ # This check will ensure that when a share creation request is handled,
+ # if the driver has the "driver handles share servers" option enabled,
+ # that a share server will be created, otherwise, not.
+ share_get = self.admin_shares_v2_client.get_share(share['id'])
+ share_server = share_get['share_server_id']
+ if CONF.share.multitenancy_enabled:
+ self.assertNotEmpty(share_server)
+ else:
+ self.assertEmpty(share_server)
+
# Delete share
self.shares_v2_client.delete_share(share['id'])
self.shares_v2_client.wait_for_resource_deletion(share_id=share['id'])
@@ -117,6 +129,7 @@
self.shares_v2_client.get_share,
share['id'])
+ @decorators.idempotent_id('775f8f87-5727-4bb7-b69f-9ce6b9bdb140')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@testtools.skipUnless(CONF.share.run_snapshot_tests,
"Snapshot tests are disabled.")
@@ -151,6 +164,7 @@
self.assertRaises(lib_exc.NotFound,
self.shares_client.get_snapshot, snap['id'])
+ @decorators.idempotent_id('8a14831d-ad1f-447f-b5de-2b8a233b24c0')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@testtools.skipUnless(CONF.share.run_snapshot_tests,
"Snapshot tests are disabled.")
@@ -182,6 +196,7 @@
"source of share %s" % (snap["id"], get["snapshot_id"]))
self.assertEqual(get["snapshot_id"], snap["id"], msg)
+ @decorators.idempotent_id('c609c0b2-d649-4ca3-8334-629b213f5c72')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@testtools.skipIf(not CONF.share.multitenancy_enabled,
"Only for multitenancy.")
diff --git a/manila_tempest_tests/tests/api/test_shares_actions.py b/manila_tempest_tests/tests/api/test_shares_actions.py
index 2212fb9..7f48ee1 100644
--- a/manila_tempest_tests/tests/api/test_shares_actions.py
+++ b/manila_tempest_tests/tests/api/test_shares_actions.py
@@ -17,6 +17,7 @@
import six
from tempest import config
from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
import testtools
from testtools import testcase as tc
@@ -130,50 +131,60 @@
CONF.share.share_size, share["size"])
self.assertEqual(CONF.share.share_size, int(share["size"]), msg)
+ @decorators.idempotent_id('188badb2-0ca3-44e5-abca-3029475d7f73')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_get_share_v2_1(self):
self._get_share('2.1')
+ @decorators.idempotent_id('45ec8e36-cb8a-4a03-8c41-ba5d5dc2a5c5')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_get_share_with_snapshot_support_key(self):
self._get_share('2.2')
+ @decorators.idempotent_id('b803a076-593a-469d-ab75-7e67ac294dd5')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@utils.skip_if_microversion_not_supported('2.6')
def test_get_share_with_share_type_name_key(self):
self._get_share('2.6')
+ @decorators.idempotent_id('c13c1cf5-c708-4e62-8b71-c47dbb45a7a0')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@utils.skip_if_microversion_not_supported('2.9')
def test_get_share_export_locations_removed(self):
self._get_share('2.9')
+ @decorators.idempotent_id('2c439716-c34e-46f1-b055-41e411fb4e66')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@utils.skip_if_microversion_not_supported('2.10')
def test_get_share_with_access_rules_status(self):
self._get_share('2.10')
+ @decorators.idempotent_id('67c9ad27-f26d-4ff9-a528-a35b4c5a55c1')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@utils.skip_if_microversion_not_supported('2.11')
def test_get_share_with_replication_type_key(self):
self._get_share('2.11')
+ @decorators.idempotent_id('2a61703d-5a62-49c5-b143-fea0c9125cd9')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@utils.skip_if_microversion_not_supported('2.16')
def test_get_share_with_user_id(self):
self._get_share('2.16')
+ @decorators.idempotent_id('2899055e-607d-4423-b1b7-27eefa6ce5f0')
@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')
+ @decorators.idempotent_id('04c359b5-74b3-4a07-9f9e-f0ac1867d58d')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@utils.skip_if_microversion_not_supported(
constants.REVERT_TO_SNAPSHOT_MICROVERSION)
def test_get_share_with_revert_to_snapshot_support(self):
self._get_share(constants.REVERT_TO_SNAPSHOT_MICROVERSION)
+ @decorators.idempotent_id('7d61311a-81b0-481c-abb9-cfb0b4f82e29')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_list_shares(self):
@@ -228,44 +239,53 @@
msg = "expected id lists %s times in share list" % (len(gen))
self.assertEqual(1, len(gen), msg)
+ @decorators.idempotent_id('d88a157a-fe4d-456e-90ba-f0bd9e5d02ec')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_list_shares_with_detail_v2_1(self):
self._list_shares_with_detail('2.1')
+ @decorators.idempotent_id('ee57db25-0fbf-40ce-8dc1-070845d245a7')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_list_shares_with_detail_and_snapshot_support_key(self):
self._list_shares_with_detail('2.2')
+ @decorators.idempotent_id('38a4cf70-8ed9-4a82-a338-9f20463b1147')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@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')
+ @decorators.idempotent_id('a313cd85-53e5-48b7-b4a7-14e9273e843d')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@utils.skip_if_microversion_not_supported('2.9')
def test_list_shares_with_detail_export_locations_removed(self):
self._list_shares_with_detail('2.9')
+ @decorators.idempotent_id('0de4dc84-bace-4b9a-8470-a40c4a9b14b4')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@utils.skip_if_microversion_not_supported('2.10')
def test_list_shares_with_detail_with_access_rules_status(self):
self._list_shares_with_detail('2.10')
+ @decorators.idempotent_id('70097cf3-76b8-49d2-b1c7-ad59394dd978')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@utils.skip_if_microversion_not_supported('2.11')
def test_list_shares_with_detail_replication_type_key(self):
self._list_shares_with_detail('2.11')
+ @decorators.idempotent_id('f8e57190-b105-4937-b96e-55725eb64739')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@utils.skip_if_microversion_not_supported('2.16')
def test_list_shares_with_user_id(self):
self._list_shares_with_detail('2.16')
+ @decorators.idempotent_id('21410324-e0b5-452a-8c7e-599a27267e1d')
@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')
+ @decorators.idempotent_id('45041fc9-bb0d-4dd6-ac0d-a40a22a91f3f')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@utils.skip_if_microversion_not_supported(
constants.REVERT_TO_SNAPSHOT_MICROVERSION)
@@ -273,6 +293,7 @@
self._list_shares_with_detail(
constants.REVERT_TO_SNAPSHOT_MICROVERSION)
+ @decorators.idempotent_id('bc24dc42-050b-4105-a90a-f5649cbd8e49')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_list_shares_with_detail_filter_by_metadata(self):
filters = {'metadata': self.metadata}
@@ -288,6 +309,7 @@
if CONF.share.capability_create_share_from_snapshot_support:
self.assertFalse(self.shares[1]['id'] in [s['id'] for s in shares])
+ @decorators.idempotent_id('685286c7-1df6-48c3-839d-8162737446b8')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipIf(
not CONF.share.multitenancy_enabled, "Only for multitenancy.")
@@ -304,6 +326,7 @@
self.assertEqual(
filters['share_network_id'], share['share_network_id'])
+ @decorators.idempotent_id('fd87884d-71a4-4ca8-8b2b-07b4df2de3bd')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipUnless(CONF.share.run_snapshot_tests,
"Snapshot tests are disabled.")
@@ -322,6 +345,7 @@
self.assertEqual(filters['snapshot_id'], share['snapshot_id'])
self.assertFalse(self.shares[0]['id'] in [s['id'] for s in shares])
+ @decorators.idempotent_id('70a9d947-bd45-46db-b529-6c48c0ff8985')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_list_shares_with_detail_with_asc_sorting(self):
filters = {'sort_key': 'created_at', 'sort_dir': 'asc'}
@@ -334,6 +358,7 @@
sorted_list = [share['created_at'] for share in shares]
self.assertEqual(sorted(sorted_list), sorted_list)
+ @decorators.idempotent_id('866194c6-3910-409e-ad81-2cff223cfaaf')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_list_shares_with_detail_filter_by_existed_name(self):
# list shares by name, at least one share is expected
@@ -341,6 +366,7 @@
shares = self.shares_client.list_shares_with_detail(params)
self.assertEqual(self.share_name, shares[0]["name"])
+ @decorators.idempotent_id('f446e8cb-5bef-45ac-8b87-f4136f44ca69')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@base.skip_if_microversion_lt("2.36")
def test_list_shares_with_detail_filter_by_existed_description(self):
@@ -349,6 +375,7 @@
shares = self.shares_v2_client.list_shares_with_detail(params)
self.assertEqual(self.share_name, shares[0]["name"])
+ @decorators.idempotent_id('1276b97b-cf46-4953-973f-f995985a1ce4')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@base.skip_if_microversion_lt("2.36")
def test_list_shares_with_detail_filter_by_inexact_name(self):
@@ -358,6 +385,7 @@
for share in shares:
self.assertIn('tempest-share', share["name"])
+ @decorators.idempotent_id('56416b95-949f-4b09-9a5e-377b674efd25')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_list_shares_with_detail_filter_by_fake_name(self):
# list shares by fake name, no shares are expected
@@ -365,6 +393,7 @@
shares = self.shares_client.list_shares_with_detail(params)
self.assertEqual(0, len(shares))
+ @decorators.idempotent_id('708e3e2e-8761-4d16-b18d-a834ee7ca69e')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_list_shares_with_detail_filter_by_active_status(self):
# list shares by active status, at least one share is expected
@@ -374,6 +403,7 @@
for share in shares:
self.assertEqual(params["status"], share["status"])
+ @decorators.idempotent_id('5ec2fcf8-18d4-4790-95de-45c8a05582c7')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_list_shares_with_detail_filter_by_fake_status(self):
# list shares by fake status, no shares are expected
@@ -381,6 +411,7 @@
shares = self.shares_client.list_shares_with_detail(params)
self.assertEqual(0, len(shares))
+ @decorators.idempotent_id('7609b7bb-613e-474d-a9b3-e41584842503')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_list_shares_with_detail_filter_by_all_tenants(self):
# non-admin user can get shares only from his project
@@ -394,6 +425,7 @@
for share in shares:
self.assertEqual(project_id, share["project_id"])
+ @decorators.idempotent_id('0019afa2-fae2-417f-a7e0-2af665a966b0')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@base.skip_if_microversion_lt("2.42")
def test_list_shares_with_detail_with_count(self):
@@ -402,6 +434,7 @@
shares = self.shares_v2_client.list_shares_with_detail(params)
self.assertGreater(shares["count"], 0)
+ @decorators.idempotent_id('557a0474-9e30-47b4-a766-19e2afb13e66')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_list_shares_public_with_detail(self):
public_share = self.create_share(
@@ -420,9 +453,7 @@
)
params = {"is_public": True}
- isolated_client = self.get_client_with_isolated_creds(
- type_of_creds='alt')
- shares = isolated_client.list_shares_with_detail(params)
+ shares = self.alt_shares_client.list_shares_with_detail(params)
keys = [
"status", "description", "links", "availability_zone",
@@ -437,6 +468,7 @@
self.assertFalse(any([s["id"] == private_share["id"] for s in shares]))
+ @decorators.idempotent_id('174829eb-fd3e-46ef-880b-f05c3d44d1fe')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipUnless(CONF.share.run_snapshot_tests,
"Snapshot tests are disabled.")
@@ -493,6 +525,7 @@
'actual': snapshot['project_id'],
'key': 'project_id'})
+ @decorators.idempotent_id('3d5d85ff-6158-4af2-a765-cfa07a46adde')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipUnless(CONF.share.run_snapshot_tests,
"Snapshot tests are disabled.")
@@ -510,6 +543,7 @@
msg = "expected id lists %s times in share list" % (len(gen))
self.assertEqual(1, len(gen), msg)
+ @decorators.idempotent_id('4d717665-e4ca-47df-b4b9-f6d096159779')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipUnless(CONF.share.run_snapshot_tests,
"Snapshot tests are disabled.")
@@ -541,6 +575,7 @@
msg = "expected id lists %s times in share list" % (len(gen))
self.assertEqual(1, len(gen), msg)
+ @decorators.idempotent_id('80497a21-7533-47b5-93aa-29e0f7924cb9')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipUnless(CONF.share.run_snapshot_tests,
"Snapshot tests are disabled.")
@@ -567,6 +602,7 @@
self.assertEqual(1, len(snaps['snapshots']))
self.assertEqual(self.snap['id'], snaps['snapshots'][0]['id'])
+ @decorators.idempotent_id('0a94e996-c4db-4fef-b486-4004ea65c11a')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipUnless(CONF.share.run_snapshot_tests,
"Snapshot tests are disabled.")
@@ -583,6 +619,7 @@
self.assertEqual(filters['status'], snap['status'])
self.assertEqual(filters['name'], snap['name'])
+ @decorators.idempotent_id('f969aba1-d293-48e3-a638-a89785bb41ef')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipUnless(CONF.share.run_snapshot_tests,
"Snapshot tests are disabled.")
@@ -599,6 +636,7 @@
for snap in snaps:
self.assertEqual(filters['description'], snap['description'])
+ @decorators.idempotent_id('59968026-12af-4029-a3d0-42c291b7db96')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipUnless(CONF.share.run_snapshot_tests,
"Snapshot tests are disabled.")
@@ -614,6 +652,7 @@
sorted_list = [snap['share_id'] for snap in snaps]
self.assertEqual(sorted(sorted_list), sorted_list)
+ @decorators.idempotent_id('17e6f579-e0d7-4724-a639-4974e82bb5ed')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@testtools.skipUnless(
CONF.share.run_extend_tests,
@@ -638,6 +677,7 @@
)
self.assertEqual(new_size, share_get['size'], msg)
+ @decorators.idempotent_id('8f64b930-9b4e-41d7-bbd6-82d9951931f3')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@testtools.skipUnless(
CONF.share.run_shrink_tests,
@@ -691,6 +731,7 @@
cls.snap = cls.create_snapshot_wait_for_active(
cls.share["id"], cls.snap_name, cls.snap_desc)
+ @decorators.idempotent_id('7661d042-8222-483c-9249-9f53931e7347')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_update_share(self):
@@ -715,6 +756,7 @@
self.assertEqual(new_desc, share["description"])
self.assertTrue(share["is_public"])
+ @decorators.idempotent_id('20f299f6-2441-4629-b44e-d791d57f413c')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipUnless(CONF.share.run_snapshot_tests,
"Snapshot tests are disabled.")
diff --git a/manila_tempest_tests/tests/api/test_shares_actions_negative.py b/manila_tempest_tests/tests/api/test_shares_actions_negative.py
index d427294..5195d14 100644
--- a/manila_tempest_tests/tests/api/test_shares_actions_negative.py
+++ b/manila_tempest_tests/tests/api/test_shares_actions_negative.py
@@ -16,6 +16,7 @@
import ddt
from tempest import config
from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
import testtools
from testtools import testcase as tc
@@ -50,6 +51,7 @@
cls.snap = cls.create_snapshot_wait_for_active(
cls.share["id"], cls.snap_name, cls.snap_desc)
+ @decorators.idempotent_id('c4481ba3-0cff-448b-a728-69a9a34e3aa6')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipUnless(
CONF.share.run_extend_tests,
@@ -68,6 +70,7 @@
self.share['id'],
new_size)
+ @decorators.idempotent_id('3448cd2b-34eb-453f-b72f-39fbea778e42')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipUnless(
CONF.share.run_extend_tests,
@@ -81,6 +84,7 @@
self.share['id'],
new_size)
+ @decorators.idempotent_id('79f2304a-7959-4169-8a76-b67814e0733a')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipUnless(
CONF.share.run_extend_tests,
@@ -94,6 +98,7 @@
self.share['id'],
new_size)
+ @decorators.idempotent_id('067c4b10-4324-45ac-8365-5d446b66c18a')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipUnless(
CONF.share.run_extend_tests,
@@ -112,6 +117,7 @@
share['id'],
new_size)
+ @decorators.idempotent_id('99d42f94-8da1-4c04-ad5b-9738d6acc139')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipUnless(
CONF.share.run_shrink_tests,
@@ -125,6 +131,7 @@
self.share['id'],
new_size)
+ @decorators.idempotent_id('3d4c8f34-49b8-4628-b1cb-652ae67473a5')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipUnless(
CONF.share.run_shrink_tests,
@@ -138,6 +145,7 @@
self.share['id'],
new_size)
+ @decorators.idempotent_id('d53ece5c-70e4-4953-a1d7-7d4384510519')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipUnless(
CONF.share.run_shrink_tests,
@@ -158,6 +166,7 @@
share['id'],
new_size)
+ @decorators.idempotent_id('ff307c91-3bb9-48b5-926c-5a2747320151')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@base.skip_if_microversion_not_supported("2.34")
@ddt.data('path', 'id')
@@ -174,6 +183,7 @@
self.assertGreater(len(shares), 0)
+ @decorators.idempotent_id('ffc3dc76-2f92-4308-a125-1d3905ed72ba')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@base.skip_if_microversion_lt("2.35")
@ddt.data('path', 'id')
@@ -187,6 +197,7 @@
self.assertEqual(0, len(shares))
+ @decorators.idempotent_id('3dbcf17b-cc63-43ea-b45f-eae12300729e')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@base.skip_if_microversion_not_supported("2.36")
def test_list_shares_with_like_filter_and_invalid_version(self):
@@ -202,6 +213,7 @@
self.assertGreater(len(shares), 0)
+ @decorators.idempotent_id('f41c6cd2-62cf-4bba-a26e-21a6e86eae15')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@base.skip_if_microversion_not_supported("2.36")
def test_list_shares_with_like_filter_not_exist(self):
@@ -213,6 +225,7 @@
self.assertEqual(0, len(shares))
+ @decorators.idempotent_id('31e33495-5ec3-4658-bdef-d9d1e034705a')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_list_shares_with_name_not_exist(self):
filters = {
@@ -222,6 +235,7 @@
self.assertEqual(0, len(shares))
+ @decorators.idempotent_id('5b0ceae1-357f-4b51-81a6-88973ea20c16')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@base.skip_if_microversion_not_supported("2.36")
def test_list_shares_with_description_not_exist(self):
@@ -232,6 +246,7 @@
self.assertEqual(0, len(shares))
+ @decorators.idempotent_id('061ee37a-96b2-4b4f-9cfe-2c8c80ed4370')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@base.skip_if_microversion_not_supported("2.36")
def test_list_snapshots_with_description_not_exist(self):
@@ -243,6 +258,7 @@
self.assertEqual(0, len(shares))
+ @decorators.idempotent_id('9d3c3158-1a92-4e37-b00f-a4a40b813109')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_list_snapshots_with_name_not_exist(self):
filters = {
diff --git a/manila_tempest_tests/tests/api/test_shares_from_snapshot_across_pools.py b/manila_tempest_tests/tests/api/test_shares_from_snapshot_across_pools.py
index 2ec167f..f8c5255 100644
--- a/manila_tempest_tests/tests/api/test_shares_from_snapshot_across_pools.py
+++ b/manila_tempest_tests/tests/api/test_shares_from_snapshot_across_pools.py
@@ -16,6 +16,7 @@
from collections import defaultdict
from tempest import config
+from tempest.lib import decorators
from testtools import testcase as tc
from manila_tempest_tests.tests.api import base
@@ -33,7 +34,7 @@
# create share_type
extra_specs = {"create_share_from_snapshot_support": True,
"snapshot_support": True}
- cls.share_type = cls._create_share_type(extra_specs)
+ cls.share_type = cls._create_share_type(specs=extra_specs)
cls.share_type_id = cls.share_type['id']
cls.admin_client = cls.admin_shares_v2_client
cls.pools = cls.get_pools_matching_share_type(cls.share_type,
@@ -69,6 +70,7 @@
'disabled.')
utils.check_skip_if_microversion_lt("2.54")
+ @decorators.idempotent_id('6f1fa7d0-94f2-4373-8730-b0986781cc88')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
def test_create_share_from_snapshot_across_pools_within_backend(self):
backends = [pool['backend'] for pool in self.pools]
@@ -133,6 +135,7 @@
" source share %s" % pool_name_a)
self.assertNotEqual(pool_name_a, pool_name_b, msg)
+ @decorators.idempotent_id('46f33338-d70d-4c9a-ae27-3dd5b7bd1531')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
def test_share_from_snapshot_across_azs(self):
azs = next((self.rep_domain_azs[rep] for rep in self.rep_domain_azs if
diff --git a/manila_tempest_tests/tests/api/test_shares_negative.py b/manila_tempest_tests/tests/api/test_shares_negative.py
index a0a1a47..9ee4202 100644
--- a/manila_tempest_tests/tests/api/test_shares_negative.py
+++ b/manila_tempest_tests/tests/api/test_shares_negative.py
@@ -14,6 +14,7 @@
# under the License.
from tempest import config
+from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
import testtools
from testtools import testcase as tc
@@ -42,12 +43,14 @@
metadata={'key': 'value'}
)
+ @decorators.idempotent_id('255011c0-4ed9-4174-bb13-8bbd06a62529')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_update_share_with_wrong_public_value(self):
self.assertRaises(lib_exc.BadRequest,
self.shares_client.update_share, self.share["id"],
is_public="truebar")
+ @decorators.idempotent_id('b9bb8dee-0c7c-4e51-909c-028335b1a6a0')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipUnless(CONF.share.run_snapshot_tests,
"Snapshot tests are disabled.")
@@ -64,6 +67,7 @@
self.assertRaises(lib_exc.Forbidden,
self.shares_client.delete_share, share["id"])
+ @decorators.idempotent_id('3df8e2d8-9b79-428d-9d8b-30bc66b5b40e')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipUnless(CONF.share.run_snapshot_tests,
"Snapshot tests are disabled.")
@@ -96,6 +100,7 @@
snapshot_id=snap["id"],
cleanup_in_class=False)
+ @decorators.idempotent_id('3047fb1c-5acc-4ef2-8796-b2d2d49829b5')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipIf(not CONF.share.multitenancy_enabled,
"Only for multitenancy.")
@@ -105,6 +110,7 @@
share_type_id=self.share_type_id,
share_network_id="wrong_sn_id")
+ @decorators.idempotent_id('e84ce567-a090-47c7-87c4-6ee427bdee7a')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@testtools.skipIf(not CONF.share.multitenancy_enabled,
"Only for multitenancy.")
@@ -148,45 +154,42 @@
snapshot_id=snap["id"],
)
+ @decorators.idempotent_id('3443493b-f56a-4faa-9968-e7cbb0d2802f')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_update_other_tenants_public_share(self):
- isolated_client = self.get_client_with_isolated_creds(
- type_of_creds='alt')
- self.assertRaises(lib_exc.Forbidden, isolated_client.update_share,
- self.share["id"], name="new_name")
+ self.assertRaises(lib_exc.Forbidden,
+ self.alt_shares_v2_client.update_share,
+ self.share["id"],
+ name="new_name")
+ @decorators.idempotent_id('68d1f1bc-16e4-4086-8982-7e44ca6bdc4d')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_delete_other_tenants_public_share(self):
- isolated_client = self.get_client_with_isolated_creds(
- type_of_creds='alt')
self.assertRaises(lib_exc.Forbidden,
- isolated_client.delete_share,
+ self.alt_shares_v2_client.delete_share,
self.share['id'])
+ @decorators.idempotent_id('1f9e5d84-0885-4a4b-9196-9031a1c01508')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_set_metadata_of_other_tenants_public_share(self):
- isolated_client = self.get_client_with_isolated_creds(
- type_of_creds='alt')
self.assertRaises(lib_exc.Forbidden,
- isolated_client.set_metadata,
+ self.alt_shares_v2_client.set_metadata,
self.share['id'],
{'key': 'value'})
+ @decorators.idempotent_id('fed7a935-9699-43a1-854e-67b61ba6233e')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_update_metadata_of_other_tenants_public_share(self):
- isolated_client = self.get_client_with_isolated_creds(
- type_of_creds='alt')
self.assertRaises(lib_exc.Forbidden,
- isolated_client.update_all_metadata,
+ self.alt_shares_v2_client.update_all_metadata,
self.share['id'],
{'key': 'value'})
+ @decorators.idempotent_id('bd62adeb-73c2-4b04-8812-80b479cd5c3b')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_delete_metadata_of_other_tenants_public_share(self):
- isolated_client = self.get_client_with_isolated_creds(
- type_of_creds='alt')
self.assertRaises(lib_exc.Forbidden,
- isolated_client.delete_metadata,
+ self.alt_shares_v2_client.delete_metadata,
self.share['id'],
'key')
@@ -200,12 +203,14 @@
cls.share_type = cls._create_share_type()
cls.share_type_id = cls.share_type['id']
+ @decorators.idempotent_id('75837f93-8c2c-40a4-bb9e-d76c53db07c7')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_unmanage_share_by_user(self):
self.assertRaises(lib_exc.Forbidden,
self.shares_client.unmanage_share,
'fake-id')
+ @decorators.idempotent_id('97a4dd2f-7c90-4eb7-bf74-d698c3060833')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_manage_share_by_user(self):
self.assertRaises(lib_exc.Forbidden,
@@ -213,18 +218,21 @@
'fake-host', 'nfs', '/export/path',
'fake-type')
+ @decorators.idempotent_id('1a438374-8a91-4566-9cef-0386f6609445')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_list_by_user_with_host_filter(self):
self.assertRaises(lib_exc.Forbidden,
self.shares_v2_client.list_shares,
params={'host': 'fake_host'})
+ @decorators.idempotent_id('73f37f33-946d-4213-9d27-25cd4e9a0208')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_list_by_share_server_by_user(self):
self.assertRaises(lib_exc.Forbidden,
self.shares_client.list_shares,
params={'share_server_id': 12345})
+ @decorators.idempotent_id('2f0df934-b2fb-4ebd-96f7-183cb699dcdd')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_create_share_non_existent_az(self):
self.assertRaises(lib_exc.NotFound,
@@ -232,6 +240,7 @@
share_type_id=self.share_type_id,
availability_zone='fake_az')
+ @decorators.idempotent_id('5ae2ecd7-a694-4ba9-ae23-cca75580b9d8')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_create_share_with_zero_size(self):
self.assertRaises(lib_exc.BadRequest,
@@ -239,6 +248,7 @@
share_type_id=self.share_type_id,
size=0)
+ @decorators.idempotent_id('3620a380-f9f9-4521-a468-473581637344')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_create_share_with_invalid_size(self):
self.assertRaises(lib_exc.BadRequest,
@@ -246,6 +256,7 @@
share_type_id=self.share_type_id,
size="#$%")
+ @decorators.idempotent_id('26ed523d-a215-4661-a038-633b74c9cad7')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_create_share_with_out_passing_size(self):
self.assertRaises(lib_exc.BadRequest,
@@ -253,6 +264,7 @@
share_type_id=self.share_type_id,
size="")
+ @decorators.idempotent_id('bf303b29-bbcb-4a96-96e9-270e12df58d1')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
@testtools.skipUnless(CONF.share.run_snapshot_tests,
"Snapshot tests are disabled.")
@@ -261,6 +273,7 @@
self.shares_client.delete_snapshot,
"wrong_share_id")
+ @decorators.idempotent_id('08e5a9c7-45cb-414c-b375-28c335f20ff1')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
@testtools.skipUnless(CONF.share.run_snapshot_tests,
"Snapshot tests are disabled.")
@@ -269,6 +282,7 @@
self.shares_client.create_snapshot,
"wrong_share_id")
+ @decorators.idempotent_id('78e5e327-c68e-4910-82b2-27f5f4d150ac')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_create_share_with_invalid_protocol(self):
self.assertRaises(lib_exc.BadRequest,
@@ -276,6 +290,7 @@
share_type_id=self.share_type_id,
share_protocol="nonexistent_protocol")
+ @decorators.idempotent_id('2b7c7ea8-c0e9-446c-a8e3-add765452c04')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_create_share_with_wrong_public_value(self):
self.assertRaises(lib_exc.BadRequest,
@@ -283,17 +298,20 @@
share_type_id=self.share_type_id,
is_public='truebar')
+ @decorators.idempotent_id('f82d1667-ae39-43bb-b5aa-bfc9b2ec7292')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_get_share_with_wrong_id(self):
self.assertRaises(lib_exc.NotFound, self.shares_client.get_share,
"wrong_share_id")
+ @decorators.idempotent_id('d03cf44e-6e69-415f-be36-25defb86df56')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_get_share_without_passing_share_id(self):
# Should not be able to get share when empty ID is passed
self.assertRaises(lib_exc.NotFound,
self.shares_client.get_share, '')
+ @decorators.idempotent_id('a9487254-606b-444f-ba6a-2f461bcaf474')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_list_shares_nonadmin_with_nonexistent_share_server_filter(self):
# filtering by share server allowed only for admins by default
@@ -301,11 +319,13 @@
self.shares_client.list_shares_with_detail,
{'share_server_id': 'fake_share_server_id'})
+ @decorators.idempotent_id('9698d1a3-8ee8-46fa-a46b-1084d98e7149')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_delete_share_with_wrong_id(self):
self.assertRaises(lib_exc.NotFound, self.shares_client.delete_share,
"wrong_share_id")
+ @decorators.idempotent_id('b8097d56-067e-4d7c-8401-31bc7021fd24')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API)
def test_delete_share_without_passing_share_id(self):
# Should not be able to delete share when empty ID is passed
diff --git a/manila_tempest_tests/tests/api/test_snapshot_rules.py b/manila_tempest_tests/tests/api/test_snapshot_rules.py
index 86cb339..e793843 100644
--- a/manila_tempest_tests/tests/api/test_snapshot_rules.py
+++ b/manila_tempest_tests/tests/api/test_snapshot_rules.py
@@ -13,15 +13,16 @@
# License for the specific language governing permissions and limitations
# under the License.
-import six
-
import ddt
+import six
from tempest import config
+from tempest.lib import decorators
from testtools import testcase as tc
from manila_tempest_tests.tests.api import base
from manila_tempest_tests import utils
+
CONF = config.CONF
@@ -34,7 +35,7 @@
super(BaseShareSnapshotRulesTest, cls).resource_setup()
# create share_type
extra_specs = {'mount_snapshot_support': 'True'}
- cls.share_type = cls._create_share_type(extra_specs)
+ cls.share_type = cls._create_share_type(specs=extra_specs)
cls.share_type_id = cls.share_type['id']
# create share
@@ -83,6 +84,7 @@
super(ShareSnapshotIpRulesForNFSTest, cls).resource_setup()
cls.access_type = "ip"
+ @decorators.idempotent_id('bdce2be8-80b9-4f68-bdc0-09a52ba0e6fd')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@ddt.data("1.1.1.1", "1.2.3.4/32")
def test_create_delete_access_rules(self, access_to):
@@ -110,6 +112,7 @@
super(ShareSnapshotUserRulesForCIFSTest, cls).resource_setup()
cls.access_type = "user"
+ @decorators.idempotent_id('c2625cd2-4dc0-431d-b47b-8f097e22f16d')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
def test_create_delete_access_rules(self):
access_to = CONF.share.username_for_user_rules
diff --git a/manila_tempest_tests/tests/api/test_snapshot_rules_negative.py b/manila_tempest_tests/tests/api/test_snapshot_rules_negative.py
index 7a4308d..92bd639 100644
--- a/manila_tempest_tests/tests/api/test_snapshot_rules_negative.py
+++ b/manila_tempest_tests/tests/api/test_snapshot_rules_negative.py
@@ -15,6 +15,7 @@
import ddt
from tempest import config
+from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
from testtools import testcase as tc
@@ -49,13 +50,14 @@
super(SnapshotIpRulesForNFSNegativeTest, cls).resource_setup()
# create share type
extra_specs = {'mount_snapshot_support': 'True'}
- cls.share_type = cls._create_share_type(extra_specs)
+ cls.share_type = cls._create_share_type(specs=extra_specs)
cls.share_type_id = cls.share_type['id']
# create share
cls.share = cls.create_share(cls.protocol,
share_type_id=cls.share_type_id)
cls.snap = cls.create_snapshot_wait_for_active(cls.share["id"])
+ @decorators.idempotent_id('a877276e-03d4-4fc5-b4b4-c8874d23f1dc')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@ddt.data("1.2.3.256", "1.1.1.-", "1.2.3.4/33", "1.2.3.*", "1.2.3.*/23",
"1.2.3.1|23", "1.2.3.1/", "1.2.3.1/-1",
@@ -67,6 +69,7 @@
self.shares_v2_client.create_snapshot_access_rule,
self.snap["id"], "ip", target)
+ @decorators.idempotent_id('dd93150f-8081-4533-abb3-f99a03652a87')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
@ddt.data("1.2.3.4", "fd8c:b029:bba6:ac54::1",
"fd8c:b029:bba6:ac54::1/128", "1.2.3.4/32")
diff --git a/manila_tempest_tests/tests/scenario/manager.py b/manila_tempest_tests/tests/scenario/manager.py
index c83dfe6..1fa03f4 100644
--- a/manila_tempest_tests/tests/scenario/manager.py
+++ b/manila_tempest_tests/tests/scenario/manager.py
@@ -21,7 +21,6 @@
from oslo_utils import netutils
from oslo_utils import uuidutils
import six
-
from tempest.common import compute
from tempest.common import image as common_image
from tempest.common.utils.linux import remote_client
@@ -32,14 +31,14 @@
from tempest.lib.common.utils import data_utils
from tempest.lib.common.utils import test_utils
from tempest.lib import exceptions as lib_exc
-import tempest.test
+from tempest import test
CONF = config.CONF
LOG = log.getLogger(__name__)
-class ScenarioTest(tempest.test.BaseTestCase):
+class ScenarioTest(test.BaseTestCase):
"""Base class for scenario tests. Uses tempest own clients. """
credentials = ['primary']
diff --git a/manila_tempest_tests/tests/scenario/manager_share.py b/manila_tempest_tests/tests/scenario/manager_share.py
index 4593e9a..64e5715 100644
--- a/manila_tempest_tests/tests/scenario/manager_share.py
+++ b/manila_tempest_tests/tests/scenario/manager_share.py
@@ -13,9 +13,16 @@
# License for the specific language governing permissions and limitations
# under the License.
+from tempfile import mkstemp
+
from oslo_log import log
import six
from six.moves.urllib.request import urlopen
+from tempest.common import waiters
+from tempest import config
+from tempest.lib.common.utils import data_utils
+from tempest.lib.common.utils import test_utils
+from tempest.lib import exceptions
from manila_tempest_tests.common import constants
from manila_tempest_tests.common import remote_client
@@ -23,13 +30,6 @@
from manila_tempest_tests.tests.scenario import manager
from manila_tempest_tests import utils
-from tempest.common import waiters
-from tempest import config
-from tempest.lib.common.utils import data_utils
-from tempest.lib import exceptions
-
-from tempfile import mkstemp
-
CONF = config.CONF
LOG = log.getLogger(__name__)
@@ -91,24 +91,13 @@
msg = ("Image %s not found. Expecting an image including "
"required share tools." %
CONF.share.image_with_share_tools)
- raise exceptions.InvalidConfiguration(message=msg)
+ raise exceptions.InvalidConfiguration(msg)
self.ssh_user = CONF.share.image_username
LOG.debug('Starting test for i:{image_id}, f:{flavor}. '
'user: {ssh_user}'.format(image_id=self.image_id,
flavor=self.flavor_ref,
ssh_user=self.ssh_user))
- self.security_group = self._create_security_group()
- self.network = self._create_network(namestart="manila-share")
- self.subnet = self._create_subnet(
- network=self.network,
- namestart="manila-share-sub",
- ip_version=self.ip_version,
- use_default_subnetpool=self.ipv6_enabled)
- router = self._get_router()
- self._create_router_interface(subnet_id=self.subnet['id'],
- router_id=router['id'])
-
self.storage_network = (
self._get_network_by_name_or_id(CONF.share.storage_network)
if CONF.share.storage_network else None
@@ -117,6 +106,24 @@
self.storage_network['name'] if self.storage_network else None
)
+ # Tests need to be able to ssh into the VM - so we need
+ # a security group, and a tenant private network
+ self.security_group = self._create_security_group()
+ self.network = self._create_network(namestart="manila-share")
+ # When not using a "storage network" to connect shares to VMs,
+ # we need the subnet to match the IP version we're testing
+ subnet_ip_params = {} if self.storage_network else {
+ 'ip_version': self.ip_version,
+ 'use_default_subnetpool': self.ipv6_enabled
+ }
+ self.subnet = self._create_subnet(
+ network=self.network,
+ namestart="manila-share-sub",
+ **subnet_ip_params)
+ router = self._get_router()
+ self._create_router_interface(subnet_id=self.subnet['id'],
+ router_id=router['id'])
+
if CONF.share.multitenancy_enabled:
# Skip if DHSS=False
self.share_network = self.create_share_network()
@@ -124,6 +131,9 @@
def mount_share(self, location, remote_client, target_dir=None):
raise NotImplementedError
+ def allow_access(self, **kwargs):
+ raise NotImplementedError
+
def unmount_share(self, remote_client, target_dir=None):
target_dir = target_dir or "/mnt"
remote_client.exec_command("sudo umount %s" % target_dir)
@@ -190,6 +200,24 @@
self.share = self.shares_client.get_share(self.share['id'])
return remote_client
+ def validate_ping_to_export_location(self, export, remote_client,
+ ping_timeout=None):
+ timeout = ping_timeout or CONF.validation.ping_timeout
+
+ def ping_to_export_location(export, remote_client):
+ ip, version = self.get_ip_and_version_from_export_location(export)
+ try:
+ remote_client.exec_command(
+ "ping{} -c5 -w1 {}".format(
+ '6' if version == 6 else '', ip))
+ return True
+ except exceptions.SSHExecCommandFailed:
+ return False
+
+ test_utils.call_until_true(ping_to_export_location,
+ timeout, 1, export=export,
+ remote_client=remote_client)
+
def write_data_to_mounted_share(self, escaped_string, remote_client,
mount_point='/mnt/t1'):
remote_client.exec_command("echo \"{escaped_string}\" "
@@ -347,6 +375,54 @@
share['id'], instance=instance, cleanup=False,
snapshot=snapshot, access_level=access_level, client=client)
+ def provide_access_to_client_identified_by_cephx(self, share=None,
+ access_level='rw',
+ access_to=None,
+ remote_client=None,
+ locations=None,
+ client=None,
+ oc_size=20971520):
+ share = share or self.share
+ client = client or self.shares_v2_client
+ access_to = access_to or data_utils.rand_name(
+ self.__class__.__name__ + '-cephx-id')
+ # Check if access is already granted to the client
+ access = self.shares_v2_client.list_access_rules(
+ share['id'], metadata={'metadata': {'access_to': access_to}})
+ access = access[0] if access else None
+
+ if not access:
+ access = self._allow_access(
+ share['id'], access_level=access_level, access_to=access_to,
+ access_type="cephx", cleanup=False, client=client)
+ # Set metadata to access rule to be filtered if necessary.
+ # This is necessary to prevent granting access to a client who
+ # already has.
+ self.shares_v2_client.update_access_metadata(
+ metadata={"access_to": "{}".format(access_to)},
+ access_id=access['id'])
+ get_access = self.shares_v2_client.get_access(access['id'])
+ # Set 'access_key' and 'access_to' attributes for being use in mount
+ # operation.
+ setattr(self, 'access_key', get_access['access_key'])
+ setattr(self, 'access_to', access_to)
+
+ remote_client.exec_command(
+ "sudo crudini --set {access_to}.keyring client.{access_to} key "
+ "{access_key}"
+ .format(access_to=access_to, access_key=self.access_key))
+ remote_client.exec_command(
+ "sudo crudini --set ceph.conf client \"client quota\" true")
+ remote_client.exec_command(
+ "sudo crudini --set ceph.conf client \"client oc size\" {}"
+ .format(oc_size))
+ if not isinstance(locations, list):
+ locations = [locations]
+ remote_client.exec_command(
+ "sudo crudini --set ceph.conf client \"mon host\" {}"
+ .format(locations[0].split(':/')[0]))
+ return access
+
def wait_for_active_instance(self, instance_id):
waiters.wait_for_server_status(
self.os_primary.servers_client, instance_id, "ACTIVE")
@@ -583,14 +659,7 @@
LOG.info('Creating Glance image using the downloaded image file')
return self._image_create('centos', 'bare', imagepath, 'qcow2')
- def get_share_export_location_for_mount(self, share):
- exports = self.get_user_export_locations(
- share=share,
- error_on_invalid_ip_version=True)
- return exports[0]
-
- def get_user_export_locations(self, share=None, snapshot=None,
- error_on_invalid_ip_version=False):
+ def get_user_export_locations(self, share=None, snapshot=None):
locations = None
if share:
locations = self.get_share_export_locations(share)
@@ -598,20 +667,20 @@
locations = self._get_snapshot_export_locations(snapshot)
self.assertNotEmpty(locations)
- locations = self._get_export_locations_according_to_ip_version(
- locations, error_on_invalid_ip_version)
- self.assertNotEmpty(locations)
+ if self.protocol != 'cephfs':
+ locations = self._get_export_locations_according_to_ip_version(
+ locations)
+ self.assertNotEmpty(locations)
return locations
- def _get_export_locations_according_to_ip_version(
- self, all_locations, error_on_invalid_ip_version):
+ def _get_export_locations_according_to_ip_version(self, all_locations):
locations = [
x for x in all_locations
if self.get_ip_and_version_from_export_location(
x)[1] == self.ip_version]
- if len(locations) == 0 and not error_on_invalid_ip_version:
+ if len(locations) == 0:
message = ("Configured backend does not support "
"ip_version %s" % self.ip_version)
raise self.skipException(message)
@@ -630,3 +699,39 @@
message = ("Protocol %s is not supported" % self.protocol)
raise self.skipException(message)
return ip, version
+
+
+class BaseShareCEPHFSTest(ShareScenarioTest):
+
+ def allow_access(self, access_level='rw', **kwargs):
+ return self.provide_access_to_client_identified_by_cephx(
+ remote_client=kwargs['remote_client'],
+ locations=kwargs['locations'], access_level=access_level)
+
+ def _fuse_client(self, mountpoint, remote_client, target_dir, access_to):
+ remote_client.exec_command(
+ "sudo ceph-fuse {target_dir} --id={access_to} --conf=ceph.conf "
+ "--keyring={access_to}.keyring --client-mountpoint={mountpoint}"
+ .format(target_dir=target_dir, access_to=access_to,
+ mountpoint=mountpoint))
+
+ def mount_share(self, location, remote_client, target_dir=None,
+ access_to=None):
+ target_dir = target_dir or "/mnt"
+ access_to = access_to or self.access_to
+ mountpoint = location.split(':')[-1]
+ if getattr(self, 'mount_client', None):
+ return self._fuse_client(mountpoint, remote_client, target_dir,
+ access_to=access_to)
+ remote_client.exec_command(
+ "sudo mount -t ceph {location} {target_dir} -o name={access_to},"
+ "secret={access_key}"
+ .format(location=location, target_dir=target_dir,
+ access_to=access_to, access_key=self.access_key))
+
+ def unmount_share(self, remote_client, target_dir=None):
+ target_dir = target_dir or "/mnt"
+ if getattr(self, 'mount_client', None):
+ return remote_client.exec_command(
+ "sudo fusermount -uz %s" % target_dir)
+ super(BaseShareCEPHFSTest, self).unmount_share(remote_client)
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 8a55b2e..2ade001 100644
--- a/manila_tempest_tests/tests/scenario/test_share_basic_ops.py
+++ b/manila_tempest_tests/tests/scenario/test_share_basic_ops.py
@@ -14,9 +14,9 @@
# under the License.
import ddt
-
from oslo_log import log as logging
from tempest import config
+from tempest.lib import decorators
from tempest.lib import exceptions
import testtools
from testtools import testcase as tc
@@ -26,6 +26,7 @@
from manila_tempest_tests.tests.scenario import manager_share as manager
from manila_tempest_tests import utils
+
CONF = config.CONF
LOG = logging.getLogger(__name__)
@@ -44,21 +45,7 @@
* Terminate the instance
"""
- @classmethod
- def skip_checks(cls):
- super(ShareBasicOpsBase, cls).skip_checks()
- if cls.protocol not in CONF.share.enable_ip_rules_for_protocols:
- message = ("%s tests for access rules other than IP are disabled" %
- cls.protocol)
- raise cls.skipException(message)
-
- def _ping_host_from_export_location(self, export, remote_client):
- ip, version = self.get_ip_and_version_from_export_location(export)
- if version == 6:
- remote_client.exec_command("ping6 -c 5 %s" % ip)
- else:
- remote_client.exec_command("ping -c 5 %s" % ip)
-
+ @decorators.idempotent_id('825be71c-cf14-4884-a0ad-cf47d511df9a')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
def test_mount_share_one_vm(self):
instance = self.boot_instance(wait_until="BUILD")
@@ -66,12 +53,14 @@
locations = self.get_user_export_locations(self.share)
instance = self.wait_for_active_instance(instance["id"])
remote_client = self.init_remote_client(instance)
- self.provide_access_to_auxiliary_instance(instance)
+ self.allow_access(instance=instance, remote_client=remote_client,
+ locations=locations)
for location in locations:
self.mount_share(location, remote_client)
self.unmount_share(remote_client)
+ @decorators.idempotent_id('7cc61131-90e1-42fb-9f07-d3786efb338f')
@tc.attr(base.TAG_NEGATIVE, base.TAG_BACKEND)
def test_write_with_ro_access(self):
'''Test if an instance with ro access can write on the share.'''
@@ -85,12 +74,17 @@
remote_client_inst = self.init_remote_client(instance)
# First, check if write works RW access.
- acc_rule_id = self.provide_access_to_auxiliary_instance(instance)['id']
+ acc_rule_id = self.allow_access(
+ instance=instance, remote_client=remote_client_inst,
+ locations=location)['id']
+
self.mount_share(location, remote_client_inst)
self.write_data_to_mounted_share(test_data, remote_client_inst)
self.deny_access(self.share['id'], acc_rule_id)
- self.provide_access_to_auxiliary_instance(instance, access_level='ro')
+ self.allow_access(instance=instance, remote_client=remote_client_inst,
+ locations=location, access_level='ro')
+
self.addCleanup(self.unmount_share, remote_client_inst)
# Test if write with RO access fails.
@@ -98,6 +92,7 @@
self.write_data_to_mounted_share,
test_data, remote_client_inst)
+ @decorators.idempotent_id('5e184576-c7d1-4c16-9b7c-bc9bcd65ba58')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
def test_read_write_two_vms(self):
"""Boots two vms and writes/reads data on it."""
@@ -113,7 +108,9 @@
# Write data to first VM
remote_client_inst1 = self.init_remote_client(instance1)
- self.provide_access_to_auxiliary_instance(instance1)
+ self.allow_access(instance=instance1,
+ remote_client=remote_client_inst1,
+ locations=location)
self.mount_share(location, remote_client_inst1)
self.addCleanup(self.unmount_share,
@@ -123,7 +120,9 @@
# Read from second VM
remote_client_inst2 = self.init_remote_client(instance2)
if not CONF.share.override_ip_for_nfs_access or self.ipv6_enabled:
- self.provide_access_to_auxiliary_instance(instance2)
+ self.allow_access(instance=instance2,
+ remote_client=remote_client_inst2,
+ locations=location)
self.mount_share(location, remote_client_inst2)
self.addCleanup(self.unmount_share,
@@ -131,6 +130,7 @@
data = self.read_data_from_mounted_share(remote_client_inst2)
self.assertEqual(test_data, data)
+ @decorators.idempotent_id('15d42949-545e-4ad8-b06e-bb2556c54375')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@base.skip_if_microversion_lt("2.29")
@testtools.skipUnless(CONF.share.run_host_assisted_migration_tests or
@@ -220,8 +220,7 @@
self.share = self.migration_complete(self.share['id'], dest_pool)
- new_exports = self.get_user_export_locations(
- self.share, error_on_invalid_ip_version=True)
+ new_exports = self.get_user_export_locations(self.share)
self.assertEqual(dest_pool, self.share['host'])
self.assertEqual(constants.TASK_STATE_MIGRATION_SUCCESS,
@@ -239,9 +238,11 @@
self.assertIn('1m4.bin', output)
self.assertIn('1m5.bin', output)
+ @decorators.idempotent_id('87b803bf-679a-492b-a538-af4c9ff013c8')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@testtools.skipUnless(
- CONF.share.run_snapshot_tests, "Snapshot tests are disabled.")
+ CONF.share.capability_create_share_from_snapshot_support,
+ "Create share from snapshot tests are disabled.")
def test_write_data_to_share_created_from_snapshot(self):
# 1 - Create UVM, ok, created
instance = self.boot_instance(wait_until="BUILD")
@@ -320,6 +321,7 @@
self.assertNotIn('file2', output)
self.assertIn('file3', output)
+ @decorators.idempotent_id('c98e6876-3a4f-40e8-8b4f-023c94c242c3')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@base.skip_if_microversion_lt("2.32")
@testtools.skipUnless(CONF.share.run_mount_snapshot_tests,
@@ -387,9 +389,21 @@
class TestShareBasicOpsNFS(ShareBasicOpsBase):
protocol = "nfs"
+ @classmethod
+ def skip_checks(cls):
+ super(TestShareBasicOpsNFS, cls).skip_checks()
+ if cls.protocol not in CONF.share.enable_ip_rules_for_protocols:
+ message = ("%s tests for access rules other than IP are disabled" %
+ cls.protocol)
+ raise cls.skipException(message)
+
+ def allow_access(self, access_level='rw', **kwargs):
+ return self.provide_access_to_auxiliary_instance(
+ instance=kwargs['instance'], access_level=access_level)
+
def mount_share(self, location, remote_client, target_dir=None):
- self._ping_host_from_export_location(location, remote_client)
+ self.validate_ping_to_export_location(location, remote_client)
target_dir = target_dir or "/mnt"
remote_client.exec_command(
@@ -399,9 +413,21 @@
class TestShareBasicOpsCIFS(ShareBasicOpsBase):
protocol = "cifs"
+ @classmethod
+ def skip_checks(cls):
+ super(TestShareBasicOpsCIFS, cls).skip_checks()
+ if cls.protocol not in CONF.share.enable_ip_rules_for_protocols:
+ message = ("%s tests for access rules other than IP are disabled" %
+ cls.protocol)
+ raise cls.skipException(message)
+
+ def allow_access(self, access_level='rw', **kwargs):
+ return self.provide_access_to_auxiliary_instance(
+ instance=kwargs['instance'], access_level=access_level)
+
def mount_share(self, location, remote_client, target_dir=None):
- self._ping_host_from_export_location(location, remote_client)
+ self.validate_ping_to_export_location(location, remote_client)
location = location.replace("\\", "/")
target_dir = target_dir or "/mnt"
@@ -409,23 +435,48 @@
"sudo mount.cifs \"%s\" %s -o guest" % (location, target_dir)
)
+ @decorators.idempotent_id('4344a47a-d316-496b-97a4-12a59297950a')
@tc.attr(base.TAG_NEGATIVE, base.TAG_BACKEND)
def test_write_with_ro_access(self):
msg = ("Skipped for CIFS protocol because RO access is not "
"supported for shares by IP.")
raise self.skipException(msg)
+ @decorators.idempotent_id('a691332b-dd7a-4041-9bbd-3893e168aefa')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
def test_read_mountable_snapshot(self):
msg = "Skipped for CIFS protocol because of bug/1649573"
raise self.skipException(msg)
+ @decorators.idempotent_id('8c936c3e-4793-49d2-8409-4038f03e7012')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
def test_write_data_to_share_created_from_snapshot(self):
msg = "Skipped for CIFS protocol because of bug/1649573"
raise self.skipException(msg)
+class TestShareBasicOpsCEPHFS(ShareBasicOpsBase, manager.BaseShareCEPHFSTest):
+ protocol = "cephfs"
+
+ @decorators.idempotent_id('9fb12879-45b3-4042-acac-82be338dbde1')
+ @tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
+ def test_mount_share_one_vm_with_ceph_fuse_client(self):
+ self.mount_client = 'fuse'
+ super(TestShareBasicOpsCEPHFS, self).test_mount_share_one_vm()
+
+ @decorators.idempotent_id('a2a70b94-f5fc-438a-9dfa-53aa60ee3949')
+ @tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
+ def test_write_with_ro_access_with_ceph_fuse_client(self):
+ self.mount_client = 'fuse'
+ super(TestShareBasicOpsCEPHFS, self).test_write_with_ro_access()
+
+ @decorators.idempotent_id('c247f51f-0ffc-4a4f-894c-781647619faf')
+ @tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
+ def test_read_write_two_vms_with_ceph_fuse_client(self):
+ self.mount_client = 'fuse'
+ super(TestShareBasicOpsCEPHFS, self).test_read_write_two_vms()
+
+
class TestShareBasicOpsNFSIPv6(TestShareBasicOpsNFS):
ip_version = 6
diff --git a/manila_tempest_tests/tests/scenario/test_share_extend.py b/manila_tempest_tests/tests/scenario/test_share_extend.py
index 7827b75..df77990 100644
--- a/manila_tempest_tests/tests/scenario/test_share_extend.py
+++ b/manila_tempest_tests/tests/scenario/test_share_extend.py
@@ -11,11 +11,11 @@
# under the License.
import ddt
-import six
-
from oslo_log import log as logging
from oslo_utils import units
+import six
from tempest import config
+from tempest.lib import decorators
from tempest.lib import exceptions
from testtools import testcase as tc
@@ -23,6 +23,7 @@
from manila_tempest_tests.tests.api import base
from manila_tempest_tests.tests.scenario import manager_share as manager
+
CONF = config.CONF
LOG = logging.getLogger(__name__)
@@ -45,14 +46,7 @@
* Terminate the instance
"""
- @classmethod
- def skip_checks(cls):
- super(ShareExtendBase, cls).skip_checks()
- if cls.protocol not in CONF.share.enable_ip_rules_for_protocols:
- message = ("%s tests for access rules other than IP are disabled" %
- cls.protocol)
- raise cls.skipException(message)
-
+ @decorators.idempotent_id('e1c0d614-c8f2-43cf-9c49-25808b07ba4a')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
def test_create_extend_and_write(self):
default_share_size = CONF.share.share_size
@@ -69,10 +63,11 @@
remote_client = self.init_remote_client(instance)
LOG.debug('Step 4 - grant access')
- self.provide_access_to_auxiliary_instance(instance, share=share)
+ location = self.get_user_export_locations(share)[0]
+ self.allow_access(instance=instance, remote_client=remote_client,
+ locations=location)
LOG.debug('Step 5 - mount')
- location = self.get_share_export_location_for_mount(share)
self.mount_share(location, remote_client)
total_blocks = (units.Ki * default_share_size) / 64
@@ -153,7 +148,22 @@
class TestShareExtendNFS(ShareExtendBase):
protocol = "nfs"
+ @classmethod
+ def skip_checks(cls):
+ super(ShareExtendBase, cls).skip_checks()
+ if cls.protocol not in CONF.share.enable_ip_rules_for_protocols:
+ message = ("%s tests for access rules other than IP are disabled" %
+ cls.protocol)
+ raise cls.skipException(message)
+
+ def allow_access(self, access_level='rw', **kwargs):
+ return self.provide_access_to_auxiliary_instance(
+ instance=kwargs['instance'], access_level=access_level)
+
def mount_share(self, location, remote_client, target_dir=None):
+
+ self.validate_ping_to_export_location(location, remote_client)
+
target_dir = target_dir or "/mnt"
remote_client.exec_command(
"sudo mount -vt nfs \"%s\" %s" % (location, target_dir)
@@ -163,7 +173,22 @@
class TestShareExtendCIFS(ShareExtendBase):
protocol = "cifs"
+ @classmethod
+ def skip_checks(cls):
+ super(ShareExtendBase, cls).skip_checks()
+ if cls.protocol not in CONF.share.enable_ip_rules_for_protocols:
+ message = ("%s tests for access rules other than IP are disabled" %
+ cls.protocol)
+ raise cls.skipException(message)
+
+ def allow_access(self, access_level='rw', **kwargs):
+ return self.provide_access_to_auxiliary_instance(
+ instance=kwargs['instance'], access_level=access_level)
+
def mount_share(self, location, remote_client, target_dir=None):
+
+ self.validate_ping_to_export_location(location, remote_client)
+
location = location.replace("\\", "/")
target_dir = target_dir or "/mnt"
remote_client.exec_command(
@@ -171,6 +196,20 @@
)
+class TestShareExtendCEPHFS(ShareExtendBase, manager.BaseShareCEPHFSTest):
+ protocol = "cephfs"
+
+ @decorators.idempotent_id('9ca1e4a9-23e3-4da6-a63e-46e7919335e0')
+ @tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
+ def test_create_extend_and_write_with_ceph_fuse_client(self):
+ self.mount_client = 'fuse'
+ super(TestShareExtendCEPHFS, self).test_create_extend_and_write()
+
+
+class TestShareExtendNFSIPv6(TestShareExtendNFS):
+ ip_version = 6
+
+
# NOTE(u_glide): this function is required to exclude ShareExtendBase
# from executed test cases.
# See: https://docs.python.org/3/library/unittest.html#load-tests-protocol
diff --git a/manila_tempest_tests/tests/scenario/test_share_manage_unmanage.py b/manila_tempest_tests/tests/scenario/test_share_manage_unmanage.py
index d58378c..7da1974 100644
--- a/manila_tempest_tests/tests/scenario/test_share_manage_unmanage.py
+++ b/manila_tempest_tests/tests/scenario/test_share_manage_unmanage.py
@@ -11,9 +11,9 @@
# under the License.
import ddt
-
from oslo_log import log as logging
from tempest import config
+from tempest.lib import decorators
from tempest.lib import exceptions
import testtools
from testtools import testcase as tc
@@ -22,6 +22,7 @@
from manila_tempest_tests.tests.scenario import manager_share as manager
from manila_tempest_tests import utils
+
CONF = config.CONF
LOG = logging.getLogger(__name__)
@@ -59,6 +60,7 @@
cls.protocol)
raise cls.skipException(message)
+ @decorators.idempotent_id('165f22b4-9417-45ee-8e1d-2b8669ac2f00')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@testtools.skipUnless(
CONF.share.run_manage_unmanage_tests,
@@ -178,6 +180,9 @@
protocol = "nfs"
def mount_share(self, location, remote_client, target_dir=None):
+
+ self.validate_ping_to_export_location(location, remote_client)
+
target_dir = target_dir or "/mnt"
remote_client.exec_command(
"sudo mount -vt nfs \"%s\" %s" % (location, target_dir)
@@ -188,6 +193,9 @@
protocol = "cifs"
def mount_share(self, location, remote_client, target_dir=None):
+
+ self.validate_ping_to_export_location(location, remote_client)
+
location = location.replace("\\", "/")
target_dir = target_dir or "/mnt"
remote_client.exec_command(
@@ -195,6 +203,10 @@
)
+class ShareManageUnmanageNFSIPv6(ShareManageUnmanageNFS):
+ ip_version = 6
+
+
# NOTE(u_glide): this function is required to exclude ShareManageUnmanageBase
# from executed test cases.
# See: https://docs.python.org/3/library/unittest.html#load-tests-protocol
diff --git a/manila_tempest_tests/tests/scenario/test_share_shrink.py b/manila_tempest_tests/tests/scenario/test_share_shrink.py
index e8ffdcb..3e498f8 100644
--- a/manila_tempest_tests/tests/scenario/test_share_shrink.py
+++ b/manila_tempest_tests/tests/scenario/test_share_shrink.py
@@ -10,11 +10,12 @@
# License for the specific language governing permissions and limitations
# under the License.
-import six
import time
from oslo_log import log as logging
+import six
from tempest import config
+from tempest.lib import decorators
from tempest.lib import exceptions
import testtools
from testtools import testcase as tc
@@ -23,6 +24,7 @@
from manila_tempest_tests.tests.api import base
from manila_tempest_tests.tests.scenario import manager_share as manager
+
CONF = config.CONF
LOG = logging.getLogger(__name__)
@@ -46,14 +48,7 @@
* Terminate the instance
"""
- @classmethod
- def skip_checks(cls):
- super(ShareShrinkBase, cls).skip_checks()
- if cls.protocol not in CONF.share.enable_ip_rules_for_protocols:
- message = ("%s tests for access rules other than IP are disabled" %
- cls.protocol)
- raise cls.skipException(message)
-
+ @decorators.idempotent_id('ed0f9c0c-5302-4cc9-9f5d-f7641cc3b83b')
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@testtools.skipUnless(
CONF.share.run_shrink_tests, 'Shrink share tests are disabled.')
@@ -72,10 +67,11 @@
remote_client = self.init_remote_client(instance)
LOG.debug('Step 4 - grant access')
- self.provide_access_to_auxiliary_instance(instance)
+ location = self.get_user_export_locations(share)[0]
+ self.allow_access(instance=instance, remote_client=remote_client,
+ locations=location)
LOG.debug('Step 5 - mount')
- location = self.get_share_export_location_for_mount(share)
self.mount_share(location, remote_client)
total_blocks = (1024 * default_share_size) / 64
@@ -167,7 +163,22 @@
class TestShareShrinkNFS(ShareShrinkBase):
protocol = "nfs"
+ @classmethod
+ def skip_checks(cls):
+ super(ShareShrinkBase, cls).skip_checks()
+ if cls.protocol not in CONF.share.enable_ip_rules_for_protocols:
+ message = ("%s tests for access rules other than IP are disabled" %
+ cls.protocol)
+ raise cls.skipException(message)
+
+ def allow_access(self, access_level='rw', **kwargs):
+ return self.provide_access_to_auxiliary_instance(
+ instance=kwargs['instance'], access_level=access_level)
+
def mount_share(self, location, ssh_client, target_dir=None):
+
+ self.validate_ping_to_export_location(location, ssh_client)
+
target_dir = target_dir or "/mnt"
ssh_client.exec_command(
"sudo mount -vt nfs \"%s\" %s" % (location, target_dir)
@@ -177,7 +188,22 @@
class TestShareShrinkCIFS(ShareShrinkBase):
protocol = "cifs"
+ @classmethod
+ def skip_checks(cls):
+ super(ShareShrinkBase, cls).skip_checks()
+ if cls.protocol not in CONF.share.enable_ip_rules_for_protocols:
+ message = ("%s tests for access rules other than IP are disabled" %
+ cls.protocol)
+ raise cls.skipException(message)
+
+ def allow_access(self, access_level='rw', **kwargs):
+ return self.provide_access_to_auxiliary_instance(
+ instance=kwargs['instance'], access_level=access_level)
+
def mount_share(self, location, ssh_client, target_dir=None):
+
+ self.validate_ping_to_export_location(location, ssh_client)
+
location = location.replace("\\", "/")
target_dir = target_dir or "/mnt"
ssh_client.exec_command(
@@ -185,6 +211,20 @@
)
+class TestShareShrinkCEPHFS(ShareShrinkBase, manager.BaseShareCEPHFSTest):
+ protocol = "cephfs"
+
+ @decorators.idempotent_id('7fb324ed-7479-4bd9-b022-b3739dee9bcb')
+ @tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
+ def test_create_shrink_and_write_with_ceph_fuse_client(self):
+ self.mount_client = 'fuse'
+ super(TestShareShrinkCEPHFS, self).test_create_shrink_and_write()
+
+
+class TestShareShrinkNFSIPv6(TestShareShrinkNFS):
+ ip_version = 6
+
+
# NOTE(u_glide): this function is required to exclude ShareShrinkBase from
# executed test cases.
# See: https://docs.python.org/3/library/unittest.html#load-tests-protocol
diff --git a/manila_tempest_tests/utils.py b/manila_tempest_tests/utils.py
index e842a33..f30c0fc 100644
--- a/manila_tempest_tests/utils.py
+++ b/manila_tempest_tests/utils.py
@@ -13,10 +13,10 @@
# License for the specific language governing permissions and limitations
# under the License.
-from netaddr import ip
import random
import re
+from netaddr import ip
import six
from tempest import config
import testtools
diff --git a/playbooks/manila-tempest-plugin-standalone/post.yaml b/playbooks/manila-tempest-plugin-standalone/post.yaml
new file mode 100644
index 0000000..6e0bcad
--- /dev/null
+++ b/playbooks/manila-tempest-plugin-standalone/post.yaml
@@ -0,0 +1,6 @@
+- hosts: tempest
+ become: true
+ roles:
+ - role: fetch-subunit-output
+ zuul_work_dir: '{{ devstack_base_dir }}/tempest'
+ - role: process-stackviz
diff --git a/playbooks/manila-tempest-plugin-standalone/run.yaml b/playbooks/manila-tempest-plugin-standalone/run.yaml
new file mode 100644
index 0000000..8df9205
--- /dev/null
+++ b/playbooks/manila-tempest-plugin-standalone/run.yaml
@@ -0,0 +1,11 @@
+- hosts: all
+ roles:
+ - orchestrate-devstack
+
+- hosts: tempest
+ roles:
+ - setup-tempest-run-dir
+ - set-tempest-config
+ - setup-tempest-data-dir
+ - acl-devstack-files
+ - run-tempest
diff --git a/roles/set-tempest-config/README.rst b/roles/set-tempest-config/README.rst
new file mode 100644
index 0000000..9402d3c
--- /dev/null
+++ b/roles/set-tempest-config/README.rst
@@ -0,0 +1,19 @@
+set-tempest-config
+==================
+
+This is a workaround for the `merge_config_file <https://opendev
+.org/openstack/devstack/src/commit/76d7d7c90c3979c72404fddd31ee884c8bfdb1ec
+/inc/meta-config#L82>`_ routine that doesn't working correctly on jobs based on
+the "devstack-minimal" profile.
+
+**Role Variables**
+
+.. zuul:rolevar:: devstack_base_dir
+ :default: /opt/stack
+
+ The devstack base directory.
+
+.. zuul:rolevar:: devstack_local_conf_path
+ :default: "{{ devstack_base_dir }}/devstack/local.conf"
+
+ Where to find the local.conf file
diff --git a/roles/set-tempest-config/defaults/main.yml b/roles/set-tempest-config/defaults/main.yml
new file mode 100644
index 0000000..5cc7ca6
--- /dev/null
+++ b/roles/set-tempest-config/defaults/main.yml
@@ -0,0 +1,3 @@
+---
+devstack_base_dir: /opt/stack
+devstack_local_conf_path: "{{ devstack_base_dir }}/devstack/local.conf"
diff --git a/roles/set-tempest-config/tasks/main.yml b/roles/set-tempest-config/tasks/main.yml
new file mode 100644
index 0000000..3572ff5
--- /dev/null
+++ b/roles/set-tempest-config/tasks/main.yml
@@ -0,0 +1,14 @@
+- name: Install required pip packages
+ pip:
+ name: devstack-tools
+ state: "latest"
+ virtualenv: /var/tmp/venv
+
+- name: Copy tempest config
+ shell: >-
+ . /var/tmp/venv/bin/activate && \
+ dsconf extract {{ devstack_local_conf_path }} \
+ test-config \
+ '$TEMPEST_CONFIG' \
+ {{ devstack_base_dir }}/tempest/etc/tempest.conf
+ become: yes
diff --git a/test-requirements.txt b/test-requirements.txt
index f230fa9..cf025c3 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -13,3 +13,4 @@
openstackdocstheme>=1.31.2 # Apache-2.0
# releasenotes
reno>=2.5.0 # Apache-2.0
+flake8-import-order
diff --git a/tox.ini b/tox.ini
index a185fab..da879bf 100644
--- a/tox.ini
+++ b/tox.ini
@@ -20,7 +20,12 @@
# commands = python setup.py test --slowest --testr-args='{posargs}'
[testenv:pep8]
-commands = flake8 {posargs}
+commands =
+ flake8 {posargs}
+ check-uuid --package manila_tempest_tests
+
+[testenv:uuidgen]
+commands = check-uuid --fix --package manila_tempest_tests
[testenv:venv]
commands = {posargs}
@@ -43,3 +48,5 @@
ignore = E123,E125,W503,W504
builtins = _
exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,build
+import-order-style = pep8
+application-import-names = manila_tempest_tests
diff --git a/zuul.d/manila-tempest-jobs.yaml b/zuul.d/manila-tempest-jobs.yaml
index e474ecd..4dc7e55 100644
--- a/zuul.d/manila-tempest-jobs.yaml
+++ b/zuul.d/manila-tempest-jobs.yaml
@@ -39,12 +39,14 @@
tls-proxy: true
devstack_localrc:
USE_PYTHON3: true
- TEMPEST_USE_TEST_ACCOUNTS: true
MANILA_USE_DOWNGRADE_MIGRATIONS: true
MANILA_INSTALL_TEMPEST_PLUGIN_SYSTEMWIDE: false
MANILA_ALLOW_NAS_SERVER_PORTS_ON_HOST: true
MANILA_DEFAULT_SHARE_TYPE_EXTRA_SPECS: 'snapshot_support=True create_share_from_snapshot_support=True'
MANILA_CONFIGURE_DEFAULT_TYPES: true
+ MANILA_SHARE_MIGRATION_PERIOD_TASK_INTERVAL: 1
+ MANILA_SERVER_MIGRATION_PERIOD_TASK_INTERVAL: 10
+ MANILA_REPLICA_STATE_UPDATE_INTERVAL: 10
- job:
@@ -60,9 +62,68 @@
vars: *manila-tempest-base-vars
- job:
+ name: manila-tempest-plugin-standalone-base
+ abstract: true
+ description: |
+ Base job for running a minimal devstack with tempest based manila jobs.
+ timeout: 3600
+ parent: devstack-minimal
+ irrelevant-files: *irrelevant-files
+ roles:
+ - zuul: opendev.org/openstack/devstack
+ - zuul: opendev.org/openstack/tempest
+ required-projects:
+ - openstack/keystone
+ - openstack/manila
+ - openstack/manila-tempest-plugin
+ - openstack/python-manilaclient
+ - openstack/tempest
+ run: playbooks/manila-tempest-plugin-standalone/run.yaml
+ post-run: playbooks/manila-tempest-plugin-standalone/post.yaml
+ vars:
+ tox_envlist: all
+ tempest_test_regex: manila_tempest_tests.tests.api
+ tempest_concurrency: 16
+ tempest_plugins:
+ - manila-tempest-plugin
+ devstack_plugins:
+ manila: https://opendev.org/openstack/manila
+ manila-tempest-plugin: https://opendev.org/openstack/manila-tempest-plugin
+ test_results_stage_name: test_results
+ zuul_copy_output:
+ '{{ devstack_base_dir }}/tempest/etc/tempest.conf': logs
+ '{{ devstack_base_dir }}/tempest/etc/accounts.yaml': logs
+ '{{ devstack_base_dir }}/tempest/tempest.log': logs
+ '{{ stage_dir }}/{{ test_results_stage_name }}.subunit': logs
+ '{{ stage_dir }}/{{ test_results_stage_name }}.html': logs
+ '{{ stage_dir }}/stackviz': logs
+ extensions_to_txt:
+ conf: true
+ log: true
+ yaml: true
+ yml: true
+ devstack_localrc:
+ USE_PYTHON3: true
+ MANILA_INSTALL_TEMPEST_PLUGIN_SYSTEMWIDE: false
+ MANILA_SERVICE_IMAGE_ENABLED: false
+ MANILA_SHARE_MIGRATION_PERIOD_TASK_INTERVAL: 1
+ MANILA_SERVER_MIGRATION_PERIOD_TASK_INTERVAL: 10
+ MANILA_REPLICA_STATE_UPDATE_INTERVAL: 10
+ devstack_services:
+ tls-proxy: true
+ key: true
+ tempest: true
+
+- job:
name: manila-tempest-plugin-zfsonlinux
description: Test ZFSOnLinux multibackend (DHSS=False) with postgresql db
parent: manila-tempest-plugin-base
+ # TODO(gmann): Remove the below nodeset setting to Bionic once
+ # https://bugs.launchpad.net/manila/+bug/1896672 is fixed
+ # Once nodeset is removed form here then devstack base job
+ # will automatically run this job on Ubuntu Focal nodeset from
+ # Victoria gate onwards.
+ nodeset: openstack-single-node-bionic
vars:
tempest_test_regex: '(^manila_tempest_tests.tests)(?=.*\[.*\bbackend\b.*\])'
devstack_localrc:
@@ -110,6 +171,12 @@
Test LVM multibackend (DHSS=False) in a 4+6 (dual-stack) devstack
environment with IPv6 control plane endpoints.
parent: manila-tempest-plugin-ipv6-base
+ # TODO(gmann): Remove the below nodeset setting to Bionic once
+ # https://bugs.launchpad.net/manila/+bug/1896672 is fixed
+ # Once nodeset is removed form here then devstack base job
+ # will automatically run this job on Ubuntu Focal nodeset from
+ # Victoria gate onwards.
+ nodeset: openstack-single-node-bionic
required-projects:
- openstack/neutron-dynamic-routing
vars:
@@ -151,7 +218,7 @@
- job:
name: manila-tempest-plugin-container
description: |
- Test the container driver multibackend (DHSS=False) with CIFS
+ Test the container driver multibackend (DHSS=True) with CIFS
and postgresql db. API only, in a minimal devstack
parent: manila-tempest-plugin-base
vars:
@@ -169,6 +236,7 @@
SHARE_BACKING_FILE_SIZE: 64000M
MANILA_CONFIGURE_DEFAULT_TYPES: false
MANILA_DEFAULT_SHARE_TYPE_EXTRA_SPECS: 'snapshot_support=false'
+ TEMPEST_USE_TEST_ACCOUNTS: true
devstack_services:
mysql: false
postgresql: true
@@ -187,3 +255,329 @@
multitenancy_enabled: true
backend_names: LONDON,PARIS
multi_backend: true
+ run_share_server_migration_tests: true
+
+- job:
+ name: manila-tempest-plugin-generic
+ description: |
+ Test the generic driver multibackend (DHSS=True) with NFS and CIFS
+ parent: manila-tempest-plugin-base
+ # TODO(gmann): Remove the below nodeset setting to Bionic once
+ # https://bugs.launchpad.net/manila/+bug/1896672 is fixed
+ # Once nodeset is removed form here then devstack base job
+ # will automatically run this job on Ubuntu Focal nodeset from
+ # Victoria gate onwards.
+ nodeset: openstack-single-node-bionic
+ vars:
+ tempest_test_regex: '(^manila_tempest_tests.tests)(?=.*\[.*\bbackend\b.*\])'
+ # The generic driver uses nova VMs as share servers; running with a
+ # high concurrency could starve the driver of RAM/Disk/CPUs to
+ # function properly in a small single node devstack VM.
+ tempest_concurrency: 2
+ devstack_localrc:
+ VOLUME_BACKING_FILE_SIZE: 24G
+ SHARE_DRIVER: manila.share.drivers.generic.GenericShareDriver
+ MANILA_ENABLED_BACKENDS: london,paris
+ MANILA_BACKEND1_CONFIG_GROUP_NAME: london
+ MANILA_BACKEND2_CONFIG_GROUP_NAME: paris
+ MANILA_SHARE_BACKEND1_NAME: LONDON
+ MANILA_SHARE_BACKEND2_NAME: PARIS
+ MANILA_OPTGROUP_london_driver_handles_share_servers: true
+ MANILA_OPTGROUP_paris_driver_handles_share_servers: true
+ MANILA_USE_SERVICE_INSTANCE_PASSWORD: true
+ MANILA_DEFAULT_SHARE_TYPE_EXTRA_SPECS: 'snapshot_support=True create_share_from_snapshot_support=True'
+ TEMPEST_USE_TEST_ACCOUNTS: true
+ devstack_services:
+ cinder: true
+ devstack_local_conf:
+ test-config:
+ $TEMPEST_CONFIG:
+ share:
+ default_share_type_name: default
+ run_share_group_tests: false
+ multitenancy_enabled: true
+ suppress_errors_in_cleanup: true
+ share_creation_retry_number: 2
+ backend_names: LONDON,PARIS
+ multi_backend: true
+ image_password: manila
+
+- job:
+ name: manila-tempest-plugin-cephfs-native
+ description: Test CephFS Native (DHSS=False)
+ parent: manila-tempest-plugin-base
+ required-projects:
+ - openstack/devstack-plugin-ceph
+ vars:
+ devstack_plugins:
+ devstack-plugin-ceph: https://opendev.org/openstack/devstack-plugin-ceph
+ tempest_test_regex: manila_tempest_tests.tests
+ devstack_localrc:
+ VOLUME_BACKING_FILE_SIZE: 60GB
+ SHARE_DRIVER: manila.share.drivers.cephfs.driver.CephFSDriver
+ MANILA_ENABLED_BACKENDS: cephfsnative
+ ENABLED_SHARE_PROTOCOLS: CEPHFS
+ MANILA_DEFAULT_SHARE_TYPE_EXTRA_SPECS: 'snapshot_support=True'
+ MANILA_OPTGROUP_cephfsnative_share_driver: manila.share.drivers.cephfs.driver.CephFSDriver
+ MANILA_OPTGROUP_cephfsnative_driver_handles_share_servers: false
+ MANILA_OPTGROUP_cephfsnative_cephfs_conf_path: /etc/ceph/ceph.conf
+ MANILA_OPTGROUP_cephfsnative_cephfs_auth_id: manila
+ # NOTE(gouthamr): The following need to use the latest images, however, there's a bug
+ # with cephfs on Ubuntu 20.04 LTS: https://tracker.ceph.com/issues/47236
+ # the latest image is built as https://tarballs.opendev.org/openstack/manila-image-elements/images/manila-service-image-cephfs-master.qcow2
+ MANILA_SERVICE_IMAGE_URL: https://tarballs.opendev.org/openstack/manila-image-elements/images/manila-service-image-cephfs-1.3.0-58-g2859569.qcow2
+ MANILA_SERVICE_IMAGE_NAME: manila-service-image-cephfs-1.3.0-58-g2859569
+ devstack_local_conf:
+ test-config:
+ $TEMPEST_CONFIG:
+ share:
+ default_share_type_name: default
+ enable_cephx_rules_for_protocols: cephfs
+ run_share_group_tests: false
+ multitenancy_enabled: false
+ capability_create_share_from_snapshot_support: false
+ suppress_errors_in_cleanup: true
+ backend_names: CEPHFSNATIVE
+ capability_storage_protocol: CEPHFS
+ enable_protocols: cephfs
+ image_password: manila
+
+
+- job:
+ name: manila-tempest-plugin-cephfs-nfs
+ description: Test CephFS NFS (DHSS=False)
+ parent: manila-tempest-plugin-base
+ # TODO(gmann): Remove the below nodeset setting to Bionic once
+ # https://bugs.launchpad.net/manila/+bug/1896672 is fixed
+ # Once nodeset is removed form here then devstack base job
+ # will automatically run this job on Ubuntu Focal nodeset from
+ # Victoria gate onwards.
+ nodeset: openstack-single-node-bionic
+ required-projects:
+ - openstack/devstack-plugin-ceph
+ - openstack/neutron-dynamic-routing
+ vars:
+ devstack_plugins:
+ devstack-plugin-ceph: https://opendev.org/openstack/devstack-plugin-ceph
+ neutron-dynamic-routing: https://opendev.org/openstack/neutron-dynamic-routing
+ devstack_localrc:
+ VOLUME_BACKING_FILE_SIZE: 60GB
+ SHARE_DRIVER: manila.share.drivers.cephfs.driver.CephFSDriver
+ MANILA_ENABLED_BACKENDS: cephfsnfs
+ ENABLED_SHARE_PROTOCOLS: NFS
+ MANILA_DEFAULT_SHARE_TYPE_EXTRA_SPECS: 'snapshot_support=True'
+ MANILA_SERVICE_IMAGE_ENABLED: true
+ MANILA_OPTGROUP_cephfsnfs_share_driver: manila.share.drivers.cephfs.driver.CephFSDriver
+ MANILA_OPTGROUP_cephfsnfs_driver_handles_share_servers: false
+ MANILA_OPTGROUP_cephfsnfs_cephfs_protocol_helper_type: NFS
+ MANILA_OPTGROUP_cephfsnfs_cephfs_conf_path: /etc/ceph/ceph.conf
+ MANILA_OPTGROUP_cephfsnfs_cephfs_auth_id: manila
+ MANILA_CEPH_DRIVER: cephfsnfs
+ MANILA_SETUP_IPV6: true
+ NEUTRON_CREATE_INITIAL_NETWORKS: false
+ MANILA_RESTORE_IPV6_DEFAULT_ROUTE: false
+ devstack_local_conf:
+ test-config:
+ $TEMPEST_CONFIG:
+ share:
+ default_share_type_name: default
+ run_ipv6_tests: true
+ run_share_group_tests: false
+ multitenancy_enabled: false
+ suppress_errors_in_cleanup: true
+ backend_names: CEPHFSNFS
+ enable_protocols: nfs
+ capability_storage_protocol: NFS
+ capability_create_share_from_snapshot_support: false
+ image_password: manila
+
+- job:
+ name: manila-tempest-plugin-dummy-no-dhss
+ description: Test the Dummy driver with DHSS=False
+ parent: manila-tempest-plugin-standalone-base
+ vars:
+ devstack_localrc:
+ SHARE_DRIVER: manila.tests.share.drivers.dummy.DummyDriver
+ MANILA_CONFIGURE_GROUPS: alpha,beta,gamma,membernet
+ MANILA_DEFAULT_SHARE_TYPE_EXTRA_SPECS: 'snapshot_support=True create_share_from_snapshot_support=True revert_to_snapshot_support=True mount_snapshot_support=True'
+ MANILA_ENABLED_BACKENDS: alpha,beta,gamma
+ MANILA_OPTGROUP_alpha_driver_handles_share_servers: false
+ MANILA_OPTGROUP_alpha_replication_domain: DUMMY_DOMAIN
+ MANILA_OPTGROUP_alpha_share_backend_name: ALPHA
+ MANILA_OPTGROUP_alpha_share_driver: manila.tests.share.drivers.dummy.DummyDriver
+ MANILA_OPTGROUP_beta_driver_handles_share_servers: false
+ MANILA_OPTGROUP_beta_replication_domain: DUMMY_DOMAIN
+ MANILA_OPTGROUP_beta_share_backend_name: BETA
+ MANILA_OPTGROUP_beta_share_driver: manila.tests.share.drivers.dummy.DummyDriver
+ # With below opts we'll enable a DHSS=True back-end solely for
+ # for the migration test case "test_migration_opposite_driver_modes"
+ MANILA_OPTGROUP_gamma_driver_handles_share_servers: true
+ MANILA_OPTGROUP_gamma_network_config_group: membernet
+ MANILA_OPTGROUP_gamma_share_backend_name: GAMMA
+ MANILA_OPTGROUP_gamma_share_driver: manila.tests.share.drivers.dummy.DummyDriver
+ MANILA_OPTGROUP_gamma_admin_network_config_group: membernet
+ MANILA_OPTGROUP_membernet_network_api_class: manila.network.standalone_network_plugin.StandaloneNetworkPlugin
+ MANILA_OPTGROUP_membernet_network_plugin_ipv4_enabled: true
+ MANILA_OPTGROUP_membernet_standalone_network_plugin_allowed_ip_ranges: 10.0.0.10-10.0.0.209
+ MANILA_OPTGROUP_membernet_standalone_network_plugin_gateway: 10.0.0.1
+ MANILA_OPTGROUP_membernet_standalone_network_plugin_mask: 24
+ MANILA_OPTGROUP_membernet_standalone_network_plugin_network_type: vlan
+ MANILA_OPTGROUP_membernet_standalone_network_plugin_segmentation_id: 1010
+ devstack_local_conf:
+ test-config:
+ "$TEMPEST_CONFIG":
+ share:
+ backend_names: ALPHA,BETA
+ backend_replication_type: readable
+ build_timeout: 180
+ capability_sg_consistent_snapshot_support: pool
+ enable_ip_rules_for_protocols: nfs
+ enable_ro_access_level_for_protocols: nfs,cifs
+ enable_user_rules_for_protocols: cifs
+ multi_backend: true
+ multitenancy_enabled: false
+ run_driver_assisted_migration_tests: true
+ run_manage_unmanage_snapshot_tests: true
+ run_manage_unmanage_tests: true
+ run_migration_with_preserve_snapshots_tests: true
+ run_mount_snapshot_tests: true
+ run_replication_tests: true
+ run_revert_to_snapshot_tests: true
+ # for migration test case "test_migration_opposite_driver_modes"
+ create_networks_when_multitenancy_enabled: false
+
+- job:
+ name: manila-tempest-plugin-dummy-dhss
+ description: Test the Dummy driver with DHSS=True
+ parent: manila-tempest-plugin-standalone-base
+ vars:
+ devstack_localrc:
+ SHARE_DRIVER: manila.tests.share.drivers.dummy.DummyDriver
+ MANILA_CONFIGURE_GROUPS: alpha,beta,gamma,membernet,adminnet
+ MANILA_DEFAULT_SHARE_TYPE_EXTRA_SPECS: 'snapshot_support=True create_share_from_snapshot_support=True revert_to_snapshot_support=True mount_snapshot_support=True'
+ MANILA_ENABLED_BACKENDS: alpha,beta
+ MANILA_OPTGROUP_DEFAULT_quota_share_networks: 50
+ MANILA_OPTGROUP_adminnet_network_api_class: manila.network.standalone_network_plugin.StandaloneNetworkPlugin
+ MANILA_OPTGROUP_adminnet_network_plugin_ipv4_enabled: true
+ MANILA_OPTGROUP_adminnet_standalone_network_plugin_allowed_ip_ranges: 11.0.0.10-11.0.0.19,11.0.0.30-11.0.0.39,11.0.0.50-11.0.0.199
+ MANILA_OPTGROUP_adminnet_standalone_network_plugin_gateway: 11.0.0.1
+ MANILA_OPTGROUP_adminnet_standalone_network_plugin_mask: 24
+ MANILA_OPTGROUP_adminnet_standalone_network_plugin_network_type: vlan
+ MANILA_OPTGROUP_adminnet_standalone_network_plugin_segmentation_id: 1011
+ MANILA_OPTGROUP_alpha_admin_network_config_group: adminnet
+ MANILA_OPTGROUP_alpha_driver_handles_share_servers: true
+ MANILA_OPTGROUP_alpha_network_config_group: membernet
+ MANILA_OPTGROUP_alpha_replication_domain: DUMMY_DOMAIN
+ MANILA_OPTGROUP_alpha_share_backend_name: ALPHA
+ MANILA_OPTGROUP_alpha_share_driver: manila.tests.share.drivers.dummy.DummyDriver
+ MANILA_OPTGROUP_beta_admin_network_config_group: adminnet
+ MANILA_OPTGROUP_beta_driver_handles_share_servers: true
+ MANILA_OPTGROUP_beta_network_config_group: membernet
+ MANILA_OPTGROUP_beta_replication_domain: DUMMY_DOMAIN
+ MANILA_OPTGROUP_beta_share_backend_name: BETA
+ MANILA_OPTGROUP_beta_share_driver: manila.tests.share.drivers.dummy.DummyDriver
+ MANILA_OPTGROUP_membernet_network_api_class: manila.network.standalone_network_plugin.StandaloneNetworkPlugin
+ MANILA_OPTGROUP_membernet_network_plugin_ipv4_enabled: true
+ MANILA_OPTGROUP_membernet_standalone_network_plugin_allowed_ip_ranges: 10.0.0.10-10.0.0.209
+ MANILA_OPTGROUP_membernet_standalone_network_plugin_gateway: 10.0.0.1
+ MANILA_OPTGROUP_membernet_standalone_network_plugin_mask: 24
+ MANILA_OPTGROUP_membernet_standalone_network_plugin_network_type: vlan
+ MANILA_OPTGROUP_membernet_standalone_network_plugin_segmentation_id: 1010
+ # With below opts we'll enable a DHSS=False back-end solely for
+ # for the migration test case "test_migration_opposite_driver_modes"
+ MANILA_OPTGROUP_gamma_driver_handles_share_servers: false
+ MANILA_OPTGROUP_gamma_share_backend_name: GAMMA
+ MANILA_OPTGROUP_gamma_share_driver: manila.tests.share.drivers.dummy.DummyDriver
+ devstack_local_conf:
+ test-config:
+ "$TEMPEST_CONFIG":
+ share:
+ backend_names: ALPHA,BETA
+ backend_replication_type: readable
+ build_timeout: 180
+ capability_sg_consistent_snapshot_support: pool
+ create_networks_when_multitenancy_enabled: false
+ enable_ip_rules_for_protocols: nfs
+ enable_ro_access_level_for_protocols: nfs,cifs
+ enable_user_rules_for_protocols: cifs
+ multi_backend: true
+ multitenancy_enabled: true
+ run_driver_assisted_migration_tests: true
+ run_manage_unmanage_snapshot_tests: true
+ run_manage_unmanage_tests: true
+ run_migration_with_preserve_snapshots_tests: true
+ run_mount_snapshot_tests: true
+ run_replication_tests: true
+ run_revert_to_snapshot_tests: true
+ run_share_server_migration_tests: true
+
+- job:
+ name: manila-tempest-plugin-glusterfs-native
+ description: |
+ Test the GlusterFS driver (DHSS=False) with the native GlusterFS protocol
+ parent: manila-tempest-plugin-standalone-base
+ required-projects:
+ - x/devstack-plugin-glusterfs
+ vars:
+ tempest_concurrency: 8
+ devstack_plugins:
+ devstack-plugin-glusterfs: https://opendev.org/x/devstack-plugin-glusterfs
+ devstack_localrc:
+ CONFIGURE_GLUSTERFS_MANILA: true
+ GLUSTERFS_MANILA_DRIVER_TYPE: glusterfs-native
+ MANILA_DEFAULT_SHARE_TYPE_EXTRA_SPECS: 'snapshot_support=True create_share_from_snapshot_support=True'
+ devstack_local_conf:
+ test-config:
+ $TEMPEST_CONFIG:
+ share:
+ run_share_group_tests: false
+ run_snapshot_tests: false
+ multitenancy_enabled: false
+ run_shrink_tests: false
+ run_extend_tests: false
+ multi_backend: false
+ suppress_errors_in_cleanup: True
+ share_creation_retry_number: 2
+ backend_names: GLUSTERNATIVE
+ enable_cert_rules_for_protocols: glusterfs
+ capability_storage_protocol: glusterfs
+ enable_protocols: glusterfs
+
+- job:
+ name: manila-tempest-plugin-glusterfs-nfs
+ description: |
+ Test the GlusterFS driver (DHSS=False) with the native NFS protocol
+ parent: manila-tempest-plugin-standalone-base
+ # TODO(gmann): Remove the below nodeset setting to Bionic once
+ # https://bugs.launchpad.net/manila/+bug/1896672 is fixed
+ # Once nodeset is removed form here then devstack base job
+ # will automatically run this job on Ubuntu Focal nodeset from
+ # Victoria gate onwards.
+ nodeset: openstack-single-node-bionic
+ required-projects:
+ - x/devstack-plugin-glusterfs
+ vars:
+ tempest_concurrency: 8
+ devstack_plugins:
+ devstack-plugin-glusterfs: https://opendev.org/x/devstack-plugin-glusterfs
+ devstack_localrc:
+ CONFIGURE_GLUSTERFS_MANILA: true
+ GLUSTERFS_MANILA_DRIVER_TYPE: glusterfs-nfs
+ MANILA_DEFAULT_SHARE_TYPE_EXTRA_SPECS: 'snapshot_support=False'
+ devstack_local_conf:
+ test-config:
+ $TEMPEST_CONFIG:
+ share:
+ run_share_group_tests: false
+ run_snapshot_tests: false
+ multitenancy_enabled: False
+ run_shrink_tests: true
+ multi_backend: false
+ suppress_errors_in_cleanup: True
+ share_creation_retry_number: 2
+ backend_names: GLUSTERFS
+ enable_ip_rules_for_protocols: nfs
+ capability_storage_protocol: NFS
+ enable_protocols: nfs
+ # read-only access rules not supported
+ enable_ro_access_level_for_protocols: ""
diff --git a/zuul.d/project.yaml b/zuul.d/project.yaml
index 899e3cc..d49b8fb 100644
--- a/zuul.d/project.yaml
+++ b/zuul.d/project.yaml
@@ -4,36 +4,28 @@
- tempest-plugin-jobs
check:
jobs:
+ - manila-tempest-plugin-dummy-no-dhss
+ - manila-tempest-plugin-dummy-dhss
- manila-tempest-plugin-lvm
- - manila-tempest-minimal-dsvm-dummy
- manila-tempest-plugin-zfsonlinux:
voting: false
+ - manila-tempest-plugin-cephfs-native:
+ voting: false
+ - manila-tempest-plugin-cephfs-nfs:
+ voting: false
- manila-tempest-plugin-container:
voting: false
- - manila-tempest-dsvm-mysql-generic:
+ - manila-tempest-plugin-generic:
voting: false
- - manila-tempest-dsvm-postgres-generic-singlebackend:
- voting: false
- - manila-tempest-dsvm-generic-no-share-servers:
- voting: false
- - manila-tempest-dsvm-scenario:
- voting: false
- - manila-tempest-minimal-dsvm-cephfs-native:
- voting: false
- - manila-tempest-minimal-dsvm-cephfs-nfs:
+ - manila-tempest-plugin-glusterfs-nfs:
voting: false
gate:
queue: manila
jobs:
- - manila-tempest-minimal-dsvm-dummy
+ - manila-tempest-plugin-dummy-no-dhss
+ - manila-tempest-plugin-dummy-dhss
- manila-tempest-plugin-lvm
experimental:
jobs:
- - manila-tempest-dsvm-glusterfs-nfs:
- voting: false
- - manila-tempest-dsvm-glusterfs-native:
- voting: false
- - manila-tempest-dsvm-glusterfs-nfs-heketi:
- voting: false
- - manila-tempest-dsvm-glusterfs-native-heketi:
+ - manila-tempest-plugin-glusterfs-native:
voting: false