From e76b089062a55967aa39d408aadfe05e42a87b15 Mon Sep 17 00:00:00 2001 From: sayaleeraut Date: Mon, 7 Sep 2020 13:18:23 +0530 Subject: [Test] Validate copy of directory This test script verifies below scenarios: 1)Sub-volume is down copy directory 2)Sub-volume is down copy directory - destination dir hash to up sub-volume 3)Sub-volume is down copy newly created directory - destination dir hash to up sub-volume 4)Sub-volume is down copy newly created directory - destination dir hash to down sub-volume Change-Id: I22b9bf79ef4775b1128477fb858c509a719efb4a Signed-off-by: sayaleeraut --- tests/functional/dht/test_copy_dir_subvol_down.py | 308 ++++++++++++++++++++++ 1 file changed, 308 insertions(+) create mode 100644 tests/functional/dht/test_copy_dir_subvol_down.py (limited to 'tests/functional/dht') diff --git a/tests/functional/dht/test_copy_dir_subvol_down.py b/tests/functional/dht/test_copy_dir_subvol_down.py new file mode 100644 index 000000000..8835bcada --- /dev/null +++ b/tests/functional/dht/test_copy_dir_subvol_down.py @@ -0,0 +1,308 @@ +# Copyright (C) 2020 Red Hat, Inc. +# +# 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 glusto.core import Glusto as g +from glustolibs.gluster.exceptions import ExecutionError +from glustolibs.gluster.gluster_base_class import GlusterBaseClass, runs_on +from glustolibs.gluster.glusterdir import mkdir +from glustolibs.io.utils import collect_mounts_arequal, validate_io_procs +from glustolibs.misc.misc_libs import upload_scripts +from glustolibs.gluster.dht_test_utils import (find_hashed_subvol, + find_new_hashed) +from glustolibs.gluster.volume_libs import get_subvols +from glustolibs.gluster.brick_libs import bring_bricks_offline + + +@runs_on([['distributed', 'distributed-replicated', + 'distributed-arbiter', 'distributed-dispersed'], + ['glusterfs']]) +class TestCopyDirSubvolDown(GlusterBaseClass): + @classmethod + def setUpClass(cls): + cls.get_super_method(cls, 'setUpClass')() + + # Check for the default dist_count value and override it if required + if cls.default_volume_type_config['distributed']['dist_count'] <= 2: + cls.default_volume_type_config['distributed']['dist_count'] = 4 + else: + cls.default_volume_type_config[cls.voltype]['dist_count'] = 3 + + # Upload io scripts for running IO on mounts + cls.script_upload_path = ("/usr/share/glustolibs/io/scripts/" + "file_dir_ops.py") + ret = upload_scripts(cls.clients, cls.script_upload_path) + if not ret: + raise ExecutionError("Failed to upload IO scripts " + "to clients %s" % cls.clients) + g.log.info("Successfully uploaded IO scripts to clients %s", + cls.clients) + + def setUp(self): + + # Calling GlusterBaseClass setUp + self.get_super_method(self, 'setUp')() + + # Setup Volume and Mount Volume + ret = self.setup_volume_and_mount_volume([self.mounts[0]]) + 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): + + # Unmount and cleanup original volume + 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") + + # Calling GlusterBaseClass tearDown + self.get_super_method(self, 'tearDown')() + + def _create_src(self, m_point): + """ + Create the source directory and files under the + source directory. + """ + # Create source dir + ret = mkdir(self.mounts[0].client_system, "{}/src_dir".format(m_point)) + self.assertTrue(ret, "mkdir of src_dir failed") + + # Create files inside source dir + cmd = ("/usr/bin/env python %s create_files " + "-f 100 %s/src_dir/" % ( + self.script_upload_path, m_point)) + proc = g.run_async(self.mounts[0].client_system, + cmd, user=self.mounts[0].user) + g.log.info("IO on %s:%s is started successfully", + self.mounts[0].client_system, m_point) + + # Validate IO + self.assertTrue( + validate_io_procs([proc], self.mounts[0]), + "IO failed on some of the clients" + ) + + def _copy_files_check_contents(self, m_point, dest_dir): + """ + Copy files from source directory to destination + directory when it hashes to up-subvol and check + if all the files are copied properly. + """ + # pylint: disable=protected-access + # collect arequal checksum on src dir + ret, src_checksum = collect_mounts_arequal( + self.mounts[0], '{}/src_dir'.format(m_point)) + self.assertTrue(ret, ("Failed to get arequal on client" + " {}".format(self.clients[0]))) + + # copy src_dir to dest_dir + command = "cd {}; cp -r src_dir {}".format(m_point, dest_dir) + ret, _, _ = g.run(self.mounts[0].client_system, command) + self.assertEqual(ret, 0, "Failed to copy of src dir to" + " dest dir") + g.log.info("Successfully copied src dir to dest dir.") + + # collect arequal checksum on destination dir + ret, dest_checksum = collect_mounts_arequal( + self.mounts[0], '{}/{}'.format(m_point, dest_dir)) + self.assertTrue(ret, ("Failed to get arequal on client" + " {}".format(self.mounts[0]))) + + # Check if the contents of src dir are copied to + # dest dir + self.assertEqual(src_checksum, + dest_checksum, + 'All the contents of src dir are not' + ' copied to dest dir') + g.log.info('Successfully copied the contents of src dir' + ' to dest dir') + + def _copy_when_dest_hash_down(self, m_point, dest_dir): + """ + Copy files from source directory to destination + directory when it hashes to down-subvol. + """ + # pylint: disable=protected-access + # copy src_dir to dest_dir (should fail as hash subvol for dest + # dir is down) + command = "cd {}; cp -r src_dir {}".format(m_point, dest_dir) + ret, _, _ = g.run(self.mounts[0].client_system, command) + self.assertEqual(ret, 1, "Unexpected : Copy of src dir to" + " dest dir passed") + g.log.info("Copy of src dir to dest dir failed as expected.") + + def test_copy_existing_dir_dest_subvol_down(self): + """ + Case 1: + - Create directory from mount point. + - Copy dir ---> Bring down dht sub-volume where destination + directory hashes to down sub-volume. + - Copy directory and make sure destination dir does not exist + """ + # pylint: disable=protected-access + m_point = self.mounts[0].mountpoint + + # Create source dir + ret = mkdir(self.mounts[0].client_system, "{}/src_dir".format(m_point)) + self.assertTrue(ret, "mkdir of src_dir failed") + g.log.info("Directory src_dir created successfully") + + # Get subvol list + subvols = (get_subvols(self.mnode, self.volname))['volume_subvols'] + self.assertIsNotNone(subvols, "Failed to get subvols") + + # Find out the destination dir name such that it hashes to + # different subvol + newdir = find_new_hashed(subvols, "/", "src_dir") + dest_dir = str(newdir.newname) + dest_count = newdir.subvol_count + + # Kill the brick/subvol to which the destination dir hashes + ret = bring_bricks_offline( + self.volname, subvols[dest_count]) + self.assertTrue(ret, ('Error in bringing down subvolume %s', + subvols[dest_count])) + g.log.info('DHT subvol %s is offline', subvols[dest_count]) + + # Copy src_dir to dest_dir (should fail as hash subvol for dest + # dir is down) + self._copy_when_dest_hash_down(m_point, dest_dir) + + def test_copy_existing_dir_dest_subvol_up(self): + """ + Case 2: + - Create files and directories from mount point. + - Copy dir ---> Bring down dht sub-volume where destination + directory should not hash to down sub-volume + - copy dir and make sure destination dir does not exist + """ + # pylint: disable=protected-access + m_point = self.mounts[0].mountpoint + + # Create source dir and create files inside it + self._create_src(m_point) + + # Get subvol list + subvols = (get_subvols(self.mnode, self.volname))['volume_subvols'] + self.assertIsNotNone(subvols, "Failed to get subvols") + + # Find out hashed brick/subvol for src dir + src_subvol, src_count = find_hashed_subvol(subvols, "/", "src_dir") + self.assertIsNotNone(src_subvol, "Could not find srchashed") + g.log.info("Hashed subvol for src_dir is %s", src_subvol._path) + + # Find out the destination dir name such that it hashes to + # different subvol + newdir = find_new_hashed(subvols, "/", "src_dir") + dest_dir = str(newdir.newname) + dest_count = newdir.subvol_count + + # Remove the hashed subvol for dest and src dir from the + # subvol list + for item in (subvols[src_count], subvols[dest_count]): + subvols.remove(item) + + # Bring down a DHT subvol + ret = bring_bricks_offline(self.volname, subvols[0]) + self.assertTrue(ret, ('Error in bringing down subvolume %s', + subvols[0])) + g.log.info('DHT subvol %s is offline', subvols[0]) + + # Create files on source dir and + # perform copy of src_dir to dest_dir + self._copy_files_check_contents(m_point, dest_dir) + + def test_copy_new_dir_dest_subvol_up(self): + """ + Case 3: + - Copy dir ---> Bring down dht sub-volume where destination + directory should not hash to down sub-volume + - Create files and directories from mount point. + - copy dir and make sure destination dir does not exist + """ + # pylint: disable=protected-access + # pylint: disable=too-many-statements + m_point = self.mounts[0].mountpoint + + # Get subvols + subvols = (get_subvols(self.mnode, self.volname))['volume_subvols'] + self.assertIsNotNone(subvols, "Failed to get subvols") + + # Find out hashed brick/subvol for src dir + src_subvol, src_count = find_hashed_subvol( + subvols, "/", "src_dir") + self.assertIsNotNone(src_subvol, "Could not find srchashed") + g.log.info("Hashed subvol for src_dir is %s", src_subvol._path) + + # Find out the destination dir name such that it hashes to + # different subvol + newdir = find_new_hashed(subvols, "/", "src_dir") + dest_dir = str(newdir.newname) + dest_count = newdir.subvol_count + + # Remove the hashed subvol for dest and src dir from the + # subvol list + for item in (subvols[src_count], subvols[dest_count]): + subvols.remove(item) + + # Bring down a dht subvol + ret = bring_bricks_offline(self.volname, subvols[0]) + self.assertTrue(ret, ('Error in bringing down subvolume %s', + subvols[0])) + g.log.info('DHT subvol %s is offline', subvols[0]) + + # Create source dir and create files inside it + self._create_src(m_point) + + # Create files on source dir and + # perform copy of src_dir to dest_dir + self._copy_files_check_contents(m_point, dest_dir) + + def test_copy_new_dir_dest_subvol_down(self): + """ + Case 4: + - Copy dir ---> Bring down dht sub-volume where destination + directory hashes to down sub-volume + - Create directory from mount point. + - Copy dir and make sure destination dir does not exist + """ + # pylint: disable=protected-access + m_point = self.mounts[0].mountpoint + + # Get subvol list + subvols = (get_subvols(self.mnode, self.volname))['volume_subvols'] + self.assertIsNotNone(subvols, "Failed to get subvols") + + # Find out the destination dir name such that it hashes to + # different subvol + newdir = find_new_hashed(subvols, "/", "src_dir") + dest_dir = str(newdir.newname) + dest_count = newdir.subvol_count + + # Bring down the hashed-subvol for dest dir + ret = bring_bricks_offline(self.volname, subvols[dest_count]) + self.assertTrue(ret, ('Error in bringing down subvolume %s', + subvols[dest_count])) + g.log.info('DHT subvol %s is offline', subvols[dest_count]) + + # Create source dir + ret = mkdir(self.mounts[0].client_system, "{}/src_dir".format(m_point)) + self.assertTrue(ret, "mkdir of src_dir failed") + g.log.info("Directory src_dir created successfully") + + # Copy src_dir to dest_dir (should fail as hash subvol for dest + # dir is down) + self._copy_when_dest_hash_down(m_point, dest_dir) -- cgit