From aec1d90b3611fec19556c9e4c639cb8abf90e4b6 Mon Sep 17 00:00:00 2001 From: Venky Shankar Date: Thu, 20 Jun 2019 06:00:40 -0400 Subject: [PATCH] test: add basic purge queue validation test .. and since we have async subvolume deletes now, check trash directory for emptiness in other tests. Fixes: http://tracker.ceph.com/issues/40036 Signed-off-by: Venky Shankar --- qa/tasks/cephfs/mount.py | 16 +++++++ qa/tasks/cephfs/test_volumes.py | 75 +++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) diff --git a/qa/tasks/cephfs/mount.py b/qa/tasks/cephfs/mount.py index 4a6917e39290b..b87bc3d1052a2 100644 --- a/qa/tasks/cephfs/mount.py +++ b/qa/tasks/cephfs/mount.py @@ -247,6 +247,22 @@ class CephFSMount(object): return rproc + def wait_for_dir_empty(self, dirname, timeout=30): + i = 0 + dirpath = os.path.join(self.mountpoint, dirname) + while i < timeout: + nr_entries = int(self.getfattr(dirpath, "ceph.dir.entries")) + if nr_entries == 0: + log.debug("Directory {0} seen empty from {1} after {2}s ".format( + dirname, self.client_id, i)) + return + else: + time.sleep(1) + i += 1 + + raise RuntimeError("Timed out after {0}s waiting for {1} to become empty from {2}".format( + i, dirname, self.client_id)) + def wait_for_visible(self, basename="background_file", timeout=30): i = 0 while i < timeout: diff --git a/qa/tasks/cephfs/test_volumes.py b/qa/tasks/cephfs/test_volumes.py index 2634dca253bc4..30756e99506c7 100644 --- a/qa/tasks/cephfs/test_volumes.py +++ b/qa/tasks/cephfs/test_volumes.py @@ -14,6 +14,14 @@ class TestVolumes(CephFSTestCase): TEST_SUBVOLUME_PREFIX="subvolume" TEST_GROUP_PREFIX="group" TEST_SNAPSHOT_PREFIX="snapshot" + TEST_FILE_NAME_PREFIX="subvolume_file" + + # for filling subvolume with data + CLIENTS_REQUIRED = 1 + + # io defaults + DEFAULT_FILE_SIZE = 1 # MB + DEFAULT_NUMBER_OF_FILES = 1024 def _fs_cmd(self, *args): return self.mgr_cluster.mon_manager.raw_cluster_cmd("fs", *args) @@ -51,6 +59,24 @@ class TestVolumes(CephFSTestCase): def _delete_test_volume(self): self._fs_cmd("volume", "rm", self.volname) + def _do_subvolume_io(self, subvolume, number_of_files=DEFAULT_NUMBER_OF_FILES, + file_size=DEFAULT_FILE_SIZE): + # get subvolume path for IO + subvolpath = self._fs_cmd("subvolume", "getpath", self.volname, subvolume) + self.assertNotEqual(subvolpath, None) + subvolpath = subvolpath[1:].rstrip() # remove "/" prefix and any trailing newline + + log.debug("filling subvolume {0} with {1} files each {2}MB size".format(subvolume, number_of_files, file_size)) + for i in range(number_of_files): + filename = "{0}.{1}".format(TestVolumes.TEST_FILE_NAME_PREFIX, i) + self.mount_a.write_n_mb(os.path.join(subvolpath, filename), file_size) + + def _wait_for_trash_empty(self, timeout=30): + # XXX: construct the trash dir path (note that there is no mgr + # [sub]volume interface for this). + trashdir = os.path.join("./", "volumes", "_deleting") + self.mount_a.wait_for_dir_empty(trashdir) + def setUp(self): super(TestVolumes, self).setUp() self.volname = None @@ -83,6 +109,9 @@ class TestVolumes(CephFSTestCase): if ce.exitstatus != errno.ENOENT: raise + # verify trash dir is clean + self._wait_for_trash_empty() + def test_subvolume_create_idempotence(self): # create subvolume subvolume = self._generate_random_subvolume_name() @@ -94,6 +123,9 @@ class TestVolumes(CephFSTestCase): # remove subvolume self._fs_cmd("subvolume", "rm", self.volname, subvolume) + # verify trash dir is clean + self._wait_for_trash_empty() + def test_nonexistent_subvolume_rm(self): # remove non-existing subvolume subvolume = "non_existent_subvolume" @@ -134,6 +166,9 @@ class TestVolumes(CephFSTestCase): # remove subvolume self._fs_cmd("subvolume", "rm", self.volname, subvolume, group) + # verify trash dir is clean + self._wait_for_trash_empty() + # remove group self._fs_cmd("subvolumegroup", "rm", self.volname, group) @@ -286,6 +321,9 @@ class TestVolumes(CephFSTestCase): # remove subvolume self._fs_cmd("subvolume", "rm", self.volname, subvolume) + # verify trash dir is clean + self._wait_for_trash_empty() + def test_subvolume_snapshot_create_idempotence(self): subvolume = self._generate_random_subvolume_name() snapshot = self._generate_random_snapshot_name() @@ -305,6 +343,9 @@ class TestVolumes(CephFSTestCase): # remove subvolume self._fs_cmd("subvolume", "rm", self.volname, subvolume) + # verify trash dir is clean + self._wait_for_trash_empty() + def test_nonexistent_subvolume_snapshot_rm(self): subvolume = self._generate_random_subvolume_name() snapshot = self._generate_random_snapshot_name() @@ -331,6 +372,9 @@ class TestVolumes(CephFSTestCase): # remove subvolume self._fs_cmd("subvolume", "rm", self.volname, subvolume) + # verify trash dir is clean + self._wait_for_trash_empty() + def test_subvolume_snapshot_in_group(self): subvolume = self._generate_random_subvolume_name() group = self._generate_random_group_name() @@ -351,6 +395,9 @@ class TestVolumes(CephFSTestCase): # remove subvolume self._fs_cmd("subvolume", "rm", self.volname, subvolume, group) + # verify trash dir is clean + self._wait_for_trash_empty() + # remove group self._fs_cmd("subvolumegroup", "rm", self.volname, group) @@ -374,6 +421,9 @@ class TestVolumes(CephFSTestCase): # remove subvolume self._fs_cmd("subvolume", "rm", self.volname, subvolume, group) + # verify trash dir is clean + self._wait_for_trash_empty() + # remove group self._fs_cmd("subvolumegroup", "rm", self.volname, group) @@ -400,6 +450,9 @@ class TestVolumes(CephFSTestCase): # remove subvolume self._fs_cmd("subvolume", "rm", self.volname, subvolume, group) + # verify trash dir is clean + self._wait_for_trash_empty() + # remove group self._fs_cmd("subvolumegroup", "rm", self.volname, group) @@ -430,5 +483,27 @@ class TestVolumes(CephFSTestCase): # remove subvolume self._fs_cmd("subvolume", "rm", self.volname, subvolume, group) + # verify trash dir is clean + self._wait_for_trash_empty() + # remove group self._fs_cmd("subvolumegroup", "rm", self.volname, group) + + def test_async_subvolume_rm(self): + subvolume = self._generate_random_subvolume_name() + + # create subvolume + self._fs_cmd("subvolume", "create", self.volname, subvolume) + + # fill subvolume w/ some data + self._do_subvolume_io(subvolume) + + self.mount_a.umount_wait() + + # remove subvolume + self._fs_cmd("subvolume", "rm", self.volname, subvolume) + + self.mount_a.mount() + + # verify trash dir is clean + self._wait_for_trash_empty() -- 2.39.5