summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tests/functional/disperse/test_ec_file_rename_on_brick_down.py221
1 files changed, 221 insertions, 0 deletions
diff --git a/tests/functional/disperse/test_ec_file_rename_on_brick_down.py b/tests/functional/disperse/test_ec_file_rename_on_brick_down.py
new file mode 100644
index 0000000..afdb223
--- /dev/null
+++ b/tests/functional/disperse/test_ec_file_rename_on_brick_down.py
@@ -0,0 +1,221 @@
+# 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-131 USA.
+
+from random import choice
+from time import sleep
+
+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.brick_libs import get_all_bricks, bring_bricks_offline
+from glustolibs.gluster.volume_libs import volume_start
+from glustolibs.gluster.glusterfile import create_link_file
+
+
+@runs_on([['replicated', 'dispersed', 'distributed-dispersed'], ['glusterfs']])
+class TestECRenameFilesOnBrickDown(GlusterBaseClass):
+
+ # pylint: disable=too-many-statements,too-many-locals
+ def setUp(self):
+ self.get_super_method(self, 'setUp')()
+
+ # Remove on fixing BZ 1596165
+ if 'dispersed' in self.volname:
+ self.skipTest("Test will fail due to BZ 1596165")
+
+ # Setup and mount volume
+ ret = self.setup_volume_and_mount_volume(self.mounts)
+ if not ret:
+ raise ExecutionError("Failed to setup and mount volume")
+
+ def tearDown(self):
+
+ # Unmount and cleanup volume
+ ret = self.unmount_volume_and_cleanup_volume(self.mounts)
+ if not ret:
+ raise ExecutionError("Failed to unmount and cleanup volume")
+
+ self.get_super_method(self, 'tearDown')()
+
+ def create_links(self, client, path):
+
+ # Soft links
+ for i in range(4, 7):
+ ret = create_link_file(client,
+ '{}/file{}_or'.format(path, i),
+ '{}/file{}_sl'.format(path, i), soft=True)
+ self.assertTrue(ret, "Fail: Not able to create soft link for "
+ "{}/file{}_or".format(path, i))
+ g.log.info("Created soft links for files successfully")
+
+ # Hard links
+ for i in range(7, 10):
+ ret = create_link_file(client,
+ '{}/file{}_or'.format(path, i),
+ '{}/file{}_hl'.format(path, i),)
+ self.assertTrue(ret, "Fail: Not able to create hard link for "
+ "{}/file{}_or".format(path, i))
+ g.log.info("Created hard links for files successfully")
+
+ def test_ec_rename_files_with_brick_down(self):
+ """
+ Description: Test to check no errors on file/dir renames when one of
+ the bricks is down in the volume.
+ Steps:
+ 1. Create an EC volume
+ 2. Mount the volume using FUSE on two different clients
+ 3. Create ~9 files from one of the client
+ 4. Create ~9 dir with ~9 files each from another client
+ 5. Create soft-links, hard-links for file{4..6}, file{7..9}
+ 6. Create soft-links for dir{4..6}
+ 7. Begin renaming the files, in multiple iterations
+ 8. Bring down a brick while renaming the files
+ 9. Bring the brick online after renaming some of the files
+ 10. Wait for renaming of the files
+ 11. Validate no data loss and files are renamed successfully
+ """
+
+ # Creating ~9 files from client 1 on mount
+ m_point = self.mounts[0].mountpoint
+ cmd = 'cd %s; touch file{1..9}_or' % m_point
+ ret, _, _ = g.run(self.clients[0], cmd)
+ self.assertEqual(ret, 0, "Fail: Not able to create files on "
+ "{}".format(m_point))
+ g.log.info("Files created successfully on mount point")
+
+ # Creating 9 dir X 9 files in each dir from client 2
+ cmd = ('cd %s; mkdir -p dir{1..9}_or; touch '
+ 'dir{1..9}_or/file{1..9}_or' % m_point)
+ ret, _, _ = g.run(self.clients[1], cmd)
+ self.assertEqual(ret, 0, "Fail: Not able to create dir with files on "
+ "{}".format(m_point))
+ g.log.info("Dirs with files are created successfully on mount point")
+
+ # Create required soft links and hard links from client 1 on mount
+ client, path = self.clients[0], m_point
+ self.create_links(client, path)
+
+ client = self.clients[1]
+ for i in range(1, 10):
+
+ # Create required soft and hard links in nested dirs
+ path = '{}/dir{}_or'.format(m_point, i)
+ self.create_links(client, path)
+
+ # Create soft links for dirs
+ path = m_point
+ for i in range(4, 7):
+ ret = create_link_file(client,
+ '{}/dir{}_or'.format(path, i),
+ '{}/dir{}_sl'.format(path, i), soft=True)
+ self.assertTrue(ret, "Fail: Not able to create soft link for "
+ "{}/dir{}_or".format(path, i))
+ g.log.info("Created nested soft and hard links for files successfully")
+
+ # Calculate all file count against each section orginal, hard, soft
+ # links
+ cmd = ('cd %s; arr=(or sl hl); '
+ 'for i in ${arr[*]}; do find . -name "*$i" | wc -l ; '
+ 'done; ' % m_point)
+ ret, out, _ = g.run(client, cmd)
+ self.assertEqual(ret, 0, "Not able get list of soft and hard links "
+ "created on the mount point")
+ all_org, all_soft, all_hard = out.split()
+
+ # Rename 2 out of 3 dir's soft links from client 1
+ client = self.clients[0]
+ cmd = ('cd %s; sl=0; '
+ 'for line in `ls -R | grep -P "dir(4|5)_sl"`; '
+ 'do mv -f "$line" "$line""_renamed"; ((sl++)); done; '
+ 'echo $sl;' % m_point)
+ ret, out, _ = g.run(client, cmd)
+ self.assertEqual(ret, 0, "Not able to rename directory soft links")
+ temp_soft = out.strip()
+
+ # Start renaming original files from client 1 and
+ # softlinks, hardlinks from client 2
+ cmd = ('cd %s; arr=(. dir{1..9}_or); or=0; '
+ 'for item in ${arr[*]}; do '
+ 'cd $item; '
+ 'for line in `ls | grep -P "file(1|2)_or"`; '
+ 'do mv -f "$line" "$line""_renamed"; ((or++)); sleep 2; done;'
+ 'cd - > /dev/null; sleep 1; done; echo $or ' % m_point)
+ proc_or = g.run_async(client, cmd)
+
+ client = self.clients[1]
+ cmd = ('cd %s; arr=(. dir{1..9}_or); sl=0; hl=0; '
+ 'for item in ${arr[*]}; do '
+ 'cd $item; '
+ 'for line in `ls | grep -P "file(4|5)_sl"`; '
+ 'do mv -f "$line" "$line""_renamed"; ((sl++)); sleep 1; done; '
+ 'for line in `ls | grep -P "file(7|8)_hl"`; '
+ 'do mv -f "$line" "$line""_renamed"; ((hl++)); sleep 1; done; '
+ 'cd - > /dev/null; sleep 1; done; echo $sl $hl; ' % m_point)
+ proc_sl_hl = g.run_async(client, cmd)
+
+ # Wait for some files to be renamed
+ sleep(20)
+
+ # Kill one of the bricks
+ brick_list = get_all_bricks(self.mnode, self.volname)
+ ret = bring_bricks_offline(self.volname, choice(brick_list))
+ self.assertTrue(ret, "Failed to bring one of the bricks offline")
+
+ # Wait for some more files to be renamed
+ sleep(20)
+
+ # Bring brick online
+ ret, _, _ = volume_start(self.mnode, self.volname, force=True)
+ self.assertEqual(ret, 0, "Not able to start Volume with force option")
+
+ # Wait for rename to complete and take count of file operations
+ ret, out, _ = proc_or.async_communicate()
+ self.assertEqual(ret, 0, "Fail: Origianl files are not renamed")
+ ren_org = out.strip()
+
+ ret, out, _ = proc_sl_hl.async_communicate()
+ self.assertEqual(ret, 0, "Fail: Soft and Hard links are not renamed")
+ ren_soft, ren_hard = out.strip().split()
+ ren_soft = str(int(ren_soft) + int(temp_soft))
+
+ # Count actual data of renaming links/files
+ cmd = ('cd %s; arr=(or or_renamed sl sl_renamed hl hl_renamed); '
+ 'for i in ${arr[*]}; do find . -name "*$i" | wc -l ; '
+ 'done; ' % m_point)
+ ret, out, _ = g.run(client, cmd)
+ self.assertEqual(ret, 0, "Not able to get count of original and link "
+ "files after brick was brought up")
+ (act_org, act_org_ren, act_soft,
+ act_soft_ren, act_hard, act_hard_ren) = out.split()
+
+ # Validate count of expected and actual rename of
+ # links/files is matching
+ for exp, act, msg in ((ren_org, act_org_ren, 'original'),
+ (ren_soft, act_soft_ren, 'soft links'),
+ (ren_hard, act_hard_ren, 'hard links')):
+ self.assertEqual(exp, act, "Count of {} files renamed while brick "
+ "was offline is not matching".format(msg))
+
+ # Validate no data is lost in rename process
+ for exp, act, msg in (
+ (int(all_org)-int(act_org_ren), int(act_org), 'original'),
+ (int(all_soft)-int(act_soft_ren), int(act_soft), 'soft links'),
+ (int(all_hard)-int(act_hard_ren), int(act_hard), 'hard links'),
+ ):
+ self.assertEqual(exp, act, "Count of {} files which are not "
+ "renamed while brick was offline "
+ "is not matching".format(msg))