From 32db5f9e2dad354f56418feeb15808f2739612f8 Mon Sep 17 00:00:00 2001 From: srivickynesh Date: Thu, 7 Jun 2018 16:43:43 +0530 Subject: [Test] Start/Stop of snapd deamon on the cloned volume Test Cases in this module tests the USS functionality of snapshots snapd on cloned volume and validated snapshots are present inside .snaps directory by terminating snapd on one by one nodes and validating .snaps directory is still accessible. Change-Id: I98d48268e7c5c5952a7f0f544960203d8634b7ac Signed-off-by: Sri Vignesh --- glustolibs-gluster/glustolibs/gluster/snap_ops.py | 28 +- tests/functional/snapshot/test_snap_uss_snapd.py | 377 ++++++++++++++++++++++ 2 files changed, 404 insertions(+), 1 deletion(-) create mode 100644 tests/functional/snapshot/test_snap_uss_snapd.py diff --git a/glustolibs-gluster/glustolibs/gluster/snap_ops.py b/glustolibs-gluster/glustolibs/gluster/snap_ops.py index 1e792ada7..0fba7771b 100644 --- a/glustolibs-gluster/glustolibs/gluster/snap_ops.py +++ b/glustolibs-gluster/glustolibs/gluster/snap_ops.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (C) 2015-2016 Red Hat, Inc. +# Copyright (C) 2015-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 @@ -859,3 +859,29 @@ def snap_deactivate(mnode, snapname): cmd = "gluster snapshot deactivate %s --mode=script" % snapname return g.run(mnode, cmd) + + +def terminate_snapd_on_node(mnode): + """Terminate snapd on the specified node + + Args: + mnode(str):node on which commands has to be executed + + Returns: + tuple: Tuple containing three elements (ret, out, err). + The first element 'ret' is of type 'int' and is the return value + of command execution. + + The second element 'out' is of type 'str' and is the stdout value + of the command execution. + + The third element 'err' is of type 'str' and is the stderr value + of the command execution. + """ + cmd = "ps aux| grep -m1 snapd | awk '{print $2}'" + _, out, _ = g.run(mnode, cmd) + if out is None: + g.log.error("Failed to get the snapd PID using command %s", cmd) + return None + cmd = "kill -9 %s" % out + return g.run(mnode, cmd) diff --git a/tests/functional/snapshot/test_snap_uss_snapd.py b/tests/functional/snapshot/test_snap_uss_snapd.py new file mode 100644 index 000000000..e008a679a --- /dev/null +++ b/tests/functional/snapshot/test_snap_uss_snapd.py @@ -0,0 +1,377 @@ +# 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. + +""" + Description: + Test Cases in this module tests the USS functionality + before and after snapd is killed. validate snapd after + volume is started with force option. +""" +from os import path +from time import sleep +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.misc.misc_libs import upload_scripts +from glustolibs.gluster.brick_libs import get_all_bricks +from glustolibs.gluster.mount_ops import (mount_volume, + is_mounted, unmount_mounts) +from glustolibs.gluster.volume_ops import (volume_start, + get_volume_info, + volume_stop) +from glustolibs.gluster.volume_libs import (log_volume_info_and_status, + cleanup_volume) +from glustolibs.gluster.snap_ops import (get_snap_list, + snap_create, + snap_activate, + snap_clone, terminate_snapd_on_node) +from glustolibs.gluster.uss_ops import (is_snapd_running, is_uss_enabled, + enable_uss, disable_uss, + uss_list_snaps) +from glustolibs.gluster.mount_ops import create_mount_objs +from glustolibs.io.utils import validate_io_procs, view_snaps_from_mount + + +@runs_on([['replicated', 'distributed-replicated', + 'dispersed', 'distributed-dispersed', 'distributed'], + ['glusterfs']]) +class SnapshotSnapdCloneVol(GlusterBaseClass): + + @classmethod + def setUpClass(cls): + cls.get_super_method(cls, 'setUpClass')() + cls.mount1 = [] + cls.mpoint = "/mnt/clone1" + cls.server_list = [] + cls.server_lists = [] + + # 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): + + self.snap = 'test_snap_clone_snapd-snap' + self.clone_vol1 = 'clone-of-test_snap_clone_snapd-clone1' + # SettingUp volume and Mounting the volume + self.get_super_method(self, 'setUp')() + ret = self.setup_volume_and_mount_volume(mounts=self.mounts) + if not ret: + raise ExecutionError("Failed to setup volume %s" % self.volname) + g.log.info("Volume %s has been setup successfully", self.volname) + + def validate_snapd(self, check_condition=True): + """ Validate snapd running """ + for server in self.server_list: + ret = is_snapd_running(server, self.clone_vol1) + if check_condition: + self.assertTrue( + ret, "Unexpected: Snapd is Not running for " + "volume %s on node %s" % (self.clone_vol1, server)) + g.log.info( + "Snapd Running for volume %s " + "on node: %s", self.clone_vol1, server) + else: + self.assertFalse( + ret, "Unexpected: Snapd is running for" + "volume %s on node %s" % (self.clone_vol1, server)) + g.log.info("Expected: Snapd is not Running for volume" + " %s on node: %s", self.clone_vol1, server) + + def check_snaps(self): + """ Check snapshots under .snaps folder """ + ret, _, _ = uss_list_snaps(self.clients[0], self.mpoint) + self.assertEqual(ret, 0, "Unexpected: .snaps directory not found") + g.log.info("Expected: .snaps directory is present") + + def validate_uss(self): + """ Validate USS running """ + ret = is_uss_enabled(self.mnode, self.clone_vol1) + self.assertTrue(ret, "USS is disabled in clone volume " + "%s" % self.clone_vol1) + g.log.info("USS enabled in cloned Volume %s", self.clone_vol1) + + def validate_snaps(self): + """ Validate snapshots under .snaps folder """ + for count in range(0, 40): + ret = view_snaps_from_mount(self.mount1, self.snaps_list) + if ret: + break + sleep(2) + count += 1 + self.assertTrue(ret, "Failed to lists .snaps folder") + g.log.info("Successfully validated snapshots from .snaps folder") + + def test_snap_clone_snapd(self): + """ + Steps: + + 1. create a volume + 2. Create a snapshots and activate + 3. Clone the snapshot and mount it + 4. Check for snapd daemon + 5. enable uss and validate snapd + 5. stop cloned volume + 6. Validate snapd + 7. start cloned volume + 8. validate snapd + 9. Create 5 more snapshot + 10. Validate total number of + snapshots created. + 11. Activate 5 snapshots + 12. Enable USS + 13. Validate snapd + 14. kill snapd on all nodes + 15. validate snapd running + 16. force start clone volume + 17. validate snaps inside .snaps directory + """ + # pylint: disable=too-many-statements, too-many-locals + + # Starting I/O + all_mounts_procs = [] + for mount_obj in self.mounts: + cmd = ("/usr/bin/env python %s create_files " + "-f 10 --base-file-name file %s" % ( + self.script_upload_path, + mount_obj.mountpoint)) + proc = g.run_async(mount_obj.client_system, cmd, + user=mount_obj.user) + all_mounts_procs.append(proc) + + # Validate I/O + ret = validate_io_procs(all_mounts_procs, self.mounts) + self.assertTrue(ret, "IO failed on some of the clients") + g.log.info("IO is successful on all mounts") + + # Creating snapshot + ret, _, _ = snap_create(self.mnode, self.volname, self.snap) + self.assertEqual(ret, 0, ("Failed to create snapshot for volume %s" + % self.volname)) + g.log.info("Snapshot %s created successfully for " + "volume %s", self.snap, self.volname) + + # Activating created snapshots + ret, _, _ = snap_activate(self.mnode, self.snap) + self.assertEqual(ret, 0, ("Failed to activate snapshot %s" + % self.snap)) + g.log.info("Snapshot snap%s activated successfully", self.snap) + + # Snapshot list + self.assertIsNotNone( + get_snap_list(self.mnode), "Failed to list snapshot") + g.log.info("Snapshot list command Successful") + + # Creating and starting a Clone of snapshot: + ret, _, _ = snap_clone(self.mnode, self.snap, self.clone_vol1) + self.assertEqual(ret, 0, "Failed to clone %s" % self.clone_vol1) + g.log.info("Clone volume %s created successfully", self.clone_vol1) + + # Start the clone volumes + ret, _, _ = volume_start(self.mnode, self.clone_vol1) + self.assertEqual(ret, 0, "Failed to start %s" % self.clone_vol1) + g.log.info("%s started successfully", self.clone_vol1) + + # Form server list + brick_list = get_all_bricks(self.mnode, self.clone_vol1) + for bricks in brick_list: + self.server_lists.append(bricks.split(":")[0]) + self.server_list = list(set(self.server_lists)) + + # Get volume info + vol_info = get_volume_info(self.mnode, self.clone_vol1) + self.assertIsNotNone(vol_info, "Failed to get vol info") + g.log.info("Successfully in getting vol info") + + # Redefining mounts for cloned volume + self.mount_points, self.mounts_dict_list = [], [] + for client in self.all_clients_info: + mount = { + 'protocol': self.mount_type, + 'server': self.mnode, + 'volname': self.volname, + 'client': self.all_clients_info[client], + 'mountpoint': (path.join( + "%s" % self.mpoint)), + 'options': '' + } + self.mounts_dict_list.append(mount) + self.mount1 = create_mount_objs(self.mounts_dict_list) + self.mount_points.append(self.mpoint) + g.log.info("Successfully made entry in self.mount1") + + # FUSE mount clone1 volume + for mount_obj in self.mounts: + ret, _, _ = mount_volume(self.clone_vol1, self.mount_type, + self.mpoint, + self.mnode, mount_obj.client_system) + self.assertEqual(ret, 0, "Volume mount failed for clone1") + g.log.info("%s mounted Successfully", self.clone_vol1) + + # Validate clone volume is mounted or not + ret = is_mounted(self.clone_vol1, self.mpoint, self.mnode, + mount_obj.client_system, self.mount_type) + self.assertTrue(ret, "Volume not mounted on mount point: " + "%s" % self.mpoint) + g.log.info("Volume %s mounted on %s", self.clone_vol1, self.mpoint) + + # Log Cloned Volume information + ret = log_volume_info_and_status(self.mnode, self.clone_vol1) + self.assertTrue("Failed to Log Info and Status of Volume " + "%s" % self.clone_vol1) + g.log.info("Successfully Logged Info and Status") + + # Validate snapd running on all nodes + self.validate_snapd(check_condition=False) + + # Enable USS + ret, _, _ = enable_uss(self.mnode, self.clone_vol1) + self.assertEqual(ret, 0, "Failed to enable USS on cloned volume") + g.log.info("Successfully enabled USS on Cloned volume") + + # Validate USS running + self.validate_uss() + + # Validate snapd running on all nodes + self.validate_snapd() + + # Stop cloned volume + ret, _, _ = volume_stop(self.mnode, self.clone_vol1) + self.assertEqual(ret, 0, "Failed to stop cloned volume " + "%s" % self.clone_vol1) + g.log.info("Successfully Stopped Cloned volume %s", self.clone_vol1) + + # Validate snapd running on all nodes + self.validate_snapd(check_condition=False) + + # Start cloned volume + ret, _, _ = volume_start(self.mnode, self.clone_vol1) + self.assertEqual(ret, 0, "Failed to start cloned volume" + " %s" % self.clone_vol1) + g.log.info("Successfully started cloned volume" + " %s", self.clone_vol1) + + # Validate snapd running on all nodes + self.validate_snapd() + + # Create 5 snapshots + self.snaps_list = [('test_snap_clone_snapd-snap%s' + % i)for i in range(0, 5)] + for snapname in self.snaps_list: + ret, _, _ = snap_create(self.mnode, self.clone_vol1, + snapname) + self.assertEqual(ret, 0, ("Failed to create snapshot for volume" + " %s" % self.clone_vol1)) + g.log.info("Snapshot %s created successfully for volume " + "%s", snapname, self.clone_vol1) + + # Validate USS running + self.validate_uss() + + # Check snapshot under .snaps directory + self.check_snaps() + + # Activate Snapshots + for snapname in self.snaps_list: + ret, _, _ = snap_activate(self.mnode, snapname) + self.assertEqual(ret, 0, ("Failed to activate snapshot %s" + % snapname)) + g.log.info("Snapshot %s activated " + "successfully", snapname) + + # Validate USS running + self.validate_uss() + + # Validate snapshots under .snaps folder + self.validate_snaps() + + # Kill snapd on node and validate snapd except management node + for server in self.servers[1:]: + ret, _, _ = terminate_snapd_on_node(server) + self.assertEqual(ret, 0, "Failed to Kill snapd on node %s" + % server) + g.log.info("snapd Killed Successfully on node %s", server) + + # Check snapd running + ret = is_snapd_running(server, self.clone_vol1) + self.assertTrue(ret, "Unexpected: Snapd running on node: " + "%s" % server) + g.log.info("Expected: Snapd is not running on node:%s", server) + + # Check snapshots under .snaps folder + g.log.info("Validating snapshots under .snaps") + ret, _, _ = uss_list_snaps(self.clients[0], self.mpoint) + self.assertEqual(ret, 0, "Target endpoint not connected") + g.log.info("Successfully listed snapshots under .snaps") + + # Kill snapd in management node + ret, _, _ = terminate_snapd_on_node(self.servers[0]) + self.assertEqual(ret, 0, "Failed to Kill snapd on node %s" + % self.servers[0]) + g.log.info("snapd Killed Successfully on node %s", self.servers[0]) + + # Validate snapd running on all nodes + self.validate_snapd(check_condition=False) + + # Validating snapshots under .snaps + ret, _, _ = uss_list_snaps(self.clients[0], self.mpoint) + self.assertNotEqual(ret, 0, "Unexpected: Successfully listed " + "snapshots under .snaps") + g.log.info("Expected: Target endpoint not connected") + + # Start the Cloned volume(force start) + ret, _, _ = volume_start(self.mnode, self.clone_vol1, force=True) + self.assertEqual(ret, 0, "Failed to start cloned volume " + "%s" % self.clone_vol1) + g.log.info("Successfully Started Cloned volume %s", self.clone_vol1) + + # Validate snapd running on all nodes + self.validate_snapd() + + # Validate snapshots under .snaps folder + self.validate_snaps() + + def tearDown(self): + + # Calling GlusterBaseClass tearDown + self.get_super_method(self, 'tearDown')() + + # Disable USS on cloned volume + ret, _, _ = disable_uss(self.mnode, self.clone_vol1) + if ret: + raise ExecutionError("Failed to disable USS on cloned volume") + g.log.info("Successfully disabled USS on Cloned volume") + + # Cleanup cloned volume + ret = unmount_mounts(self.mount1) + if not ret: + raise ExecutionError("Failed to unmount cloned volume") + ret = cleanup_volume(self.mnode, self.clone_vol1) + if not ret: + raise ExecutionError("Failed to unmount and cleanup cloned volume") + g.log.info("Successfully umounted and cleanup cloned volume") + + # Unmount and cleanup-volume + ret = self.unmount_volume_and_cleanup_volume(mounts=self.mounts) + if not ret: + raise ExecutionError("Failed to Unmount and Cleanup Volume") + g.log.info("Successful in Unmount Volume and Cleanup Volume") -- cgit