Merge "Allow share server migration with replica"
diff --git a/manila_tempest_tests/config.py b/manila_tempest_tests/config.py
index 03dfafb..4afa4e7 100644
--- a/manila_tempest_tests/config.py
+++ b/manila_tempest_tests/config.py
@@ -40,7 +40,7 @@
"This value is only used to validate the versions "
"response from Manila."),
cfg.StrOpt("max_api_microversion",
- default="2.85",
+ default="2.88",
help="The maximum api microversion is configured to be the "
"value of the latest microversion supported by Manila."),
cfg.StrOpt("region",
@@ -108,6 +108,12 @@
cfg.ListOpt("enable_ro_access_level_for_protocols",
default=["nfs", ],
help="List of protocols to run tests with ro access level."),
+ cfg.ListOpt("nfs_versions",
+ default=["4", ],
+ help="Specifies the NFS protocol version to use when mounting "
+ "an NFS share. Set to '3' for NFSv3, and '4' or '4.1' "
+ "for NFSv4. Leave it blank to use the default version."),
+
# Capabilities
cfg.StrOpt("capability_storage_protocol",
diff --git a/manila_tempest_tests/services/share/json/shares_client.py b/manila_tempest_tests/services/share/json/shares_client.py
index fb03afc..63a634c 100644
--- a/manila_tempest_tests/services/share/json/shares_client.py
+++ b/manila_tempest_tests/services/share/json/shares_client.py
@@ -304,37 +304,41 @@
return True
else:
return self._is_resource_deleted(
- self.get_share, kwargs.get("share_id"))
+ self.get_share, kwargs.get("share_id"), "share")
elif "snapshot_id" in kwargs:
return self._is_resource_deleted(
- self.get_snapshot, kwargs.get("snapshot_id"))
+ self.get_snapshot, kwargs.get("snapshot_id"), "snapshot")
elif "sn_id" in kwargs:
return self._is_resource_deleted(
- self.get_share_network, kwargs.get("sn_id"))
+ self.get_share_network, kwargs.get("sn_id"), "share_network")
elif "ss_id" in kwargs:
return self._is_resource_deleted(
- self.get_security_service, kwargs.get("ss_id"))
+ self.get_security_service, kwargs.get("ss_id"),
+ "security_service")
elif "vt_id" in kwargs:
return self._is_resource_deleted(
- self.get_volume_type, kwargs.get("vt_id"))
+ self.get_volume_type, kwargs.get("vt_id"), "volume_type")
elif "st_id" in kwargs:
return self._is_resource_deleted(
- self.get_share_type, kwargs.get("st_id"))
+ self.get_share_type, kwargs.get("st_id"), "share_type")
elif "server_id" in kwargs:
return self._is_resource_deleted(
- self.show_share_server, kwargs.get("server_id"))
+ self.show_share_server, kwargs.get("server_id"),
+ "share_server")
elif "backup_id" in kwargs:
return self._is_resource_deleted(
- self.get_share_backup, kwargs.get("backup_id"))
+ self.get_share_backup, kwargs.get("backup_id"),
+ "share_backup")
else:
raise share_exceptions.InvalidResource(
message=str(kwargs))
- def _is_resource_deleted(self, func, res_id, **kwargs):
+ def _is_resource_deleted(self, func, res_id, resource_name, **kwargs):
try:
- res = func(res_id, **kwargs)
+ res = func(res_id, **kwargs)[resource_name]
except exceptions.NotFound:
return True
+
if res.get('status') in ['error_deleting', 'error']:
# Resource has "error_deleting" status and can not be deleted.
resource_type = func.__name__.split('_', 1)[-1]
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 e3a022e..a9ab199 100644
--- a/manila_tempest_tests/services/share/v2/json/shares_client.py
+++ b/manila_tempest_tests/services/share/v2/json/shares_client.py
@@ -208,29 +208,33 @@
"""
if "share_instance_id" in kwargs:
return self._is_resource_deleted(
- self.get_share_instance, kwargs.get("share_instance_id"))
+ self.get_share_instance, kwargs.get("share_instance_id"),
+ "share_instance")
elif "share_group_id" in kwargs:
return self._is_resource_deleted(
- self.get_share_group, kwargs.get("share_group_id"))
+ self.get_share_group, kwargs.get("share_group_id"),
+ "share_group")
elif "share_group_snapshot_id" in kwargs:
return self._is_resource_deleted(
self.get_share_group_snapshot,
- kwargs.get("share_group_snapshot_id"))
+ kwargs.get("share_group_snapshot_id"), "share_group_snapshot")
elif "share_group_type_id" in kwargs:
return self._is_resource_deleted(
- self.get_share_group_type, kwargs.get("share_group_type_id"))
+ self.get_share_group_type, kwargs.get("share_group_type_id"),
+ "share_group_type")
elif "replica_id" in kwargs:
return self._is_resource_deleted(
- self.get_share_replica, kwargs.get("replica_id"))
+ self.get_share_replica, kwargs.get("replica_id"),
+ "share_replica")
elif "message_id" in kwargs:
return self._is_resource_deleted(
- self.get_message, kwargs.get("message_id"))
+ self.get_message, kwargs.get("message_id"), "message")
elif "share_network_subnet_id" in kwargs:
subnet_kwargs = {
- "sn_id": kwargs["extra_params"]["share_network_id"]}
+ "share_network_id": kwargs["sn_id"]}
return self._is_resource_deleted(
self.get_subnet, kwargs.get("share_network_subnet_id"),
- **subnet_kwargs
+ "share_network_subnet", **subnet_kwargs
)
else:
return super(SharesV2Client, self).is_resource_deleted(
@@ -899,6 +903,15 @@
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
+ def update_access_rule(self, access_id, access_level,
+ version=LATEST_MICROVERSION):
+ url = 'share-access-rules/%s' % access_id
+ body = {'update_access': {"access_level": access_level}}
+ resp, body = self.put(url, json.dumps(body), version=version)
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
def update_access_metadata(self, access_id, metadata,
version=LATEST_MICROVERSION):
url = 'share-access-rules/%s/metadata' % access_id
diff --git a/manila_tempest_tests/tests/api/base.py b/manila_tempest_tests/tests/api/base.py
old mode 100755
new mode 100644
index 5afe11c..9583de8
--- a/manila_tempest_tests/tests/api/base.py
+++ b/manila_tempest_tests/tests/api/base.py
@@ -898,69 +898,80 @@
res["deleted"] = False
if "client" not in res.keys():
res["client"] = cls.shares_client
- if not res["deleted"]:
- res_id = res['id']
- client = res["client"]
- with handle_cleanup_exceptions():
- if res["type"] == "share":
- cls.clear_share_replicas(res_id)
- share_group_id = res.get('share_group_id')
- if share_group_id:
- params = {'share_group_id': share_group_id}
- client.delete_share(res_id, params=params)
+ if not (res["deleted"]):
+ try:
+ res_id = res['id']
+ client = res["client"]
+ with handle_cleanup_exceptions():
+ if res["type"] == "share":
+ cls.clear_share_replicas(res_id)
+ share_group_id = res.get('share_group_id')
+ if share_group_id:
+ params = {'share_group_id': share_group_id}
+ client.delete_share(res_id, params=params)
+ else:
+ client.delete_share(res_id)
+ client.wait_for_resource_deletion(share_id=res_id)
+ elif res["type"] == "snapshot":
+ client.delete_snapshot(res_id)
+ client.wait_for_resource_deletion(
+ snapshot_id=res_id)
+ elif (res["type"] == "share_network" and
+ 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)
+ elif res["type"] == "share_type":
+ client.delete_share_type(res_id)
+ client.wait_for_resource_deletion(st_id=res_id)
+ elif res["type"] == "share_group":
+ client.delete_share_group(res_id)
+ client.wait_for_resource_deletion(
+ share_group_id=res_id)
+ elif res["type"] == "share_group_type":
+ client.delete_share_group_type(res_id)
+ client.wait_for_resource_deletion(
+ share_group_type_id=res_id)
+ elif res["type"] == "share_group_snapshot":
+ client.delete_share_group_snapshot(res_id)
+ client.wait_for_resource_deletion(
+ share_group_snapshot_id=res_id)
+ elif res["type"] == "share_replica":
+ client.delete_share_replica(res_id)
+ client.wait_for_resource_deletion(
+ replica_id=res_id)
+ elif res["type"] == "share_backup":
+ client.delete_share_backup(res_id)
+ client.wait_for_resource_deletion(backup_id=res_id)
+ elif res["type"] == "share_network_subnet":
+ sn_id = res["extra_params"]["share_network_id"]
+ client.delete_subnet(sn_id, res_id)
+ 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)
+ elif res["type"] == "resource_lock":
+ client.delete_resource_lock(res_id)
else:
- client.delete_share(res_id)
- client.wait_for_resource_deletion(share_id=res_id)
- elif res["type"] == "snapshot":
- client.delete_snapshot(res_id)
- client.wait_for_resource_deletion(snapshot_id=res_id)
- elif (res["type"] == "share_network" and
- 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)
- elif res["type"] == "share_type":
- client.delete_share_type(res_id)
- client.wait_for_resource_deletion(st_id=res_id)
- elif res["type"] == "share_group":
- client.delete_share_group(res_id)
- client.wait_for_resource_deletion(
- share_group_id=res_id)
- elif res["type"] == "share_group_type":
- client.delete_share_group_type(res_id)
- client.wait_for_resource_deletion(
- share_group_type_id=res_id)
- elif res["type"] == "share_group_snapshot":
- client.delete_share_group_snapshot(res_id)
- client.wait_for_resource_deletion(
- share_group_snapshot_id=res_id)
- elif res["type"] == "share_replica":
- client.delete_share_replica(res_id)
- client.wait_for_resource_deletion(replica_id=res_id)
- elif res["type"] == "share_backup":
- client.delete_share_backup(res_id)
- client.wait_for_resource_deletion(backup_id=res_id)
- elif res["type"] == "share_network_subnet":
- sn_id = res["extra_params"]["share_network_id"]
- client.delete_subnet(sn_id, res_id)
- 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)
- elif res["type"] == "resource_lock":
- client.delete_resource_lock(res_id)
- else:
- LOG.warning("Provided unsupported resource type for "
- "cleanup '%s'. Skipping.", res["type"])
+ LOG.warning("Provided unsupported resource type "
+ "for cleanup '%s'. Skipping.",
+ res["type"])
+ except share_exceptions.ResourceReleaseFailed as e:
+ # Resource is on error deleting state, so we remove it from
+ # the list to delete, since it cannot be deleted anymore.
+ # It raises because the current cleanup class or method
+ # must fail.
+ res["deleted"] = True
+ raise e
res["deleted"] = True
# Useful assertions
@@ -1283,12 +1294,18 @@
cls.admin_project = cls.os_admin.auth_provider.auth_data[1]['project']
identity_clients = getattr(
cls.os_admin, 'identity_%s' % CONF.identity.auth_version)
- cls.os_admin.identity_client = identity_clients.IdentityClient()
- cls.os_admin.projects_client = identity_clients.ProjectsClient()
- cls.os_admin.users_client = identity_clients.UsersClient()
- cls.os_admin.roles_client = identity_clients.RolesClient()
+ endpoint_type = CONF.share.endpoint_type
+ cls.os_admin.identity_client = identity_clients.IdentityClient(
+ endpoint_type=endpoint_type)
+ cls.os_admin.projects_client = identity_clients.ProjectsClient(
+ endpoint_type=endpoint_type)
+ cls.os_admin.users_client = identity_clients.UsersClient(
+ endpoint_type=endpoint_type)
+ cls.os_admin.roles_client = identity_clients.RolesClient(
+ endpoint_type=endpoint_type)
cls.os_admin.domains_client = (
- cls.os_admin.identity_v3.DomainsClient() if
+ cls.os_admin.identity_v3.DomainsClient(
+ endpoint_type=endpoint_type) if
CONF.identity.auth_version == 'v3' else None)
cls.admin_project_member_client = cls.create_user_and_get_client(
project=cls.admin_project, add_member_role=True)
diff --git a/manila_tempest_tests/tests/api/test_metadata.py b/manila_tempest_tests/tests/api/test_metadata.py
index 862de50..be5b1cf 100644
--- a/manila_tempest_tests/tests/api/test_metadata.py
+++ b/manila_tempest_tests/tests/api/test_metadata.py
@@ -13,11 +13,14 @@
# License for the specific language governing permissions and limitations
# 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
+CONF = config.CONF
+
class SharesMetadataTest(base.BaseSharesMixedTest):
@@ -263,3 +266,35 @@
body_get = self.shares_v2_client.get_metadata(
self.share["id"])['metadata']
self.assertEqual(max_value, body_get["key"])
+
+
+class SharesMetadataCEPHFSTest(base.BaseSharesMixedTest):
+
+ protocol = "cephfs"
+
+ @classmethod
+ def resource_setup(cls):
+ super(SharesMetadataCEPHFSTest, cls).resource_setup()
+ # 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)
+
+ @classmethod
+ def skip_checks(cls):
+ super(SharesMetadataCEPHFSTest, cls).skip_checks()
+ if not (cls.protocol in CONF.share.enable_protocols):
+ msg = (
+ "CEPHFS filesystem metadata tests are disabled "
+ "for the %s protocol." % cls.protocol)
+ raise cls.skipException(msg)
+
+ @decorators.idempotent_id('58edc9c8-8b85-49aa-80aa-209fc8f40a13')
+ @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+ def test_cephfs_share_contains_mount_option(self):
+ body_get = self.shares_v2_client.get_metadata(
+ self.share["id"])['metadata']
+
+ self.assertIn("__mount_options", body_get)
+ self.assertIn("fs", body_get["__mount_options"])
diff --git a/manila_tempest_tests/tests/api/test_rules.py b/manila_tempest_tests/tests/api/test_rules.py
index 5f39852..99ac254 100644
--- a/manila_tempest_tests/tests/api/test_rules.py
+++ b/manila_tempest_tests/tests/api/test_rules.py
@@ -22,6 +22,7 @@
import testtools
from testtools import testcase as tc
+from manila_tempest_tests.common import waiters
from manila_tempest_tests.tests.api import base
from manila_tempest_tests import utils
@@ -62,6 +63,7 @@
self.share['id'])['access_list']
rule = [r for r in rules if r['id'] == rule['id']][0]
self.assertEqual("active", rule['state'])
+ return rule
@ddt.ddt
@@ -162,8 +164,23 @@
"RO access rule tests are disabled for NFS protocol.")
@ddt.data(*utils.deduplicate(['1.0', '2.9', '2.27', '2.28',
LATEST_MICROVERSION]))
- def test_create_delete_ro_access_rule(self, client_name):
- _create_delete_ro_access_rule(self, client_name)
+ def test_create_delete_ro_access_rule(self, version):
+ _create_delete_ro_access_rule(self, version)
+
+ @utils.skip_if_microversion_not_supported('2.88')
+ @decorators.idempotent_id('01940881-6f95-77f8-b47d-0941c4e6bafb')
+ @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+ @testtools.skipIf(
+ "nfs" not in CONF.share.enable_ro_access_level_for_protocols,
+ "RO access rule tests are disabled for NFS protocol.")
+ def test_update_access_rule(self):
+ rule = _create_delete_ro_access_rule(self, LATEST_MICROVERSION)
+ rule = self.shares_v2_client.update_access_rule(
+ access_id=rule['id'], access_level='rw')['access']
+ waiters.wait_for_resource_status(
+ self.shares_v2_client, self.share['id'], status='active',
+ resource_name='access_rule', rule_id=rule['id'])
+ self.assertEqual(rule['access_level'], 'rw')
@ddt.ddt
@@ -180,6 +197,18 @@
def test_create_delete_ro_access_rule(self, version):
_create_delete_ro_access_rule(self, version)
+ @utils.skip_if_microversion_not_supported('2.88')
+ @decorators.idempotent_id('02940881-6f95-77f8-b47d-0941c4e6bafb')
+ @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+ @testtools.skipIf(
+ "cifs" not in CONF.share.enable_ro_access_level_for_protocols,
+ "RO access rule tests are disabled for CIFS protocol.")
+ def test_update_access_rule(self):
+ super(
+ ShareIpRulesForCIFSTest,
+ self
+ ).test_update_access_rule()
+
@ddt.ddt
class ShareUserRulesForNFSTest(base.BaseSharesMixedTest):
diff --git a/manila_tempest_tests/tests/api/test_rules_negative.py b/manila_tempest_tests/tests/api/test_rules_negative.py
index 84b416d..0757c8e 100644
--- a/manila_tempest_tests/tests/api/test_rules_negative.py
+++ b/manila_tempest_tests/tests/api/test_rules_negative.py
@@ -368,6 +368,27 @@
CONF.share.username_for_user_rules,
'su')
+ @utils.skip_if_microversion_not_supported('2.88')
+ @decorators.idempotent_id('d5b1e7c9-7e6b-4918-a1c4-e03c8d82c46a')
+ @tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
+ def test_update_access_rule_with_wrong_level(self):
+ access_type, access_to = utils.get_access_rule_data_from_config(
+ self.protocol)
+ if access_type != 'ip':
+ msg = "Access rule updates supported only for 'ip' access."
+ raise self.skipException(msg)
+
+ rule = self.allow_access(
+ self.share["id"], client=self.shares_v2_client,
+ access_type=access_type, access_to=access_to)
+
+ self.assertRaises(
+ lib_exc.BadRequest,
+ self.shares_v2_client.update_access_rule,
+ rule['id'],
+ access_level='fake_level'
+ )
+
@ddt.ddt
class ShareUserRulesForCIFSNegativeTest(ShareUserRulesForNFSNegativeTest):
@@ -499,22 +520,24 @@
@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):
+ scheduler_hint = {"same_host": "%s" % self.share["id"]}
+
# 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,
+ share2 = self.create_share(client=self.admin_shares_v2_client,
share_protocol=self.protocol,
- share_type_id=self.share_type_id)
+ share_type_id=self.share_type_id,
+ scheduler_hints=scheduler_hint)
# 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,
+ self.allow_access(share2['id'], client=self.admin_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(
+ share_alt_updated = self.admin_shares_v2_client.get_share(
share2['id'])['share']
self.assertEqual('error', share_alt_updated['access_rules_status'])
@@ -522,35 +545,39 @@
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_can_apply_new_cephx_rules_when_one_is_in_error_state(self):
# Create share on "primary" tenant
- share_primary = self.create_share(share_type_id=self.share_type_id)
+ share_primary = self.create_share(
+ share_type_id=self.share_type_id)
# 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, share_type_id=self.share_type_id)
- # Add access rule to "Joe" by "alt" user.
+ scheduler_hint = {"same_host": "%s" % share_primary["id"]}
+ # Create share on "admin" tenant
+ share_adm = self.create_share(
+ client=self.admin_shares_v2_client,
+ share_type_id=self.share_type_id,
+ scheduler_hints=scheduler_hint)
+ # Add access rule to "Joe" by "admin" user.
# Rule must be set to "error" status.
- rule1 = self.allow_access(share_alt['id'],
- client=self.alt_shares_v2_client,
+ rule1 = self.allow_access(share_adm['id'],
+ client=self.admin_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'])['share']
- self.assertEqual('error', share_alt_updated['access_rules_status'])
+ share_adm_updated = self.admin_shares_v2_client.get_share(
+ share_adm['id'])['share']
+ self.assertEqual('error', share_adm_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)
+ # Add second access rule to different client by "admin" user.
+ self.allow_access(share_adm['id'], client=self.admin_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.admin_shares_v2_client.delete_access_rule(
+ share_adm['id'], rule1['id'])
waiters.wait_for_resource_status(
- self.alt_shares_v2_client, share_alt['id'], 'active',
+ self.admin_shares_v2_client, share_adm['id'], 'active',
status_attr='access_rules_status')
diff --git a/manila_tempest_tests/tests/api/test_scheduler_hints.py b/manila_tempest_tests/tests/api/test_scheduler_hints.py
index 5012f17..e5e51a5 100644
--- a/manila_tempest_tests/tests/api/test_scheduler_hints.py
+++ b/manila_tempest_tests/tests/api/test_scheduler_hints.py
@@ -72,14 +72,17 @@
# get metadata of share
metadata_a = self.shares_v2_client.get_metadata(
self.share_a["id"])['metadata']
- md_a = {"__affinity_same_host": "%s" % share_b["id"]}
+ expected_md_a = {"__affinity_same_host": "%s" % share_b["id"]}
metadata_b = self.shares_v2_client.get_metadata(
share_b["id"])['metadata']
- md_b = {"__affinity_same_host": "%s" % self.share_a["id"]}
+ expected_md_b = {"__affinity_same_host": "%s" % self.share_a["id"]}
# verify metadata
- self.assertEqual(md_a, metadata_a)
- self.assertEqual(md_b, metadata_b)
+ for key, value in expected_md_a.items():
+ self.assertEqual(value, metadata_a.get(key))
+
+ for key, value in expected_md_b.items():
+ self.assertEqual(value, metadata_b.get(key))
@decorators.idempotent_id('6569e0c3-43c9-4ee2-84ff-ea7fa8da8110')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
diff --git a/manila_tempest_tests/tests/rbac/test_rules.py b/manila_tempest_tests/tests/rbac/test_rules.py
index 8a6d46f..4c86787 100644
--- a/manila_tempest_tests/tests/rbac/test_rules.py
+++ b/manila_tempest_tests/tests/rbac/test_rules.py
@@ -58,10 +58,10 @@
access['access_level'] = access_level
return access
- def allow_access(self, client, share_id, access_type, access_to,
- access_level='rw', metadata=None, status='active',
- cleanup=True):
-
+ def allow_access(self, client, share_id, access_level='rw', metadata=None,
+ status='active', cleanup=True):
+ access_type, access_to = (
+ utils.get_access_rule_data_from_config(self.protocol))
kwargs = {
'access_type': access_type,
'access_to': access_to,
@@ -93,6 +93,10 @@
pass
@abc.abstractmethod
+ def test_update_access(self):
+ pass
+
+ @abc.abstractmethod
def test_delete_access(self):
pass
@@ -127,35 +131,27 @@
@decorators.idempotent_id('5b6897d1-4b2a-490c-990e-941ea4893f47')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_get_access(self):
- access_type, access_to = (
- utils.get_access_rule_data_from_config(self.protocol))
access = self.allow_access(
- self.share_member_client, self.share['id'],
- access_type=access_type, access_to=access_to)
+ self.share_member_client, self.share['id'])
self.do_request(
'get_access_rule', expected_status=200, access_id=access['id'])
alt_access = self.allow_access(
- self.alt_project_share_v2_client, self.alt_share['id'],
- access_type=access_type, access_to=access_to)
+ self.alt_project_share_v2_client, self.alt_share['id'])
self.do_request(
'get_access_rule', expected_status=200, access_id=alt_access['id'])
@decorators.idempotent_id('f8e9a2bb-ccff-4fc5-8d61-2930f87406cd')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_list_access(self):
- access_type, access_to = (
- utils.get_access_rule_data_from_config(self.protocol))
access = self.allow_access(
- self.share_member_client, self.share['id'],
- access_type=access_type, access_to=access_to)
+ self.share_member_client, self.share['id'])
access_list = self.do_request(
'list_access_rules', expected_status=200,
share_id=self.share['id'])['access_list'][0]['id']
alt_access = self.allow_access(
- self.alt_project_share_v2_client, self.alt_share['id'],
- access_type=access_type, access_to=access_to)
+ self.alt_project_share_v2_client, self.alt_share['id'])
alt_access_list = self.do_request(
'list_access_rules', expected_status=200,
share_id=self.share['id'])['access_list'][0]['id']
@@ -163,6 +159,33 @@
self.assertIn(access['id'], access_list)
self.assertNotIn(alt_access['id'], alt_access_list)
+ @utils.skip_if_microversion_not_supported('2.88')
+ @decorators.idempotent_id('01939b69-ef9b-75cf-abf7-5171fec7c397')
+ @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+ def test_update_access(self):
+ access_type, access_to = (
+ utils.get_access_rule_data_from_config(self.protocol))
+ if access_type != 'ip':
+ msg = "Access rule updates supported only for 'ip' access."
+ raise self.skipException(msg)
+
+ access = self.allow_access(self.share_member_client, self.share['id'])
+ rule = self.do_request(
+ 'update_access_rule', expected_status=200,
+ access_id=access['id'], access_level='ro')['access']
+ waiters.wait_for_resource_status(
+ self.share_member_client, self.share['id'], status='active',
+ resource_name='access_rule', rule_id=rule['id'])
+
+ alt_access = self.allow_access(
+ self.alt_project_share_v2_client, self.alt_share['id'])
+ rule = self.do_request(
+ 'update_access_rule', expected_status=200,
+ access_id=alt_access['id'], access_level='ro')['access']
+ waiters.wait_for_resource_status(
+ self.alt_project_share_v2_client, self.alt_share['id'],
+ status='active', resource_name='access_rule', rule_id=rule['id'])
+
@decorators.idempotent_id('b4d7a91c-a75e-4ad9-93cb-8e5234fea97a')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_grant_access_rule(self):
@@ -180,6 +203,8 @@
self.addCleanup(
self.client.delete_access_rule, self.share['id'], access['id'])
+ access_type, access_to = (
+ utils.get_access_rule_data_from_config(self.protocol))
alt_access = self.do_request(
'create_access_rule', expected_status=200,
**self.access(
@@ -197,12 +222,8 @@
@decorators.idempotent_id('e24d7018-cb49-4306-9947-716b4e4250c5')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_delete_access(self):
- access_type, access_to = (
- utils.get_access_rule_data_from_config(self.protocol))
access = self.allow_access(
- self.share_member_client, self.share['id'],
- access_type=access_type,
- access_to=access_to, cleanup=False)
+ self.share_member_client, self.share['id'], cleanup=False)
self.do_request(
'delete_access_rule', expected_status=202,
share_id=self.share['id'], rule_id=access['id'])
@@ -211,7 +232,6 @@
alt_access = self.allow_access(
self.alt_project_share_v2_client, self.alt_share['id'],
- access_type=access_type, access_to=access_to,
cleanup=False)
self.do_request(
'delete_access_rule', expected_status=202,
@@ -222,18 +242,14 @@
@decorators.idempotent_id('ffc07445-d0d1-4bf9-9fbc-4f409d48bccd')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_update_access_rule_metadata(self):
- access_type, access_to = (
- utils.get_access_rule_data_from_config(self.protocol))
access = self.allow_access(
- self.share_member_client, self.share['id'],
- access_type=access_type, access_to=access_to)
+ self.share_member_client, self.share['id'])
self.do_request(
'update_access_metadata', expected_status=200,
access_id=access['id'], metadata=self.metadata)
alt_access = self.allow_access(
- self.alt_project_share_v2_client, self.alt_share['id'],
- access_type=access_type, access_to=access_to)
+ self.alt_project_share_v2_client, self.alt_share['id'])
self.do_request(
'update_access_metadata', expected_status=200,
access_id=alt_access['id'], metadata=self.metadata)
@@ -241,19 +257,14 @@
@decorators.idempotent_id('fd580d91-1d8d-4dd0-8484-01c412ddb768')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_delete_access_rule_metadata(self):
- access_type, access_to = (
- utils.get_access_rule_data_from_config(self.protocol))
access = self.allow_access(
- self.share_member_client, self.share['id'],
- access_type=access_type, access_to=access_to,
- metadata=self.metadata)
+ self.share_member_client, self.share['id'], metadata=self.metadata)
self.do_request(
'delete_access_metadata', expected_status=200,
access_id=access['id'], key='key')
alt_access = self.allow_access(
self.alt_project_share_v2_client, self.alt_share['id'],
- access_type=access_type, access_to=access_to,
metadata=self.metadata)
self.do_request(
'delete_access_metadata', expected_status=200,
@@ -276,18 +287,13 @@
@decorators.idempotent_id('de643909-88a2-470b-8a14-0417696ec451')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_get_access(self):
- access_type, access_to = (
- utils.get_access_rule_data_from_config(self.protocol))
share_client = getattr(self, 'share_member_client', self.client)
- access = self.allow_access(
- share_client, self.share['id'], access_type=access_type,
- access_to=access_to)
+ access = self.allow_access(share_client, self.share['id'])
self.do_request(
'get_access_rule', expected_status=200, access_id=access['id'])
alt_access = self.allow_access(
- self.alt_project_share_v2_client, self.alt_share['id'],
- access_type=access_type, access_to=access_to)
+ self.alt_project_share_v2_client, self.alt_share['id'])
self.do_request(
'get_access_rule', expected_status=lib_exc.NotFound,
access_id=alt_access['id'])
@@ -295,15 +301,10 @@
@decorators.idempotent_id('7c6c4262-5095-4cd7-9d9c-8064009a9055')
@tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
def test_list_access(self):
- access_type, access_to = (
- utils.get_access_rule_data_from_config(self.protocol))
share_client = getattr(self, 'share_member_client', self.client)
- access = self.allow_access(
- share_client, self.share['id'], access_type=access_type,
- access_to=access_to)
+ access = self.allow_access(share_client, self.share['id'])
alt_access = self.allow_access(
- self.alt_project_share_v2_client, self.alt_share['id'],
- access_type=access_type, access_to=access_to)
+ self.alt_project_share_v2_client, self.alt_share['id'])
access_list = self.do_request(
'list_access_rules', expected_status=200,
@@ -315,6 +316,31 @@
self.assertIn(access['id'], access_id_list)
self.assertNotIn(alt_access['id'], access_id_list)
+ @utils.skip_if_microversion_not_supported('2.88')
+ @decorators.idempotent_id('02939b69-ef9b-75cf-abf7-5171fec7c397')
+ @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+ def test_update_access(self):
+ access_type, access_to = (
+ utils.get_access_rule_data_from_config(self.protocol))
+ if access_type != 'ip':
+ msg = "Access rule updates supported only for 'ip' access."
+ raise self.skipException(msg)
+
+ share_client = getattr(self, 'share_member_client', self.client)
+ access = self.allow_access(share_client, self.share['id'])
+ rule = self.do_request(
+ 'update_access_rule', client=share_client, expected_status=200,
+ access_id=access['id'], access_level='ro')['access']
+ waiters.wait_for_resource_status(
+ share_client, self.share['id'], status='active',
+ resource_name='access_rule', rule_id=rule['id'])
+
+ alt_access = self.allow_access(
+ self.alt_project_share_v2_client, self.alt_share['id'])
+ self.do_request(
+ 'update_access_rule', expected_status=lib_exc.NotFound,
+ access_id=alt_access['id'], access_level='ro')
+
@decorators.idempotent_id('61cf6f6c-5d7c-48d7-9d5a-e6ea288afdbc')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_grant_access_rule(self):
@@ -333,6 +359,8 @@
self.addCleanup(
self.client.delete_access_rule, self.share['id'], access['id'])
+ access_type, access_to = (
+ utils.get_access_rule_data_from_config(self.protocol))
self.do_request(
'create_access_rule', client=share_client,
expected_status=lib_exc.NotFound,
@@ -341,12 +369,9 @@
@decorators.idempotent_id('8665d1b1-de4c-42d4-93ff-8dc6d2b73a2d')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_delete_access(self):
- access_type, access_to = (
- utils.get_access_rule_data_from_config(self.protocol))
share_client = getattr(self, 'share_member_client', self.client)
access = self.allow_access(
- share_client, self.share['id'], access_type=access_type,
- access_to=access_to, cleanup=False)
+ share_client, self.share['id'], cleanup=False)
self.do_request(
'delete_access_rule', expected_status=202,
share_id=self.share['id'], rule_id=access['id'])
@@ -354,8 +379,7 @@
rule_id=access['id'], share_id=self.share['id'])
alt_access = self.allow_access(
- self.alt_project_share_v2_client, self.alt_share['id'],
- access_type=access_type, access_to=access_to)
+ self.alt_project_share_v2_client, self.alt_share['id'])
self.do_request(
'delete_access_rule', expected_status=lib_exc.NotFound,
share_id=self.alt_share['id'], rule_id=alt_access['id'])
@@ -363,19 +387,14 @@
@decorators.idempotent_id('c5e84362-6075-425b-bfa3-898abfd9d5a0')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_update_access_rule_metadata(self):
- access_type, access_to = (
- utils.get_access_rule_data_from_config(self.protocol))
share_client = getattr(self, 'share_member_client', self.client)
- access = self.allow_access(
- share_client, self.share['id'], access_type=access_type,
- access_to=access_to)
+ access = self.allow_access(share_client, self.share['id'])
self.do_request(
'update_access_metadata', expected_status=200,
access_id=access['id'], metadata=self.metadata)
alt_access = self.allow_access(
- self.alt_project_share_v2_client, self.alt_share['id'],
- access_type=access_type, access_to=access_to)
+ self.alt_project_share_v2_client, self.alt_share['id'])
self.do_request(
'update_access_metadata', expected_status=lib_exc.NotFound,
access_id=alt_access['id'], metadata=self.metadata)
@@ -383,19 +402,15 @@
@decorators.idempotent_id('abb17315-6510-4b6e-ae6c-dd99a6088954')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_delete_access_rule_metadata(self):
- access_type, access_to = (
- utils.get_access_rule_data_from_config(self.protocol))
share_client = getattr(self, 'share_member_client', self.client)
access = self.allow_access(
- share_client, self.share['id'], access_type=access_type,
- access_to=access_to, metadata=self.metadata)
+ share_client, self.share['id'], metadata=self.metadata)
self.do_request(
'delete_access_metadata', expected_status=200,
access_id=access['id'], key='key')
alt_access = self.allow_access(
self.alt_project_share_v2_client, self.alt_share['id'],
- access_type=access_type, access_to=access_to,
metadata=self.metadata)
self.do_request(
'delete_access_metadata', expected_status=lib_exc.NotFound,
@@ -432,6 +447,20 @@
def test_list_access(self):
super(TestProjectReaderTestsNFS, self).test_list_access()
+ @decorators.idempotent_id('03939b69-ef9b-75cf-abf7-5171fec7c397')
+ @tc.attr(base.TAG_POSITIVE, base.TAG_API_WITH_BACKEND)
+ def test_update_access(self):
+ access = self.allow_access(self.share_member_client, self.share['id'])
+ self.do_request(
+ 'update_access_rule', expected_status=lib_exc.Forbidden,
+ access_id=access['id'], access_level='ro')
+
+ alt_access = self.allow_access(
+ self.alt_project_share_v2_client, self.alt_share['id'])
+ self.do_request(
+ 'update_access_rule', expected_status=lib_exc.Forbidden,
+ access_id=alt_access['id'], access_level='ro')
+
@decorators.idempotent_id('ace870f9-af91-4259-8760-dc7d7107b7ff')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_grant_access_rule(self):
@@ -441,6 +470,8 @@
'create_access_rule', expected_status=lib_exc.Forbidden,
**self.access(self.share['id'], access_type, access_to))
+ access_type, access_to = (
+ utils.get_access_rule_data_from_config(self.protocol))
self.do_request(
'create_access_rule', expected_status=lib_exc.Forbidden,
**self.access(self.alt_share['id'], access_type, access_to))
@@ -448,18 +479,13 @@
@decorators.idempotent_id('7a702c74-8d31-49e3-859a-cc8a78d7915e')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_delete_access(self):
- access_type, access_to = (
- utils.get_access_rule_data_from_config(self.protocol))
- access = self.allow_access(
- self.share_member_client, self.share['id'],
- access_type=access_type, access_to=access_to)
+ access = self.allow_access(self.share_member_client, self.share['id'])
self.do_request(
'delete_access_rule', expected_status=lib_exc.Forbidden,
share_id=self.share['id'], rule_id=access['id'])
alt_access = self.allow_access(
- self.alt_project_share_v2_client, self.alt_share['id'],
- access_type=access_type, access_to=access_to)
+ self.alt_project_share_v2_client, self.alt_share['id'])
self.do_request(
'delete_access_rule', expected_status=lib_exc.Forbidden,
share_id=self.alt_share['id'], rule_id=alt_access['id'])
@@ -467,18 +493,13 @@
@decorators.idempotent_id('a61d7f06-6f0e-4da3-b11d-1c3a0b5bd416')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_update_access_rule_metadata(self):
- access_type, access_to = (
- utils.get_access_rule_data_from_config(self.protocol))
- access = self.allow_access(
- self.share_member_client, self.share['id'],
- access_type=access_type, access_to=access_to)
+ access = self.allow_access(self.share_member_client, self.share['id'])
self.do_request(
'update_access_metadata', expected_status=lib_exc.Forbidden,
access_id=access['id'], metadata=self.metadata)
alt_access = self.allow_access(
- self.alt_project_share_v2_client, self.alt_share['id'],
- access_type=access_type, access_to=access_to)
+ self.alt_project_share_v2_client, self.alt_share['id'])
self.do_request(
'update_access_metadata', expected_status=lib_exc.Forbidden,
access_id=alt_access['id'], metadata=self.metadata)
@@ -486,19 +507,14 @@
@decorators.idempotent_id('5faf0e0b-b246-4392-901d-9e7d628f0d6e')
@tc.attr(base.TAG_NEGATIVE, base.TAG_API_WITH_BACKEND)
def test_delete_access_rule_metadata(self):
- access_type, access_to = (
- utils.get_access_rule_data_from_config(self.protocol))
access = self.allow_access(
- self.share_member_client, self.share['id'],
- access_type=access_type, access_to=access_to,
- metadata=self.metadata)
+ self.share_member_client, self.share['id'], metadata=self.metadata)
self.do_request(
'delete_access_metadata', expected_status=lib_exc.Forbidden,
access_id=access['id'], key='key')
alt_access = self.allow_access(
self.alt_project_share_v2_client, self.alt_share['id'],
- access_type=access_type, access_to=access_to,
metadata=self.metadata)
self.do_request(
'delete_access_metadata', expected_status=lib_exc.Forbidden,
diff --git a/manila_tempest_tests/tests/scenario/manager_share.py b/manila_tempest_tests/tests/scenario/manager_share.py
index 3e06323..f9df340 100644
--- a/manila_tempest_tests/tests/scenario/manager_share.py
+++ b/manila_tempest_tests/tests/scenario/manager_share.py
@@ -186,7 +186,7 @@
storage_net_nic[0]['addr']
)
# Attach a floating IP
- self.associate_floating_ip(floating_ip, instance)
+ self.associate_floating_ip(floating_ip, instance, ip_addr=ip_addr)
self.assertIsNotNone(server_ip)
# Check ssh
@@ -752,8 +752,11 @@
self.validate_ping_to_export_location(location, ssh_client)
target_dir = target_dir or "/mnt"
+ nfs_version = getattr(self, 'nfs_version', None)
+ version_option = f"-o vers={nfs_version}" if nfs_version else ""
ssh_client.exec_command(
- "sudo mount -vt nfs \"%s\" %s" % (location, target_dir)
+ "sudo mount -vt nfs %s \"%s\" %s" % (
+ version_option, location, target_dir)
)
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 d832974..e7402ef 100644
--- a/manila_tempest_tests/tests/scenario/test_share_basic_ops.py
+++ b/manila_tempest_tests/tests/scenario/test_share_basic_ops.py
@@ -417,32 +417,41 @@
"sudo touch %s/file3" % snapshot_dir)
+@ddt.ddt
class TestShareBasicOpsNFS(manager.BaseShareScenarioNFSTest,
ShareBasicOpsBase):
- pass
+
+ @decorators.idempotent_id('4bad2073-a19b-4851-8cbe-75b20ade5cdb')
+ @tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
+ @ddt.data(*utils.deduplicate(CONF.share.nfs_versions))
+ def test_mount_share_one_vm(self, nfs_version):
+ self.nfs_version = nfs_version
+ super(TestShareBasicOpsNFS, self).test_mount_share_one_vm()
class TestShareBasicOpsCIFS(manager.BaseShareScenarioCIFSTest,
ShareBasicOpsBase):
+ @testtools.skipIf(
+ "cifs" not in CONF.share.enable_ro_access_level_for_protocols,
+ "RO access rule tests are disabled for CIFS protocol.")
@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)
+ super(TestShareBasicOpsCIFS, self).test_write_with_ro_access()
+ @decorators.skip_because(bug='1649573')
@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)
+ super(TestShareBasicOpsCIFS, self).test_read_mountable_snapshot()
+ @decorators.skip_because(bug='1649573')
@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)
+ super(TestShareBasicOpsCIFS,
+ self).test_write_data_to_share_created_from_snapshot()
class TestBaseShareBasicOpsScenarioCEPHFS(manager.BaseShareScenarioCEPHFSTest,
diff --git a/releasenotes/notes/add-update-access-rules-e43b4d0fbabdb596.yaml b/releasenotes/notes/add-update-access-rules-e43b4d0fbabdb596.yaml
new file mode 100644
index 0000000..29b2936
--- /dev/null
+++ b/releasenotes/notes/add-update-access-rules-e43b4d0fbabdb596.yaml
@@ -0,0 +1,6 @@
+---
+features:
+ - |
+ Added tests to verify share access rule update operation. Update is
+ allowed only for admin and project member. Also supported microversion is
+ increased to 2.88.
diff --git a/releasenotes/notes/bug-2006792-fix-stop-cleanup-error-2a314862576f655b.yaml b/releasenotes/notes/bug-2006792-fix-stop-cleanup-error-2a314862576f655b.yaml
new file mode 100644
index 0000000..aaa3105
--- /dev/null
+++ b/releasenotes/notes/bug-2006792-fix-stop-cleanup-error-2a314862576f655b.yaml
@@ -0,0 +1,6 @@
+---
+fixes:
+ - |
+ Fixed bug #2006792. Now the clear resources function has an error
+ treatment to avoid time out exceptions. Also fix the returned
+ object in the _is_resource_deleted function
diff --git a/releasenotes/notes/nfs-versions-6886a2dd1bab094f.yaml b/releasenotes/notes/nfs-versions-6886a2dd1bab094f.yaml
new file mode 100644
index 0000000..b18d197
--- /dev/null
+++ b/releasenotes/notes/nfs-versions-6886a2dd1bab094f.yaml
@@ -0,0 +1,8 @@
+---
+upgrade:
+ - |
+ A new configuration option, nfs_version, has been added to control
+ the NFS protocol version used for mounting NFS shares during testing.
+ This option allows users to specify which version of NFS should be used,
+ supporting environments where compatibility with specific versions is
+ required.
diff --git a/tox.ini b/tox.ini
index 907516f..1cf0c94 100644
--- a/tox.ini
+++ b/tox.ini
@@ -6,7 +6,6 @@
basepython = python3
usedevelop = True
setenv =
- VIRTUAL_ENV={envdir}
PYTHONWARNINGS=default::DeprecationWarning
OS_STDOUT_CAPTURE=1
OS_STDERR_CAPTURE=1
diff --git a/zuul.d/manila-tempest-jobs.yaml b/zuul.d/manila-tempest-jobs.yaml
index 208bec3..36a1faf 100644
--- a/zuul.d/manila-tempest-jobs.yaml
+++ b/zuul.d/manila-tempest-jobs.yaml
@@ -164,6 +164,8 @@
name: manila-tempest-plugin-zfsonlinux
description: Test ZFSOnLinux multibackend (DHSS=False) with postgresql db
parent: manila-tempest-plugin-zfsonlinux-base
+ # https://bugs.launchpad.net/manila/+bug/2087192
+ nodeset: openstack-single-node-jammy
branches: &ubuntu_jammy_test_image_branches
regex: ^stable/(yoga|xena|wallaby|victoria|ussuri)$
negate: true
@@ -250,6 +252,18 @@
MANILA_SETUP_IPV6: false
NEUTRON_CREATE_INITIAL_NETWORKS: true
+
+# TODO(gmann): As per the 2025.1 testing runtime, we need to run at least
+# one job on jammy. This job can be removed as per the future testing
+# runtime (whenever we start testing Ubuntu 26.04 as default version).
+- job:
+ name: manila-tempest-plugin-lvm-jammy
+ description: This is integrated job testing on Ubuntu jammy(22.04)
+ parent: manila-tempest-plugin-lvm
+ nodeset: openstack-single-node-jammy
+ branches:
+ - stable/2025.1
+
- job:
name: manila-tempest-plugin-container
description: |
@@ -377,6 +391,10 @@
devstack-plugin-ceph: https://opendev.org/openstack/devstack-plugin-ceph
tempest_test_regex: manila_tempest_tests.tests
devstack_localrc:
+ # TODO (gouthamr): update to squid after
+ # https://bugs.launchpad.net/manila/+bug/2105833
+ CEPH_RELEASE: 'reef'
+ CONTAINER_IMAGE: 'quay.io/ceph/ceph:v18.2'
VOLUME_BACKING_FILE_SIZE: 60GB
SHARE_DRIVER: manila.share.drivers.cephfs.driver.CephFSDriver
MANILA_ENABLED_BACKENDS: cephfsnative
@@ -516,7 +534,6 @@
MANILA_SETUP_IPV6: false
NEUTRON_CREATE_INITIAL_NETWORKS: true
IP_VERSION: 4
- CEPH_INGRESS_IP: "{{hostvars['controller'].ansible_default_ipv6.address}}"
- job:
name: manila-tempest-plugin-multinode-base
@@ -577,6 +594,7 @@
devstack_localrc:
MYSQL_REDUCE_MEMORY: True
CEPHADM_DEPLOY: True
+ ENABLE_INGRESS: False
CEPHADM_DEV_OSD: true
CEPH_LOOPBACK_DISK_SIZE: 40GB
ENABLED_SHARE_PROTOCOLS: NFS
@@ -596,7 +614,6 @@
MANILA_SETUP_IPV6: false
SHARE_DRIVER: manila.share.drivers.cephfs.driver.CephFSDriver
TARGET_DEV_OSD_DIR: /opt/stack
- CEPH_INGRESS_IP: "{{hostvars['controller'].ansible_default_ipv6.address}}"
devstack_local_conf:
test-config:
$TEMPEST_CONFIG:
@@ -875,6 +892,7 @@
check:
jobs:
- manila-tempest-plugin-lvm
+ - manila-tempest-plugin-lvm-jammy
- manila-tempest-plugin-generic-scenario:
voting: false
- manila-tempest-plugin-generic:
@@ -888,3 +906,4 @@
gate:
jobs:
- manila-tempest-plugin-lvm
+ - manila-tempest-plugin-lvm-jammy
diff --git a/zuul.d/manila-tempest-stable-jobs.yaml b/zuul.d/manila-tempest-stable-jobs.yaml
index c5a692b..07f013a 100644
--- a/zuul.d/manila-tempest-stable-jobs.yaml
+++ b/zuul.d/manila-tempest-stable-jobs.yaml
@@ -69,6 +69,19 @@
vars: *manila_tempest_image_pinned_vars
- job:
+ name: manila-tempest-plugin-lvm-2025.1
+ parent: manila-tempest-plugin-lvm-base
+ override-checkout: stable/2025.1
+ vars:
+ # TODO(gouthamr): some tests are disabled due to bugs
+ # IPv6 Tests: https://bugs.launchpad.net/manila/+bug/1998489
+ # drop these overrides once we address that bug.
+ tempest_exclude_regex: '(^manila_tempest_tests.tests.scenario.*IPv6.*)'
+ devstack_localrc:
+ MANILA_SETUP_IPV6: false
+ NEUTRON_CREATE_INITIAL_NETWORKS: true
+
+- job:
name: manila-tempest-plugin-lvm-2024.2
parent: manila-tempest-plugin-lvm-base
override-checkout: stable/2024.2
@@ -94,19 +107,6 @@
MANILA_SETUP_IPV6: false
NEUTRON_CREATE_INITIAL_NETWORKS: true
-- job:
- name: manila-tempest-plugin-lvm-2023.2
- parent: manila-tempest-plugin-lvm-base
- override-checkout: stable/2023.2
- vars:
- # TODO(gouthamr): some tests are disabled due to bugs
- # IPv6 Tests: https://bugs.launchpad.net/manila/+bug/1998489
- # drop these overrides once we address that bug.
- tempest_exclude_regex: '(^manila_tempest_tests.tests.scenario.*IPv6.*)'
- devstack_localrc:
- MANILA_SETUP_IPV6: false
- NEUTRON_CREATE_INITIAL_NETWORKS: true
-
- project-template:
name: manila-tempest-plugin-jobs-using-service-image-stable
description: |
diff --git a/zuul.d/project.yaml b/zuul.d/project.yaml
index d2a654e..3ca5092 100644
--- a/zuul.d/project.yaml
+++ b/zuul.d/project.yaml
@@ -8,9 +8,9 @@
jobs:
- manila-tempest-plugin-dummy-no-dhss
- manila-tempest-plugin-dummy-dhss
+ - manila-tempest-plugin-lvm-2025.1
- manila-tempest-plugin-lvm-2024.2
- manila-tempest-plugin-lvm-2024.1
- - manila-tempest-plugin-lvm-2023.2
- manila-tempest-plugin-dummy-no-dhss-rbac
- manila-tempest-plugin-container:
voting: false