Merge "Preparation for support scenario tests on CephFS Native"
diff --git a/manila_tempest_tests/tests/scenario/manager_share.py b/manila_tempest_tests/tests/scenario/manager_share.py
index 4593e9a..10074b1 100644
--- a/manila_tempest_tests/tests/scenario/manager_share.py
+++ b/manila_tempest_tests/tests/scenario/manager_share.py
@@ -124,6 +124,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)
@@ -347,6 +350,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")
@@ -598,9 +649,10 @@
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, error_on_invalid_ip_version)
+ self.assertNotEmpty(locations)
return locations
@@ -630,3 +682,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..06a23bf 100644
--- a/manila_tempest_tests/tests/scenario/test_share_basic_ops.py
+++ b/manila_tempest_tests/tests/scenario/test_share_basic_ops.py
@@ -44,14 +44,6 @@
* 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:
@@ -66,7 +58,8 @@
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)
@@ -85,12 +78,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.
@@ -113,7 +111,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 +123,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,
@@ -387,6 +389,18 @@
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)
@@ -399,6 +413,18 @@
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)
@@ -426,6 +452,25 @@
raise self.skipException(msg)
+class TestShareBasicOpsCEPHFS(ShareBasicOpsBase, manager.BaseShareCEPHFSTest):
+ protocol = "cephfs"
+
+ @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()
+
+ @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()
+
+ @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..e0a1e4a 100644
--- a/manila_tempest_tests/tests/scenario/test_share_extend.py
+++ b/manila_tempest_tests/tests/scenario/test_share_extend.py
@@ -45,14 +45,6 @@
* 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)
-
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
def test_create_extend_and_write(self):
default_share_size = CONF.share.share_size
@@ -69,10 +61,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_share_export_location_for_mount(share)
+ 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,6 +146,18 @@
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):
target_dir = target_dir or "/mnt"
remote_client.exec_command(
@@ -163,6 +168,18 @@
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):
location = location.replace("\\", "/")
target_dir = target_dir or "/mnt"
@@ -171,6 +188,15 @@
)
+class TestShareExtendCEPHFS(ShareExtendBase, manager.BaseShareCEPHFSTest):
+ protocol = "cephfs"
+
+ @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()
+
+
# 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_shrink.py b/manila_tempest_tests/tests/scenario/test_share_shrink.py
index e8ffdcb..785c6ce 100644
--- a/manila_tempest_tests/tests/scenario/test_share_shrink.py
+++ b/manila_tempest_tests/tests/scenario/test_share_shrink.py
@@ -46,14 +46,6 @@
* 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)
-
@tc.attr(base.TAG_POSITIVE, base.TAG_BACKEND)
@testtools.skipUnless(
CONF.share.run_shrink_tests, 'Shrink share tests are disabled.')
@@ -72,10 +64,11 @@
remote_client = self.init_remote_client(instance)
LOG.debug('Step 4 - grant access')
- self.provide_access_to_auxiliary_instance(instance)
+ location = self.get_share_export_location_for_mount(share)
+ 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,6 +160,18 @@
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):
target_dir = target_dir or "/mnt"
ssh_client.exec_command(
@@ -177,6 +182,18 @@
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):
location = location.replace("\\", "/")
target_dir = target_dir or "/mnt"
@@ -185,6 +202,15 @@
)
+class TestShareShrinkCEPHFS(ShareShrinkBase, manager.BaseShareCEPHFSTest):
+ protocol = "cephfs"
+
+ @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()
+
+
# 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