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)
else:
self.volname = result[0]['name']
+ def _get_subvolume_group_path(self, vol_name, group_name):
+ args = ("subvolumegroup", "getpath", vol_name, group_name)
+ path = self._fs_cmd(*args)
+ # remove the leading '/', and trailing whitespaces
+ return path[1:].rstrip()
+
def _get_subvolume_path(self, vol_name, subvol_name, group_name=None):
args = ["subvolume", "getpath", vol_name, subvol_name]
if group_name:
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
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()
# 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"
if ce.exitstatus != errno.ENOENT:
raise
+ def test_default_uid_gid_subvolume(self):
+ subvolume = self._generate_random_subvolume_name()
+ expected_uid = 0
+ expected_gid = 0
+
+ # create subvolume
+ self._fs_cmd("subvolume", "create", self.volname, subvolume)
+ subvol_path = self._get_subvolume_path(self.volname, subvolume)
+
+ # check subvolume's uid and gid
+ stat = self.mount_a.stat(subvol_path)
+ self.assertEqual(stat['st_uid'], expected_uid)
+ self.assertEqual(stat['st_gid'], expected_gid)
+
+ # remove subvolume
+ self._fs_cmd("subvolume", "rm", self.volname, subvolume)
+
### subvolume group operations
def test_subvolume_create_and_rm_in_group(self):
# 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)
# create group
self._fs_cmd("subvolumegroup", "create", self.volname, group1)
- group1_path = os.path.join('volumes', group1)
+ group1_path = self._get_subvolume_group_path(self.volname, group1)
default_pool = self.mount_a.getfattr(group1_path, "ceph.dir.layout.pool")
new_pool = "new_pool"
# create group specifying the new data pool as its pool layout
self._fs_cmd("subvolumegroup", "create", self.volname, group2,
"--pool_layout", new_pool)
- group2_path = os.path.join('volumes', group2)
+ group2_path = self._get_subvolume_group_path(self.volname, group2)
desired_pool = self.mount_a.getfattr(group2_path, "ceph.dir.layout.pool")
self.assertEqual(desired_pool, new_pool)
self._fs_cmd("subvolumegroup", "create", self.volname, group1)
self._fs_cmd("subvolumegroup", "create", self.volname, group2, "--mode", "777")
- group1_path = os.path.join('volumes', group1)
- group2_path = os.path.join('volumes', group2)
+ group1_path = self._get_subvolume_group_path(self.volname, group1)
+ group2_path = self._get_subvolume_group_path(self.volname, group2)
# check group's mode
actual_mode1 = self.mount_a.run_shell(['stat', '-c' '%a', group1_path]).stdout.getvalue().strip()
self.assertEqual(actual_mode2, expected_mode2)
self.assertEqual(actual_mode3, expected_mode2)
- self._fs_cmd("subvolume", "rm", self.volname, subvol2, group)
self._fs_cmd("subvolume", "rm", self.volname, subvol1, group)
+ self._fs_cmd("subvolume", "rm", self.volname, subvol2, group)
+ self._fs_cmd("subvolume", "rm", self.volname, subvol3, group)
self._fs_cmd("subvolumegroup", "rm", self.volname, group)
def test_nonexistent_subvolme_group_rm(self):
# force remove subvolume
self._fs_cmd("subvolumegroup", "rm", self.volname, group, "--force")
+ def test_default_uid_gid_subvolume_group(self):
+ group = self._generate_random_group_name()
+ expected_uid = 0
+ expected_gid = 0
+
+ # create group
+ self._fs_cmd("subvolumegroup", "create", self.volname, group)
+ group_path = self._get_subvolume_group_path(self.volname, group)
+
+ # check group's uid and gid
+ stat = self.mount_a.stat(group_path)
+ self.assertEqual(stat['st_uid'], expected_uid)
+ self.assertEqual(stat['st_gid'], expected_gid)
+
+ # remove group
+ self._fs_cmd("subvolumegroup", "rm", self.volname, group)
+
### snapshot operations
def test_subvolume_snapshot_create_and_rm(self):
# 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()
# 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()
# 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()
# 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)
# 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)
# 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)
# 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()