summaryrefslogtreecommitdiffstats
path: root/tests/functional/ctime_feature
diff options
context:
space:
mode:
authornchilaka <nchilaka@redhat.com>2020-05-27 21:41:41 +0530
committerBala Konda Reddy M <bala12352@gmail.com>2020-06-05 12:00:07 +0000
commita68bbffd03697e1960b120917d8c666ee488bab7 (patch)
tree4910e1a99a26c9e03c5d1ae9f249e23afa538743 /tests/functional/ctime_feature
parent6171d5dba1513139f0f893374653ffbbd8990c01 (diff)
[Test] Validate Consistent Time(ctime) feature
Description: This testcase tests the new xattr glusterfs.mdata attributes when features.ctime is enabled Change-Id: I3c2dd6537f88b6d9da85aa6819c96e1c236a0d61 Signed-off-by: nchilaka <nchilaka@redhat.com>
Diffstat (limited to 'tests/functional/ctime_feature')
-rw-r--r--tests/functional/ctime_feature/test_consistent_timestamps_feature.py205
1 files changed, 205 insertions, 0 deletions
diff --git a/tests/functional/ctime_feature/test_consistent_timestamps_feature.py b/tests/functional/ctime_feature/test_consistent_timestamps_feature.py
new file mode 100644
index 000000000..a5e85e6db
--- /dev/null
+++ b/tests/functional/ctime_feature/test_consistent_timestamps_feature.py
@@ -0,0 +1,205 @@
+# Copyright (C) 2020 Red Hat, Inc. <http://www.redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+from re import sub
+from glusto.core import Glusto as g
+from glustolibs.gluster.gluster_base_class import (GlusterBaseClass, runs_on)
+from glustolibs.gluster.exceptions import ExecutionError
+from glustolibs.io.utils import run_crefi
+from glustolibs.gluster.brick_libs import get_subvols
+from glustolibs.gluster.glusterdir import (rmdir, get_dir_contents)
+from glustolibs.gluster.lib_utils import get_extended_attributes_info
+from glustolibs.gluster.volume_libs import get_volume_type_info
+from glustolibs.gluster.volume_ops import set_volume_options
+
+
+@runs_on([['distributed', 'replicated', 'distributed-replicated', 'dispersed',
+ 'distributed-dispersed', 'arbiter', 'distributed-arbiter'],
+ ['glusterfs']])
+class ValidateCtimeFeatures(GlusterBaseClass):
+ """
+ This testcase validates ctime(consistent times) feature
+ """
+
+ def setUp(self):
+ # Calling GlusterBaseClass setUp
+ self.get_super_method(self, 'setUp')()
+
+ self.all_mounts_procs = []
+ self.io_validation_complete = False
+
+ # Setup Volume and Mount Volume
+ ret = self.setup_volume_and_mount_volume(mounts=[self.mounts[0]],
+ volume_create_force=False)
+ if not ret:
+ raise ExecutionError("Failed to Setup_Volume and Mount_Volume")
+ g.log.info("Successful in Setup Volume and Mount Volume")
+
+ def tearDown(self):
+ """tearDown"""
+ self.get_super_method(self, 'tearDown')()
+ ret = self.unmount_volume_and_cleanup_volume(mounts=[self.mounts[0]])
+ if not ret:
+ raise ExecutionError("Failed to umount the vol & cleanup Volume")
+ g.log.info("Successful in umounting the volume and Cleanup")
+
+ # Need to get list of host and resp brickpaths
+ # Get list of entries under any one path
+ # Get xattr values on each brick of same path
+ # Compare them to see if mdata exists and value is same
+ # For arbiter the value may not be same on arbiter brick
+
+ def validate_xattr_values(self, dirname, ctime=True):
+ """Validate existence and consistency of a specific
+ xattr value across replica set
+
+ Args:
+ dirname (str): parent directory name
+ Kwargs:
+ ctime(bool): ctime feature enablement
+ """
+ # pylint: disable=too-many-branches
+ # Fetch all replica sets(subvols) in the volume
+ ret = get_subvols(self.mnode, self.volname)
+ # Iterating through each subvol(replicaset)
+ for subvol in ret['volume_subvols']:
+ brick_host_list = {} # Dict for storing host,brickpath pairs
+ for each in subvol: # Fetching each replica in replica set
+ # Splitting to brick,hostname pairs
+ host, brick_path = each.split(':')
+ brick_host_list[host] = brick_path
+ # Fetch Complete parent directory path
+ directory = brick_path + '/' + dirname
+ # Fetching all entries recursively in a replicaset
+ entry_list = get_dir_contents(host, directory, recursive=True)
+ for each in entry_list:
+ xattr_value = [] # list to store xattr value
+ # Logic to get xattr values
+ for host, brickpath in brick_host_list.items():
+ # Remove the prefix brick_path from entry-name
+ each = sub(brick_path, '', each)
+ # Adding the right brickpath name for fetching xattrval
+ brick_entry_path = brickpath + each
+ ret = get_extended_attributes_info(host,
+ [brick_entry_path],
+ encoding='hex',
+ attr_name='trusted'
+ '.glusterfs.'
+ 'mdata')
+ if ret:
+ ret = ret[brick_entry_path]['trusted.glusterfs.mdata']
+ g.log.info("mdata xattr value of %s is %s",
+ brick_entry_path, ret)
+ else:
+ pass
+ if ctime:
+ self.assertIsNotNone(ret, "glusterfs.mdata not set on"
+ " {}"
+ .format(brick_entry_path))
+ g.log.info("mdata xattr %s is set on the back-end"
+ " bricks", ret)
+ else:
+ self.assertIsNone(ret, "trusted.glusterfs.mdata seen "
+ " on {}"
+ .format(brick_entry_path))
+ g.log.info("mdata xattr %s is not set on the back-end"
+ " bricks", ret)
+ xattr_value.append(ret)
+ voltype = get_volume_type_info(self.mnode, self.volname)
+ if voltype['volume_type_info']['arbiterCount'] == '0':
+ ret = bool(xattr_value.count(xattr_value[0]) ==
+ len(xattr_value))
+ elif voltype['volume_type_info']['arbiterCount'] == '1':
+ ret = bool(((xattr_value.count(xattr_value[0])) or
+ (xattr_value.count(xattr_value[1])) > 1))
+ else:
+ g.log.error("Arbiter value is neither 0 nor 1")
+ if ctime:
+ self.assertTrue(ret, 'trusted.glusterfs.mdata' +
+ ' value not same across bricks for '
+ 'entry ' + each)
+ else:
+ self.assertTrue(ret, 'trusted.glusterfs.mdata' +
+ ' seems to be set on some bricks for ' +
+ each)
+
+ def data_create(self, dirname):
+ """Create different files and directories"""
+ dirname = self.mounts[0].mountpoint + '/' + dirname
+ list_of_fops = ["create", "rename", "chmod", "chown", "chgrp",
+ "hardlink", "truncate", "setxattr"]
+ for fops in list_of_fops:
+ ret = run_crefi(self.mounts[0].client_system,
+ dirname, 10, 3, 3, thread=4,
+ random_size=True, fop=fops, minfs=0,
+ maxfs=102400, multi=True, random_filename=True)
+ self.assertTrue(ret, "crefi failed during {}".format(fops))
+ g.log.info("crefi PASSED FOR fop %s", fops)
+ g.log.info("IOs were successful using crefi")
+
+ def data_delete(self, dirname):
+ """Delete created data"""
+ dirname = self.mounts[0].mountpoint + '/' + dirname
+ ret = rmdir(self.mounts[0].client_system, dirname, force=True)
+ self.assertTrue(ret, 'deletion of data failed')
+
+ def test_consistent_timestamps_feature(self):
+ '''
+ Test Steps:
+ 1. Create a volume, enable features.ctime, mount volume
+ 2. Create different files and directories
+ 3. For each entry trusted.glusterfs.mdata must be set
+ 4. For every entry, above xattr must match on each brick of replicaset
+ 5. Delete all data created
+ 6. turn off features.ctime
+ 7. Again create different files and directories
+ 8. "glusterfs.mdata xattr" must not be present for any entry
+ 9. Delete created data
+ '''
+ # pylint: disable=too-many-statements
+
+ # Enable features.ctime
+ ret = set_volume_options(self.mnode, self.volname,
+ {'features.ctime': 'on'})
+ self.assertTrue(ret, 'failed to enable ctime feature on %s'
+ % self.volume)
+ g.log.info("Successfully enabled ctime feature on %s", self.volume)
+
+ # Create different files and directories
+ self.data_create('ctime-on')
+
+ # Check if mdata xattr has been set for all entries
+ # Check if the values are same across all replica copies
+ self.validate_xattr_values('ctime-on')
+
+ # Delete all the existing data
+ self.data_delete('ctime-on')
+
+ # Disable features.ctime
+ ret = set_volume_options(self.mnode, self.volname,
+ {'features.ctime': 'off'})
+ self.assertTrue(ret, 'failed to disable features_ctime feature on %s'
+ % self.volume)
+ g.log.info("Successfully disabled ctime feature on %s", self.volume)
+
+ # Create different files and directories
+ self.data_create('ctime-off')
+
+ # Check that mdata xattr has not been set for any entries
+ self.validate_xattr_values('ctime-off', ctime=False)
+
+ # Delete all the existing data
+ self.data_delete('ctime-off')