summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xglustolibs-gluster/glustolibs/gluster/glusterfile.py33
-rw-r--r--tests/functional/disperse/test_no_fresh_lookup_on_directory.py183
2 files changed, 216 insertions, 0 deletions
diff --git a/glustolibs-gluster/glustolibs/gluster/glusterfile.py b/glustolibs-gluster/glustolibs/gluster/glusterfile.py
index 4d712a5f3..97eb50163 100755
--- a/glustolibs-gluster/glustolibs/gluster/glusterfile.py
+++ b/glustolibs-gluster/glustolibs/gluster/glusterfile.py
@@ -480,6 +480,39 @@ def check_if_pattern_in_file(host, pattern, fqpath):
return 0
+def occurences_of_pattern_in_file(node, search_pattern, filename):
+ """
+ Get the number of occurences of pattern in the file
+
+ Args:
+ node (str): Host on which the command is executed.
+ search_pattern (str): Pattern to be found in the file.
+ filename (str): File in which the pattern is to be validated
+
+ Returns:
+ (int): (-1), When the file doesn't exists.
+ (0), When pattern doesn't exists in the file.
+ (number), When pattern is found and the number of
+ occurences of pattern in the file.
+
+ Example:
+ occurences_of_pattern_in_file(node, search_pattern, filename)
+ """
+
+ ret = file_exists(node, filename)
+ if not ret:
+ g.log.error("File %s is not present on the node " % filename)
+ return -1
+
+ cmd = ("grep -c '%s' %s" % (search_pattern, filename))
+ ret, out, _ = g.run(node, cmd)
+ if ret:
+ g.log.error("No occurence of the pattern found in the file %s" %
+ filename)
+ return 0
+ return int(out.strip('\n'))
+
+
class GlusterFile(object):
"""Class to handle files specific to Gluster (client and backend)"""
def __init__(self, host, fqpath):
diff --git a/tests/functional/disperse/test_no_fresh_lookup_on_directory.py b/tests/functional/disperse/test_no_fresh_lookup_on_directory.py
new file mode 100644
index 000000000..7be18b4e1
--- /dev/null
+++ b/tests/functional/disperse/test_no_fresh_lookup_on_directory.py
@@ -0,0 +1,183 @@
+# 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 random import choice
+
+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.gluster.glusterdir import mkdir
+from glustolibs.gluster.brickdir import file_exists
+from glustolibs.gluster.mount_ops import mount_volume, umount_volume
+from glustolibs.gluster.volume_libs import set_volume_options, get_subvols
+from glustolibs.gluster.glusterfile import occurences_of_pattern_in_file
+from glustolibs.gluster.brick_libs import (bring_bricks_offline,
+ get_online_bricks_list)
+from glustolibs.gluster.volume_ops import volume_start
+from glustolibs.gluster.volume_libs import wait_for_volume_process_to_be_online
+
+
+@runs_on([['distributed-dispersed', 'distributed-replicated',
+ 'distributed-arbiter'], ['glusterfs']])
+class TestNoFreshLookUpBrickDown(GlusterBaseClass):
+
+ def setUp(self):
+ """
+ setUp method for every test
+ """
+ # calling GlusterBaseClass setUp
+ self.get_super_method(self, 'setUp')()
+
+ # Setting client log-level to Debug
+ self.volume['options'] = {'diagnostics.client-log-level': 'DEBUG'}
+
+ # Creating Volume and mounting
+ ret = self.setup_volume()
+ if not ret:
+ raise ExecutionError("Volume creation failed: %s" % self.volname)
+ g.log.info("Volume is created and started")
+
+ def tearDown(self):
+ """
+ tearDown method for every test
+ """
+ # Calling GlusterBaseClass tearDown
+ self.get_super_method(self, 'tearDown')()
+
+ ret = umount_volume(mclient=self.mounts[0].client_system,
+ mpoint=self.mountpoint)
+ if not ret:
+ raise ExecutionError("Unable to umount the volume")
+ g.log.info("Unmounting of the volume %s succeeded", self.volname)
+
+ # Resetting the volume option set in the setup
+ ret = set_volume_options(self.mnode, self.volname,
+ {'diagnostics.client-log-level': 'INFO'})
+ if not ret:
+ raise ExecutionError("Unable to set the client log level to INFO")
+ g.log.info("Volume option is set successfully.")
+
+ ret = self.cleanup_volume()
+ if not ret:
+ raise ExecutionError("Unable to perform volume clenaup")
+ g.log.info("Volume cleanup is successfull")
+
+ def do_lookup(self, dirname):
+ """
+ Performes a look up on the directory.
+ """
+ ret = file_exists(self.mounts[0].client_system, dirname)
+ self.assertTrue(ret, "Directory %s doesn't exists " % dirname)
+ g.log.info("Directory present on the %s",
+ self.mounts[0].client_system)
+
+ def match_occurences(self, first_count, search_pattern, filename):
+ """
+ Validating the count of the search pattern before and after
+ lookup.
+ """
+ newcount = occurences_of_pattern_in_file(self.mounts[0].client_system,
+ search_pattern, filename)
+ self.assertEqual(first_count, newcount, "Failed: The lookups logged"
+ " for the directory <dirname> are more than expected")
+ g.log.info("No more new lookups for the dir1")
+
+ def test_no_fresh_lookup(self):
+ """
+ The testcase covers negative lookup of a directory in distributed-
+ replicated and distributed-dispersed volumes
+ 1. Mount the volume on one client.
+ 2. Create a directory
+ 3. Validate the number of lookups for the directory creation from the
+ log file.
+ 4. Perform a new lookup of the directory
+ 5. No new lookups should have happened on the directory, validate from
+ the log file.
+ 6. Bring down one subvol of the volume and repeat step 4, 5
+ 7. Bring down one brick from the online bricks and repeat step 4, 5
+ 8. Start the volume with force and wait for all process to be online.
+ """
+
+ # Mounting the volume on a distinct directory for the validation of
+ # testcase
+ self.mountpoint = "/mnt/" + self.volname
+ ret, _, _ = mount_volume(self.volname, mtype=self.mount_type,
+ mpoint=self.mountpoint,
+ mserver=self.mnode,
+ mclient=self.mounts[0].client_system)
+ self.assertEqual(ret, 0, ("Volume %s is not mounted") % self.volname)
+ g.log.info("Volume mounted successfully : %s", self.volname)
+
+ # Distinct log file for the validation of this test
+ filename = "/var/log/glusterfs/mnt-" + self.volname + ".log"
+ # Creating a dir on the mount point.
+ dirname = self.mountpoint + "/dir1"
+ ret = mkdir(host=self.mounts[0].client_system, fqpath=dirname)
+ self.assertTrue(ret, "Failed to create dir1")
+ g.log.info("dir1 created successfully for %s",
+ self.mounts[0].client_system)
+
+ search_pattern = "/dir1: Calling fresh lookup"
+
+ # Check log file for the pattern in the log file
+ first_count = occurences_of_pattern_in_file(
+ self.mounts[0].client_system, search_pattern, filename)
+ self.assertGreater(first_count, 0, "Unable to find "
+ "pattern in the given file")
+ g.log.info("Searched for the pattern in the log file successfully")
+
+ # Perform a lookup of the directory dir1
+ self.do_lookup(dirname)
+
+ # Recheck for the number of lookups from the log file
+ self.match_occurences(first_count, search_pattern, filename)
+
+ # Bring down one subvol of the volume
+ ret = get_subvols(self.mnode, self.volname)
+ brick_list = choice(ret['volume_subvols'])
+ ret = bring_bricks_offline(self.volname, brick_list)
+ self.assertTrue(ret, "Unable to bring the given bricks offline")
+ g.log.info("Able to bring all the bricks in the subvol offline")
+
+ # Do a lookup on the mountpoint for the directory dir1
+ self.do_lookup(dirname)
+
+ # Re-check the number of occurences of lookup
+ self.match_occurences(first_count, search_pattern, filename)
+
+ # From the online bricks, bring down one brick
+ online_bricks = get_online_bricks_list(self.mnode, self.volname)
+ self.assertIsNotNone(online_bricks, "Unable to fetch online bricks")
+ g.log.info("Able to fetch the online bricks")
+ offline_brick = choice(online_bricks)
+ ret = bring_bricks_offline(self.volname, [offline_brick])
+ self.assertTrue(ret, "Unable to bring the brick %s offline " %
+ offline_brick)
+ g.log.info("Successfully brought the brick %s offline", offline_brick)
+
+ # Do a lookup on the mounpoint and check for new lookups from the log
+ self.do_lookup(dirname)
+ self.match_occurences(first_count, search_pattern, filename)
+
+ # Start volume with force
+ ret, _, err = volume_start(self.mnode, self.volname, force=True)
+ self.assertEqual(ret, 0, "Unable to force start the volume %s " % err)
+ g.log.info("Volume started successfully")
+
+ # Wait for all the processess to be online.
+ ret = wait_for_volume_process_to_be_online(self.mnode, self.volname)
+ self.assertTrue(ret, "Some processes are offline")
+ g.log.info("All processes of the volume")