From c455c6030f1f1678ae66752e5e11ea988d062df4 Mon Sep 17 00:00:00 2001 From: Nigel Babu Date: Thu, 22 Dec 2016 14:28:27 +0530 Subject: tests: Remove tests/distaf We will not be using it in the future BUG: 1408131 Change-Id: Idebaaadb06786eebc08969ce0cc15a9df4bd9f42 Signed-off-by: Nigel Babu Reviewed-on: http://review.gluster.org/16270 CentOS-regression: Gluster Build System NetBSD-regression: NetBSD Build System Smoke: Gluster Build System Reviewed-by: Raghavendra Talur Reviewed-by: Vijay Bellur --- tests/distaf/README.md | 66 -- tests/distaf/__init__.py | 0 .../distaflibs-gluster/distaflibs/__init__.py | 1 - .../distaflibs/gluster/__init__.py | 0 .../distaflibs/gluster/bitrot_ops.py | 683 ------------- .../distaflibs/gluster/brick_ops.py | 90 -- .../gluster/class_setup_nfs_ganesha_vol.py | 119 --- .../distaflibs/gluster/ctdb_libs.py | 586 ----------- .../distaflibs/gluster/ganesha.py | 592 ----------- .../distaflibs/gluster/gluster_base_class.py | 160 --- .../distaflibs/gluster/gluster_init.py | 77 -- .../distaflibs/gluster/lib_utils.py | 467 --------- .../distaflibs/gluster/mount_ops.py | 210 ---- .../distaflibs/gluster/peer_ops.py | 449 --------- .../distaflibs/gluster/quota_ops.py | 575 ----------- .../distaflibs/gluster/rebalance_ops.py | 334 ------- .../distaflibs/gluster/samba_ops.py | 116 --- .../distaflibs/gluster/snap_ops.py | 961 ------------------ .../distaflibs/gluster/tiering_ops.py | 1057 -------------------- .../distaflibs/gluster/volume_ops.py | 949 ------------------ .../distaf/distaf_libs/distaflibs-gluster/setup.py | 47 - .../distaflibs-io/distaflibs/__init__.py | 1 - .../distaflibs-io/distaflibs/io/__init__.py | 0 .../distaflibs-io/distaflibs/io/file_ops.py | 245 ----- tests/distaf/distaf_libs/distaflibs-io/setup.py | 47 - tests/distaf/tests_d/__init__.py | 0 tests/distaf/tests_d/ctdb_gluster/__init__.py | 0 .../ctdb_gluster/test_ctdb_gluster_setup.py | 51 - tests/distaf/tests_d/distaf_gluster_config.yml | 190 ---- tests/distaf/tests_d/examples/__init__.py | 0 .../tests_d/examples/test_basic_gluster_tests.py | 64 -- tests/distaf/tests_d/examples/test_docstring.py | 130 --- tests/distaf/tests_d/examples/test_passfail.py | 97 -- tests/distaf/tests_d/nfs_ganesha/__init__.py | 0 .../tests_d/nfs_ganesha/test_nfs_ganesha_setup.py | 63 -- tests/distaf/tests_d/sanity/__init__.py | 0 tests/distaf/tests_d/sanity/io_config.yml | 14 - tests/distaf/tests_d/sanity/test_dd_writes.py | 139 --- 38 files changed, 8580 deletions(-) delete mode 100644 tests/distaf/README.md delete mode 100644 tests/distaf/__init__.py delete mode 100644 tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/__init__.py delete mode 100644 tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/__init__.py delete mode 100644 tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/bitrot_ops.py delete mode 100644 tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/brick_ops.py delete mode 100644 tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/class_setup_nfs_ganesha_vol.py delete mode 100644 tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/ctdb_libs.py delete mode 100644 tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/ganesha.py delete mode 100644 tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/gluster_base_class.py delete mode 100644 tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/gluster_init.py delete mode 100644 tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/lib_utils.py delete mode 100644 tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/mount_ops.py delete mode 100644 tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/peer_ops.py delete mode 100644 tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/quota_ops.py delete mode 100644 tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/rebalance_ops.py delete mode 100644 tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/samba_ops.py delete mode 100644 tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/snap_ops.py delete mode 100644 tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/tiering_ops.py delete mode 100644 tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/volume_ops.py delete mode 100644 tests/distaf/distaf_libs/distaflibs-gluster/setup.py delete mode 100644 tests/distaf/distaf_libs/distaflibs-io/distaflibs/__init__.py delete mode 100644 tests/distaf/distaf_libs/distaflibs-io/distaflibs/io/__init__.py delete mode 100644 tests/distaf/distaf_libs/distaflibs-io/distaflibs/io/file_ops.py delete mode 100644 tests/distaf/distaf_libs/distaflibs-io/setup.py delete mode 100644 tests/distaf/tests_d/__init__.py delete mode 100644 tests/distaf/tests_d/ctdb_gluster/__init__.py delete mode 100644 tests/distaf/tests_d/ctdb_gluster/test_ctdb_gluster_setup.py delete mode 100644 tests/distaf/tests_d/distaf_gluster_config.yml delete mode 100644 tests/distaf/tests_d/examples/__init__.py delete mode 100644 tests/distaf/tests_d/examples/test_basic_gluster_tests.py delete mode 100644 tests/distaf/tests_d/examples/test_docstring.py delete mode 100644 tests/distaf/tests_d/examples/test_passfail.py delete mode 100644 tests/distaf/tests_d/nfs_ganesha/__init__.py delete mode 100644 tests/distaf/tests_d/nfs_ganesha/test_nfs_ganesha_setup.py delete mode 100644 tests/distaf/tests_d/sanity/__init__.py delete mode 100644 tests/distaf/tests_d/sanity/io_config.yml delete mode 100644 tests/distaf/tests_d/sanity/test_dd_writes.py (limited to 'tests') diff --git a/tests/distaf/README.md b/tests/distaf/README.md deleted file mode 100644 index 8e6cd54f46d..00000000000 --- a/tests/distaf/README.md +++ /dev/null @@ -1,66 +0,0 @@ -# DiSTAF - -DiSTAF (or distaf) is a test framework for distributed systems like glusterfs. - -This file contains information about how to contribute automated test cases to gluster. For information about overview and architecture, please refer to [README](https://github.com/gluster/distaf/blob/master/README.md). To know more about how to write tests and more about the distaf APIs please refer [HOWTO](https://github.com/gluster/distaf/blob/master/docs/HOWTO.md). - -## Before contributing tests to gluster - -This doc assumes that you are familiar with distaf and know how to write a test case in distaf. These tests are meant for running perodically in a CI environment. So avoid assuming any test environment and make sure you are aware of the environment where the tests are being run. For example do not assume that some non-standard packages will be present in the test environment. - -### Installing distaf and distaflibs packages -DiSTAF is devided into packages. The core part of distaf (the framework which provides connection manager and core APIs) are part of [distaf.git](https://github.com/gluster/distaf) and are available through distaf package. The gluster libraries are part of [glusterfs.git](https://github.com/gluster/glusterfs/tree/master/tests/distaf) and are available through distaflibs namespace packages. Please note that, to install these packages you need to have [python-setuptools](https://pypi.python.org/pypi/setuptools) (Most likely will be available through yum/apt-get) and should be run with root privilages. - -The distaf core package can be installed through below command. It will install the distaf core package from the git HEAD available from distaf.git. -```bash -pip install git+https://github.com/gluster/distaf@master -``` - -The libraries related to gluster, which enables to write gluster tests are available through the namespace package distaflibs. And as part of namespace package distaflibs, We have 2 sub-packages (and provision to add more sub-packages in future if need arises) `distaflibs-gluster` and `distaflibs-io`. These libraries and the tests are part of [glusterfs.git](https://github.com/gluster/glusterfs). If you have cloned the glusterfs.git, please follow the below steps to install both sub-packages of distaflibs. -```bash -cd /tests/distaf/distaf_libs/distaflibs-gluster -python setup.py install # Installs distaflibs.gluster package -cd /tests/distaf/distaf_libs/io_libs -python setup.py install # Installs distaflibs.iolibs package -``` - -## Writing the gluster tests - -DiSTAF supports both python function and python class as the testcase. But for gluster, each test case should be a python class and should be a sub class of `GlusterBaseClass`. This base class takes care of few of the basic things like creating volume based on the `global_mode` flag in configuration file etc. So the test case should implement the `run()` method with the test case logic. Any extra setup part done in `run()` should be cleaned up in `teardown()` method, which also should be implemented by test, if necessary. - -Also `GlusterBaseClass` exposes few of the variable which are accesible from the connection manager object `tc`. Please consider below example. -```python -from distaf.util import tc, testcase -from distaflibs.gluster.gluster_base_class import GlusterBaseClass -from distaflibs.gluster.mount_ops import mount_volume, umount_volume - -@testcase("nfs-test-01") -class nfs_test_01(GlusterBaseClass): - """ - runs_on_volumes: ALL - run_on_protocol: [ nfs ] - reuse_setup: True - """ - def run(self): - tc.logger.debug("The volume name is %s and is of the type %s", self.volname, - self.voltype) - tc.logger.debug("This test mounts the volume at %s with %s mount protocol", - self.mountpoint, self.mount_proto) - client = self.clients[0] - ret, out, err = mount_volume(self.volname, self.mount_proto, self.mountpoint, - mclient=client) - if ret!= 0: - tc.logger.error("The mount failed") - return False - return True - - def teardown(self): - umount_volume(self.clients[0], self.mountpoint) - return True -``` - -So the volume name and volume type are accessible with the variables `self.volname` and `self.voltype` respectively. Since the test calls the `mount_volume()` in `run()`, it is the responsibility of the test to call `umount_volume()` in `teardown()`. - -NOTE: The `setup()` only creats the volume. All other test logic has to be built inside the `run()` method. - -For any more questions/comments please send a mail to [gluster-devel](https://www.gluster.org/mailman/listinfo/gluster-devel) diff --git a/tests/distaf/__init__.py b/tests/distaf/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/__init__.py b/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/__init__.py deleted file mode 100644 index de40ea7ca05..00000000000 --- a/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/__init__.py +++ /dev/null @@ -1 +0,0 @@ -__import__('pkg_resources').declare_namespace(__name__) diff --git a/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/__init__.py b/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/bitrot_ops.py b/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/bitrot_ops.py deleted file mode 100644 index 671dd762c76..00000000000 --- a/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/bitrot_ops.py +++ /dev/null @@ -1,683 +0,0 @@ -#!/usr/bin/env python -# This file is part of DiSTAF -# Copyright (C) 2015-2016 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: Library for gluster bitrot operations. -""" - -from distaf.util import tc -from distaflibs.gluster.volume_ops import get_volume_option, get_volume_status -from distaflibs.gluster.lib_utils import (get_pathinfo, - calculate_checksum, - get_extended_attributes_info) -import time -import re - -try: - import xml.etree.cElementTree as etree -except ImportError: - import xml.etree.ElementTree as etree - - -# Global variables -SCRUBBER_TIMEOUT = 100 - - -def enable_bitrot(volname, mnode=None): - """Enables bitrot for given volume - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - - 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. - - Example: - enable_bitrot(testvol) - """ - - if mnode is None: - mnode = tc.servers[0] - - cmd = "gluster volume bitrot %s enable" % volname - return tc.run(mnode, cmd) - - -def disable_bitrot(volname, mnode=None): - """Disables bitrot for given volume - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - - 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. - - Example: - disable_bitrot(testvol) - """ - - if mnode is None: - mnode = tc.servers[0] - - cmd = "gluster volume bitrot %s disable" % volname - return tc.run(mnode, cmd) - - -def is_bitrot_enabled(volname, mnode=None): - """Checks if bitrot is enabled in given volume - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - - Returns: - True on success, False otherwise - - Example: - is_bitrot_enabled(testvol) - """ - if mnode is None: - mnode = tc.servers[0] - - output = get_volume_option(volname, "features.bitrot", mnode) - if output is None: - return False - - tc.logger.info("Bitrot Status in volume %s: %s" - % (volname, output["features.bitrot"])) - if output["features.bitrot"] != 'on': - return False - - return True - - -def is_file_signed(filename, mountpoint, expected_file_version=None): - """Verifies if the given file is signed - - Args: - filename (str): relative path of filename to be verified - mountpoint (str): mount point of the file. If mount type is - nfs or cifs, then mount the volume with gluster mount and - give the gluster mount path for this parameter. - - Kwargs: - expected_file_version (str): file version to check with getfattr output - If this option is set, this function - will check file versioning as part of signing verification. - If this option is set to None, function will not check - for file versioning. Defaults to None. - - Returns: - True on success, False otherwise - - Example: - is_file_signed('file1', "/mnt/glusterfs", expected_file_version='2') - """ - - filename_mnt = mountpoint + "/" + filename - - # Getting file path in the rhs node - file_location = get_pathinfo(filename_mnt) - if file_location is None: - tc.logger.error("Failed to get backend file path in is_file_signed()") - return False - - path_info = file_location[0].split(':') - - expected_file_signature = (calculate_checksum([path_info[1]], - mnode=path_info[0]) - [path_info[1]]) - - attr_info = get_extended_attributes_info([path_info[1]], - mnode=path_info[0]) - if attr_info is None: - tc.logger.error("Failed to get attribute info in is_file_signed()") - return False - - file_signature = attr_info[path_info[1]]['trusted.bit-rot.signature'] - - if expected_file_version is not None: - expected_file_version = ('{0:02d}'.format(int( - expected_file_version))).ljust(16, '0') - actual_signature_file_version = re.findall('.{16}', - file_signature[4:]).pop(0) - - # Verifying file version after signing - if actual_signature_file_version != expected_file_version: - tc.logger.error("File version mismatch in signature.Filename: %s ." - "Expected file version: %s.Actual file version: %s" - % (filename, expected_file_version, - actual_signature_file_version)) - return False - - actual_file_signature = ''.join(re.findall('.{16}', - file_signature[4:])[1:]) - - # Verifying file signature - if actual_file_signature != expected_file_signature: - tc.logger.error("File signature mismatch. File name: %s . Expected " - "file signature: %s. Actual file signature: %s" - % (filename, expected_file_signature, - actual_file_signature)) - return False - return True - - -def is_file_bad(filename, mnode): - """Verifies if scrubber identifies bad file - Args: - filename (str): absolute path of the file in mnode - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - - Returns: - True on success, False otherwise - - Example: - is_file_bad("/bricks/file1", "abc.xyz.com") - """ - ret = True - count = 0 - flag = 0 - while (count < SCRUBBER_TIMEOUT): - attr_info = get_extended_attributes_info([filename], mnode=mnode) - if attr_info is None: - ret = False - - if 'trusted.bit-rot.bad-file' in attr_info[filename]: - flag = 1 - break - - time.sleep(10) - count = count + 10 - if not flag: - tc.logger.error("Scrubber failed to identify bad file") - ret = False - - return ret - - -def bring_down_bitd(mnode=None): - """Brings down bitd process - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - - Returns: - True on success, False otherwise - - Example: - bring_down_bitd() - """ - - if mnode is None: - mnode = tc.servers[0] - - kill_cmd = ("pid=`cat /var/lib/glusterd/bitd/run/bitd.pid` && " - "kill -15 $pid || kill -9 $pid") - ret, _, _ = tc.run(mnode, kill_cmd) - if ret != 0: - tc.logger.error("Unable to kill the bitd for %s" - % mnode) - return False - else: - return True - - -def bring_down_scrub_process(mnode=None): - """Brings down scrub process - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - - Returns: - True on success, False otherwise - - Example: - bring_down_scrub_process() - """ - - if mnode is None: - mnode = tc.servers[0] - - kill_cmd = ("pid=`cat /var/lib/glusterd/scrub/run/scrub.pid` && " - "kill -15 $pid || kill -9 $pid") - - ret, _, _ = tc.run(mnode, kill_cmd) - if ret != 0: - tc.logger.error("Unable to kill the scrub process for %s" - % mnode) - return False - else: - return True - - -def set_scrub_throttle(volname, mnode=None, type='lazy'): - """Sets scrub throttle - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - type (str): throttling type (lazy|normal|aggressive) - Defaults to 'lazy' - - 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. - - Example: - set_scrub_throttle(testvol) - """ - if mnode is None: - mnode = tc.servers[0] - - cmd = "gluster volume bitrot %s scrub-throttle %s" % (volname, type) - return tc.run(mnode, cmd) - - -def set_scrub_frequency(volname, mnode=None, type='biweekly'): - """Sets scrub frequency - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - type (str): frequency type (hourly|daily|weekly|biweekly|monthly) - Defaults to 'biweekly' - - 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. - - Example: - set_scrub_frequency(testvol) - """ - - if mnode is None: - mnode = tc.servers[0] - - cmd = "gluster volume bitrot %s scrub-frequency %s" % (volname, type) - return tc.run(mnode, cmd) - - -def pause_scrub(volname, mnode=None): - """Pauses scrub - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - - 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. - - Example: - pause_scrub(testvol) - """ - - if mnode is None: - mnode = tc.servers[0] - - cmd = "gluster volume bitrot %s scrub pause" % volname - return tc.run(mnode, cmd) - - -def resume_scrub(volname, mnode=None): - """Resumes scrub - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - - 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. - - Example: - resume_scrub(testvol) - """ - - if mnode is None: - mnode = tc.servers[0] - - cmd = "gluster volume bitrot %s scrub resume" % volname - return tc.run(mnode, cmd) - - -def get_bitd_pid(mnode=None): - """Gets bitd process id for the given node - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - - Returns: - str: pid of the bitd process on success - NoneType: None if command execution fails, errors. - - Example: - get_bitd_pid() - """ - - if mnode is None: - mnode = tc.servers[0] - - cmd = ("cat /var/lib/glusterd/bitd/run/bitd.pid") - ret, out, _ = tc.run(mnode, cmd) - if ret != 0: - tc.logger.error("Unable to get bitd pid for %s" - % mnode) - return None - - return out.strip("\n") - - -def get_scrub_process_pid(mnode=None): - """Gets scrub process id for the given node - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - - Returns: - str: pid of the scrub process on success - NoneType: None if command execution fails, errors. - - Example: - get_scrub_process_pid() - """ - - if mnode is None: - mnode = tc.servers[0] - - cmd = ("cat /var/lib/glusterd/scrub/run/scrub.pid") - ret, out, _ = tc.run(mnode, cmd) - if ret != 0: - tc.logger.error("Unable to get scrub pid for %s" - % mnode) - return None - - return out.strip("\n") - - -def is_bitd_running(volname, mnode=None): - """Checks if bitd is running on the given node - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - - Returns: - True on success, False otherwise - - Example: - is_bitd_running("testvol") - """ - if mnode is None: - mnode = tc.servers[0] - - vol_status = get_volume_status(volname=volname, mnode=mnode) - if vol_status is None: - tc.logger.error("Failed to get volume status in isBitdRunning()") - return False - - if 'Bitrot Daemon' not in vol_status[volname]['localhost']: - tc.logger.error("Bitrot is not enabled in volume %s" - % volname) - return False - - bitd_status = vol_status[volname]['localhost']['Bitrot Daemon']['status'] - if bitd_status != '1': - tc.logger.error("Bitrot Daemon is not running in node %s" - % mnode) - return False - return True - - -def is_scrub_process_running(volname, mnode=None): - """Checks if scrub process is running on the given node - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - - Returns: - True on success, False otherwise - - Example: - is_scrub_process_running("testvol") - """ - if mnode is None: - mnode = tc.servers[0] - - vol_status = get_volume_status(volname=volname, mnode=mnode) - if vol_status is None: - tc.logger.error("Failed to get volume status in " - "isScrubProcessRunning()") - return False - - if 'Scrubber Daemon' not in vol_status[volname]['localhost']: - tc.logger.error("Bitrot is not enabled in volume %s" - % volname) - return False - - bitd_status = vol_status[volname]['localhost']['Scrubber Daemon']['status'] - if bitd_status != '1': - tc.logger.error("Scrubber Daemon is not running in node %s" - % mnode) - return False - return True - - -def scrub_status(volname, mnode=None): - """Executes gluster bitrot scrub status command - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - - 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. - - Example: - scrub_status(testvol) - """ - if mnode is None: - mnode = tc.servers[0] - - cmd = "gluster volume bitrot %s scrub status" % volname - return tc.run(mnode, cmd) - - -def get_scrub_status(volname, mnode=None): - """Parse the output of gluster bitrot scrub status command - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - - Returns: - dict: scrub status in dict format - NoneType: None if command execution fails, errors. - - Example: - >>>get_scrub_status(testvol) - {'State of scrub': 'Active', 'Bitrot error log location': - '/var/log/glusterfs/bitd.log', 'Scrub impact': 'aggressive', - 'Scrub frequency': 'hourly', 'status_info': {'localhost': - {'Duration of last scrub (D:M:H:M:S)': '0:0:0:0', 'corrupted_gfid': - ['475ca13f-577f-460c-a5d7-ea18bb0e7779'], 'Error count': '1', - 'Last completed scrub time': '2016-06-21 12:46:19', - 'Number of Skipped files': '0', 'Number of Scrubbed files': '0'}, - '10.70.47.118': {'Duration of last scrub (D:M:H:M:S)': '0:0:0:1', - 'corrupted_gfid': ['19e62b26-5942-4867-a2f6-e354cd166da9', - 'fab55c36-0580-4d11-9ac0-d8e4e51f39a0'], 'Error count': '2', - 'Last completed scrub time': '2016-06-21 12:46:03', - 'Number of Skipped files': '0', 'Number of Scrubbed files': '2'}}, - 'Volume name': 'testvol', 'Scrubber error log location': - '/var/log/glusterfs/scrub.log'} - """ - if mnode is None: - mnode = tc.servers[0] - - cmd = "gluster volume bitrot %s scrub status" % volname - ret, out, err = tc.run(mnode, cmd) - if ret != 0: - tc.logger.error("Unable to get scrub status for volume %s" - % volname) - return False - - match = re.search('(.*?)(==.*==.*)', out, re.S) - if match is None: - tc.logger.error("Mismatch in regex. Scrub status raw output is not" - " in expected format") - return False - info = match.group(2).replace('\n\n', '\n') - - if "Corrupted object's [GFID]" in info: - info = info.replace("Corrupted object's [GFID]:\n", - "Corrupted object's [GFID]:") - regex = 'Node(?:(?!Node).)*?Corrupted object.*?:.*?\n+=' - temp_list = re.findall(regex, info, re.S) - corrupt_list = [] - for node in temp_list: - tmp_reg = ('Node: (\S+)\n.*Error count.*' - + 'Corrupted object.*?:(.*)\n=.*') - m = re.search(tmp_reg, node, re.S) - if m is None: - tc.logger.error("Mismatch in cli output when bad file" - "is identified") - return False - corrupt_list.append(m.groups()) - else: - corrupt_list = [] - info_list = re.findall('Node:.*?\n.*:.*\n.*:.*\n.*:.*\n.*:.*\n.*:.*\n+', - info) - temp_list = [] - for item in info_list: - item = item.replace('\n\n', '') - temp_list.append(item) - - tmp_dict1 = {} - for item in temp_list: - tmp = item.split('\n') - tmp_0 = tmp[0].split(':') - tmp.pop(0) - tmp_dict = {} - for tmp_item in tmp[:-1]: - tmp_1 = tmp_item.split(': ') - tmp_dict[tmp_1[0].strip(' ')] = tmp_1[1].strip(' ') - tmp_dict1[tmp_0[1].strip(' ')] = tmp_dict - status_dict = {} - for item in match.group(1).split('\n\n')[:-1]: - elmt = item.split(':') - tmp_elmt = elmt[1].strip(' ').strip('\n') - status_dict[elmt[0].strip(' ').strip('\n')] = tmp_elmt - - status_dict['status_info'] = tmp_dict1 - for elmt in corrupt_list: - if elmt[0].strip(' ') in status_dict['status_info'].keys(): - val = elmt[1].split('\n') - val = filter(None, val) - gfid = "corrupted_gfid" - status_dict['status_info'][elmt[0].strip(' ')][gfid] = val - return status_dict diff --git a/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/brick_ops.py b/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/brick_ops.py deleted file mode 100644 index a8fad5a3efb..00000000000 --- a/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/brick_ops.py +++ /dev/null @@ -1,90 +0,0 @@ -# This file is part of DiSTAF -# Copyright (C) 2015-2016 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. - - -import re -from distaf.util import tc - -""" - This file contains the gluster brick operations like - add-brick, bring_down_brick replace/remove brick -""" - - -def add_brick(volname, nbricks, replica=1, stripe=1, peers='', mnode=''): - """ - Does the gluster add-brick. If peer is '', peers from the config - is taken. And replica/stripe will not be used by default. - Returns the output of add-brick command, which would be a tuple of - (retcode, stdout, sstderr) from gluster add-brick command. - """ - global tc - if peers == '': - peers = tc.peers[:] - if mnode == '': - mnode = tc.servers[0] - replica = int(replica) - stripe = int(stripe) - volinfo = tc.run(mnode, "gluster volume info | egrep \"^Brick[0-9]+\"", \ - verbose=False) - if volinfo[0] != 0: - tc.logger.error("Unable to get volinfo for add-brick") - return (-1, -1, -1) - bi = int(re.findall(r"%s_brick([0-9]+)" % volname, volinfo[1])[-1]) + 1 - tempn = 0 - n = 0 - add_bricks = '' - brick_root = "/bricks" - for i in range(bi, bi + nbricks): - sn = len(re.findall(r"%s" % peers[n], volinfo[1])) + tempn - add_bricks = "%s %s:%s/brick%d/%s_brick%d" % (add_bricks, peers[n], \ - brick_root, sn, volname, i) - if n < len(peers[:]) - 1: - n = n + 1 - else: - n = 0 - tempn = tempn + 1 - repc = strc = '' - if replica != 1: - repc = "replica %d" % replica - if stripe != 1: - strc = "stripe %d" % stripe - ret = tc.run(mnode, "gluster volume add-brick %s %s %s %s" % \ - (volname, repc, strc, add_bricks)) - return ret - - -def bring_down_brick(volname, bindex, node=''): - """ - Kills the glusterfsd process of the particular brick - Returns True on success and False on failure - """ - global tc - if node == '': - node = tc.servers[0] - ret, rnode, _ = tc.run(node, "gluster volume info %s | egrep \"^Brick%d:\"" - " | awk '{print $2}' | awk -F : '{print $1}'" - % (volname, bindex)) - if ret != 0: - return False - ret, _, _ = tc.run(rnode.rstrip(), \ - "pid=`cat /var/lib/glusterd/vols/%s/run/*%s_brick%d.pid` && kill -15 $pid \ - || kill -9 $pid" % (volname, volname, bindex - 1)) - if ret != 0: - return False - else: - return True diff --git a/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/class_setup_nfs_ganesha_vol.py b/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/class_setup_nfs_ganesha_vol.py deleted file mode 100644 index b9599f40174..00000000000 --- a/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/class_setup_nfs_ganesha_vol.py +++ /dev/null @@ -1,119 +0,0 @@ -#!/usr/bin/env python -# This file is part of DiSTAF -# Copyright (C) 2015-2016 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. - - -import time -from distaflibs.gluster.mount_ops import mount_volume, umount_volume -from distaflibs.gluster.volume_ops import (setup_vol, get_volume_info, - get_volume_status) -from distaf.util import testcase, tc -from distaflibs.gluster.ganesha import (setup_nfs_ganesha, - teardown_nfs_ganesha_setup) -from distaflibs.gluster.gluster_base_class import GlusterBaseClass - - -class SetupNfsGaneshaVol(GlusterBaseClass): - """ - This is the base class for the ganesha-gluster tests - It is a subclass of GlusterBaseClass. All ganesha-gluster - tests can subclass this and then write test cases - """ - - def __init__(self, config_data, nfs_options="vers=3"): - """ - Initialise the class with the config values - Kwargs: - nfs_options (str): This argument takes the nfs options, - say vers=3 or vers=4. - Default value is vers=3. - """ - GlusterBaseClass.__init__(self, config_data) - self.options = nfs_options - self.no_of_ganesha_nodes = (config_data["gluster"] - ["cluster_config"]["nfs_ganesha"] - ["num_of_nfs_ganesha_nodes"]) - self.no_of_ganesha_nodes = int(self.no_of_ganesha_nodes) - self.vips = (config_data["gluster"]["cluster_config"] - ["nfs_ganesha"]["vips"]) - - def setup(self): - """ - Function to setup ganesha and create volume for testing. - """ - ret = setup_nfs_ganesha(self.no_of_ganesha_nodes) - if ret: - tc.logger.info("setup of ganesha for %s node is successfull" - % self.no_of_ganesha_nodes) - else: - tc.logger.error("setup of ganesha for %s node is unsuccessfull" - % self.no_of_ganesha_nodes) - return False - ret = GlusterBaseClass.setup(self) - if not ret: - return False - time.sleep(10) - ret = get_volume_status(self.volname) - if ret is None: - return False - ret = get_volume_info(self.volname) - if ret is None: - return False - ret, out, err = tc.run(self.mnode, "showmount -e localhost") - if ret != 0: - return False - ret, out, err = mount_volume(self.volname, self.mount_proto, - self.mountpoint, self.vips[0], - self.clients[0], self.options) - if ret != 0: - tc.logger.error("Mounting Volume %s failed on %s:%s" % - (self.volname, self.clients[0], self.mountpoint)) - return False - - return True - - def teardown(self, teardown_ganesha_setup=False): - """ - The function to cleanup the test setup - Kwargs: - teardown_ganesha_setup (bool): If True teardowns ganesha setup, - else leaves the ganesha setup as it is. - Default value is False - """ - umount_volume(tc.clients[0], self.mountpoint) - ret, out, err = tc.run(tc.clients[0], "rm -rf %s/*" % self.mountpoint) - time.sleep(5) - if ret != 0: - tc.logger.error("rm -rf command failed on the mountpoint %s" - % self.mountpoint) - return False - if teardown_ganesha_setup: - ret = teardown_nfs_ganesha_setup() - return ret - return True - - def cleanup(Self, delete_vol=False): - """ - The function to cleanup the volume - Kwargs: - delete_vol (bool): If True deletes the volume. - else leaves the volume as it is. - Defualt value is False - """ - if not delete_vol: - return True - return GlusterBaseClass.cleanup(self) diff --git a/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/ctdb_libs.py b/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/ctdb_libs.py deleted file mode 100644 index 0e4571a706c..00000000000 --- a/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/ctdb_libs.py +++ /dev/null @@ -1,586 +0,0 @@ -#!/usr/bin/env python -# This file is part of DiSTAF -# Copyright (C) 2015-2016 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: Library for setting up CTDB on gluster setup -""" -import time -import re -from distaf.util import tc -from distaflibs.gluster.volume_ops import start_volume -from distaflibs.gluster.peer_ops import peer_probe_servers - - -def ctdb_firewall_settings(servers=None): - '''Firewall settings required for setting up CTDB - Kwargs: - servers (list): The list of servers on which we need - to add firewall settings for setting up CTDB. - Defaults to ctdb_servers as specified in the config file. - Returns: - bool: True if successful, False otherwise - Example: - ctdb_firewall_settings() - ''' - if servers is None: - servers = tc.global_config['cluster_config']['smb']['ctdb_servers'] - if not isinstance(servers, list): - servers = [servers] - server_host_list = [] - for server in servers: - server_host_list.append(server['host']) - servers = server_host_list - _rc = True - for server in servers: - ret, out, _ = tc.run(server, "cat /etc/redhat-release") - if not ret: - match = re.search('.*release (\d+).*', out) - if match is None: - tc.logger.error("Failed to find OS version") - return False - if match.group(1) == '7': - ret, out, err = tc.run(server, "service firewalld start") - if ret != 0: - tc.logger.error("Failed to start firewalld") - ret, _, _ = tc.run(server, "firewall-cmd --zone=public " - "--add-service=samba --add-service=" - "glusterfs") - if ret != 0: - tc.logger.error("Failed to set firewall zone for samba") - _rc = False - ret, _, _ = tc.run(server, "firewall-cmd --zone=public " - "--add-service=samba --add-service=" - "glusterfs --permanent") - if ret != 0: - tc.logger.error("Failed to set firewall zone for samba" - " permanently") - _rc = False - - ret, _, _ = tc.run(server, "firewall-cmd --zone=public " - "--add-port=4379/tcp") - if ret != 0: - tc.logger.error("Failed to add port for samba") - _rc = False - ret, _, _ = tc.run(server, "firewall-cmd --zone=public " - "--add-port=4379/tcp --permanent") - if ret != 0: - tc.logger.error("Failed to add port for samba permanently") - _rc = False - return _rc - - -def update_smb_conf(servers=None): - '''Update the /etc/samba/smb.conf file. - Adds a parameter called clustering=yes. - Kwargs: - servers (list): The list of servers on which we need - to update the /etc/samba/smb.conf file. - Defaults to ctdb_servers as specified in the config file. - Returns: - bool: True if successful, False otherwise - Example: - update_smb_conf() - ''' - if servers is None: - servers = (tc.global_config['gluster']['cluster_config'] - ['smb']['ctdb_servers']) - file_path = "/etc/samba/smb.conf" - if not isinstance(servers, list): - servers = [servers] - server_host_list = [] - for server in servers: - server_host_list.append(server['host']) - servers = server_host_list - _rc = True - for server in servers: - ret, _, _ = tc.run(server, "grep 'clustering=yes' %s" % file_path) - if ret == 0: - tc.logger.info("%s file is already edited") - continue - ret, _, _ = tc.run(server, "sed -i '/^\[global\]/a clustering=yes' %s" - % file_path) - if ret != 0: - tc.logger.error("failed to edit %s file on %s" - % (file_path, server)) - _rc = False - - return _rc - - -def update_hook_scripts(servers=None): - '''Update the hook scripts. - Changes the META parameter value from "all" to "ctdb". - Kwargs: - servers (list): The list of servers on which we need - to update the hook scripts. - Defaults to ctdb_servers as specified in the config file. - Returns: - bool: True if successful, False otherwise - Example: - update_hook_scripts() - ''' - if servers is None: - servers = (tc.global_config['gluster']['cluster_config'] - ['smb']['ctdb_servers']) - server_host_list = [] - for server in servers: - server_host_list.append(server['host']) - servers = server_host_list - file1_path = "/var/lib/glusterd/hooks/1/start/post/S29CTDBsetup.sh" - file2_path = "/var/lib/glusterd/hooks/1/stop/pre/S29CTDB-teardown.sh" - _rc = True - if not isinstance(servers, list): - servers = [servers] - for server in servers: - ret, _, _ = tc.run(server, "sed -i s/'META=\"all\"'/'META=\"ctdb\"'/g" - " %s %s" % (file1_path, file2_path)) - if ret != 0: - tc.logger.error("failed to edit %s hook-script on %s" - % (file_path, server)) - _rc = False - - return _rc - - -def create_ctdb_nodes_file(servers=None): - '''Creates the /etc/ctdb/nodes file. - This file will have a list of IPs of all the servers. - Kwargs: - servers (list): The list of servers on which we need - to update the /etc/ctdb/nodes file. - Defaults to ctdb_servers as specified in the config file. - Returns: - bool: True if successful, False otherwise - Example: - create_ctdb_nodes_file() - ''' - if servers is None: - servers = (tc.global_config['gluster']['cluster_config'] - ['smb']['ctdb_servers']) - server_host_list = [] - for server in servers: - server_host_list.append(server['host']) - servers = server_host_list - file_path = "/etc/ctdb/nodes" - _rc = True - ctdb_ips_list = [] - if not isinstance(servers, list): - servers = [servers] - for server in servers: - ret, out, _ = tc.run(server, "hostname -i") - if ret != 0: - tc.logger.error("failed to get ip of %s" % server) - _rc = False - ctdb_ips_list.append(out) - for server in servers: - conn = tc.get_connection(server, "root") - try: - FH = conn.builtin.open(file_path, "w") - FH.write("".join(ctdb_ips_list)) - except IOError as e: - tc.logger.error(e) - _rc = False - finally: - FH.close() - - return _rc - - -def create_ctdb_meta_volume(mnode=None, servers=None, meta_volname=None): - '''Creates meta volume for ctdb setup - Kwargs: - mnode (str): Node on which the command has - to be executed. Default value is ctdb_servers[0]. - servers (list): The list of servers on which we need - the meta volume to be created. - Defaults to ctdb_servers as specified in the config file. - meta_volname (str) : Name for the ctdb meta volume. - Dafault ctdb meta volume name is "ctdb". - Returns: - bool: True if successful, False otherwise - Example: - create_ctdb_meta_volume() - ''' - if mnode is None: - mnode = (tc.global_config['gluster']['cluster_config'] - ['smb']['ctdb_servers'][0]['host']) - if servers is None: - servers = (tc.global_config['gluster']['cluster_config'] - ['smb']['ctdb_servers']) - server_host_list = [] - for server in servers: - server_host_list.append(server['host']) - servers = server_host_list - if meta_volname is None: - meta_volname = "ctdb" - replica_count = len(servers) - brick_list = "" - brick_path = (tc.global_config['gluster']['cluster_config'] - ['smb']['ctdb_metavol_brick_path']) - if not isinstance(servers, list): - servers = [servers] - for i, server in enumerate(servers): - brick_list = (brick_list + "%s:%s/ctdb_brick%s " - % (server, brick_path, i)) - ret, _, _ = tc.run(mnode, "gluster volume create %s replica %s %s force " - "--mode=script" % (meta_volname, replica_count, - brick_list)) - if ret != 0: - tc.logger.error("failed to create meta volume ctdb") - return False - - return True - - -def check_if_gluster_lock_mount_exists(servers=None): - '''Checks if /gluster/lock mount exists - Kwargs: - servers (list): The list of servers on which we need - to check if /gluster/lock mount exists. - Defaults to ctdb_servers as specified in the config file. - Returns: - bool: True if successful, False otherwise - Example: - check_if_gluster_lock_mount_exists() - ''' - if servers is None: - servers = (tc.global_config['gluster']['cluster_config'] - ['smb']['ctdb_servers']) - server_host_list = [] - for server in servers: - server_host_list.append(server['host']) - servers = server_host_list - if not isinstance(servers, list): - servers = [servers] - _rc = True - for server in servers: - ret, _, _ = tc.run(server, "cat /proc/mounts | grep '/gluster/lock'") - if ret != 0: - tc.logger.error("/gluster/lock mount does not exist on %s" - % server) - _rc = False - - return _rc - - -def check_if_ctdb_file_exists(servers=None): - '''Checks if /etc/sysconfig/ctdb file exists - Kwargs: - servers (list): The list of servers on which we need - to check if /etc/sysconfig/ctdb file exists. - Defaults to ctdb_servers as specified in the config file. - Returns: - bool: True if successful, False otherwise - Example: - check_if_ctdb_file_exists() - ''' - if servers is None: - servers = (tc.global_config['gluster']['cluster_config'] - ['smb']['ctdb_servers']) - server_host_list = [] - for server in servers: - server_host_list.append(server['host']) - servers = server_host_list - file_path = "/etc/sysconfig/ctdb" - if not isinstance(servers, list): - servers = [servers] - _rc = True - for server in servers: - conn = tc.get_connection(server, "root") - if not conn.modules.os.path.isfile(file_path): - tc.logger.error("%s file not found on %s" % (file_path, server)) - _rc = False - conn.close() - - return _rc - - -def create_ctdb_public_addresses(servers=None): - '''Creates the /etc/ctdb/public_addresses file. - This file will have a list of vips, routing-prefix and interface, - in the following format - vip/routing-prefix interface. - Kwargs: - servers (list): The list of servers on which we need - to create the /etc/ctdb/public_addresses file. - Defaults to ctdb_servers as specified in the config file. - Returns: - bool: True if successful, False otherwise - Example: - create_ctdb_public_addresses() - ''' - if servers is None: - servers = (tc.global_config['gluster']['cluster_config'] - ['smb']['ctdb_servers']) - server_host_list = [] - for server in servers: - server_host_list.append(server['host']) - servers = server_host_list - ctdb_vips = (tc.global_config['gluster']['cluster_config'] - ['smb']['ctdb_vips']) - if not isinstance(servers, list): - servers = [servers] - _rc = True - data_to_write = "" - file_path = "/etc/ctdb/public_addresses" - for each_vip in ctdb_vips: - data_to_write = (data_to_write + each_vip['vip'] + "/" + - str(each_vip['routing_prefix']) + " " + - each_vip['interface'] + "\n") - for server in servers: - conn = tc.get_connection(server, "root") - try: - FH = conn.builtin.open(file_path, "w") - FH.write(data_to_write) - except IOError as e: - tc.logger.error(e) - _rc = False - finally: - FH.close() - - return _rc - - -def start_ctdb_service(servers=None): - '''Starts the CTDB service - Kwargs: - servers (list): The list of servers on which we need - to start the CTDB service. - Defaults to ctdb_servers as specified in the config file. - Returns: - bool: True if successful, False otherwise - Example: - start_ctdb_service() - ''' - if servers is None: - servers = (tc.global_config['gluster']['cluster_config'] - ['smb']['ctdb_servers']) - server_host_list = [] - for server in servers: - server_host_list.append(server['host']) - servers = server_host_list - if not isinstance(servers, list): - servers = [servers] - _rc = True - for server in servers: - ret, _, _ = tc.run(server, "service ctdb start") - if ret != 0: - tc.logger.error("failed to start the ctdb service on %s" % server) - _rc = False - - return _rc - - -def verify_ctdb_status(mnode=None): - '''Verifies the ctdb status. - For each server ip mentioned in /etc/ctdb/nodes file, - it checks if the ctdb status is OK for it. - Kwargs: - mnode (str): Node on which the command has - to be executed. Default value is ctdb_servers[0]. - Returns: - bool: True if successful, False otherwise - Example: - verify_ctdb_status() - ''' - if mnode is None: - mnode = (tc.global_config['gluster']['cluster_config'] - ['smb']['ctdb_servers'][0]['host']) - _rc = True - ret, out, _ = tc.run(mnode, "cat /etc/ctdb/nodes") - if ret != 0: - tc.logger.error("failed to get the details of /etc/ctdb/nodes file") - return False - servers_list = out.strip().split("\n") - ret, out, _ = tc.run(mnode, "ctdb status | grep pnn") - if ret != 0: - tc.logger.error("failed to get the details of ctdb status") - return False - status_list = out.strip().split("\n") - for status in status_list: - for server in servers_list: - if server in status: - if "OK" in status: - tc.logger.info("ctdb status for %s is OK" % server) - else: - tc.logger.error("ctdb status for %s is not OK" % server) - _rc = False - - return _rc - - -def ctdb_gluster_setup(mnode=None, servers=None, meta_volname=None): - '''Setup CTDB on gluster setup - Kwargs: - mnode (str): Node on which the command has - to be executed. Default value is ctdb_servers[0] - servers (list): The list of servers on which we need - the CTDB setup. - Defaults to ctdb_servers as specified in the config file. - meta_volname (str) : Name for the ctdb meta volume. - Dafault ctdb meta volume name is "ctdb". - Returns: - bool: True if successful, False otherwise - Example: - ctdb_gluster_setup() - ''' - if mnode is None: - mnode = (tc.global_config['gluster']['cluster_config'] - ['smb']['ctdb_servers'][0]['host']) - if servers is None: - servers = (tc.global_config['gluster']['cluster_config'] - ['smb']['ctdb_servers']) - server_host_list = [] - for server in servers: - server_host_list.append(server['host']) - servers = server_host_list - if not isinstance(servers, list): - servers = [servers] - no_of_ctdb_servers = len(servers) - if meta_volname is None: - meta_volname = "ctdb" - - # 1. firewall setting for ctdb setup - ret = ctdb_firewall_settings(servers[:]) - if ret: - tc.logger.info("firewall settings successfull for ctdb setup") - else: - tc.logger.error("firewall settings failed for ctdb setup") - return False - - # 2. peer probe - ret = peer_probe_servers(servers[:], mnode=mnode) - if not ret: - return False - - # 3. create ctdb meta volume - ret = create_ctdb_meta_volume(mnode, servers[:], meta_volname) - if ret: - tc.logger.info("successfully created ctdb meta volume") - else: - tc.logger.error("failed to create ctdb meta volume") - return False - tc.run(mnode, "gluster v info %s" % meta_volname) - - # 4. update the ctdb hook scripts - ret = update_hook_scripts(servers[:]) - if ret: - tc.logger.info("successfully updated the hook scripts on all servers") - else: - tc.logger.error("failed to update the hook scripts on " - "one or more servers") - return False - - # 5. update the smb.conf file - ret = update_smb_conf(servers[:]) - if ret: - tc.logger.info("successfully updated the smb.conf file on all servers") - else: - tc.logger.error("failed to update the smb.conf file on " - "one or more servers") - return False - - # 6a. start the meta volume - ret = start_volume(meta_volname, mnode) - if ret: - tc.logger.info("successfully started the meta volume") - tc.run(mnode, "gluster v status ctdb") - else: - tc.logger.error("failed to start the meta volume") - return False - time.sleep(20) - # 6.b check if /gluster/lock mount exists on all servers - ret = check_if_gluster_lock_mount_exists(servers[:]) - if ret: - tc.logger.info("/gluster/lock mount exists on all servers") - else: - return False - - # 7. check if /etc/sysconfig/ctdb file exists - ret = check_if_ctdb_file_exists(servers[:]) - if ret: - tc.logger.info("/etc/sysconfig/ctdb file exists on all servers") - else: - return False - - # 8. create /etc/ctdb/nodes file - ret = create_ctdb_nodes_file(servers[:]) - if ret: - tc.logger.info("successfully created /etc/ctdb/nodes file on " - "all servers") - else: - tc.logger.error("failed to create /etc/ctdb/nodes file on " - "one or more servers") - return False - - # 9. create /etc/ctdb/public_addresses file - ret = create_ctdb_public_addresses(servers[:]) - if ret: - tc.logger.info("successfully created /etc/ctdb/public_addresses file " - "on all servers") - else: - tc.logger.error("failed to create /etc/ctdb/public_addresses file " - "on one or more servers") - return False - - # 10. start the ctdb service - ret = start_ctdb_service(servers[:]) - if ret: - tc.logger.info("successfully started ctdb service on all servers") - else: - return False - time.sleep(360) - - # 11. verify the ctdb status - ret = verify_ctdb_status(mnode) - if ret: - tc.logger.info("ctdb status is correct") - else: - tc.logger.error("ctdb status is incorrect") - return False - - return True - - -def stop_ctdb_service(servers=None): - '''Stops the CTDB service - Kwargs: - servers (list): The list of servers on which we need - to stop the CTDB service. - Defaults to ctdb_servers as specified in the config file. - Returns: - bool: True if successful, False otherwise - Example: - stop_ctdb_service() - ''' - if servers is None: - servers = (tc.global_config['gluster']['cluster_config'] - ['smb']['ctdb_servers']) - server_host_list = [] - for server in servers: - server_host_list.append(server['host']) - servers = server_host_list - if not isinstance(servers, list): - servers = [servers] - _rc = True - for server in servers: - ret, _, _ = tc.run(server, "service ctdb stop") - if ret != 0: - tc.logger.error("failed to stop the ctdb service on %s" % server) - _rc = False - - return _rc diff --git a/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/ganesha.py b/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/ganesha.py deleted file mode 100644 index 7e58077eb23..00000000000 --- a/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/ganesha.py +++ /dev/null @@ -1,592 +0,0 @@ -#!/usr/bin/env python -# This file is part of DiSTAF -# Copyright (C) 2015-2016 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: Library for gluster NFS-Ganesha operations. -""" - -import re -import os -import time -import socket -from collections import OrderedDict -from distaf.util import tc -from distaflibs.gluster.volume_ops import get_volume_info -from distaflibs.gluster.peer_ops import (peer_probe_servers, - nodes_from_pool_list) - - -def vol_set_nfs_disable(volname, option=True, mnode=None): - '''Enables/Disables nfs for the volume. - Args: - volname (str): Volume name. - Kwargs: - option (Optional[bool]): If True it disables nfs for - that volume else enables nfs for that volume. - Default value is True. - mnode (Optional[str]): Node on which the command has - to be executed. Default value is tc.servers[0]. - Returns: - bool: True if successful, False otherwise. - ''' - if mnode is None: - mnode = tc.servers[0] - if option: - volinfo = get_volume_info(volname, mnode) - nfs_disable = volinfo[volname]['options'].get('nfs.disable') - if nfs_disable == "on": - tc.logger.info(" nfs is already disabled for the volume %s" - % volname) - return True - ret, _, _ = tc.run(mnode, "gluster volume set %s nfs.disable on " - "--mode=script" % volname) - if ret != 0: - tc.logger.error("failed to set nfs.disable on %s" % volname) - return False - else: - ret, _, _ = tc.run(mnode, "gluster volume set %s nfs.disable off " - "--mode=script" % volname) - if ret != 0: - return False - - return True - - -def vol_set_ganesha(volname, option=True, mnode=None): - '''Enables/Disables ganesha for the volume. - Args: - volname (str): Volume name. - Kwargs: - option (Optional[bool]): If True it enables ganesha for - that volume else disables ganesha for that volume. - Default value is True. - mnode (Optional[str]): Node on which the command has - to be executed. Default value is tc.servers[0]. - Returns: - bool: True if successful, False otherwise. - ''' - if mnode is None: - mnode = tc.servers[0] - if option: - ret = vol_set_nfs_disable(volname) - if not ret: - return False - volinfo = get_volume_info(volname, mnode) - enable = volinfo[volname]['options'].get('ganesha.enable') - if enable == "on": - tc.logger.info(" ganesha is already enabled for the volume %s" - % volname) - return True - ret, _, _ = tc.run(mnode, "gluster volume set %s ganesha.enable on " - "--mode=script" % volname) - if ret != 0: - tc.logger.error("failed to set ganesha.enable on %s" % volname) - return False - else: - ret, _, _ = tc.run(mnode, "gluster volume set %s ganesha.enable off " - "--mode=script" % volname) - if ret != 0: - return False - - return True - - -def validate_ganesha_ha_status(mnode=None): - '''Validates Ganesha HA Status. - Kwargs: - mnode (Optional[str]): Node on which the command has - to be executed. Default value is tc.servers[0]. - Returns: - bool: True if successful(HA status is correct), - False otherwise. - ''' - if mnode is None: - mnode = tc.servers[0] - ret, out, _ = tc.run(mnode, "/usr/libexec/ganesha/ganesha-ha.sh --status " - "| grep -v 'Online' | cut -d ' ' -f 1 | sed s/" - "'-cluster_ip-1'//g | sed s/'-trigger_ip-1'//g") - if ret != 0: - tc.logger.error("failed to execute the ganesha-ha status command") - return False - list1 = filter(None, out.split("\n")) - - ret, out, _ = tc.run(mnode, "/usr/libexec/ganesha/ganesha-ha.sh --status " - "| grep -v 'Online' | cut -d ' ' -f 2") - if ret != 0: - tc.logger.error("failed to execute the ganesha-ha status command") - return False - list2 = filter(None, out.split("\n")) - - if list1 == list2: - tc.logger.info("ganesha ha status is correct") - return True - - tc.logger.error("ganesha ha status is incorrect") - return False - - -def set_nfs_ganesha(option=True, mnode=None): - '''Enables/Disables NFS-Ganesha Cluster - Kwargs: - option (Optional[bool]): If True it enables the nfs-ganesha - HA Cluster, else disables the nfs-ganesha HA Cluster. - Default value is True. - mnode (Optional[str]): Node on which the command has - to be executed. Default value is tc.servers[0]. - Returns: - bool: True if successful, False otherwise. - ''' - if mnode is None: - mnode = tc.servers[0] - servers = nodes_from_pool_list() - no_of_servers = len(servers) - if option: - ret, _, _ = tc.run(mnode, "gluster nfs-ganesha enable --mode=script") - if ret == 0: - tc.logger.info("nfs-ganesha enable success") - time.sleep(45) - ret, _, _ = tc.run(mnode, "pcs status") - ret = validate_ganesha_ha_status(mnode) - if ret: - return True - else: - return False - else: - tc.logger.error("nfs-ganesha enable falied") - return False - else: - ret, _, _ = tc.run(tc.servers[0], "gluster nfs-ganesha disable " - "--mode=script") - if ret == 0: - tc.logger.info("nfs-ganesha disable success") - time.sleep(10) - for node in tc.servers[0:no_of_servers]: - ret, _, _ = tc.run(node, "pcs status") - return True - else: - tc.logger.error("nfs-ganesha disable falied") - return False - - -def get_host_by_name(servers=None): - '''Get hostname of the specified servers. - Kwargs: - servers (Optional[str]): Get hostnames of the specified servers. - Returns: - dict: dict with 'hostname or ip_address" of the server as key and - 'hostname' of the server as value. - ''' - if servers is None: - servers = nodes_from_pool_list() - - if not isinstance(servers, list): - servers = [servers] - - server_hostname_dict = OrderedDict() - for server in servers: - server_hostname_dict[server] = socket.gethostbyaddr(server)[0] - - return server_hostname_dict - - -def create_nfs_passwordless_ssh(snodes=[], guser=None, mnode=None): - '''Sets up the passwordless ssh between mnode and all other snodes. - Args: - snodes (list): List of nodes for which we require passwordless - ssh from mnode. - Kwargs: - guser (Optional[str]): Username . Default value is root. - mnode (Optional[str]): Node from which we require passwordless - ssh to snodes. Default value is tc.servers[0]. - Returns: - bool: True if successfull, False otherwise - ''' - if guser is None: - guser = 'root' - if mnode is None: - mnode = tc.servers[0] - if not isinstance(snodes, list): - snodes = [snodes] - loc = "/var/lib/glusterd/nfs/" - mconn = tc.get_connection(mnode, user='root') - if not mconn.modules.os.path.isfile('/root/.ssh/id_rsa'): - if not mconn.modules.os.path.isfile('%s/secret.pem' % loc): - ret, _, _ = tc.run(mnode, "ssh-keygen -f /var/lib/glusterd/nfs/" - "secret.pem -q -N ''") - if ret != 0: - tc.logger.error("Unable to generate the secret pem file") - return False - mconn.modules.os.chmod("%s/secret.pem" % loc, 0600) - mconn.modules.shutil.copyfile("%s/secret.pem" % loc, - "/root/.ssh/id_rsa") - mconn.modules.os.chmod("/root/.ssh/id_rsa", 0600) - tc.logger.debug("Copying the secret.pem.pub to id_rsa.pub") - mconn.modules.shutil.copyfile("%s/secret.pem.pub" % loc, - "/root/.ssh/id_rsa.pub") - else: - mconn.modules.shutil.copyfile("/root/.ssh/id_rsa", - "%s/secret.pem" % loc) - mconn.modules.os.chmod("%s/secret.pem" % loc, 0600) - tc.logger.debug("Copying the id_rsa.pub to secret.pem.pub") - mconn.modules.shutil.copyfile("/root/.ssh/id_rsa.pub", - "%s/secret.pem.pub" % loc) - if not isinstance(snodes, list): - snodes = [snodes] - for snode in snodes: - sconn = tc.get_connection(snode, user=guser) - try: - slocal = sconn.modules.os.path.expanduser('~') - sfh = sconn.builtin.open("%s/.ssh/authorized_keys" % slocal, "a") - with mconn.builtin.open("/root/.ssh/id_rsa.pub", 'r') as f: - for line in f: - sfh.write(line) - except: - tc.logger.error("Unable to establish passwordless ssh %s@%s to " - "%s@%s" % ('root', mnode, guser, snode)) - return False - finally: - sfh.close() - sconn.close() - mconn.close() - time.sleep(30) - for snode in snodes: - ret, _, _ = tc.run(mnode, "ssh-keyscan -H %s >> ~/.ssh/known_hosts" - % snode) - if snode != mnode: - ret, _, _ = tc.run(mnode, "scp /var/lib/glusterd/nfs/secret.* " - "%s:/var/lib/glusterd/nfs/" % snode) - if ret != 0: - return False - - return True - - -def validate_ganesha_ha_failover(mnode=None, snodes=None): - '''Validates HA failover status - Kwargs: - mnode (Optional[str]): Node on which the ha status command has - to be executed. Default value is tc.servers[0]. - snodes (Optional[str]): Node/Nodes on which ganesha process is - Killed/stopped or Node shutdown - Returns: - bool: True if successfull, False otherwise. - ''' - if mnode is None: - mnode = tc.servers[0] - if snodes is None: - snodes = tc.servers[1] - if not isinstance(snodes, list): - snodes = [snodes] - ha_flag = True - ret, out, _ = tc.run(mnode, "/usr/libexec/ganesha/ganesha-ha.sh --status " - "| grep -v 'Online' | grep -v 'dead' | cut -d ' ' " - "-f 1 | sed s/'-cluster_ip-1'//g | sed s/" - "'-trigger_ip-1'//g") - if ret == 0: - list1 = filter(None, out.split("\n")) - ret, out, _ = tc.run(mnode, "/usr/libexec/ganesha/ganesha-ha.sh --status " - "| grep -v 'Online' | grep -v 'dead' | cut -d ' ' " - "-f 2 | sed s/'-cluster_ip-1'//g | sed s/" - "'-trigger_ip-1'//g") - if ret == 0: - list2 = filter(None, out.split("\n")) - server_hostname_dict = get_host_by_name() - snodes_hostnames = [] - for snode in snodes: - snodes_hostnames.append(server_hostname_dict[snode]) - for val1, val2 in zip(list1, list2): - if val1 in snodes_hostnames: - if val1 == val2: - tc.logger.error("Failover dint happen, wrong failover status " - "-> %s %s" % (val1, val2)) - ha_flag = False - else: - tc.logger.info("%s successfully failed over on %s" - % (val1, val2)) - else: - if val1 != val2: - tc.logger.error("Failover not required, wrong failover status " - "-> %s %s" % (val1, val2)) - ha_flag = False - - return ha_flag - - -def get_ganesha_ha_failover_nodes(mnode=None, snodes=None): - '''Returns HA status and dictionary of - Kwargs: - mnode (Optional[str]): Node on which the ha status command has - to be executed. Default value is tc.servers[0]. - snodes (Optional[str]): Node/Nodes on which ganesha process - is Killed/stopped or Node shutdown - Returns: - bool,dict: If successfull True,dict - False otherwise - ''' - if mnode is None: - mnode = tc.servers[0] - if snodes is None: - snodes = tc.servers[1] - if not isinstance(snodes, list): - snodes = [snodes] - ha_flag = True - tnode = OrderedDict() - ret, out, _ = tc.run(mnode, "/usr/libexec/ganesha/ganesha-ha.sh --status " - "| grep -v 'Online' | grep -v 'dead' | cut -d ' ' " - "-f 1 | sed s/'-cluster_ip-1'//g | sed s/" - "'-trigger_ip-1'//g") - if ret == 0: - list1 = filter(None, out.split("\n")) - ret, out, _ = tc.run(mnode, "/usr/libexec/ganesha/ganesha-ha.sh --status " - "| grep -v 'Online' | grep -v 'dead' | cut -d ' ' " - "-f 2 | sed s/'-cluster_ip-1'//g | sed s/" - "'-trigger_ip-1'//g") - if ret == 0: - list2 = filter(None, out.split("\n")) - server_hostname_dict = get_host_by_name() - snodes_hostnames = [] - for snode in snodes: - snodes_hostnames.append(server_hostname_dict[snode]) - for val1, val2 in zip(list1, list2): - if val1 in snodes_hostnames: - if val1 == val2: - tc.logger.error("Failover dint happen, wrong failover status " - "-> %s %s" % (val1, val2)) - ha_flag = False - else: - tnode[server_hostname_dict[val1]] = server_hostname_dict[val2] - tc.logger.info("%s successfully failed over on %s" - % (val1, val2)) - else: - if val1 != val2: - tc.logger.error("Failover not required, wrong failover status " - "-> %s %s" % (val1, val2)) - ha_flag = False - - return (ha_flag, tnode) - - -def update_ganesha_ha_conf(no_of_servers=None): - '''Updates the ganesha-ha.conf file, with VIPs and hostnames. - Kwargs: - no_of_servers (Optional[int]): The number of nodes on which we have - to modify the ganesha-ha.conf file. Default it takes - the number of servers from the pool list. - Returns: - bool: True if successfull, False otherwise. - ''' - if no_of_servers is None: - servers = nodes_from_pool_list() - no_of_servers = len(servers) - else: - servers = tc.servers[0:no_of_servers] - server_hostname_dict = get_host_by_name(servers) - hostnames = server_hostname_dict.values() - hosts = ','.join(hostnames) - file_src_path = "/etc/ganesha/ganesha-ha.conf.sample" - file_dest_path = "/etc/ganesha/ganesha-ha.conf" - ha_server = tc.run(tc.servers[0], "hostname") - conn = tc.get_connection(tc.servers[0], "root") - if conn.modules.os.path.isfile(file_src_path) == True: - tc.logger.info("%s file available and should be updated as " - "ganesha-ha.conf" % file_src_path) - try: - conn.modules.shutil.copy(file_src_path, file_dest_path) - FH = conn.builtin.open(file_dest_path, "r+") - except IOError as e: - tc.logger.error(e) - return False - lines = FH.readlines() - FH.seek(0) - FH.truncate() - for i in range(len(lines)): - if re.search("HA_NAME", lines[i]) != None: - lines[i] = re.sub(r'^HA_NAME.*', "HA_NAME=\"G"+str(time.time()) + - "\"", lines[i]) - if re.search("HA_VOL_SERVER", lines[i]) != None: - lines[i] = re.sub(r'^HA_VOL_SERVER.*', "HA_VOL_SERVER=\"" + - ha_server[1].strip()+"\"", lines[i]) - if re.search("HA_CLUSTER_NODES", lines[i]) != None: - lines[i] = re.sub(r'^HA_CLUSTER_NODES.*', "HA_CLUSTER_NODES=\"" + - hosts+"\"", lines[i]) - if re.search("VIP_", lines[i]) != None: - lines[i] = re.sub(r'.*VIP_.*\n', "", lines[i]) - vips = (tc.global_config["gluster"]["cluster_config"] - ["nfs_ganesha"]["vips"]) - for i in range(no_of_servers): - lines += "VIP_%s=\"%s\"\n" % (hostnames[i], vips[i]) - FH.write(''.join(lines)) - # create a local copy of this ha.conf file - f = open("/tmp/ganesha-ha.conf", "w") - f.write(''.join(lines)) - f.close() - FH.close() - conn.close() - # copy this ha.conf file to all the other nodes - for node in tc.servers[1:no_of_servers]: - ret = tc.upload(node, "/tmp/ganesha-ha.conf", file_dest_path) - - return True - - -def cluster_auth_setup(no_of_servers=None): - '''Sets the hacluster password, starts pcsd service and runs - pcs cluster auth command. - Kwargs: - no_of_servers (Optional[int]): The number of nodes on which we have - to setup the HA cluster. Default it takes the number - of servers from the pool list. - Returns: - bool: True if successfull, False otherwise. - ''' - if no_of_servers is None: - servers = nodes_from_pool_list() - no_of_servers = len(servers) - else: - servers = tc.servers[0:no_of_servers] - result = True - for node in tc.servers[0:no_of_servers]: - ret, _, _ = tc.run(node, "echo hacluster | passwd --stdin hacluster") - if ret != 0: - tc.logger.error("unable to set password for hacluster on %s" - % node) - return False - else: - ret, _, _ = tc.run(node, "service pcsd start") - if ret != 0: - tc.looger.error("service pcsd start command failed on %s" - % node) - return False - server_hostname_dict = get_host_by_name(servers) - for node in tc.servers[0:no_of_servers]: - val = "" - for key in server_hostname_dict: - val += server_hostname_dict[key] - val += " " - ret, _, _ = tc.run(node, "pcs cluster auth %s -u hacluster -p " - "hacluster" % val) - if ret != 0: - tc.logger.error("pcs cluster auth command failed on %s" % node) - result = False - - return result - - -def setup_nfs_ganesha(no_of_servers=None): - '''Setup NFS-Ganesha HA cluster. - Kwargs: - no_of_servers (Optional[int]): The number of nodes on which we have - to setup the HA cluster. Default it takes the number - of servers from the pool list. - Returns: - bool: True if successfull, False otherwise. - ''' - if ('setup_nfs_ganesha' in tc.global_flag and - tc.global_flag['setup_nfs_ganesha'] == True): - tc.logger.debug("The setup nfs-ganesha is already setup, returning...") - return True - if no_of_servers is None: - servers = tc.servers - no_of_servers = len(servers) - servers = tc.servers[0:no_of_servers] - no_of_servers = int(no_of_servers) - # Step 1: Peer probe - ret = peer_probe_servers(tc.servers[1:no_of_servers], mnode=tc.servers[0]) - if not ret: - return False - # Step 2: Passwordless ssh for nfs - ret = create_nfs_passwordless_ssh(snodes=tc.servers[0:no_of_servers], - mnode=tc.servers[0]) - if ret: - tc.logger.info("passwordless ssh between nodes successfull") - else: - tc.logger.error("passwordless ssh between nodes unsuccessfull") - return False - # Step 3: Update ganesha-ha.conf file - ret = update_ganesha_ha_conf(no_of_servers) - if ret: - tc.logger.info("ganesha-ha.conf files succeessfully updated on all " - "the nodes") - else: - tc.logger.error("ganesha-ha.conf files not succeessfully updated on " - "all the nodes") - return False - # Step 4: Cluster setup - ret = cluster_auth_setup(no_of_servers) - if ret: - tc.logger.info("successfull cluster setup") - else: - tc.logger.error("unsuccessfull cluster setup") - return False - # Step 5: Using CLI to create shared volume - ret, _, _ = tc.run(tc.servers[0], "gluster v list | grep " - "'gluster_shared_storage'") - if ret != 0: - ret, _, _ = tc.run(tc.servers[0], "gluster volume set all " - "cluster.enable-shared-storage enable") - if ret != 0: - tc.logger.error("shared volume creation unsuccessfull") - return False - else: - tc.logger.info("shared volume creation successfull") - time.sleep(10) - else: - tc.logger.info("shared volume already exists") - time.sleep(60) - # Step 6: Enable NFS-Ganesha - ret = set_nfs_ganesha(True) - if ret: - tc.logger.info("gluster nfs-ganesha enable success") - else: - tc.logger.error("gluster nfs-ganesha enable failed") - return False - # Setting globalflag to True - tc.global_flag["setup_nfs_ganesha"] = True - - return True - - -def teardown_nfs_ganesha_setup(mnode=None): - '''Teardowns the NFS-Ganesha HA setup. - Kwargs: - mnode (Optional[str]): Node on which the command has - to be executed. Default value is tc.servers[0]. - Returns: - bool: True if successful, False otherwise. - ''' - if mnode is None: - mnode = tc.servers[0] - # Step 1: Disable NFS-Ganesha - ret = set_nfs_ganesha(False) - if ret: - tc.logger.info("gluster nfs-ganesha disable success") - else: - tc.logger.error("gluster nfs-ganesha disable failed") - return False - # Step 2: Using CLI to delete the shared volume - ret, _, _ = tc.run(mnode, "gluster volume set all " - "cluster.enable-shared-storage disable --mode=script") - if ret != 0: - tc.logger.error("shared volume deletion unsuccessfull") - return False - else: - tc.logger.info("shared volume deletion successfull") - # Setting globalflag to False - tc.global_flag["setup_nfs_ganesha"] = False - - return True diff --git a/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/gluster_base_class.py b/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/gluster_base_class.py deleted file mode 100644 index 367570d6e0e..00000000000 --- a/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/gluster_base_class.py +++ /dev/null @@ -1,160 +0,0 @@ -# This file is part of DiSTAF -# Copyright (C) 2015-2016 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 distaf.util import tc -from distaflibs.gluster.volume_ops import (setup_vol, get_volume_info, - cleanup_volume) -from distaflibs.gluster.mount_ops import GlusterMount -from distaflibs.gluster.gluster_init import env_setup_servers - - -class GlusterBaseClass(): - """ - This is the base class for the distaf tests - - All tests can subclass this and then write test cases - """ - - def __init__(self, config_data): - """ - Initialise the class with the config values - """ - if config_data['global_mode']: - self.volname = config_data['gluster']['volumes'][0]['name'] - self.voltype = (config_data['gluster']['volumes'][0]['voltype'] - ['type']) - self.servers = [] - for server in config_data['gluster']['volumes'][0]['servers']: - self.servers.append(server['host']) - self.peers = config_data['gluster']['volumes'][0]['peers'] - self.mounts = [] - for mount in config_data['gluster']['mounts']: - mount['client'] = mount['client']['host'] - mount['server'] = mount['server']['host'] - self.mounts.append(GlusterMount(mount)) - self.clients = [] - for mount_obj in self.mounts: - self.clients.append(mount_obj.client_system) - self.clients = filter(None, self.clients) - - else: - self.voltype = config_data['voltype'] - self.volname = "%s-testvol" % self.voltype - self.servers = [] - for server in config_data['servers']: - self.servers.append(server['host']) - self.clients = [] - for client in config_data['clients']: - self.clients.append(client['host']) - self.peers = [] - if config_data['peers'] is not None: - for peer in config_data['peers']: - self.peers.append(peers['host']) - self.mounts = [] - self.mount_proto = config_data['mount_proto'] - self.mountpoint = "/mnt/%s_mount" % self.mount_proto - for client in self.clients: - mount = {} - mount['protocol'] = config_data['mount_proto'] - mount['mountpoint'] = "/mnt/%s_mount" % self.mount_proto - mount['server'] = self.servers[0] - mount['client'] = client - mount['volname'] = self.volname - mount['options'] = "" - self.mounts.append(GlusterMount(mount)) - self.mnode = self.servers[0] - self.config_data = config_data - - def _create_volume(self): - """ - Create the volume with proper configurations - """ - dist = rep = dispd = red = stripe = 1 - trans = '' - if self.voltype == 'distribute': - dist = (self.config_data['gluster']['volume_types'][self.voltype] - ['dist_count']) - trans = (self.config_data['gluster']['volume_types'][self.voltype] - ['transport']) - elif self.voltype == 'replicate': - rep = (self.config_data['gluster']['volume_types'][self.voltype] - ['replica_count']) - trans = (self.config_data['gluster']['volume_types'][self.voltype] - ['transport']) - elif self.voltype == 'dist_rep': - dist = (self.config_data['gluster']['volume_types'][self.voltype] - ['dist_count']) - rep = (self.config_data['gluster']['volume_types'][self.voltype] - ['replica_count']) - trans = (self.config_data['gluster']['volume_types'][self.voltype] - ['transport']) - elif self.voltype == 'disperse': - dispd = (self.config_data['gluster']['volume_types'][self.voltype] - ['disperse_count']) - red = (self.config_data['gluster']['volume_types'][self.voltype] - ['redundancy_count']) - trans = (self.config_data['gluster']['volume_types'][self.voltype] - ['transport']) - elif self.voltype == 'dist_disperse': - dist = self.config_data[self.voltype]['dist_count'] - dispd = self.config_data[self.voltype]['disperse_count'] - red = self.config_data[self.voltype]['redundancy_count'] - trans = self.config_data[self.voltype]['transport'] - else: - tc.logger.error("The volume type is not present") - return False - ret = setup_vol(self.volname, self.mnode, dist, rep, dispd, red, - stripe, trans, servers=self.servers) - if not ret: - tc.logger.error("Unable to setup volume %s", self.volname) - return False - return True - - def setup(self): - """ - Function to setup the volume for testing. - """ - if not env_setup_servers(): - tc.logger.error("Unable to setup testenv") - return False - - volinfo = get_volume_info(mnode=self.servers[0]) - if volinfo is not None and self.volname in volinfo.keys(): - tc.logger.debug("The volume %s is already present in %s", - self.volname, self.mnode) - if not self.config_data['reuse_setup']: - ret = cleanup_volume(self.volname, self.mnode) - if not ret: - tc.logger.error("Unable to cleanup the setup") - return False - return self._create_volume() - else: - return self._create_volume() - return True - - def teardown(self): - """ - The function to cleanup the test setup - """ - return True - - def cleanup(self): - """ - The function to cleanup the volume - """ - return cleanup_volume(self.volname, self.mnode) diff --git a/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/gluster_init.py b/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/gluster_init.py deleted file mode 100644 index 9a3c8599724..00000000000 --- a/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/gluster_init.py +++ /dev/null @@ -1,77 +0,0 @@ -# This file is part of DiSTAF -# Copyright (C) 2015-2016 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 distaf.util import tc -import re -""" - This file contains the glusterd and other initial gluster - options like start/stop glusterd and env_setup_servers for - initial back-end brick preperation -""" - - -def start_glusterd(servers=''): - """ - Starts glusterd in all servers if they are not running - - Returns True if glusterd started in all servers - Returns False if glusterd failed to start in any server - - (Will be enhanced to support systemd in future) - """ - if servers == '': - servers = tc.servers - ret, _ = tc.run_servers("pgrep glusterd || service glusterd start", \ - servers=servers) - return ret - - -def stop_glusterd(servers=''): - """ - Stops the glusterd in specified machine(s) - - Returns True if glusterd is stopped in all nodes - Returns False on failure - """ - if servers == '': - servers = tc.servers - ret, _ = tc.run_servers("service glusterd stop", servers=servers) - return ret - - -#TODO: THIS IS NOT IMPLEMENTED YET. PLEASE DO THIS MANUALLY -# TILL WE IMPLEMENT THIS PART - -def env_setup_servers(snap=True, servers=''): - """ - Sets up the env for all the tests - Install all the gluster bits and it's dependencies - Installs the xfs bits and then formats the backend fs for gluster use - - Returns 0 on success and non-zero upon failing - """ - tc.logger.info("The function isn't implemented yet") - tc.logger.info("Please setup the bricks manually.") - - if servers == '': - servers = tc.servers - - if not start_glusterd(servers): - return False - - return True diff --git a/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/lib_utils.py b/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/lib_utils.py deleted file mode 100644 index 24267f8bc1d..00000000000 --- a/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/lib_utils.py +++ /dev/null @@ -1,467 +0,0 @@ -#!/usr/bin/env python -# This file is part of DiSTAF -# Copyright (C) 2015-2016 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: Helper library for gluster modules. -""" - -from distaf.util import tc -from distaflibs.gluster.volume_ops import get_volume_info -from distaflibs.gluster.mount_ops import mount_volume, umount_volume -import re -import time -from collections import OrderedDict -import tempfile - -try: - import xml.etree.cElementTree as etree -except ImportError: - import xml.etree.ElementTree as etree - - -def append_string_to_file(mnode, filename, str_to_add_in_file): - """Appends the given string in the file. - - Example: - append_string_to_file("abc.def.com", "/var/log/messages", - "test_1_string") - - Args: - mnode (str): Node on which cmd has to be executed. - filename (str): absolute file path to append the string - str_to_add_in_file (str): string to be added in the file, - which is used as a start and stop string for parsing - the file in search_pattern_in_file(). - - Returns: - True, on success, False otherwise - """ - try: - conn = tc.get_connection(mnode, 'root') - if conn == -1: - tc.logger.error("Unable to get connection to 'root' of node %s" - " in append_string_to_file()" % mnode) - return False - - with conn.builtin.open(filename, 'a') as _filehandle: - _filehandle.write(str_to_add_in_file) - - return True - except: - tc.logger.error("Exception occured while adding string to " - "file %s in append_string_to_file()" % filename) - return False - finally: - conn.close() - - -def search_pattern_in_file(mnode, search_pattern, filename, start_str_to_parse, - end_str_to_parse): - """checks if the given search pattern exists in the file - in between 'start_str_to_parse' and 'end_str_to_parse' string. - - Example: - search_pattern = r'.*scrub.*' - search_log("abc.def.com", search_pattern, "/var/log/messages", - "start_pattern", "end_pattern") - - Args: - mnode (str): Node on which cmd has to be executed. - search_pattern (str): regex string to be matched in the file - filename (str): absolute file path to search given string - start_str_to_parse (str): this will be as start string in the - file from which this method will check - if the given search string is present. - end_str_to_parse (str): this will be as end string in the - file whithin which this method will check - if the given search string is present. - - Returns: - True, if search_pattern is present in the file - False, otherwise - """ - - cmd = ("awk '{a[NR]=$0}/" + start_str_to_parse + "/{s=NR}/" + - end_str_to_parse + "/{e=NR}END{for(i=s;i<=e;++i)print " - "a[i]}' " + filename) - - ret, out, err = tc.run(mnode, cmd) - if ret != 0: - tc.logger.error("Failed to match start and end pattern in file" - % filename) - return False - - if not re.search(search_pattern, str(out), re.S): - tc.logger.error("file %s did not have the expected message" - % filename) - return False - - return True - - -def calculate_checksum(file_list, chksum_type='sha256sum', mnode=None): - """This module calculates given checksum for the given file list - - Example: - calculate_checksum([file1, file2]) - - Args: - file_list (list): absolute file names for which checksum - to be calculated - - Kwargs: - mnode (str): Node on which cmd has to be executed. - chksum_type (str): type of the checksum algorithm. - Defaults to sha256sum - - Returns: - NoneType: None if command execution fails, parse errors. - dict: checksum value for each file in the given file list - """ - - if mnode is None: - mnode = tc.servers[0] - - cmd = chksum_type + " %s" % ' '.join(file_list) - ret = tc.run(mnode, cmd) - if ret[0] != 0: - tc.logger.error("Failed to execute checksum command in server %s" - % mnode) - return None - - checksum_dict = {} - for line in ret[1].split('\n')[:-1]: - match = re.search(r'^(\S+)\s+(\S+)', line.strip()) - if match is None: - tc.logger.error("checksum output is not in" - "expected format") - return None - - checksum_dict[match.group(2)] = match.group(1) - - return checksum_dict - - -def get_extended_attributes_info(file_list, encoding='hex', attr_name='', - mnode=None): - """This module gets extended attribute info for the given file list - - Example: - get_extended_attributes_info([file1, file2]) - - Args: - file_list (list): absolute file names for which extended - attributes to be fetched - - Kwargs: - encoding (str): encoding format - attr_name (str): extended attribute name - mnode (str): Node on which cmd has to be executed. - - Returns: - NoneType: None if command execution fails, parse errors. - dict: extended attribute for each file in the given file list - """ - - if mnode is None: - mnode = tc.servers[0] - - if attr_name == '': - cmd = "getfattr -d -m . -e %s %s" % (encoding, ' '.join(file_list)) - else: - cmd = "getfattr -d -m . -n %s %s" % (attr_name, ' '.join(file_list)) - - ret = tc.run(mnode, cmd) - if ret[0] != 0: - tc.logger.error("Failed to execute getfattr command in server %s" - % mnode) - return None - - attr_dict = {} - for each_attr in ret[1].split('\n\n')[:-1]: - for line in each_attr.split('\n'): - if line.startswith('#'): - match = re.search(r'.*file:\s(\S+).*', line) - if match is None: - tc.logger.error("getfattr output is not in " - "expected format") - return None - key = "/" + match.group(1) - attr_dict[key] = {} - else: - output = line.split('=') - attr_dict[key][output[0]] = output[1] - return attr_dict - - -def get_pathinfo(filename, volname, mnode=None): - """This module gets filepath of the given file in gluster server. - - Example: - get_pathinfo("file1", "testvol") - - Args: - filename (str): relative path of file - volname (str): volume name - - Kwargs: - mnode (str): Node on which cmd has to be executed. Defaults - to tc.servers[0]. - - Returns: - NoneType: None if command execution fails, parse errors. - list: file path for the given file in gluster server - """ - - if mnode is None: - mnode = tc.servers[0] - - mount_point = tempfile.mkdtemp() - - # Performing glusterfs mount because only with glusterfs mount - # the file location in gluster server can be identified - ret, _, _ = mount_volume(volname, mtype='glusterfs', - mpoint=mount_point, - mserver=mnode, - mclient=mnode) - if ret != 0: - tc.logger.error("Failed to do gluster mount on volume %s to fetch" - "pathinfo from server %s" - % (volname, mnode)) - return None - - filename = mount_point + '/' + filename - attr_name = 'trusted.glusterfs.pathinfo' - output = get_extended_attributes_info([filename], - attr_name=attr_name, - mnode=mnode) - if output is None: - tc.logger.error("Failed to get path info for %s" % filename) - return None - - pathinfo = output[filename][attr_name] - - umount_volume(mnode, mount_point) - tc.run(mnode, "rm -rf " + mount_point) - - return re.findall(".*?POSIX.*?:(\S+)\>", pathinfo) - - -def list_files(dir_path, parse_str="", mnode=None): - """This module list files from the given file path - - Example: - list_files("/root/dir1/") - - Args: - dir_path (str): directory path name - - Kwargs: - parse_str (str): sub string of the filename to be fetched - mnode (str): Node on which cmd has to be executed. - - Returns: - NoneType: None if command execution fails, parse errors. - list: files with absolute name - """ - if mnode is None: - mnode = tc.clients[0] - - try: - conn = tc.get_connection(mnode, 'root') - if conn == -1: - tc.logger.error("Unable to get connection to 'root' of node %s" - % mnode) - return None - - filepaths = [] - for root, directories, files in conn.modules.os.walk(dir_path): - for filename in files: - if parse_str != "": - if parse_str in filename: - filepath = conn.modules.os.path.join(root, filename) - filepaths.append(filepath) - else: - filepath = conn.modules.os.path.join(root, filename) - filepaths.append(filepath) - return filepaths - except: - tc.logger.error("Exception occured in list_files()") - return None - - finally: - conn.close() - - -def get_servers_bricks_dict(servers): - """This module returns servers_bricks dictionary. - Args: - servers (list): List of servers for which we need the - list of bricks available on it. - Returns: - OrderedDict: key - server - value - list of bricks - Example: - get_servers_bricks_dict(tc.servers) - """ - servers_bricks_dict = OrderedDict() - if not isinstance(servers, list): - servers = [servers] - for server in servers: - for server_list in tc.global_config["servers"]: - if server_list["host"] == server: - brick_root = server_list["brick_root"] - ret, out, err = tc.run(server, "cat /proc/mounts | grep %s" - " | awk '{ print $2}'" % brick_root) - if ret != 0: - tc.logger.error("bricks not available on %s" % server) - else: - servers_bricks_dict[server] = out.strip().split("\n") - - for key, value in servers_bricks_dict.items(): - value.sort() - - return servers_bricks_dict - - -def get_servers_used_bricks_dict(servers, mnode): - """This module returns servers_used_bricks dictionary. - This information is fetched from gluster volume info command. - Args: - servers (list): List of servers for which we need the - list of unused bricks on it. - mnode (str): The node on which gluster volume info command has - to be executed. - Returns: - OrderedDict: key - server - value - list of used bricks - or empty list(if all bricks are free) - Example: - get_servers_used_bricks_dict(tc.servers[:], tc.servers[0]) - """ - if not isinstance(servers, list): - servers = [servers] - - servers_used_bricks_dict = OrderedDict() - for server in servers: - servers_used_bricks_dict[server] = [] - - ret, out, err = tc.run(mnode, "gluster volume info | egrep " - "\"^Brick[0-9]+\" | grep -v \"ss_brick\"", - verbose=False) - if ret != 0: - tc.logger.error("error in getting bricklist using gluster v info") - else: - list1 = list2 = [] - list1 = out.strip().split('\n') - for item in list1: - x = re.search(':(.*)/(.*)', item) - list2 = x.group(1).strip().split(':') - if servers_used_bricks_dict.has_key(list2[0]): - value = servers_used_bricks_dict[list2[0]] - value.append(list2[1]) - else: - servers_used_bricks_dict[list2[0]] = [list2[1]] - - for key, value in servers_used_bricks_dict.items(): - value.sort() - - return servers_used_bricks_dict - - -def get_servers_unused_bricks_dict(servers, mnode): - """This module returns servers_unused_bricks dictionary. - Gets a list of unused bricks for each server by using functions, - get_servers_bricks_dict() and get_servers_used_bricks_dict() - Args: - servers (list): List of servers for which we need the - list of unused bricks available on it. - mnode (str): The node on which gluster volume info command has - to be executed. - Returns: - OrderedDict: key - server - value - list of unused bricks - Example: - get_servers_unused_bricks_dict(tc.servers, tc.servers[0]) - """ - if not isinstance(servers, list): - servers = [servers] - dict1 = get_servers_bricks_dict(servers) - dict2 = get_servers_used_bricks_dict(servers, mnode) - servers_unused_bricks_dict = OrderedDict() - for key, value in dict1.items(): - if dict2.has_key(key): - unused_bricks = list(set(value) - set(dict2[key])) - servers_unused_bricks_dict[key] = unused_bricks - else: - servers_unused_bricks_dict[key] = value - - for key, value in servers_unused_bricks_dict.items(): - value.sort() - - return servers_unused_bricks_dict - - -def form_bricks_path(number_of_bricks, servers, mnode, volname): - """Forms complete bricks path for create-volume/add-brick - given the num_of_bricks - Args: - number_of_bricks (int): The number of bricks for which brick list - has to be created. - servers (list): The list of servers from which the bricks - needs to be selected for creating the brick list. - mnode (str): The node on which the command has to be run. - volname (str): Volume name for which we require brick-list. - Returns: - str - complete brick path. - None - if number_of_bricks is greater than unused bricks. - Example: - form_bricks_path(6, tc.servers, tc.servers(0), "testvol") - """ - if not isinstance(servers, list): - servers = [servers] - dict_index = 0 - bricks_path = '' - - server_bricks_dict = get_servers_unused_bricks_dict(servers, servers[0]) - num_of_unused_bricks = 0 - for server_brick in server_bricks_dict.values(): - num_of_unused_bricks = num_of_unused_bricks + len(server_brick) - - if num_of_unused_bricks < number_of_bricks: - tc.logger.error("Not enough bricks available for creating the bricks") - return None - - brick_index = 0 - vol_info_dict = get_volume_info(volname, mnode) - if vol_info_dict: - brick_index = int(vol_info_dict[volname]['brickCount']) - - for num in range(brick_index, brick_index + number_of_bricks): - if server_bricks_dict.values()[dict_index]: - bricks_path = ("%s %s:%s/%s_brick%s" % (bricks_path, - server_bricks_dict.keys()[dict_index], - server_bricks_dict.values()[dict_index][0], - volname, num)) - server_bricks_dict.values()[dict_index].pop(0) - if dict_index < len(server_bricks_dict) - 1: - dict_index = dict_index + 1 - else: - dict_index = 0 - - return bricks_path diff --git a/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/mount_ops.py b/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/mount_ops.py deleted file mode 100644 index 3082da0484f..00000000000 --- a/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/mount_ops.py +++ /dev/null @@ -1,210 +0,0 @@ -# This file is part of DiSTAF -# Copyright (C) 2015-2016 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 distaf.util import tc - -class GlusterMount(): - """Gluster Mount class - - Args: - mount (dict): Mount dict with 'mount_protocol', 'mountpoint', - 'server', 'client', 'volname', 'options' as keys - - Returns: - Instance of GlusterMount class - """ - client_register = 0 - - def __init__(self, mount): - if mount['protocol']: - self.mounttype = mount['protocol'] - else: - self.mounttype = "glusterfs" - - if mount['mountpoint']: - self.mountpoint = mount['mountpoint'] - else: - self.mountpoint = "/mnt/%s" % self.mounttype - - self.server_system = mount['server'] - self.client_system = mount['client'] - self.volname = mount['volname'] - self.options = mount['options'] - - def mount(self): - """Mounts the volume - - Args: - uses instance args passed at init - - Returns: - bool: True on success and False on failure. - """ - (_retcode, _, _) = mount_volume(self.volname, - mtype=self.mounttype, - mpoint=self.mountpoint, - mserver=self.server_system, - mclient=self.client_system, - options=self.options) - - if _retcode == 0: - return True - else: - return False - - def is_mounted(self): - """Tests for mount on client - - Args: - uses instance args passed at init - - Returns: - bool: True on success and False on failure. - """ - _retcode = is_mounted(self.volname, - mpoint=self.mountpoint, - mserver=self.server_system, - mclient=self.client_system) - - if _retcode: - return True - else: - return False - - def unmount(self): - """Unmounts the volume - - Args: - uses instance args passed at init - - Returns: - bool: True on success and False on failure. - """ - (_retcode, _, _) = umount_volume(self.client_system, - self.mountpoint) - - if _retcode == 0: - return True - else: - return False - -def is_mounted(volname, mpoint, mserver, mclient): - """Check if mount exist. - - Args: - volname (str): Name of the volume - mpoint (str): Mountpoint dir - mserver (str): Server to which it is mounted to - mclient (str): Client from which it is mounted. - - Returns: - bool: True if mounted and False otherwise. - """ - # python will error on missing arg, so just checking for empty args here - if not volname or not mpoint or not mserver or not mclient: - tc.logger.error("Missing arguments for mount.") - return False - - ret, _, _ = tc.run(mclient, "mount | grep %s | grep %s | grep \"%s\"" - % (volname, mpoint, mserver), verbose=False) - if ret == 0: - tc.logger.debug("Volume %s is mounted at %s:%s" % (volname, - mclient, - mpoint)) - return True - else: - tc.logger.error("Volume %s is not mounted at %s:%s" % (volname, - mclient, - mpoint)) - return False - -def mount_volume(volname, mtype='glusterfs', mpoint='/mnt/glusterfs', - mserver='', mclient='', options=''): - """Mount the gluster volume with specified options. - - Args: - volname (str): Name of the volume to mount. - - Kwargs: - mtype (str): Protocol to be used to mount. - mpoint (str): Mountpoint dir. - mserver (str): Server to mount. - mclient (str): Client from which it has to be mounted. - option (str): Options for the mount command. - - Returns: - tuple: Tuple containing three elements (ret, out, err). - (0, '', '') if already mounted. - (1, '', '') if setup_samba_service fails in case of smb. - (ret, out, err) of mount commnd execution otherwise. - """ - global tc - if mserver == '': - mserver = tc.servers[0] - if mclient == '': - mclient = tc.clients[0] - if options != '': - options = "-o %s" % options - if mtype == 'nfs' and options != '': - options = "%s" % options - elif mtype == 'nfs' and options == '': - options = '-o vers=3' - - if is_mounted(volname, mpoint, mserver, mclient): - tc.logger.debug("Volume %s is already mounted at %s" % - (volname, mpoint)) - return (0, '', '') - - mcmd = ("mount -t %s %s %s:/%s %s" % - (mtype, options, mserver, volname, mpoint)) - - if mtype == 'cifs': - from distaflibs.gluster.samba_ops import setup_samba_service - smbuser = tc.global_config['gluster']['cluster_config']['smb']['user'] - smbpasswd = (tc.global_config['gluster']['cluster_config']['smb'] - ['passwd']) - - if not setup_samba_service(volname, mserver, smbuser, smbpasswd): - tc.logger.error("Failed to setup samba service %s" % mserver) - return (1, '', '') - - mcmd = ("mount -t cifs -o username=root,password=%s " - "\\\\\\\\%s\\\\gluster-%s %s" % (smbpasswd, mserver, - volname, mpoint)) - # Create mount dir - _, _, _ = tc.run(mclient, "test -d %s || mkdir -p %s" % (mpoint, mpoint), - verbose=False) - - # Create mount - return tc.run(mclient, mcmd) - - -def umount_volume(mclient, mpoint): - """Unmounts the mountpoint. - - Args: - mclient (str): Client from which it has to be mounted. - mpoint (str): Mountpoint dir. - - Returns: - tuple: Tuple containing three elements (ret, out, err) as returned by - umount command execution. - """ - cmd = ("umount %s || umount -f %s || umount -l %s" % - (mpoint, mpoint, mpoint)) - return tc.run(mclient, cmd) diff --git a/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/peer_ops.py b/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/peer_ops.py deleted file mode 100644 index c235e637801..00000000000 --- a/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/peer_ops.py +++ /dev/null @@ -1,449 +0,0 @@ -#!/usr/bin/env python -# This file is part of DiSTAF -# Copyright (C) 2015-2016 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: Library for gluster peer operations. -""" - - -from distaf.util import tc -import re -import time -import socket -try: - import xml.etree.cElementTree as etree -except ImportError: - import xml.etree.ElementTree as etree - - -def peer_probe(server, mnode=None): - """Probe the specified server. - - Args: - server (str): Server to be peer probed. - - Kwargs: - mnode (str): Node on which command has to be executed. - If None, defaults to nodes[0]. - - 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. - """ - if mnode is None: - mnode = tc.servers[0] - - cmd = "gluster peer probe %s" % server - return tc.run(mnode, cmd) - -def peer_detach(server, force=False, mnode=None): - """Detach the specified server. - - Args: - server (str): Server to be peer detached. - - Kwargs: - force (bool): option to detach peer. - Defaults to False. - mnode (str): Node on which command has to be executed. - If None, defaults to nodes[0]. - - 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. - """ - if mnode is None: - mnode = tc.servers[0] - - if force: - cmd = "gluster peer detach %s force" % server - else: - cmd = "gluster peer detach %s" % server - return tc.run(mnode, cmd) - - -def peer_status(mnode=None): - """Runs 'gluster peer status' on specified node. - - Kwargs: - mnode (str): Node on which command has to be executed. - If None, defaults to nodes[0]. - - 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. - """ - tc.logger.info("Inside peer status") - if mnode is None: - mnode = tc.servers[0] - - cmd = "gluster peer status" - return tc.run(mnode, cmd) - - -def pool_list(mnode=None): - """Runs 'gluster pool list' command on the specified node. - - Kwargs: - mnode (str): Node on which command has to be executed. - If None, defaults to nodes[0]. - - 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. - """ - if mnode is None: - mnode = tc.servers[0] - - cmd = "gluster pool list" - return tc.run(mnode, cmd) - - -def peer_probe_servers(servers=None, validate=True, time_delay=10, mnode=None): - """Probe specified servers and validate whether probed servers - are in cluster and connected state if validate is set to True. - - Kwargs: - servers (list): List of servers to be peer probed. - If None, defaults to nodes. - validate (bool): True to validate if probed peer is in cluster and - connected state. False otherwise. Defaults to True. - time_delay (int): time delay before validating peer status. - Defaults to 10 seconds. - mnode (str): Node on which command has to be executed. - If None, defaults to nodes[0]. - - Returns: - bool: True on success and False on failure. - """ - if servers is None: - servers = tc.servers[:] - if not isinstance(servers, list): - servers = [servers] - if mnode is None: - mnode = tc.servers[0] - if mnode in servers: - servers.remove(mnode) - - # Get list of nodes from 'gluster pool list' - nodes_in_pool_list = nodes_from_pool_list(mnode) - if nodes_in_pool_list is None: - tc.logger.error("Unable to get nodes from gluster pool list. " - "Failing peer probe.") - return False - - for server in servers: - if server not in nodes_in_pool_list: - ret, out, _ = peer_probe(server, mnode) - if (ret != 0 or - re.search(r'^peer\sprobe\:\ssuccess(.*)', out) is None): - tc.logger.error("Failed to peer probe the node '%s'.", server) - return False - else: - tc.logger.info("Successfully peer probed the node '%s'.", - server) - - # Validating whether peer is in connected state after peer probe - if validate: - time.sleep(time_delay) - if not is_peer_connected(servers, mnode): - tc.logger.error("Validation after peer probe failed.") - return False - else: - tc.logger.info("Validation after peer probe is successful.") - - return True - -def peer_detach_servers(servers=None, force=False, validate=True, - time_delay=10, mnode=None): - """Detach peers and validate status of peer if validate is set to True. - - Kwargs: - servers (list): List of servers to be peer detached. - If None, defaults to nodes. - force (bool): option to detach peer. - Defaults to False. - validate (bool): True if status of the peer needs to be validated, - False otherwise. Defaults to True. - time_delay (int): time delay before executing validating peer. - status. Defaults to 10 seconds. - mnode (str): Node on which command has to be executed. - If None, defaults to nodes[0]. - - Returns: - bool: True on success and False on failure. - """ - if servers is None: - servers = tc.servers[:] - if not isinstance(servers, list): - servers = [servers] - if mnode is None: - mnode = tc.servers[0] - if mnode in servers: - servers.remove(mnode) - - for server in servers: - ret, out, _ = peer_detach(server, force, mnode) - if (ret != 0 or - re.search(r'^peer\sdetach\:\ssuccess(.*)', out) is None): - tc.logger.error("Failed to peer detach the node '%s'.", server) - return False - - # Validating whether peer detach is successful - if validate: - time.sleep(time_delay) - if is_peer_connected(servers, mnode): - tc.logger.error("Validation after peer detach failed.") - return False - else: - tc.logger.info("Validation after peer detach is successful") - - return True - -def nodes_from_pool_list(mnode=None): - """Return list of nodes from the 'gluster pool list'. - - Kwargs: - mnode (str): Node on which command has to be executed. - If None, defaults to nodes[0]. - - Returns: - NoneType: None if command execution fails. - list: List of nodes in pool on Success, Empty list on failure. - """ - if mnode is None: - mnode = tc.servers[0] - - pool_list_data = get_pool_list(mnode) - if pool_list_data is None: - tc.logger.error("Unable to get Nodes from the pool list command.") - return None - - nodes = [] - for item in pool_list_data: - nodes.append(item['hostname']) - return nodes - - -def get_peer_status(mnode=None): - """Parse the output of command 'gluster peer status'. - - Kwargs: - mnode (str): Node on which command has to be executed. - if None, defaults to nodes[0]. - - Returns: - NoneType: None if command execution fails or parse errors. - list: list of dicts on success. - - Examples: - >>> get_peer_status(mnode = 'abc.lab.eng.xyz.com') - [{'uuid': '77dc299a-32f7-43d8-9977-7345a344c398', - 'hostname': 'ijk.lab.eng.xyz.com', - 'state': '3', - 'hostnames' : ['ijk.lab.eng.xyz.com'], - 'connected': '1', - 'stateStr': 'Peer in Cluster'}, - - {'uuid': 'b15b8337-9f8e-4ec3-8bdb-200d6a67ae12', - 'hostname': 'def.lab.eng.xyz.com', - 'state': '3', - 'hostnames': ['def.lab.eng.xyz.com'], - 'connected': '1', - 'stateStr': 'Peer in Cluster'} - ] - """ - if mnode is None: - mnode = tc.servers[0] - - ret, out, _ = tc.run(mnode, "gluster peer status --xml", verbose=False) - if ret != 0: - tc.logger.error("Failed to execute peer status command on node '%s'. " - "Hence failed to parse the peer status.", mnode) - return None - - try: - root = etree.XML(out) - except etree.ParseError: - tc.logger.error("Failed to parse the gluster peer status xml output.") - return None - - peer_status_list = [] - for peer in root.findall("peerStatus/peer"): - peer_dict = {} - for element in peer.getchildren(): - if element.tag == "hostnames": - hostnames_list = [] - for hostname in element.getchildren(): - hostnames_list.append(hostname.text) - element.text = hostnames_list - peer_dict[element.tag] = element.text - peer_status_list.append(peer_dict) - return peer_status_list - - -def get_pool_list(mnode=None): - """Parse the output of 'gluster pool list' command. - - Kwargs: - mnode (str): Node on which command has to be executed. - If None, defaults to nodes[0]. - - Returns: - NoneType: None if command execution fails, parse errors. - list: list of dicts on success. - - Examples: - >>> get_pool_list(mnode = 'abc.lab.eng.xyz.com') - [{'uuid': 'a2b88b10-eba2-4f97-add2-8dc37df08b27', - 'hostname': 'abc.lab.eng.xyz.com', - 'state': '3', - 'connected': '1', - 'stateStr': 'Peer in Cluster'}, - - {'uuid': 'b15b8337-9f8e-4ec3-8bdb-200d6a67ae12', - 'hostname': 'def.lab.eng.xyz.com', - 'state': '3', - 'hostnames': ['def.lab.eng.xyz.com'], - 'connected': '1', - 'stateStr': 'Peer in Cluster'} - ] - """ - if mnode is None: - mnode = tc.servers[0] - - ret, out, _ = tc.run(mnode, "gluster pool list --xml", verbose=False) - if ret != 0: - tc.logger.error("Failed to execute 'pool list' on node %s. " - "Hence failed to parse the pool list.", mnode) - return None - - try: - root = etree.XML(out) - except etree.ParseError: - tc.logger.error("Failed to parse the gluster pool list xml output.") - return None - - pool_list_list = [] - for peer in root.findall("peerStatus/peer"): - peer_dict = {} - for element in peer.getchildren(): - if element.tag == "hostname" and element.text == 'localhost': - element.text = mnode - if element.tag == "hostnames": - hostnames_list = [] - for hostname in element.getchildren(): - hostnames_list.append(hostname.text) - element.text = hostnames_list - peer_dict[element.tag] = element.text - - pool_list_list.append(peer_dict) - return pool_list_list - - -def is_peer_connected(servers=None, mnode=None): - """Checks whether specified peers are in cluster and 'Connected' state. - - Kwargs: - servers (list): List of servers to be validated. - If None, defaults to nodes. - mnode (str): Node from which peer probe has to be executed. - If None, defaults to nodes[0]. - - Returns - bool : True on success (peer in cluster and connected), False on - failure. - """ - if servers is None: - servers = tc.servers[:] - if not isinstance(servers, list): - servers = [servers] - if mnode is None: - mnode = tc.servers[0] - if mnode in servers: - servers.remove(mnode) - - peer_connected = True - peer_status_list = get_peer_status(mnode) - if peer_status_list is None: - tc.logger.error("Failed to parse the peer status. Hence failed to " - "validate the peer connected state.") - return False - if peer_status_list == []: - tc.logger.error("No peers present in the pool. Servers are not yet " - "connected.") - return False - - server_ips = [] - for server in servers: - server_ips.append(socket.gethostbyname(server)) - - is_connected = True - for peer_stat in peer_status_list: - if socket.gethostbyname(peer_stat['hostname']) in servers: - if (re.match(r'([0-9a-f]{8})(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}', - peer_stat['uuid'], re.I) is None): - tc.logger.error("Invalid UUID for the node '%s'", - peer_stat['hostname']) - is_connected = False - if (peer_stat['stateStr'] != "Peer in Cluster" or - peer_stat['connected'] != '1'): - tc.logger.error("Peer '%s' not in connected state", - peer_stat['Hostname']) - is_connected = False - - if not is_connected: - return False - - peer_nodes = [stat_key['hostname'] for stat_key in peer_status_list] - if not (set(servers).issubset(peer_nodes)): - tc.logger.error("Servers: '%s' not yet added to the pool.", - (list(set(servers).difference(peer_nodes)))) - return False - - tc.logger.info("Servers: '%s' are all 'Peer in Cluster' and 'Connected' " - "state.", servers) - return True diff --git a/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/quota_ops.py b/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/quota_ops.py deleted file mode 100644 index 13ad13dd8d4..00000000000 --- a/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/quota_ops.py +++ /dev/null @@ -1,575 +0,0 @@ -#!/usr/bin/env python -# This file is part of DiSTAF -# Copyright (C) 2015-2016 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: Library for gluster quota operations. -""" - -from distaf.util import tc -import re -import time - -try: - import xml.etree.cElementTree as etree -except ImportError: - import xml.etree.ElementTree as etree - - -def enable_quota(volname, mnode=None): - """Enables quota on given volume - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - - 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. - - Example: - enable_quota(testvol) - """ - if mnode is None: - mnode = tc.servers[0] - - cmd = "gluster volume quota %s enable" % volname - ret = tc.run(mnode, cmd) - return ret - - -def disable_quota(volname, mnode=None): - """Disables quota on given volume - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - - 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. - - Example: - disable_quota(testvol) - """ - if mnode is None: - mnode = tc.servers[0] - - cmd = "gluster volume quota %s disable --mode=script" % volname - ret = tc.run(mnode, cmd) - return ret - - -def is_quota_enabled(volname, mnode=None): - """Checks if quota is enabled on given volume - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - - Returns: - bool: True, if quota is enabled - False, if quota is disabled - - Example: - is_quota_enabled(testvol) - """ - - import distaflibs.gluster.volume_ops - - if mnode is None: - mnode = tc.servers[0] - - output = distaflibs.gluster.volume_ops.get_volume_option(volname, - "features.quota", - mnode) - if output is None: - return False - - tc.logger.info("Quota Status in volume %s %s" - % (volname, output["features.quota"])) - if output["features.quota"] != 'on': - return False - - return True - - -def quota_list(volname, mnode=None): - """Executes quota list command for given volume - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - - 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. - - Example: - quota_list(testvol) - """ - if mnode is None: - mnode = tc.servers[0] - - cmd = "gluster volume quota %s list" % volname - ret = tc.run(mnode, cmd) - return ret - - -def set_quota_limit_usage(volname, path='/', limit='100GB', soft_limit='', - mnode=None): - """Sets limit-usage on the path of the specified volume to - specified limit - - Args: - volname (str): volume name - - Kwargs: - path (str): path to which quota limit usage is set. - Defaults to /. - limit (str): quota limit usage. defaults to 100GB - soft_limit (str): quota soft limit to be set - mnode (str): Node on which command has to be executed. - If None, defaults to servers[0]. - - 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. - - Examples: - >>> set_quota_limit_usage("testvol") - - """ - if mnode is None: - mnode = tc.servers[0] - - cmd = ("gluster volume quota %s limit-usage %s %s %s --mode=script" - % (volname, path, limit, soft_limit)) - return tc.run(mnode, cmd) - - -def get_quota_list(volname, mnode=None): - """Parse the output of 'gluster quota list' command. - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which command has to be executed. - If None, defaults to servers[0]. - - Returns: - NoneType: None if command execution fails, parse errors. - dict: dict on success. - - Examples: - >>> get_quota_list("testvol", mnode = 'abc.lab.eng.xyz.com') - {'/': {'used_space': '0', 'hl_exceeded': 'No', 'soft_limit_percent': - '60%', 'avail_space': '2147483648', 'soft_limit_value': '1288490188', - 'sl_exceeded': 'No', 'hard_limit': '2147483648'}} - """ - - if mnode is None: - mnode = tc.servers[0] - - cmd = "gluster volume quota %s list --xml" % volname - ret, out, _ = tc.run(mnode, cmd, verbose=False) - if ret != 0: - tc.logger.error("Failed to execute 'quota list' on node %s. " - "Hence failed to get the quota list.", mnode) - return None - - try: - root = etree.XML(out) - except etree.ParseError: - tc.logger.error("Failed to parse the gluster quota list xml output.") - return None - - quotalist = {} - for path in root.findall("volQuota/limit"): - for elem in path.getchildren(): - if elem.tag == "path": - path = elem.text - quotalist[path] = {} - else: - quotalist[path][elem.tag] = elem.text - return quotalist - - -def set_quota_limit_objects(volname, path='/', limit='10', soft_limit='', - mnode=None): - """Sets limit-objects on the path of the specified volume to - specified limit - - Args: - volname (str): volume name - - Kwargs: - path (str): path to which quota limit usage is set. - Defaults to /. - limit (str): quota limit objects. defaults to 10. - soft_limit (str): quota soft limit to be set - mnode (str): Node on which command has to be executed. - If None, defaults to servers[0]. - - 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. - - Examples: - >>> set_quota_limit_objects("testvol") - - """ - if mnode is None: - mnode = tc.servers[0] - - cmd = ("gluster volume quota %s limit-objects %s %s %s --mode=script" - % (volname, path, limit, soft_limit)) - return tc.run(mnode, cmd) - - -def quota_list_objects(volname, mnode=None): - """Executes quota list command for given volume - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - - 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. - - Example: - quota_list_objects(testvol) - - """ - if mnode is None: - mnode = tc.servers[0] - - cmd = "gluster volume quota %s list-objects" % volname - ret = tc.run(mnode, cmd) - return ret - - -def get_quota_list_objects(volname, mnode=None): - """Parse the output of 'gluster quota list-objects' command. - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which command has to be executed. - If None, defaults to servers[0]. - - Returns: - NoneType: None if command execution fails, parse errors. - dict: dict of dict on success. - - Examples: - >>> get_quota_list_objects("testvol", mnode = 'abc.lab.eng.xyz.com') - {'/': {'available': '7', 'hl_exceeded': 'No', 'soft_limit_percent': - '80%', 'soft_limit_value': '8', 'dir_count': '3', 'sl_exceeded': - 'No', 'file_count': '0', 'hard_limit': '10'}} - """ - - if mnode is None: - mnode = tc.servers[0] - - cmd = "gluster volume quota %s list-objects --xml" % volname - ret, out, _ = tc.run(mnode, cmd, verbose=False) - if ret != 0: - tc.logger.error("Failed to execute 'quota list' on node %s. " - "Hence failed to get the quota list.", mnode) - return None - - try: - root = etree.XML(out) - except etree.ParseError: - tc.logger.error("Failed to parse the gluster quota list xml output.") - return None - - quotalist = {} - for path in root.findall("volQuota/limit"): - for elem in path.getchildren(): - if elem.tag == "path": - path = elem.text - quotalist[path] = {} - else: - quotalist[path][elem.tag] = elem.text - return quotalist - - -def set_quota_alert_time(volname, time, mnode=None): - """Sets quota alert time - - Args: - volname (str): volume name - - Kwargs: - time (str): quota limit usage. defaults to 100GB - mnode (str): Node on which command has to be executed. - If None, defaults to servers[0]. - - 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. - - Examples: - >>> set_quota_alert_time("testvol", ) - - """ - if mnode is None: - mnode = tc.servers[0] - - cmd = ("gluster volume quota %s alert-time %s --mode=script" - % (volname, time)) - return tc.run(mnode, cmd) - - -def set_quota_soft_timeout(volname, timeout, mnode=None): - """Sets quota soft timeout - - Args: - volname (str): volume name - - Kwargs: - timeout (str): quota soft limit timeout value - mnode (str): Node on which command has to be executed. - If None, defaults to servers[0]. - - 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. - - Examples: - >>> set_quota_soft_timeout("testvol", ) - - """ - if mnode is None: - mnode = tc.servers[0] - - cmd = ("gluster volume quota %s soft-timeout %s --mode=script" - % (volname, timeout)) - return tc.run(mnode, cmd) - - -def set_quota_hard_timeout(volname, timeout, mnode=None): - """Sets quota hard timeout - - Args: - volname (str): volume name - timeout (str): quota hard limit timeout value - - Kwargs: - mnode (str): Node on which command has to be executed. - If None, defaults to servers[0]. - - 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. - - Examples: - >>> set_quota_hard_timeout("testvol", ) - - """ - if mnode is None: - mnode = tc.servers[0] - - cmd = ("gluster volume quota %s hard-timeout %s --mode=script" - % (volname, timeout)) - return tc.run(mnode, cmd) - - -def set_quota_default_soft_limit(volname, timeout, mnode=None): - """Sets quota default soft limit - - Args: - volname (str): volume name - timeout (str): quota soft limit timeout value - - Kwargs: - mnode (str): Node on which command has to be executed. - If None, defaults to servers[0]. - - 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. - - Examples: - >>> set_quota_default_soft_limit("testvol", ) - - """ - if mnode is None: - mnode = tc.servers[0] - - cmd = ("gluster volume quota %s default-soft-limit %s --mode=script" - % (volname, timeout)) - return tc.run(mnode, cmd) - - -def remove_quota(volname, path, mnode=None): - """Removes quota for the given path - - Args: - volname (str): volume name - path (str): path to which quota limit usage is set. - Defaults to /. - - Kwargs: - mnode (str): Node on which command has to be executed. - If None, defaults to servers[0]. - - 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. - - Examples: - >>> remove_quota("testvol", ) - - """ - if mnode is None: - mnode = tc.servers[0] - - cmd = "gluster volume quota %s remove %s --mode=script" % (volname, path) - return tc.run(mnode, cmd) - - -def remove_quota_objects(volname, path, mnode=None): - """Removes quota objects for the given path - - Args: - volname (str): volume name - path (str): path to which quota limit usage is set. - Defaults to /. - - Kwargs: - mnode (str): Node on which command has to be executed. - If None, defaults to servers[0]. - - 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. - - Examples: - >>> remove_quota_objects("testvol", ) - - """ - if mnode is None: - mnode = tc.servers[0] - - cmd = ("gluster volume quota %s remove-objects %s --mode=script" - % (volname, path)) - return tc.run(mnode, cmd) diff --git a/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/rebalance_ops.py b/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/rebalance_ops.py deleted file mode 100644 index 2679cc3eac3..00000000000 --- a/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/rebalance_ops.py +++ /dev/null @@ -1,334 +0,0 @@ -#!/usr/bin/env python -# This file is part of DiSTAF -# Copyright (C) 2015-2016 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: Library for gluster rebalance operations. -""" - -from distaf.util import tc -import re -import time - -try: - import xml.etree.cElementTree as etree -except ImportError: - import xml.etree.ElementTree as etree - - -def rebalance_start(volname, mnode=None, fix_layout=False, force=False): - """Starts rebalance on the given volume. - - Example: - rebalance_start(testvol) - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to nodes[0]. - fix_layout (bool) : If this option is set to True, then rebalance - start will get execute with fix-layout option. If set to False, - then rebalance start will get executed without fix-layout option - force (bool): If this option is set to True, then rebalance - start will get execute with force option. If it is set to False, - then rebalance start will get executed without force option - - 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. - """ - if mnode is None: - mnode = tc.servers[0] - - flayout = '' - if fix_layout: - flayout = "fix-layout" - - frce = '' - if force: - frce = 'force' - - if fix_layout and force: - tc.logger.warning("Both fix-layout and force option is specified." - "Ignoring force option") - frce = '' - - cmd = "gluster volume rebalance %s %s start %s" % (volname, flayout, frce) - ret = tc.run(mnode, cmd) - return ret - - -def rebalance_stop(volname, mnode=None): - """Stops rebalance on the given volume. - - Example: - rebalance_stop(testvol) - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to nodes[0]. - - 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. - """ - if mnode is None: - mnode = tc.servers[0] - - cmd = "gluster volume rebalance %s stop" % volname - ret = tc.run(mnode, cmd) - return ret - - -def rebalance_status(volname, mnode=None): - """Executes rebalance status on the given volume. - - Example: - rebalance_status(testvol) - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to nodes[0]. - - 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. - """ - if mnode is None: - mnode = tc.servers[0] - - cmd = "gluster volume rebalance %s status" % volname - ret = tc.run(mnode, cmd) - return ret - - -def get_rebalance_status(volname, mnode=None): - """Parse the output of 'gluster vol rebalance status' command - for the given volume - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which command has to be executed. - If None, defaults to nodes[0]. - - Returns: - NoneType: None if command execution fails, parse errors. - dict: dict on success. rebalance status will be - in dict format - - Examples: - >>> get_rebalance_status(testvol, mnode = 'abc.lab.eng.xyz.com') - {'node': [{'files': '0', 'status': '3', 'lookups': '0', 'skipped': '0', - 'nodeName': 'localhost', 'failures': '0', 'runtime': '0.00', 'id': - '11336017-9561-4e88-9ac3-a94d4b403340', 'statusStr': 'completed', - 'size': '0'}, {'files': '0', 'status': '1', 'lookups': '0', 'skipped': - '0', 'nodeName': '10.70.47.16', 'failures': '0', 'runtime': '0.00', - 'id': 'a2b88b10-eba2-4f97-add2-8dc37df08b27', 'statusStr': - 'in progress', 'size': '0'}, {'files': '0', 'status': '3', - 'lookups': '0', 'skipped': '0', 'nodeName': '10.70.47.152', - 'failures': '0', 'runtime': '0.00', 'id': - 'b15b8337-9f8e-4ec3-8bdb-200d6a67ae12', 'statusStr': 'completed', - 'size': '0'}, {'files': '0', 'status': '3', 'lookups': '0', 'skipped': - '0', 'nodeName': '10.70.46.52', 'failures': '0', 'runtime': '0.00', - 'id': '77dc299a-32f7-43d8-9977-7345a344c398', 'statusStr': 'completed', - 'size': '0'}], 'task-id': 'a16f99d1-e165-40e7-9960-30508506529b', - 'aggregate': {'files': '0', 'status': '1', 'lookups': '0', 'skipped': - '0', 'failures': '0', 'runtime': '0.00', 'statusStr': 'in progress', - 'size': '0'}, 'nodeCount': '4', 'op': '3'} - """ - - if mnode is None: - mnode = tc.servers[0] - - cmd = "gluster volume rebalance %s status --xml" % volname - ret, out, _ = tc.run(mnode, cmd, verbose=False) - if ret != 0: - tc.logger.error("Failed to execute 'rebalance status' on node %s. " - "Hence failed to get the rebalance status.", mnode) - return None - - try: - root = etree.XML(out) - except etree.ParseError: - tc.logger.error("Failed to parse the gluster rebalance status " - "xml output.") - return None - - rebal_status = {} - rebal_status["node"] = [] - for info in root.findall("volRebalance"): - for element in info.getchildren(): - if element.tag == "node": - status_info = {} - for elmt in element.getchildren(): - status_info[elmt.tag] = elmt.text - rebal_status[element.tag].append(status_info) - elif element.tag == "aggregate": - status_info = {} - for elmt in element.getchildren(): - status_info[elmt.tag] = elmt.text - rebal_status[element.tag] = status_info - else: - rebal_status[element.tag] = element.text - return rebal_status - - -def rebalance_stop_and_get_status(volname, mnode=None): - """Parse the output of 'gluster vol rebalance stop' command - for the given volume - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which command has to be executed. - If None, defaults to nodes[0]. - - Returns: - NoneType: None if command execution fails, parse errors. - dict: dict on success. rebalance status will be - in dict format - - Examples: - >>> rebalance_stop_and_get_status(testvol, mnode = 'abc.xyz.com') - {'node': [{'files': '0', 'status': '3', 'lookups': '0', 'skipped': '0', - 'nodeName': 'localhost', 'failures': '0', 'runtime': '0.00', 'id': - '11336017-9561-4e88-9ac3-a94d4b403340', 'statusStr': 'completed', - 'size': '0'}, {'files': '0', 'status': '1', 'lookups': '0', 'skipped': - '0', 'nodeName': '10.70.47.16', 'failures': '0', 'runtime': '0.00', - 'id': 'a2b88b10-eba2-4f97-add2-8dc37df08b27', 'statusStr': - 'in progress', 'size': '0'}, {'files': '0', 'status': '3', - 'lookups': '0', 'skipped': '0', 'nodeName': '10.70.47.152', - 'failures': '0', 'runtime': '0.00', 'id': - 'b15b8337-9f8e-4ec3-8bdb-200d6a67ae12', 'statusStr': 'completed', - 'size': '0'}, {'files': '0', 'status': '3', 'lookups': '0', 'skipped': - '0', 'nodeName': '10.70.46.52', 'failures': '0', 'runtime': '0.00', - 'id': '77dc299a-32f7-43d8-9977-7345a344c398', 'statusStr': 'completed', - 'size': '0'}], 'task-id': 'a16f99d1-e165-40e7-9960-30508506529b', - 'aggregate': {'files': '0', 'status': '1', 'lookups': '0', 'skipped': - '0', 'failures': '0', 'runtime': '0.00', 'statusStr': 'in progress', - 'size': '0'}, 'nodeCount': '4', 'op': '3'} - """ - - if mnode is None: - mnode = tc.servers[0] - - cmd = "gluster volume rebalance %s stop --xml" % volname - ret, out, _ = tc.run(mnode, cmd, verbose=False) - if ret != 0: - tc.logger.error("Failed to execute 'rebalance stop' on node %s. " - "Hence failed to parse the rebalance status.", mnode) - return None - - try: - root = etree.XML(out) - except etree.ParseError: - tc.logger.error("Failed to parse gluster rebalance stop xml output.") - return None - - rebal_status = {} - rebal_status["node"] = [] - for info in root.findall("volRebalance"): - for element in info.getchildren(): - if element.tag == "node": - status_info = {} - for elmt in element.getchildren(): - status_info[elmt.tag] = elmt.text - rebal_status[element.tag].append(status_info) - elif element.tag == "aggregate": - status_info = {} - for elmt in element.getchildren(): - status_info[elmt.tag] = elmt.text - rebal_status[element.tag] = status_info - else: - rebal_status[element.tag] = element.text - return rebal_status - - -def wait_for_rebalance_to_complete(volname, mnode=None, timeout=300): - """Waits for the rebalance to complete - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which command has to be executed. - If None, defaults to nodes[0]. - timeout (int): timeout value in seconds to wait for rebalance - to complete - - Returns: - True on success, False otherwise - - Examples: - >>> wait_for_rebalance_to_complete("testvol") - """ - - if mnode is None: - mnode = tc.servers[0] - - count = 0 - flag = 0 - while (count < timeout): - status_info = get_rebalance_status(volname, mnode=mnode) - if status_info is None: - return False - - status = status_info['aggregate']['statusStr'] - if status == 'completed': - flag = 1 - break - - time.sleep(10) - count = count + 10 - if not flag: - tc.logger.error("rebalance is not completed") - return False - else: - tc.logger.info("rebalance is successfully completed") - return True diff --git a/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/samba_ops.py b/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/samba_ops.py deleted file mode 100644 index 63d7aea0b7e..00000000000 --- a/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/samba_ops.py +++ /dev/null @@ -1,116 +0,0 @@ -#!/usr/bin/env python -# This file is part of DiSTAF -# Copyright (C) 2015-2016 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 distaf.util import tc - - -def setup_samba_service(volname, mnode, username, smbpasswd): - """This module Sets up the servers for samba mount - Takes care of editing the glusterd-volfile and - starting the samba services - Args: - volname(str): Volume name - mnode(str): where the samba setup will be done - username: samba username - smbpasswd: samba password - Returns: - bool: - True: On Success - False: On Failure - Example: - setup_samba_service("testvol", "tc.servers[0]", "Bond", "redhat") - """ - try: - if tc.global_flag['SAMBA_SETUP_DONE'] == True: - tc.logger.error("samba is already setup for the cluster") - return True - except KeyError: - pass - - glusterd_volfile = "/etc/glusterfs/glusterd.vol" - glstrd_edit_cmd = ("grep -F 'option rpc-auth-allow-insecure on' %s > " - "/dev/null || (cp %s %s.orig && " - "sed -i '/^end-volume/d' %s && " - "echo ' option rpc-auth-allow-insecure on' >> %s && " - "echo 'end-volume' >> %s && " - "service glusterd restart)" - % (glusterd_volfile, glusterd_volfile, - glusterd_volfile, glusterd_volfile, - glusterd_volfile, glusterd_volfile)) - - ret, _ = tc.run_servers(glstrd_edit_cmd) - if not ret: - tc.logger.error("Unable to edit glusterd in all servers") - return False - - ret, _, _ = tc.run(mnode, "chkconfig smb on") - - if ret != 0: - tc.logger.error("Unable to set chkconfig smb on") - return False - - tc.logger.info("chkconfig smb on successfull") - - ret, _, _ = tc.run(mnode, "service smb start") - if ret != 0: - tc.logger.error("Unable to start the smb service") - return False - - smbpasswd_cmd = ("(echo \"%s\"; echo \"%s\") | smbpasswd -a %s" % - (smbpasswd, smbpasswd, username)) - - ret, _, _ = tc.run(mnode, smbpasswd_cmd) - if ret != 0: - tc.logger.error("Unable to set the smb password") - return False - - time.sleep(20) - - ret, out, err = tc.run(mnode, "gluster volume set %s " - "server.allow-insecure on" % volname) - if ret != 0: - tc.logger.error("Failed to set the volume option " - "server-allow-insecure") - return False - - ret, out, err = tc.run(mnode, "gluster volume set %s stat-prefetch off" - % volname) - if ret != 0: - tc.logger.error("Failed to set the volume option stat-prefetch off") - return False - - set_volume_cmd = ("gluster volume set %s storage.batch-fsync-delay-usec 0" - % volname) - ret, out, err = tc.run(mnode, set_volume_cmd) - if ret != 0: - tc.logger.error("Failed to set the volume option storage" - "batch-fsync-delay-usec 0") - return False - - smb_cmd = "smbclient -L localhost -U " + username + "%" + smbpasswd - - ret, out, err = tc.run(mnode, smb_cmd + "| grep -i -Fw gluster-%s " - % volname) - if ret != 0: - tc.logger.error("unable to find share entry") - return False - tc.logger.info("Share entry present") - - tc.global_flag['SAMBA_SETUP_DONE'] = True - return True diff --git a/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/snap_ops.py b/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/snap_ops.py deleted file mode 100644 index 91785cc618f..00000000000 --- a/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/snap_ops.py +++ /dev/null @@ -1,961 +0,0 @@ -#!/usr/bin/env python -# This file is part of DiSTAF -# Copyright (C) 2015-2016 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: Library for gluster snapshot operations. -""" - -from distaf.util import tc -from distaflibs.gluster.volume_ops import start_volume, stop_volume -import re -import time - -try: - import xml.etree.cElementTree as etree -except ImportError: - import xml.etree.ElementTree as etree - - -def snap_create(volname, snapname, timestamp=False, description='', - force=False, mnode=None): - """Creates snapshot for the given volume. - - Example: - snap_create(testvol, testsnap) - - Args: - volname (str): volume name - snapname (str): snapshot name - - Kwargs: - timestamp (bool): If this option is set to True, then - timestamps will get appended to the snapname. If this option - is set to False, then timestamps will not be appended to snapname. - description (str): description for snapshot creation - force (bool): If this option is set to True, then snap - create will get execute with force option. If it is set to False, - then snap create will get executed without force option - mnode (str): Node on which cmd has to be executed. - If None, defaults to nodes[0]. - - 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. - """ - if mnode is None: - mnode = tc.servers[0] - - if description != '': - description = "description '%s'" % description - - tstamp = '' - if not timestamp: - tstamp = "no-timestamp" - - frce = '' - if force: - frce = 'force' - - cmd = ("gluster snapshot create %s %s %s %s %s" - % (snapname, volname, tstamp, description, frce)) - ret = tc.run(mnode, cmd) - return ret - - -def snap_clone(snapname, clonename, mnode=None): - """Clones the given snapshot - - Example: - snap_clone(testsnap, clone1) - - Args: - snapname (str): snapshot name to be cloned - clonename (str): clone name - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to nodes[0]. - - 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. - """ - if mnode is None: - mnode = tc.servers[0] - cmd = "gluster snapshot clone %s %s --mode=script" % (clonename, snapname) - return tc.run(mnode, cmd) - - -def snap_restore(snapname, mnode=None): - """Executes snap restore cli for the given snapshot - - Example: - snap_restore(testsnap) - - Args: - snapname (str): snapshot name to be cloned - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to nodes[0]. - - 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. - """ - - if mnode is None: - mnode = tc.servers[0] - cmd = "gluster snapshot restore %s --mode=script" % snapname - return tc.run(mnode, cmd) - - -def snap_restore_complete(volname, snapname, mnode=None): - """stops the volume restore the snapshot and starts the volume - - Example: - snap_restore_complete(testvol, testsnap) - - Args: - volname (str): volume name - snapname (str): snapshot name - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to nodes[0]. - - Returns: - bool: True on success, False on failure - """ - if mnode is None: - mnode = tc.servers[0] - - # Stopping volume before snap restore - ret = stop_volume(volname, mnode) - if not ret: - tc.logger.error("Failed to stop volume %s before restoring snapshot " - "%s in node %s" % (volname, snapname, mnode)) - return False - ret, _, _ = snap_restore(snapname, mnode=mnode) - if ret != 0: - tc.logger.error("snapshot restore cli execution failed") - return False - - # Starting volume after snap restore - ret = start_volume(volname, mnode) - if not ret: - tc.logger.error("Failed to start volume %s after restoring snapshot " - "%s in node %s" % (volname, snapname, mnode)) - return False - return True - - -def snap_status(snapname="", volname="", mnode=None): - """Runs 'gluster snapshot status' on specific node - - Example: - snap_status() - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to nodes[0]. - snapname (str): snapshot name - volname (str): volume name - - 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. - """ - if mnode is None: - mnode = tc.servers[0] - - if snapname != "" and volname != "": - tc.logger.error("Incorrect cmd. snap status cli accepts either " - "snapname or volname") - return (-1, None, None) - - if volname != '': - volname = "volume %s" % volname - - cmd = "gluster snapshot status %s %s" % (snapname, volname) - return tc.run(mnode, cmd) - - -def get_snap_status(mnode=None): - """Parse the output of 'gluster snapshot status' command. - - Kwargs: - mnode (str): Node on which command has to be executed. - If None, defaults to nodes[0]. - - Returns: - NoneType: None if command execution fails, parse errors. - list: list of dict on success. Each snap status will be - in dict format - - Examples: - >>> get_snap_status(mnode = 'abc.lab.eng.xyz.com') - [{'volCount': '1', 'volume': {'brick': [{'path': '10.70.47.11: - testvol_brick0', 'pid': '26747', 'lvUsage': '3.52', 'volumeGroup': - 'RHS_vg0', 'lvSize': '9.95g'}, {'path': '10.70.47.16:/testvol_brick1', - 'pid': '25497', 'lvUsage': '3.52', 'volumeGroup': 'RHS_vg0', - 'lvSize': '9.95g'}], 'brickCount': '2'}, 'name': 'snap2', 'uuid': - '56a39a92-c339-47cc-a8b2-9e54bb2a6324'}, {'volCount': '1', 'volume': - {'brick': [{'path': '10.70.47.11:testvol_next_brick0', 'pid': '26719', - 'lvUsage': '4.93', 'volumeGroup': 'RHS_vg1', 'lvSize': '9.95g'}], - 'brickCount': '1'}, 'name': 'next_snap1', - 'uuid': 'dcf0cd31-c0db-47ad-92ec-f72af2d7b385'}] - """ - - if mnode is None: - mnode = tc.servers[0] - - ret, out, _ = tc.run(mnode, "gluster snapshot status --xml", verbose=False) - if ret != 0: - tc.logger.error("Failed to execute 'snapshot status' on node %s. " - "Hence failed to get the snapshot status.", mnode) - return None - - try: - root = etree.XML(out) - except etree.ParseError: - tc.logger.error("Failed to parse the gluster snapshot " - "status xml output.") - return None - - snap_status_list = [] - for snap in root.findall("snapStatus/snapshots/snapshot"): - snap_status = {} - for element in snap.getchildren(): - if element.tag == "volume": - status = {} - status["brick"] = [] - for elmt in element.getchildren(): - if elmt.tag == "brick": - brick_info = {} - for el in elmt.getchildren(): - brick_info[el.tag] = el.text - status["brick"].append(brick_info) - else: - status[elmt.tag] = elmt.text - - snap_status[element.tag] = status - else: - snap_status[element.tag] = element.text - snap_status_list.append(snap_status) - return snap_status_list - - -def get_snap_status_by_snapname(snapname, mnode=None): - """Parse the output of 'gluster snapshot status' command - for the given snapshot. - - Args: - snapname (str): snapshot name - Kwargs: - mnode (str): Node on which command has to be executed. - If None, defaults to nodes[0]. - - Returns: - NoneType: None if command execution fails, parse errors. - dict: on success. - - Examples: - >>> get_snap_status_by_snapname('snap1', - mnode = 'abc.lab.eng.xyz.com') - {'volCount': '1', 'volume': {'brick': [{'path': '10.70.47.11: - testvol_brick0', 'pid': '26747', 'lvUsage': '3.52', 'volumeGroup': - 'RHS_vg0', 'lvSize': '9.95g'}, {'path': '10.70.47.16:/testvol_brick1', - 'pid': '25497', 'lvUsage': '3.52', 'volumeGroup': 'RHS_vg0', - 'lvSize': '9.95g'}], 'brickCount': '2'}, 'name': 'snap2', 'uuid': - '56a39a92-c339-47cc-a8b2-9e54bb2a6324'} - """ - - if mnode is None: - mnode = tc.servers[0] - - snap_status_list = get_snap_status(mnode=mnode) - if not snap_status_list: - tc.logger.error("Failed to parse snap status in " - "get_snap_status_by_snapname()") - return None - - for snap_status in snap_status_list: - if "name" in snap_status: - if snap_status["name"] == snapname: - return snap_status - tc.logger.error("The snap %s not found" % (snapname)) - return None - - -def get_snap_status_by_volname(volname, mnode=None): - """Parse the output of 'gluster snapshot status' command - for the given volume. - - Args: - volname (str): snapshot name - Kwargs: - mnode (str): Node on which command has to be executed. - If None, defaults to nodes[0]. - - Returns: - NoneType: None if command execution fails, parse errors. - list: list of dicts on success. - - Examples: - >>> get_snap_status_by_volname('testvol', - mnode = 'abc.lab.eng.xyz.com') - [{'volCount': '1', 'volume': {'brick': [{'path': '10.70.47.11: - testvol_brick0', 'pid': '26747', 'lvUsage': '3.52', 'volumeGroup': - 'RHS_vg0', 'lvSize': '9.95g'}, {'path': '10.70.47.16:/testvol_brick1', - 'pid': '25497', 'lvUsage': '3.52', 'volumeGroup': 'RHS_vg0', - 'lvSize': '9.95g'}], 'brickCount': '2'}, 'name': 'snap2', 'uuid': - '56a39a92-c339-47cc-a8b2-9e54bb2a6324'}, {'volCount': '1', 'volume': - {'brick': [{'path': '10.70.47.11:testvol_next_brick0', 'pid': '26719', - 'lvUsage': '4.93', 'volumeGroup': 'RHS_vg1', 'lvSize': '9.95g'}], - 'brickCount': '1'}, 'name': 'next_snap1', - 'uuid': 'dcf0cd31-c0db-47ad-92ec-f72af2d7b385'}] - """ - if mnode is None: - mnode = tc.servers[0] - - cmd = "gluster snapshot status volume %s --xml" % volname - ret, out, _ = tc.run(mnode, cmd, verbose=False) - if ret != 0: - tc.logger.error("Failed to execute 'snapshot status' on node %s. " - "Hence failed to get the snapshot status.", mnode) - return None - - try: - root = etree.XML(out) - except etree.ParseError: - tc.logger.error("Failed to parse the gluster snapshot " - "status xml output.") - return None - - snap_status_list = [] - for snap in root.findall("snapStatus/snapshots/snapshot"): - snap_status = {} - for element in snap.getchildren(): - if element.tag == "volume": - status = {} - status["brick"] = [] - for elmt in element.getchildren(): - if elmt.tag == "brick": - brick_info = {} - for el in elmt.getchildren(): - brick_info[el.tag] = el.text - status["brick"].append(brick_info) - else: - status[elmt.tag] = elmt.text - - snap_status[element.tag] = status - else: - snap_status[element.tag] = element.text - snap_status_list.append(snap_status) - return snap_status_list - - -def snap_info(snapname="", volname="", mnode=None): - """Runs 'gluster snapshot info' on specific node - - Example: - snap_info() - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to nodes[0]. - snapname (str): snapshot name - volname (str): volume name - - 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. - """ - if mnode is None: - mnode = tc.servers[0] - - if snapname != "" and volname != "": - tc.logger.error("Incorrect cmd. snap info cli accepts either " - "snapname or volname") - return (-1, None, None) - - if volname != '': - volname = "volume %s" % volname - - cmd = "gluster snapshot info %s %s" % (snapname, volname) - return tc.run(mnode, cmd) - - -def get_snap_info(mnode=None): - """Parse the output of 'gluster snapshot info' command. - - Kwargs: - mnode (str): Node on which command has to be executed. - If None, defaults to nodes[0]. - - Returns: - NoneType: None if command execution fails, parse errors. - list: list of dicts on success. - - Examples: - >>> get_snap_info(mnode = 'abc.lab.eng.xyz.com') - [{'description': 'This is snap2', 'uuid': - '56a39a92-c339-47cc-a8b2-9e54bb2a6324', 'volCount': '1', - 'snapVolume': {'status': 'Stopped', 'name': - 'df1882d3f86d48738e69f298096f3810'}, 'createTime': - '2016-04-07 12:01:21', 'name': 'snap2'}, {'description': None, - 'uuid': 'a322d93a-2732-447d-ab88-b943fa402fd2', 'volCount': '1', - 'snapVolume': {'status': 'Stopped', 'name': - '2c790e6132e447e79168d9708d4abfe7'}, 'createTime': - '2016-04-07 13:59:43', 'name': 'snap1'}] - """ - if mnode is None: - mnode = tc.servers[0] - - ret, out, _ = tc.run(mnode, "gluster snapshot info --xml", verbose=False) - if ret != 0: - tc.logger.error("Failed to execute 'snapshot info' on node %s. " - "Hence failed to get the snapshot info.", mnode) - return None - - try: - root = etree.XML(out) - except etree.ParseError: - tc.logger.error("Failed to parse the gluster snapshot " - "info xml output.") - return None - - snap_info_list = [] - for snap in root.findall("snapInfo/snapshots/snapshot"): - snap_info = {} - for element in snap.getchildren(): - if element.tag == "snapVolume": - info = {} - for elmt in element.getchildren(): - if elmt.tag == "originVolume": - info["originVolume"] = {} - for el in elmt.getchildren(): - info[elmt.tag][el.tag] = el.text - else: - info[elmt.tag] = elmt.text - snap_info[element.tag] = info - else: - snap_info[element.tag] = element.text - snap_info_list.append(snap_info) - return snap_info_list - - -def get_snap_info_by_snapname(snapname, mnode=None): - """Parse the output of 'gluster snapshot info' command - for the given snapshot. - - Args: - snapname (str): snapshot name - Kwargs: - mnode (str): Node on which command has to be executed. - If None, defaults to nodes[0]. - - Returns: - NoneType: None if command execution fails, parse errors. - dict: on success. - - Examples: - >>> get_snap_info_by_snapname('snap1', mnode = 'abc.lab.eng.xyz.com') - {'description': 'This is snap2', 'uuid': - '56a39a92-c339-47cc-a8b2-9e54bb2a6324', 'volCount': '1', - 'snapVolume': {'status': 'Stopped', 'name': - 'df1882d3f86d48738e69f298096f3810'} - """ - - if mnode is None: - mnode = tc.servers[0] - - snap_info_list = get_snap_info(mnode=mnode) - if not snap_info_list: - tc.logger.error("Failed to parse snap info in " - "get_snap_info_by_snapname()") - return None - - for snap_info in snap_info_list: - if "name" in snap_info: - if snap_info["name"] == snapname: - return snap_info - tc.logger.error("The snap %s not found" % (snapname)) - return None - - -def get_snap_info_by_volname(volname, mnode=None): - """Parse the output of 'gluster snapshot info' command - for the given volume. - - Args: - volname (str): snapshot name - Kwargs: - mnode (str): Node on which command has to be executed. - If None, defaults to nodes[0]. - - Returns: - NoneType: None if command execution fails, parse errors. - list: list of dicts on success. - - Examples: - >>> get_snap_info_by_volname('testvol', - mnode = 'abc.lab.eng.xyz.com') - {'originVolume': {'snapCount': '1', 'name': 'testvol', - 'snapRemaining': '255'}, 'count': '1', 'snapshots': - [{'description': 'This is next snap1', 'uuid': - 'dcf0cd31-c0db-47ad-92ec-f72af2d7b385', 'volCount': '1', - 'snapVolume': {'status': 'Stopped', 'name': - '49c290d6e8b74205adb3cce1206b5bc5'}, 'createTime': - '2016-04-07 12:03:11', 'name': 'next_snap1'}]} - """ - if mnode is None: - mnode = tc.servers[0] - - cmd = "gluster snapshot info volume %s --xml" % volname - ret, out, _ = tc.run(mnode, cmd, verbose=False) - if ret != 0: - tc.logger.error("Failed to execute 'snapshot info' on node %s. " - "Hence failed to get the snapshot info.", mnode) - return None - - try: - root = etree.XML(out) - except etree.ParseError: - tc.logger.error("Failed to parse the gluster snapshot " - "info xml output.") - return None - - snap_vol_info = {} - - for snap in root.findall("snapInfo"): - for element in snap.getchildren(): - if element.tag == "originVolume": - info = {} - for elmt in element.getchildren(): - info[elmt.tag] = elmt.text - snap_vol_info[element.tag] = info - else: - snap_vol_info[element.tag] = element.text - - snap_info_list = [] - for snap in root.findall("snapInfo/snapshots/snapshot"): - snap_info = {} - for element in snap.getchildren(): - if element.tag == "snapVolume": - info = {} - for elmt in element.getchildren(): - if elmt.tag == "originVolume": - info["originVolume"] = {} - for el in elmt.getchildren(): - info[elmt.tag][el.tag] = el.text - else: - info[elmt.tag] = elmt.text - snap_info[element.tag] = info - else: - snap_info[element.tag] = element.text - snap_info_list.append(snap_info) - snap_vol_info["snapshots"] = snap_info_list - return snap_vol_info - - -def snap_list(mnode=None): - """Lists the snapshots - - Example: - snap_list() - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to nodes[0]. - - 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. - """ - - if mnode is None: - mnode = tc.servers[0] - cmd = "gluster snapshot list" - return tc.run(mnode, cmd) - - -def get_snap_list(mnode=None): - """Parse the output of 'gluster snapshot list' command. - - Kwargs: - mnode (str): Node on which command has to be executed. - If None, defaults to nodes[0]. - - Returns: - NoneType: None if command execution fails, parse errors. - list: list of snapshots on success. - - Examples: - >>> get_snap_list(mnode = 'abc.lab.eng.xyz.com') - ['snap1', 'snap2'] - """ - if mnode is None: - mnode = tc.servers[0] - - ret, out, _ = tc.run(mnode, "gluster snapshot list --xml", verbose=False) - if ret != 0: - tc.logger.error("Failed to execute 'snapshot list' on node %s. " - "Hence failed to get the snapshot list.", mnode) - return None - - try: - root = etree.XML(out) - except etree.ParseError: - tc.logger.error("Failed to parse the gluster snapshot " - "list xml output.") - return None - - snap_list = [] - for snap in root.findall("snapList/snapshot"): - snap_list.append(snap.text) - - return snap_list - - -def snap_config(volname=None, mnode=None): - """Runs 'gluster snapshot config' on specific node - - Example: - snap_config() - - Kwargs: - volname (str): volume name - mnode (str): Node on which cmd has to be executed. - If None, defaults to nodes[0]. - - 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. - """ - if mnode is None: - mnode = tc.servers[0] - - if volname is None: - volname = "" - - cmd = "gluster snapshot config %s" % volname - return tc.run(mnode, cmd) - - -def get_snap_config(volname=None, mnode=None): - """Parse the output of 'gluster snapshot config' command. - - Kwargs: - volname (str): volume name - mnode (str): Node on which command has to be executed. - If None, defaults to nodes[0]. - - Returns: - NoneType: None if command execution fails, parse errors. - dict: on success. - - Examples: - >>> get_snap_config() - {'volumeConfig': [{'softLimit': '230', 'effectiveHardLimit': '256', - 'name': 'testvol', 'hardLimit': '256'}, {'softLimit': '230', - 'effectiveHardLimit': '256', 'name': 'testvol_next', - 'hardLimit': '256'}], 'systemConfig': {'softLimit': '90%', - 'activateOnCreate': 'disable', 'hardLimit': '256', - 'autoDelete': 'disable'}} - """ - if mnode is None: - mnode = tc.servers[0] - - ret, out, _ = tc.run(mnode, "gluster snapshot config --xml", verbose=False) - if ret != 0: - tc.logger.error("Failed to execute 'snapshot config' on node %s. " - "Hence failed to get the snapshot config.", mnode) - return None - - try: - root = etree.XML(out) - except etree.ParseError: - tc.logger.error("Failed to parse the gluster snapshot " - "config xml output.") - return None - - snap_config = {} - for config in root.findall("snapConfig/systemConfig"): - sys_config = {} - for element in config.getchildren(): - sys_config[element.tag] = element.text - snap_config["systemConfig"] = sys_config - - volume_config = [] - for config in root.findall("snapConfig/volumeConfig/volume"): - vol_config = {} - for element in config.getchildren(): - vol_config[element.tag] = element.text - - if volname is not None: - if volname == vol_config["name"]: - volume_config.append(vol_config) - else: - volume_config.append(vol_config) - - snap_config["volumeConfig"] = volume_config - return snap_config - - -def set_snap_config(option, volname=None, mnode=None): - """Sets given snap config on the given node - - Example: - >>>option={'snap-max-hard-limit':'200'} - set_snap_config(option) - - Args: - option (dict): dict of single snap config option - Kwargs: - volname (str): volume name - mnode (str): Node on which cmd has to be executed. - If None, defaults to nodes[0]. - - 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. - """ - if mnode is None: - mnode = tc.servers[0] - - if volname is None: - volname = "" - - cmd = ("gluster snapshot config %s %s %s --mode=script" - % (volname, option.keys()[0], option.values()[0])) - return tc.run(mnode, cmd) - - -def snap_delete(snapname, mnode=None): - """Deletes the given snapshot - - Example: - snap_delete(testsnap) - - Args: - snapname (str): snapshot name to be deleted - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to nodes[0]. - - 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. - """ - if mnode is None: - mnode = tc.servers[0] - - cmd = "gluster snapshot delete %s --mode=script" % snapname - return tc.run(mnode, cmd) - - -def snap_delete_by_volumename(volname, mnode=None): - """Deletes the given snapshot - - Example: - snap_delete_by_volumename(testvol) - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to nodes[0]. - - 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. - """ - if mnode is None: - mnode = tc.servers[0] - - cmd = "gluster snapshot delete volume %s --mode=script" % volname - return tc.run(mnode, cmd) - - -def snap_delete_all(mnode=None): - """Deletes all the snapshot in the cluster - - Example: - snap_delete_all(testsnap) - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to nodes[0]. - - 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. - """ - if mnode is None: - mnode = tc.servers[0] - cmd = "gluster snapshot delete all --mode=script" - return tc.run(mnode, cmd) - - -def snap_activate(snapname, force=False, mnode=None): - """Activates the given snapshot - - Example: - snap_activate(testsnap) - - Args: - snapname (str): snapshot name to be cloned - - Kwargs: - force (bool): If this option is set to True, then snap - activate will get execute with force option. If it is set to False, - then snap activate will get executed without force option - mnode (str): Node on which cmd has to be executed. - If None, defaults to nodes[0]. - - 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. - """ - if mnode is None: - mnode = tc.servers[0] - - frce = '' - if force: - frce = 'force' - - cmd = "gluster snapshot activate %s %s --mode=script" % (snapname, frce) - return tc.run(mnode, cmd) - - -def snap_deactivate(snapname, mnode=None): - """Deactivates the given snapshot - - Example: - snap_deactivate(testsnap) - - Args: - snapname (str): snapshot name to be cloned - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to nodes[0]. - - 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. - """ - if mnode is None: - mnode = tc.servers[0] - cmd = "gluster snapshot deactivate %s --mode=script" % snapname - return tc.run(mnode, cmd) diff --git a/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/tiering_ops.py b/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/tiering_ops.py deleted file mode 100644 index 4074fb7c634..00000000000 --- a/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/tiering_ops.py +++ /dev/null @@ -1,1057 +0,0 @@ -#!/usr/bin/env python -# This file is part of DiSTAF -# Copyright (C) 2015-2016 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: Library for gluster tiering operations. -""" - -import re -from distaf.util import tc -import distaflibs.gluster.volume_ops -from distaflibs.gluster.peer_ops import peer_probe_servers -from distaflibs.gluster.gluster_init import start_glusterd -from distaflibs.gluster.lib_utils import list_files - -try: - import xml.etree.cElementTree as etree -except ImportError: - import xml.etree.ElementTree as etree - - -def add_peer_nodes_to_cluster(peers, mnode=None): - """Adds the given peer nodes to cluster - - Args: - peers (list) : list of peer nodes to be attached to cluster - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - - Returns: - bool: True, if peer nodes are attached to cluster - False, otherwise - - Example: - add_peer_nodes_to_cluster(['peer_node1','peer_node2']) - """ - - if mnode is None: - mnode = tc.servers[0] - - if not isinstance(peers, list): - peers = [peers] - - ret = start_glusterd(servers=peers) - if not ret: - tc.logger.error("glusterd did not start in peer nodes") - return False - - ret = peer_probe_servers(servers=peers, mnode=mnode) - if not ret: - tc.logger.error("Unable to do peer probe on peer machines") - return False - - return True - - -def tier_attach(volname, num_bricks_to_add, peers, replica=1, force=False, - mnode=None): - """Attaches tier to the volume - - Args: - volname (str): volume name - num_bricks_to_add (str): number of bricks to be added as hot tier - peers (list): from these servers, hot tier will be added to volume - - Kwargs: - replica (str): replica count of the hot tier - force (bool): If this option is set to True, then attach tier - will get executed with force option. If it is set to False, - then attach tier will get executed without force option - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - - 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. - - Example: - tier_attach(testvol, '2', ['peer_node1','peer_node2']) - """ - - if mnode is None: - mnode = tc.servers[0] - - replica = int(replica) - repc = '' - if replica != 1: - repc = "replica %d" % replica - - frce = '' - if force: - frce = 'force' - - num_bricks_to_add = int(num_bricks_to_add) - - from distaflibs.gluster.lib_utils import form_bricks_path - bricks_path = form_bricks_path(num_bricks_to_add, peers[:], - mnode, volname) - if bricks_path is None: - tc.logger.error("number of bricks required are greater than " - "unused bricks") - return (-1, '', '') - - bricks_path = [re.sub(r"(.*\/\S+\_)brick(\d+)", r"\1tier\2", item) - for item in bricks_path.split() if item] - tier_bricks_path = " ".join(bricks_path) - cmd = ("gluster volume tier %s attach %s %s %s --mode=script" - % (volname, repc, tier_bricks_path, frce)) - - return tc.run(mnode, cmd) - - -def tier_start(volname, force=False, mnode=None): - """Starts the tier volume - - Args: - volname (str): volume name - - Kwargs: - force (bool): If this option is set to True, then attach tier - will get executed with force option. If it is set to False, - then attach tier will get executed without force option - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - 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. - - Example: - tier_start(testvol) - """ - - if mnode is None: - mnode = tc.servers[0] - - frce = '' - if force: - frce = 'force' - - cmd = ("gluster volume tier %s start %s --mode=script" - % (volname, frce)) - return tc.run(mnode, cmd) - - -def tier_status(volname, mnode=None): - """executes tier status command - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - 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. - - Example: - tier_status(testvol) - """ - - if mnode is None: - mnode = tc.servers[0] - - cmd = "gluster volume tier %s status" % volname - ret = tc.run(mnode, cmd) - - return ret - - -def get_tier_status(volname, mnode=None): - """Parse the output of 'gluster tier status' command. - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which command has to be executed. - If None, defaults to servers[0]. - - Returns: - NoneType: None if command execution fails, parse errors. - dict: dict on success. - - Examples: - >>> get_tier_status(mnode = 'abc.lab.eng.xyz.com') - {'node': [{'promotedFiles': '0', 'demotedFiles': '0', 'nodeName': - 'localhost', 'statusStr': 'in progress'}, {'promotedFiles': '0', - 'demotedFiles': '0', 'nodeName': '10.70.47.16', 'statusStr': - 'in progress'}], 'task-id': '2ed28cbd-4246-493a-87b8-1fdcce313b34', - 'nodeCount': '4', 'op': '7'} - """ - - if mnode is None: - mnode = tc.servers[0] - - cmd = "gluster volume tier %s status --xml" % volname - ret, out, _ = tc.run(mnode, cmd, verbose=False) - if ret != 0: - tc.logger.error("Failed to execute 'tier status' on node %s. " - "Hence failed to get tier status.", mnode) - return None - - try: - root = etree.XML(out) - except etree.ParseError: - tc.logger.error("Failed to parse the gluster tier status xml output.") - return None - - tier_status = {} - tier_status["node"] = [] - for info in root.findall("volRebalance"): - for element in info.getchildren(): - if element.tag == "node": - status_info = {} - for elmt in element.getchildren(): - status_info[elmt.tag] = elmt.text - tier_status[element.tag].append(status_info) - else: - tier_status[element.tag] = element.text - return tier_status - - -def tier_detach_start(volname, mnode=None): - """starts detaching tier on given volume - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - - 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. - - Example: - tier_detach_start(testvol) - - """ - if mnode is None: - mnode = tc.servers[0] - - cmd = "gluster volume tier %s detach start --mode=script" % volname - return tc.run(mnode, cmd) - - -def tier_detach_status(volname, mnode=None): - """executes detach tier status on given volume - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - - 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. - - Example: - tier_detach_status(testvol) - - """ - if mnode is None: - mnode = tc.servers[0] - - cmd = "gluster volume tier %s detach status --mode=script" % volname - return tc.run(mnode, cmd) - - -def tier_detach_stop(volname, mnode=None): - """stops detaching tier on given volume - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - - 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. - - Example: - tier_detach_stop(testvol) - - """ - if mnode is None: - mnode = tc.servers[0] - - cmd = "gluster volume tier %s detach stop --mode=script" % volname - return tc.run(mnode, cmd) - - -def tier_detach_commit(volname, mnode=None): - """commits detach tier on given volume - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - - 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. - - Example: - tier_detach_commit(testvol) - - """ - if mnode is None: - mnode = tc.servers[0] - - cmd = "gluster volume tier %s detach commit --mode=script" % volname - return tc.run(mnode, cmd) - - -def tier_detach_force(volname, mnode=None): - """detaches tier forcefully on given volume - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - - 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. - - Example: - tier_detach_force(testvol) - - """ - if mnode is None: - mnode = tc.servers[0] - - cmd = "gluster volume tier %s detach force --mode=script" % volname - return tc.run(mnode, cmd) - - -def get_detach_tier_status(volname, mnode=None): - """Parse the output of 'gluster volume tier detach status' command. - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which command has to be executed. - If None, defaults to servers[0]. - - Returns: - NoneType: None if command execution fails, parse errors. - dict: dict on success. - - Examples: - >>> get_detach_tier_status("testvol", mnode = 'abc.lab.eng.xyz.com') - {'node': [{'files': '0', 'status': '3', 'lookups': '1', 'skipped': '0', - 'nodeName': 'localhost', 'failures': '0', 'runtime': '0.00', 'id': - '11336017-9561-4e88-9ac3-a94d4b403340', 'statusStr': 'completed', - 'size': '0'}, {'files': '0', 'status': '3', 'lookups': '0', 'skipped': - '0', 'nodeName': '10.70.47.16', 'failures': '0', 'runtime': '0.00', - 'id': 'a2b88b10-eba2-4f97-add2-8dc37df08b27', 'statusStr': 'completed', - 'size': '0'}], 'nodeCount': '4', 'aggregate': {'files': '0', 'status': - '3', 'lookups': '1', 'skipped': '0', 'failures': '0', 'runtime': '0.0', - 'statusStr': 'completed', 'size': '0'}} - """ - - if mnode is None: - mnode = tc.servers[0] - - cmd = "gluster volume tier %s detach status --xml" % volname - ret, out, _ = tc.run(mnode, cmd, verbose=False) - if ret != 0: - tc.logger.error("Failed to execute 'detach tier status' on node %s. " - "Hence failed to get detach tier status.", mnode) - return None - - try: - root = etree.XML(out) - except etree.ParseError: - tc.logger.error("Failed to parse the detach tier status xml output.") - return None - - tier_status = {} - tier_status["node"] = [] - for info in root.findall("volDetachTier"): - for element in info.getchildren(): - if element.tag == "node": - status_info = {} - for elmt in element.getchildren(): - status_info[elmt.tag] = elmt.text - tier_status[element.tag].append(status_info) - elif element.tag == "aggregate": - status_info = {} - for elmt in element.getchildren(): - status_info[elmt.tag] = elmt.text - tier_status[element.tag] = status_info - else: - tier_status[element.tag] = element.text - return tier_status - - -def tier_detach_start_and_get_taskid(volname, mnode=None): - """Parse the output of 'gluster volume tier detach start' command. - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which command has to be executed. - If None, defaults to servers[0]. - - Returns: - NoneType: None if command execution fails, parse errors. - dict: dict on success. - - Examples: - >>> tier_detach_start_and_get_taskid("testvol", - mnode = 'abc.lab.eng.xyz.com') - {'task-id': '8020835c-ff0d-4ea1-9f07-62dd067e92d4'} - """ - - if mnode is None: - mnode = tc.servers[0] - - cmd = "gluster volume tier %s detach start --xml" % volname - ret, out, _ = tc.run(mnode, cmd, verbose=False) - if ret != 0: - tc.logger.error("Failed to execute 'detach tier start' on node %s. " - "Hence failed to parse the detach tier start.", mnode) - return None - - try: - root = etree.XML(out) - except etree.ParseError: - tc.logger.error("Failed to parse the gluster detach tier " - "start xml output.") - return None - - tier_status = {} - for info in root.findall("volDetachTier"): - for element in info.getchildren(): - tier_status[element.tag] = element.text - return tier_status - - -def tier_detach_stop_and_get_status(volname, mnode=None): - """Parse the output of 'gluster volume tier detach stop' command. - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which command has to be executed. - If None, defaults to servers[0]. - - Returns: - NoneType: None if command execution fails, parse errors. - dict: dict on success. - - Examples: - >>> tier_detach_stop_and_get_status("testvol", - mnode = 'abc.lab.eng.xyz.com') - {'node': [{'files': '0', 'status': '3', 'lookups': '1', 'skipped': '0', - 'nodeName': 'localhost', 'failures': '0', 'runtime': '0.00', 'id': - '11336017-9561-4e88-9ac3-a94d4b403340', 'statusStr': 'completed', - 'size': '0'}, {'files': '0', 'status': '3', 'lookups': '0', 'skipped': - '0', 'nodeName': '10.70.47.16', 'failures': '0', 'runtime': '0.00', - 'id': 'a2b88b12-eba2-4f97-add2-8dc37df08b27', 'statusStr': 'completed', - 'size': '0'}], 'nodeCount': '4', 'aggregate': {'files': '0', 'status': - '3', 'lookups': '1', 'skipped': '0', 'failures': '0', 'runtime': '0.0', - 'statusStr': 'completed', 'size': '0'}} - """ - - if mnode is None: - mnode = tc.servers[0] - - cmd = "gluster volume tier %s detach stop --xml" % volname - ret, out, _ = tc.run(mnode, cmd, verbose=False) - if ret != 0: - tc.logger.error("Failed to execute 'tier start' on node %s. " - "Hence failed to parse the tier start.", mnode) - return None - - try: - root = etree.XML(out) - except etree.ParseError: - tc.logger.error("Failed to parse the gluster detach tier stop" - " xml output.") - return None - - tier_status = {} - tier_status["node"] = [] - for info in root.findall("volDetachTier"): - for element in info.getchildren(): - if element.tag == "node": - status_info = {} - for elmt in element.getchildren(): - status_info[elmt.tag] = elmt.text - tier_status[element.tag].append(status_info) - elif element.tag == "aggregate": - status_info = {} - for elmt in element.getchildren(): - status_info[elmt.tag] = elmt.text - tier_status[element.tag] = status_info - else: - tier_status[element.tag] = element.text - return tier_status - - -def wait_for_detach_tier_to_complete(volname, mnode=None, timeout=300): - """Waits for the detach tier to complete - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which command has to be executed. - If None, defaults to servers[0]. - timeout (int): timeout value to wait for detach tier to complete - - Returns: - True on success, False otherwise - - Examples: - >>> wait_for_detach_tier_to_complete("testvol") - """ - - if mnode is None: - mnode = tc.servers[0] - - count = 0 - flag = 0 - while (count < timeout): - status_info = get_detach_tier_status(volname, mnode=mnode) - if status_info is None: - return False - - status = status_info['aggregate']['statusStr'] - if status == 'completed': - flag = 1 - break - - time.sleep(10) - count = count + 10 - if not flag: - tc.logger.error("detach tier is not completed") - return False - else: - tc.logger.info("detach tier is successfully completed") - return True - - -def get_files_from_hot_tier(volname): - """Lists files from hot tier for the given volume - - Args: - volname (str): volume name - - Returns: - Emptylist: if there are no files in hot tier. - list: list of files in hot tier on success. - - Examples: - >>>get_files_from_hot_tier("testvol") - """ - - files = [] - subvols = distaflibs.gluster.volume_ops.get_subvols(volname) - for subvol in subvols['hot_tier_subvols']: - info = subvol[0].split(':') - file_list = list_files(info[1], server=info[0]) - for file in file_list: - if ".glusterfs" not in file: - files.append(file) - - return files - - -def get_files_from_cold_tier(volname): - """Lists files from cold tier for the given volume - - Args: - volname (str): volume name - - Returns: - Emptylist: if there are no files in cold tier. - list: list of files in cold tier on success. - - Examples: - >>>get_files_from_hot_tier("testvol") - """ - - files = [] - subvols = distaflibs.gluster.volume_ops.get_subvols(volname) - for subvol in subvols['cold_tier_subvols']: - info = subvol[0].split(':') - file_list = list_files(info[1], server=info[0]) - for file in file_list: - if ".glusterfs" not in file: - files.append(file) - - return files - - -def get_tier_promote_frequency(volname): - """Gets tier promote frequency value for given volume. - - Args: - volname (str): volume name - - Returns: - NoneType: None if command execution fails, parse errors. - str: promote frequency value on success. - - Examples: - >>>get_tier_promote_frequency("testvol") - """ - - vol_options = distaflibs.gluster.volume_ops.get_volume_option(volname) - if vol_options is None: - tc.logger.error("Failed to get volume options") - return None - - return vol_options['cluster.tier-promote-frequency'] - - -def get_tier_demote_frequency(volname): - """Gets tier demote frequency value for given volume. - - Args: - volname (str): volume name - - Returns: - NoneType: None if command execution fails, parse errors. - str: demote frequency value on success. - - Examples: - >>>get_tier_demote_frequency("testvol") - """ - - vol_options = distaflibs.gluster.volume_ops.get_volume_option(volname) - if vol_options is None: - tc.logger.error("Failed to get volume options") - return None - - return vol_options['cluster.tier-demote-frequency'] - - -def get_tier_mode(volname): - """Gets tier mode for given volume. - - Args: - volname (str): volume name - - Returns: - NoneType: None if command execution fails, parse errors. - str: tier mode on success. - - Examples: - >>>get_tier_mode("testvol") - """ - - vol_options = distaflibs.gluster.volume_ops.get_volume_option(volname) - if vol_options is None: - tc.logger.error("Failed to get volume options") - return None - - return vol_options['cluster.tier-mode'] - - -def get_tier_max_mb(volname): - """Gets tier max mb for given volume. - - Args: - volname (str): volume name - - Returns: - NoneType: None if command execution fails, parse errors. - str: tier max mb on success. - - Examples: - >>>get_tier_max_mb("testvol") - """ - - vol_options = distaflibs.gluster.volume_ops.get_volume_option(volname) - if vol_options is None: - tc.logger.error("Failed to get volume options") - return None - - return vol_options['cluster.tier-max-mb'] - - -def get_tier_max_files(volname): - """Gets tier max files for given volume. - - Args: - volname (str): volume name - - Returns: - NoneType: None if command execution fails, parse errors. - str: tier max files on success. - - Examples: - >>>get_tier_max_files("testvol") - """ - - vol_options = distaflibs.gluster.volume_ops.get_volume_option(volname) - if vol_options is None: - tc.logger.error("Failed to get volume options") - return None - - return vol_options['cluster.tier-max-files'] - - -def get_tier_watermark_high_limit(volname): - """Gets tier watermark high limit for given volume. - - Args: - volname (str): volume name - - Returns: - NoneType: None if command execution fails, parse errors. - str: tier watermark high limit on success. - - Examples: - >>>get_tier_watermark_high_limit("testvol") - """ - - vol_options = distaflibs.gluster.volume_ops.get_volume_option(volname) - if vol_options is None: - tc.logger.error("Failed to get volume options") - return None - - return vol_options['cluster.watermark-hi'] - - -def get_tier_watermark_low_limit(volname): - """Gets tier watermark low limit for given volume. - - Args: - volname (str): volume name - - Returns: - NoneType: None if command execution fails, parse errors. - str: tier watermark low limit on success. - - Examples: - >>>get_tier_watermark_low_limit("testvol") - """ - - vol_options = distaflibs.gluster.volume_ops.get_volume_option(volname) - if vol_options is None: - tc.logger.error("Failed to get volume options") - return None - - return vol_options['cluster.watermark-low'] - - -def set_tier_promote_frequency(volname, value): - """Sets tier promote frequency value for given volume. - - Args: - volname (str): volume name - value (str): promote frequency value - - Returns: - bool: True on success, False Otherwise - - Examples: - >>>set_tier_promote_frequency("testvol", '1000') - """ - - option = {'cluster.tier-promote-frequency': value} - - if not distaflibs.gluster.volume_ops.set_volume_option(volname, - options=option): - tc.logger.error("Failed to set promote frequency to %s" - % value) - return False - - return True - - -def set_tier_demote_frequency(volname, value): - """Sets tier demote frequency value for given volume. - - Args: - volname (str): volume name - value (str): demote frequency value - - Returns: - bool: True on success, False Otherwise - - Examples: - >>>set_tier_demote_frequency("testvol", "500") - """ - - option = {'cluster.tier-demote-frequency': value} - - if not distaflibs.gluster.volume_ops.set_volume_option(volname, - options=option): - tc.logger.error("Failed to set demote frequency to %s" - % value) - return False - - return True - - -def set_tier_mode(volname, value): - """Sets tier mode for given volume. - - Args: - volname (str): volume name - value (str): tier mode value - - Returns: - bool: True on success, False Otherwise - - Examples: - >>>set_tier_mode("testvol", "cache") - """ - - option = {'cluster.tier-mode': value} - - if not distaflibs.gluster.volume_ops.set_volume_option(volname, - options=option): - tc.logger.error("Failed to set tier mode to %s" - % value) - return False - - return True - - -def set_tier_max_mb(volname, value): - """Sets tier max mb for given volume. - - Args: - volname (str): volume name - value (str): tier mode value - - Returns: - bool: True on success, False Otherwise - - Examples: - >>>set_tier_max_mb("testvol", "50") - """ - - option = {'cluster.tier-max-mb': value} - - if not distaflibs.gluster.volume_ops.set_volume_option(volname, - options=option): - tc.logger.error("Failed to set tier max mb to %s" - % value) - return False - - return True - - -def set_tier_max_files(volname, value): - """Sets tier max files for given volume. - - Args: - volname (str): volume name - value (str): tier mode value - - Returns: - bool: True on success, False Otherwise - - Examples: - >>>set_tier_max_files("testvol", "10") - """ - - option = {'cluster.tier-max-files': value} - - if not distaflibs.gluster.volume_ops.set_volume_option(volname, - options=option): - tc.logger.error("Failed to set tier max files to %s" - % value) - return False - - return True - - -def set_tier_watermark_high_limit(volname, value): - """Sets tier watermark high limit for given volume. - - Args: - volname (str): volume name - value (str): tier mode value - - Returns: - bool: True on success, False Otherwise - - Examples: - >>>set_tier_watermark_high_limit("testvol", "95") - """ - - option = {'cluster.watermark-hi': value} - - if not distaflibs.gluster.volume_ops.set_volume_option(volname, - options=option): - tc.logger.error("Failed to set tier watermark high limit to %s" - % value) - return False - - return True - - -def set_tier_watermark_low_limit(volname, value): - """Sets tier watermark low limit for given volume. - - Args: - volname (str): volume name - value (str): tier mode value - - Returns: - bool: True on success, False Otherwise - - Examples: - >>>set_tier_watermark_low_limit("testvol", "40") - """ - - option = {'cluster.watermark-low': value} - - if not distaflibs.gluster.volume_ops.set_volume_option(volname, - options=option): - tc.logger.error("Failed to set tier watermark low limit to %s" - % value) - return False - - return True - - -def get_tier_pid(volname, mnode): - """Gets tier pid for given volume. - - Args: - volname (str): volume name - mnode (str): Node on which command has to be executed. - - Returns: - NoneType: None if command execution fails, parse errors. - str: pid of tier process on success. - - Examples: - >>>get_tier_pid("testvol", "abc.xyz.com") - """ - - cmd = ("ps -ef | grep -v grep | grep '/var/log/glusterfs/%s-tier.log' |" - "awk '{print $2}'" % volname) - ret, out, err = tc.run(mnode, cmd) - if ret != 0: - tc.logger.error("Failed to execute 'ps' cmd") - return None - - return out.strip("\n") - - -def is_tier_process_running(volname, mnode): - """Checks whether tier process is running - - Args: - volname (str): volume name - mnode (str): Node on which command has to be executed. - - Returns: - True on success, False otherwise - - Examples: - >>>is_tier_process_running("testvol", "abc.xyz.com") - """ - - pid = get_tier_pid(volname, mnode) - if pid == '': - return False - return True diff --git a/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/volume_ops.py b/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/volume_ops.py deleted file mode 100644 index 58939377939..00000000000 --- a/tests/distaf/distaf_libs/distaflibs-gluster/distaflibs/gluster/volume_ops.py +++ /dev/null @@ -1,949 +0,0 @@ -#!/usr/bin/env python -# This file is part of DiSTAF -# Copyright (C) 2015-2016 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. - - -import re -import time -from distaf.util import tc -from pprint import pformat -try: - import xml.etree.cElementTree as etree -except ImportError: - import xml.etree.ElementTree as etree -from distaflibs.gluster.mount_ops import mount_volume -from distaflibs.gluster.gluster_init import env_setup_servers, start_glusterd -from distaflibs.gluster.peer_ops import (peer_probe_servers, - nodes_from_pool_list) - -""" - This file contains the gluster volume operations like create volume, - start/stop volume etc -""" - - -def create_volume(volname, mnode=None, dist=1, rep=1, stripe=1, trans='tcp', - servers=None, disp=1, dispd=1, red=1): - """Create the gluster volume specified configuration - volname and distribute count are mandatory argument - Args: - volname(str): volume name that has to be created - - Kwargs: - mnode(str): server on which command has to be execeuted, - defaults to tc.servers[0] - dist(int): distribute count, defaults to 1 - rep(int): replica count, defaults to 1 - stripe(int): stripe count, defaults to 1 - trans(str): transport type, defaults to tcp - servers(list): servers on which volume has to be created, - defaults to number of servers in pool list, if that is None, - then takes tc.servers - disp(int): disperse count, defaults to 1 - dispd(int): disperse-data count, defaults to 1 - red(int): rdundancy count, defaults to 1 - - 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. - - (-1, '', ''): If not enough bricks are available to create volume. - (ret, out, err): As returned by volume create command execution. - - Example: - create_volume(volname) - """ - if servers is None: - servers = nodes_from_pool_list() - if not servers: - servers = tc.servers[:] - if mnode is None: - mnode = tc.servers[0] - dist = int(dist) - rep = int(rep) - stripe = int(stripe) - disp = int(disp) - dispd = int(dispd) - red = int(red) - dispc = 1 - - if disp != 1 and dispd != 1: - tc.logger.error("volume can't have both disperse and disperse-data") - return (-1, None, None) - if disp != 1: - dispc = int(disp) - elif dispd != 1: - dispc = int(dispd) + int(red) - - number_of_bricks = dist * rep * stripe * dispc - replica = stripec = disperse = disperse_data = redundancy = '' - - from distaflibs.gluster.lib_utils import form_bricks_path - bricks_path = form_bricks_path(number_of_bricks, servers[:], - mnode, volname) - if bricks_path is None: - tc.logger.error("number of bricks required are greater than " - "unused bricks") - return (-1, '', '') - - if rep != 1: - replica = "replica %d" % rep - if stripe != 1: - stripec = "stripe %d" % stripe - ttype = "transport %s" % trans - if disp != 1: - disperse = "disperse %d" % disp - redundancy = "redundancy %d" % red - elif dispd != 1: - disperse_data = "disperse-data %d" % dispd - redundancy = "redundancy %d" % red - - ret = tc.run(mnode, "gluster volume create %s %s %s %s %s %s %s %s " - "--mode=script" % (volname, replica, stripec, disperse, - disperse_data, redundancy, ttype, - bricks_path)) - - return ret - - -def start_volume(volname, mnode=None, force=False): - """Starts the gluster volume - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - force (bool): If this option is set to True, then start volume - will get executed with force option. If it is set to False, - then start volume will get executed without force option - - 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. - - Example: - start_volume("testvol") - """ - if mnode is None: - mnode = tc.servers[0] - frce = '' - if force: - frce = 'force' - cmd = "gluster volume start %s %s --mode=script" % (volname, frce) - return tc.run(mnode, cmd) - - -def stop_volume(volname, mnode=None, force=False): - """Stops the gluster volume - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - force (bool): If this option is set to True, then stop volume - will get executed with force option. If it is set to False, - then stop volume will get executed without force option - - 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. - - Example: - stop_volume("testvol") - """ - if mnode is None: - mnode = tc.servers[0] - frce = '' - if force: - frce = 'force' - cmd = "gluster volume stop %s %s --mode=script" % (volname, frce) - return tc.run(mnode, cmd) - - -def delete_volume(volname, mnode=None): - """Deletes the gluster volume if given volume exists in - gluster and deletes the directories in the bricks - associated with the given volume - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - - Returns: - bool: True, if volume is deleted - False, otherwise - """ - - if mnode is None: - mnode = tc.servers[0] - - volinfo = get_volume_info(volname, mnode) - if volinfo is None or volname not in volinfo: - tc.logger.info("Volume %s does not exist in %s" % (volname, mnode)) - return True - - if volinfo[volname]['typeStr'] == 'Tier': - tmp_hot_brick = volinfo[volname]["bricks"]["hotBricks"]["brick"] - hot_bricks = [x["name"] for x in tmp_hot_brick if "name" in x] - tmp_cold_brick = volinfo[volname]["bricks"]["coldBricks"]["brick"] - cold_bricks = [x["name"] for x in tmp_cold_brick if "name" in x] - bricks = hot_bricks + cold_bricks - else: - bricks = [x["name"] for x in volinfo[volname]["bricks"]["brick"] - if "name" in x] - ret, _, _ = tc.run(mnode, "gluster volume delete %s --mode=script" - % volname) - if ret != 0: - return False - try: - del tc.global_flag[volname] - except KeyError: - pass - for brick in bricks: - node, vol_dir = brick.split(":") - ret = tc.run(node, "rm -rf %s" % vol_dir) - - return True - - -def reset_volume(volname, mnode=None, force=False): - """Resets the gluster volume - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - force (bool): If this option is set to True, then reset volume - will get executed with force option. If it is set to False, - then reset volume will get executed without force option - - 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. - - Example: - reset_volume("testvol") - """ - if mnode is None: - mnode = tc.servers[0] - frce = '' - if force: - frce = 'force' - cmd = "gluster volume reset %s %s --mode=script" % (volname, frce) - return tc.run(mnode, cmd) - - -def cleanup_volume(volname, mnode=None): - """deletes snapshots in the volume, stops and deletes the gluster - volume if given volume exists in gluster and deletes the - directories in the bricks associated with the given volume - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - - Returns: - bool: True, if volume is deleted successfully - False, otherwise - - Example: - cleanup_volume("testvol") - """ - from distaflibs.gluster.snap_ops import snap_delete_by_volumename - - if mnode is None: - mnode = tc.servers[0] - - ret, _, _ = snap_delete_by_volumename(volname, mnode=mnode) - if ret != 0: - tc.logger.error("Failed to delete the snapshots in " - "volume %s" % volname) - return False - - ret, _, _ = stop_volume(volname, mnode, True) - if ret != 0: - tc.logger.error("Failed to stop volume %s" % volname) - return False - - ret = delete_volume(volname, mnode) - if not ret: - tc.logger.error("Unable to cleanup the volume %s" % volname) - return False - return True - - -def setup_vol(volname, mnode=None, dist=1, rep=1, dispd=1, red=1, - stripe=1, trans="tcp", servers=None): - """ - Setup a gluster volume for testing. - It first formats the back-end bricks and then creates a - trusted storage pool by doing peer probe. And then it creates - a volume of specified configuration. - - When the volume is created, it sets a global flag to indicate - that the volume is created. If another testcase calls this - function for the second time with same volume name, the function - checks for the flag and if found, will return True. - Args: - volname(str): volume name that has to be created - - Kwargs: - mnode(str): server on which command has to be execeuted, - defaults to tc.servers[0] - dist(int): distribute count, defaults to 1 - rep(int): replica count, defaults to 1 - stripe(int): stripe count, defaults to 1 - trans(str): transport type, defaults to tcp - servers(list): servers on which volume has to be created, - defaults to number of servers in pool list, if that is None, - then takes tc.servers - disp(int): disperse count, defaults to 1 - dispd(int): disperse-data count, defaults to 1 - red(int): rdundancy count, defaults to 1 - - Returns: - bool: True on success and False for failure. - """ - if servers is None: - servers = tc.servers[:] - if mnode is None: - mnode = tc.servers[0] - volinfo = get_volume_info(mnode=mnode) - if volinfo is not None and volname in volinfo.keys(): - tc.logger.debug("volume %s already exists in %s. Returning..." \ - % (volname, servers[0])) - return True - ret = env_setup_servers(servers=servers) - if not ret: - tc.logger.error("Formatting backend bricks failed. Aborting...") - return False - ret = start_glusterd(servers) - if not ret: - tc.logger.error("glusterd did not start in at least one server") - return False - time.sleep(5) - ret = peer_probe_servers(servers[1:], mnode=mnode) - if not ret: - tc.logger.error("Unable to peer probe one or more machines") - return False - if rep != 1 and dispd != 1: - tc.logger.warning("Both replica count and disperse count is specified") - tc.logger.warning("Ignoring the disperse and using the replica count") - dispd = 1 - red = 1 - ret = create_volume(volname, mnode, dist, rep, stripe, trans, servers, - dispd=dispd, red=red) - if ret[0] != 0: - tc.logger.error("Unable to create volume %s" % volname) - return False - time.sleep(2) - ret = start_volume(volname, mnode) - if not ret: - tc.logger.error("volume start %s failed" % volname) - return False - if tc.global_config["gluster"]["cluster_config"]["nfs_ganesha"]["enable"]: - from distaflibs.gluster.ganesha import vol_set_ganesha - ret = vol_set_ganesha(volname) - if not ret: - tc.logger.error("failed to set the ganesha option for %s" % volname) - return False - tc.global_flag[volname] = True - return True - - -def volume_status(volname='all', service='', options='', mnode=None): - """Executes gluster volume status cli command - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - volname (str): volume name. Defaults to 'all' - service (str): name of the service to get status. - serivce can be, [nfs|shd||quotad]], If not given, - the function returns all the services - options (str): options can be, - [detail|clients|mem|inode|fd|callpool|tasks]. If not given, - the function returns the output of gluster volume status - - 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. - - Example: - volume_status() - """ - if mnode is None: - mnode = tc.servers[0] - - cmd = "gluster vol status %s %s %s" % (volname, service, options) - - return tc.run(mnode, cmd) - - -def _parse_volume_status_xml(root_xml): - """ - Helper module for get_volume_status. It takes root xml object as input, - parses and returns the 'volume' tag xml object. - """ - - for element in root_xml: - if element.findall("volume"): - return element.findall("volume") - root_vol = _parse_volume_status_xml(element) - if root_vol is not None: - return root_vol - - -def parse_xml(tag_obj): - """ - This helper module takes any xml element object and parses all the child - nodes and returns the parsed data in dictionary format - """ - node_dict = {} - for tag in tag_obj: - if re.search(r'\n\s+', tag.text) is not None: - port_dict = {} - port_dict = parse_xml(tag) - node_dict[tag.tag] = port_dict - else: - node_dict[tag.tag] = tag.text - return node_dict - - -def get_volume_status(volname='all', service='', options='', mnode=None): - """ - This module gets the status of all or specified volume(s)/brick - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - volname (str): volume name. Defaults to 'all' - service (str): name of the service to get status. - serivce can be, [nfs|shd||quotad]], If not given, - the function returns all the services - options (str): options can be, - [detail|clients|mem|inode|fd|callpool|tasks]. If not given, - the function returns the output of gluster volume status - Returns: - dict: volume status in dict of dictionary format, on success - NoneType: on failure - - Example: - get_volume_status(volname="testvol") - >>>{'testvol': {'10.70.47.89': {'/bricks/brick1/a11': {'status': '1', - 'pid': '28963', 'bricktype': 'cold', 'port': '49163', 'peerid': - '7fc9015e-8134-4753-b837-54cbc6030c98', 'ports': {'rdma': 'N/A', - 'tcp': '49163'}}, '/bricks/brick2/a31': {'status': '1', 'pid': - '28982', 'bricktype': 'cold', 'port': '49164', 'peerid': - '7fc9015e-8134-4753-b837-54cbc6030c98', 'ports': {'rdma': 'N/A', - 'tcp': '49164'}}, 'NFS Server': {'status': '1', 'pid': '30525', - 'port': '2049', 'peerid': '7fc9015e-8134-4753-b837-54cbc6030c98', - 'ports': {'rdma': 'N/A', 'tcp': '2049'}}, '/bricks/brick1/a12': - {'status': '1', 'pid': '30505', 'bricktype': 'hot', 'port': '49165', - 'peerid': '7fc9015e-8134-4753-b837-54cbc6030c98', 'ports': {'rdma': - 'N/A', 'tcp': '49165'}}}, '10.70.47.118': {'/bricks/brick1/a21': - {'status': '1', 'pid': '5427', 'bricktype': 'cold', 'port': '49162', - 'peerid': '5397d8f5-2986-453a-b0b5-5c40a9bb87ff', 'ports': {'rdma': - 'N/A', 'tcp': '49162'}}, '/bricks/brick2/a41': {'status': '1', 'pid': - '5446', 'bricktype': 'cold', 'port': '49163', 'peerid': - '5397d8f5-2986-453a-b0b5-5c40a9bb87ff', 'ports': {'rdma': 'N/A', - 'tcp': '49163'}}, 'NFS Server': {'status': '1', 'pid': '6397', 'port': - '2049', 'peerid': '5397d8f5-2986-453a-b0b5-5c40a9bb87ff', 'ports': - {'rdma': 'N/A', 'tcp': '2049'}}}}} - """ - - if mnode is None: - mnode = tc.servers[0] - - cmd = "gluster vol status %s %s %s --xml" % (volname, service, options) - - ret, out, _ = tc.run(mnode, cmd) - if ret != 0: - tc.logger.error("Failed to execute gluster volume status command") - return None - - root = etree.XML(out) - volume_list = _parse_volume_status_xml(root) - if volume_list is None: - tc.logger.error("No volumes exists in the gluster") - return None - - vol_status = {} - for volume in volume_list: - tmp_dict1 = {} - tmp_dict2 = {} - hot_bricks = [] - cold_bricks = [] - vol_name = [vol.text for vol in volume if vol.tag == "volName"] - - # parsing volume status xml output - if options == 'tasks': - tasks = volume.findall("tasks") - for each_task in tasks: - tmp_dict3 = parse_xml(each_task) - node_name = 'task_status' - if 'task' in tmp_dict3.keys(): - if node_name in tmp_dict2.keys(): - tmp_dict2[node_name].append(tmp_dict3['task']) - else: - tmp_dict2[node_name] = [tmp_dict3['task']] - else: - tmp_dict2[node_name] = [tmp_dict3] - else: - elem_tag = [] - for elem in volume.getchildren(): - elem_tag.append(elem.tag) - if ('hotBricks' in elem_tag) or ('coldBricks' in elem_tag): - for elem in volume.getchildren(): - if (elem.tag == 'hotBricks'): - nodes = elem.findall("node") - hot_bricks = [node.find('path').text - for node in nodes - if ( - node.find('path').text.startswith('/'))] - if (elem.tag == 'coldBricks'): - for n in elem.findall("node"): - nodes.append(n) - cold_bricks = [node.find('path').text - for node in nodes - if ( - (node.find('path'). - text.startswith('/')))] - else: - nodes = volume.findall("node") - - for each_node in nodes: - if each_node.find('path').text.startswith('/'): - node_name = each_node.find('hostname').text - elif each_node.find('path').text == 'localhost': - node_name = mnode - else: - node_name = each_node.find('path').text - node_dict = parse_xml(each_node) - tmp_dict3 = {} - if "hostname" in node_dict.keys(): - if node_dict['path'].startswith('/'): - if node_dict['path'] in hot_bricks: - node_dict["bricktype"] = 'hot' - elif node_dict['path'] in cold_bricks: - node_dict["bricktype"] = 'cold' - else: - node_dict["bricktype"] = 'None' - tmp = node_dict["path"] - tmp_dict3[node_dict["path"]] = node_dict - else: - tmp_dict3[node_dict["hostname"]] = node_dict - tmp = node_dict["hostname"] - del tmp_dict3[tmp]["path"] - del tmp_dict3[tmp]["hostname"] - if node_name in tmp_dict1.keys(): - tmp_dict1[node_name].append(tmp_dict3) - else: - tmp_dict1[node_name] = [tmp_dict3] - - tmp_dict4 = {} - for item in tmp_dict1[node_name]: - for key, val in item.items(): - tmp_dict4[key] = val - tmp_dict2[node_name] = tmp_dict4 - - vol_status[vol_name[0]] = tmp_dict2 - tc.logger.debug("Volume status output: %s" - % pformat(vol_status, indent=10)) - return vol_status - - -def get_volume_option(volname, option='all', mnode=None): - """gets the option values for the given volume. - - Args: - volname (str): volume name - - Kwargs: - option (str): volume option to get status. - If not given, the function returns all the options for - the given volume - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - - Returns: - dict: value for the given volume option in dict format, on success - NoneType: on failure - - Example: - get_volume_option("testvol") - """ - if mnode is None: - mnode = tc.servers[0] - - cmd = "gluster volume get %s %s" % (volname, option) - ret, out, _ = tc.run(mnode, cmd) - if ret != 0: - tc.logger.error("Failed to execute gluster volume get command" - "for volume %s" % volname) - return None - - volume_option = {} - raw_output = out.split("\n") - for line in raw_output[2:-1]: - match = re.search(r'^(\S+)(.*)', line.strip()) - if match is None: - tc.logger.error("gluster get volume output is not in " - "expected format") - return None - - volume_option[match.group(1)] = match.group(2).strip() - - return volume_option - - -def set_volume_options(volname, options, mnode=None): - """sets the option values for the given volume. - - Args: - volname (str): volume name - options (dict): volume options in key - value format - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - - Returns: - bool: True, if the volume option is set - False, on failure - - Example: - options = {"user.cifs":"enable","user.smb":"enable"} - set_volume_option("testvol", options=options) - """ - if mnode is None: - mnode = tc.servers[0] - _rc = True - for option in options: - cmd = ("gluster volume set %s %s %s" - % (volname, option, options[option])) - ret, _, _ = tc.run(mnode, cmd) - if ret != 0: - tc.logger.error("Unable to set value %s for option %s" - % (options[option], option)) - _rc = False - return _rc - - -def volume_info(volname='all', mnode=None): - """Executes gluster volume info cli command - - Kwargs: - volname (str): volume name. Defaults to 'all' - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - - 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. - - Example: - volume_status() - """ - if mnode is None: - mnode = tc.servers[0] - - cmd = "gluster volume info %s" % volname - return tc.run(mnode, cmd) - - -def get_volume_info(volname='all', mnode=None): - """Fetches the volume information as displayed in the volume info. - Uses xml output of volume info and parses the into to a dict - - Kwargs: - volname (str): volume name. Defaults to 'all' - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - - Returns: - NoneType: If there are errors - dict: volume info in dict of dicts - - Example: - get_volume_info(volname="testvol") - >>>{'testvol': {'status': '1', 'xlators': None, 'disperseCount': '0', - 'bricks': {'coldBricks': {'colddisperseCount': '0', - 'coldarbiterCount': '0', 'coldBrickType': 'Distribute', - 'coldbrickCount': '4', 'numberOfBricks': '4', 'brick': - [{'isArbiter': '0', 'name': '10.70.47.89:/bricks/brick1/a11', - 'hostUuid': '7fc9015e-8134-4753-b837-54cbc6030c98'}, {'isArbiter': - '0', 'name': '10.70.47.118:/bricks/brick1/a21', 'hostUuid': - '7fc9015e-8134-4753-b837-54cbc6030c98'}, {'isArbiter': '0', 'name': - '10.70.47.89:/bricks/brick2/a31', 'hostUuid': - '7fc9015e-8134-4753-b837-54cbc6030c98'}, {'isArbiter': '0', - 'name': '10.70.47.118:/bricks/brick2/a41', 'hostUuid': - '7fc9015e-8134-4753-b837-54cbc6030c98'}], 'coldreplicaCount': '1'}, - 'hotBricks': {'hotBrickType': 'Distribute', 'numberOfBricks': '1', - 'brick': [{'name': '10.70.47.89:/bricks/brick1/a12', 'hostUuid': - '7fc9015e-8134-4753-b837-54cbc6030c98'}], 'hotbrickCount': '1', - 'hotreplicaCount': '1'}}, 'type': '5', 'distCount': '1', - 'replicaCount': '1', 'brickCount': '5', 'options': - {'cluster.tier-mode': 'cache', 'performance.readdir-ahead': 'on', - 'features.ctr-enabled': 'on'}, 'redundancyCount': '0', 'transport': - '0', 'typeStr': 'Tier', 'stripeCount': '1', 'arbiterCount': '0', - 'id': 'ffa8a8d1-546f-4ebf-8e82-fcc96c7e4e05', 'statusStr': 'Started', - 'optCount': '3'}} - """ - if mnode is None: - mnode = tc.servers[0] - - cmd = "gluster volume info %s --xml" % volname - ret, out, _ = tc.run(mnode, cmd, verbose=False) - if ret != 0: - tc.logger.error("volume info returned error") - return None - root = etree.XML(out) - volinfo = {} - for volume in root.findall("volInfo/volumes/volume"): - for elem in volume.getchildren(): - if elem.tag == "name": - volname = elem.text - volinfo[volname] = {} - elif elem.tag == "bricks": - volinfo[volname]["bricks"] = {} - tag_list = [x.tag for x in elem.getchildren() if x] - if 'brick' in tag_list: - volinfo[volname]["bricks"]["brick"] = [] - for el in elem.getchildren(): - if el.tag == 'brick': - brick_info_dict = {} - for elmt in el.getchildren(): - brick_info_dict[elmt.tag] = elmt.text - (volinfo[volname]["bricks"]["brick"]. - append(brick_info_dict)) - - if el.tag == "hotBricks" or el.tag == "coldBricks": - volinfo[volname]["bricks"][el.tag] = {} - volinfo[volname]["bricks"][el.tag]["brick"] = [] - for elmt in el.getchildren(): - if elmt.tag == 'brick': - brick_info_dict = {} - for el_brk in elmt.getchildren(): - brick_info_dict[el_brk.tag] = el_brk.text - (volinfo[volname]["bricks"][el.tag]["brick"]. - append(brick_info_dict)) - else: - volinfo[volname]["bricks"][el.tag][elmt.tag] = elmt.text - elif elem.tag == "options": - volinfo[volname]["options"] = {} - for option in elem.findall("option"): - for el in option.getchildren(): - if el.tag == "name": - opt = el.text - if el.tag == "value": - volinfo[volname]["options"][opt] = el.text - else: - volinfo[volname][elem.tag] = elem.text - - tc.logger.debug("Volume info output: %s" - % pformat(volinfo, indent=10)) - - return volinfo - - -def sync_volume(hostname, volname="all", mnode=None): - """syncs the volume - - Args: - hostname (str): host name - - Kwargs: - volname (str): volume name. Defaults to 'all'. - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - - 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. - - Example: - sync_volume("abc.xyz.com",volname="testvol") - """ - if mnode is None: - mnode = tc.servers[0] - - cmd = "gluster volume sync %s %s --mode=script" % (hostname, volname) - return tc.run(mnode, cmd) - - -def get_subvols(volname, mnode=None): - """Gets the subvolumes in the given volume - - Args: - volname (str): volume name - - Kwargs: - mnode (str): Node on which cmd has to be executed. - If None, defaults to servers[0]. - - Returns: - dict: with empty list values for all keys, if volume doesn't exist - dict: Dictionary of subvols, value of each key is list of lists - containing subvols - Example: - get_subvols("testvol") - """ - - subvols = { - 'hot_tier_subvols': [], - 'cold_tier_subvols': [], - 'volume_subvols': [] - } - if mnode is None: - mnode = tc.servers[0] - volinfo = get_volume_info(volname, mnode) - if volinfo is not None: - voltype = volinfo[volname]['typeStr'] - if voltype == 'Tier': - hot_tier_type = (volinfo[volname]["bricks"] - ['hotBricks']['hotBrickType']) - tmp = volinfo[volname]["bricks"]['hotBricks']["brick"] - hot_tier_bricks = [x["name"] for x in tmp if "name" in x] - if (hot_tier_type == 'Distribute'): - for brick in hot_tier_bricks: - subvols['hot_tier_subvols'].append([brick]) - - elif (hot_tier_type == 'Replicate' or - hot_tier_type == 'Distributed-Replicate'): - rep_count = int((volinfo[volname]["bricks"]['hotBricks'] - ['numberOfBricks']).split("=", 1)[0]. - split("x")[1].strip()) - subvol_list = ([hot_tier_bricks[i:i + rep_count] - for i in range(0, len(hot_tier_bricks), - rep_count)]) - subvols['hot_tier_subvols'] = subvol_list - cold_tier_type = (volinfo[volname]["bricks"]['coldBricks'] - ['coldBrickType']) - tmp = volinfo[volname]["bricks"]['coldBricks']["brick"] - cold_tier_bricks = [x["name"] for x in tmp if "name" in x] - if (cold_tier_type == 'Distribute' or - cold_tier_type == 'Disperse'): - for brick in cold_tier_bricks: - subvols['cold_tier_subvols'].append([brick]) - - elif (cold_tier_type == 'Replicate' or - cold_tier_type == 'Distributed-Replicate'): - rep_count = int((volinfo[volname]["bricks"]['coldBricks'] - ['numberOfBricks']).split("=", 1)[0]. - split("x")[1].strip()) - subvol_list = ([cold_tier_bricks[i:i + rep_count] - for i in range(0, len(cold_tier_bricks), - rep_count)]) - subvols['cold_tier_subvols'] = subvol_list - - elif (cold_tier_type == 'Distributed-Disperse'): - disp_count = sum([int(nums) for nums in - ((volinfo[volname]["bricks"]['coldBricks'] - ['numberOfBricks']).split("x", 1)[1]. - strip().split("=")[0].strip().strip("()"). - split()) if nums.isdigit()]) - subvol_list = [cold_tier_bricks[i:i + disp_count] - for i in range(0, len(cold_tier_bricks), - disp_count)] - subvols['cold_tier_subvols'] = subvol_list - return subvols - - tmp = volinfo[volname]["bricks"]["brick"] - bricks = [x["name"] for x in tmp if "name" in x] - if voltype == 'Replicate' or voltype == 'Distributed-Replicate': - rep_count = int(volinfo[volname]['replicaCount']) - subvol_list = [bricks[i:i + rep_count]for i in range(0, - len(bricks), - rep_count)] - subvols['volume_subvols'] = subvol_list - elif voltype == 'Distribute' or voltype == 'Disperse': - for brick in bricks: - subvols['volume_subvols'].append([brick]) - - elif voltype == 'Distributed-Disperse': - disp_count = int(volinfo[volname]['disperseCount']) - subvol_list = [bricks[i:i + disp_count]for i in range(0, - len(bricks), - disp_count)] - subvols['volume_subvols'] = subvol_list - return subvols diff --git a/tests/distaf/distaf_libs/distaflibs-gluster/setup.py b/tests/distaf/distaf_libs/distaflibs-gluster/setup.py deleted file mode 100644 index c2d40e4e2d2..00000000000 --- a/tests/distaf/distaf_libs/distaflibs-gluster/setup.py +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/python -# Copyright (c) 2015 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 -# (at your option) 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 setuptools import setup, find_packages - -version = '0.1.0' -name = 'distaflibs-gluster' - -setup( - name=name, - version=version, - description='DiSTAF Gluster Library', - license='GPLv2+', - author='Red Hat, Inc.', - author_email='gluster-devel@gluster.org', - url='http://www.gluster.org', - packages=find_packages(), - classifiers=[ - 'Development Status :: 4 - Beta' - 'Environment :: Console' - 'Intended Audience :: Developers' - 'License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)' - 'Operating System :: POSIX :: Linux' - 'Programming Language :: Python' - 'Programming Language :: Python :: 2' - 'Programming Language :: Python :: 2.6' - 'Programming Language :: Python :: 2.7' - 'Topic :: Software Development :: Testing' - ], - install_requires=['distaf'], - namespace_packages = ['distaflibs'] -) diff --git a/tests/distaf/distaf_libs/distaflibs-io/distaflibs/__init__.py b/tests/distaf/distaf_libs/distaflibs-io/distaflibs/__init__.py deleted file mode 100644 index de40ea7ca05..00000000000 --- a/tests/distaf/distaf_libs/distaflibs-io/distaflibs/__init__.py +++ /dev/null @@ -1 +0,0 @@ -__import__('pkg_resources').declare_namespace(__name__) diff --git a/tests/distaf/distaf_libs/distaflibs-io/distaflibs/io/__init__.py b/tests/distaf/distaf_libs/distaflibs-io/distaflibs/io/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/tests/distaf/distaf_libs/distaflibs-io/distaflibs/io/file_ops.py b/tests/distaf/distaf_libs/distaflibs-io/distaflibs/io/file_ops.py deleted file mode 100644 index 796c0982882..00000000000 --- a/tests/distaf/distaf_libs/distaflibs-io/distaflibs/io/file_ops.py +++ /dev/null @@ -1,245 +0,0 @@ -#!/usr/bin/env python -# This file is part of DiSTAF -# Copyright (C) 2015-2016 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: Library for file operations. -""" - - -import re -import socket -from distaf.util import tc - - -def write_file(filename, file_contents=" ", create_mode='', filesize='', \ - server=''): - """ - This module writes the file along with file contents - @paramater: - * filename - absolute path name of the file to be created - * file_contents - (optional) file content - * create_mode - (optional) mode to create the file - * filesize - (optional) filesize - * server - (optional) name of the server to write the - file. If not given, the function takes the - first node from config file - @Returns: True, on success - False, on failure - """ - if server == '': - server = tc.servers[0] - - if create_mode == '': - create_mode = 'open' - - if create_mode != 'open': - try: - conn = tc.get_connection(server, 'root') - if conn == -1: - tc.logger.error("Unable to get connection to 'root' of " - "node %s" % server) - return False - if not conn.modules.os.path.exists(conn.modules.os.path.\ - dirname(filename)): - conn.modules.os.makedirs(conn.modules.os.path.\ - dirname(filename)) - except: - tc.logger.error("Exception occured while creating directory for " - "file %s" % filename) - return False - finally: - conn.close() - - if create_mode == 'open': - try: - conn = tc.get_connection(server, 'root') - if conn == -1: - tc.logger.error("Unable to get connection to 'root' of node " - "%s" % server) - return False - - if not conn.modules.os.path.exists(conn.modules.os.path.\ - dirname(filename)): - conn.modules.os.makedirs(conn.modules.os.path.\ - dirname(filename)) - - with conn.builtin.open(filename, 'w') as _filehandle: - _filehandle.write(file_contents) - except: - tc.logger.error("Exception occured while writing file %s" \ - % filename) - return False - - finally: - conn.close() - elif create_mode == 'echo': - cmd = "echo " + file_contents + " > " + filename - ret, _, _ = tc.run(server, cmd) - if ret != 0: - return False - elif create_mode == 'touch': - cmd = "touch " + filename - ret, _, _ = tc.run(server, cmd) - if ret != 0: - return False - elif create_mode == 'dd': - if filesize == '': - tc.logger.error("Invalid argument for dd cmd. Pass correct \ - number of parameters") - return False - - cmd = "dd if=/dev/zero of=%s bs=%s count=1" % (filename, filesize) - ret, _, _ = tc.run(server, cmd) - if ret != 0: - return False - - return True - - -def remove_file(filename, server=''): - """ - This module removes the given file - @paramater: - * filename - absolute path name of the file to be created - * server - (optional) name of the server to write the - file. If not given, the function takes the - first node from config file - @Returns: True, on success - False, on failure - """ - if server == '': - server = tc.servers[0] - try: - conn = tc.get_connection(server, 'root') - if conn == -1: - tc.logger.error("Unable to get connection to 'root' of node %s" \ - % server) - return False - if conn.modules.os.path.exists(filename): - conn.modules.os.remove(filename) - except: - tc.logger.error("Exception occured while removing file %s" % filename) - return False - - finally: - conn.close() - - return True - - -def calculate_checksum(file_list, server=''): - """ - This module calculates checksum (sha256sum) for the given file list - @paramater: - * file_list - absolute file names for which checksum to be - calculated - * server - (optional) name of the server. - If not given, the function takes the - first node from config file - @Returns: checksum value in dict format, on success - None, on failure - """ - if server == '': - server = tc.servers[0] - - cmd = "sha256sum %s" % ' '.join(file_list) - ret = tc.run(server, cmd) - if ret[0] != 0: - tc.logger.error("Failed to execute checksum command in server %s" \ - % server) - return None - - checksum_dict = {} - for line in ret[1].split('\n')[:-1]: - match = re.search(r'^(\S+)\s+(\S+)', line.strip()) - if match is None: - tc.logger.error("checksum output is not in \ - expected format") - return None - - checksum_dict[match.group(2)] = match.group(1) - - return checksum_dict - - -def get_extended_attributes_info(file_list, encoding='hex', attr_name='', \ - server=''): - """ - This module gets extended attribute info for the given file list - @paramater: - * file_list - absolute file names - * encoding - (optional) encoding format - * server - (optional) name of the server. - If not given, the function takes the - first node from config file - @Returns: Extended attribute info in dict format, on success - None, on failure - """ - if server == '': - server = tc.servers[0] - - server = socket.gethostbyname(server) - if attr_name == '': - cmd = "getfattr -d -m . -e %s %s" % (encoding, ' '.join(file_list)) - else: - cmd = "getfattr -d -m . -n %s %s" % (attr_name, ' '.join(file_list)) - - ret = tc.run(server, cmd) - if ret[0] != 0: - tc.logger.error("Failed to execute getfattr command in server %s" \ - % server) - return None - - attr_dict = {} - for each_attr in ret[1].split('\n\n')[:-1]: - for line in each_attr.split('\n'): - if line.startswith('#'): - match = re.search(r'.*file:\s(\S+).*', line) - if match is None: - tc.logger.error("getfattr output isn't in expected format") - return None - key = "/" + match.group(1) - attr_dict[key] = {} - else: - output = line.split('=') - attr_dict[key][output[0]] = output[1] - return attr_dict - - -def get_filepath_from_rhsnode(filename, server=''): - """ - This module gets filepath of the given file from rhsnode - @paramater: - * filename - absolute name of the file - * server - (optional) name of the server. - If not given, the function takes the - first client from config file - @Returns: file path for the given file in rhs node in list format - on success None, on failure - """ - if server == '': - server = tc.clients[0] - - output = get_extended_attributes_info([filename], \ - attr_name='trusted.glusterfs.pathinfo', server=server) - if output is None: - tc.logger.error("Failed to get path info") - return None - - pathinfo = output[filename]['trusted.glusterfs.pathinfo'] - return re.findall(".*?POSIX.*?:(\S+)\>", pathinfo) diff --git a/tests/distaf/distaf_libs/distaflibs-io/setup.py b/tests/distaf/distaf_libs/distaflibs-io/setup.py deleted file mode 100644 index 3f74ccd7fbb..00000000000 --- a/tests/distaf/distaf_libs/distaflibs-io/setup.py +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/python -# Copyright (c) 2015 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 -# (at your option) 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 setuptools import setup, find_packages - -version = '0.1.0' -name = 'distaflibs-io' - -setup( - name=name, - version=version, - description='DiSTAF Gluster Library', - license='GPLv2+', - author='Red Hat, Inc.', - author_email='gluster-devel@gluster.org', - url='http://www.gluster.org', - packages=find_packages(), - classifiers=[ - 'Development Status :: 4 - Beta' - 'Environment :: Console' - 'Intended Audience :: Developers' - 'License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)' - 'Operating System :: POSIX :: Linux' - 'Programming Language :: Python' - 'Programming Language :: Python :: 2' - 'Programming Language :: Python :: 2.6' - 'Programming Language :: Python :: 2.7' - 'Topic :: Software Development :: Testing' - ], - install_requires=['distaf'], - namespace_packages = ['distaflibs'] -) diff --git a/tests/distaf/tests_d/__init__.py b/tests/distaf/tests_d/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/tests/distaf/tests_d/ctdb_gluster/__init__.py b/tests/distaf/tests_d/ctdb_gluster/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/tests/distaf/tests_d/ctdb_gluster/test_ctdb_gluster_setup.py b/tests/distaf/tests_d/ctdb_gluster/test_ctdb_gluster_setup.py deleted file mode 100644 index 90a86489c40..00000000000 --- a/tests/distaf/tests_d/ctdb_gluster/test_ctdb_gluster_setup.py +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env python -# This file is part of DiSTAF -# Copyright (C) 2015-2016 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 distaf.util import tc, testcase -from distaflibs.gluster.gluster_base_class import GlusterBaseClass -from distaflibs.gluster.ctdb_libs import ctdb_gluster_setup - - -@testcase("test_ctdb_gluster_setup") -class TestCtdbGlusterSetup(GlusterBaseClass): - """ - Test case to setup CTDB on gluster setup - """ - def __init__(self, config_data): - """ - Initialise the class with the config values - """ - tc.logger.info("Starting testcase for CTDB gluster setup") - GlusterBaseClass.__init__(self, config_data) - - def setup(self): - """ - The function to setup the CTDB setup - """ - ret = ctdb_gluster_setup() - return ret - - def run(self): - return True - - def cleanup(self): - """ - The function to cleanup the test setup - """ - return True diff --git a/tests/distaf/tests_d/distaf_gluster_config.yml b/tests/distaf/tests_d/distaf_gluster_config.yml deleted file mode 100644 index 9d48f66250a..00000000000 --- a/tests/distaf/tests_d/distaf_gluster_config.yml +++ /dev/null @@ -1,190 +0,0 @@ -log_file: /var/log/tests/distaf_test_run.log -log_level: DEBUG -remote_user: root - -servers: - - &server1 - host: server-vm1 - devices: ["/dev/vdb", "/dev/vdc", "/dev/vdd", "/dev/vde"] - brick_root: "/bricks" - - &server2 - host: server-vm2 - devices: ["/dev/vdb", "/dev/vdc", "/dev/vdd", "/dev/vde"] - brick_root: "/bricks" - - &server3 - host: server-vm3 - devices: ["/dev/vdb", "/dev/vdc", "/dev/vdd", "/dev/vde"] - brick_root: "/bricks" - - &server4 - host: server-vm4 - devices: ["/dev/vdb", "/dev/vdc", "/dev/vdd", "/dev/vde"] - brick_root: "/bricks" - - &server5 - host: server-vm5 - devices: ["/dev/vdb", "/dev/vdc", "/dev/vdd", "/dev/vde"] - brick_root: "/bricks" - - &server6 - host: server-vm2 - devices: ["/dev/vdb", "/dev/vdc", "/dev/vdd", "/dev/vde"] - brick_root: "/bricks" - - &server7 - host: server-vm7 - devices: ["/dev/vdb", "/dev/vdc", "/dev/vdd", "/dev/vde"] - brick_root: "/bricks" - - &server8 - host: server-vm8 - devices: ["/dev/vdb", "/dev/vdc", "/dev/vdd", "/dev/vde"] - brick_root: "/bricks" - - &server9 - host: server-vm9 - devices: ["/dev/vdb", "/dev/vdc", "/dev/vdd", "/dev/vde"] - brick_root: "/bricks" - - &server10 - host: server-vm10 - devices: ["/dev/vdb", "/dev/vdc", "/dev/vdd", "/dev/vde"] - brick_root: "/bricks" - - &server11 - host: server-vm11 - devices: ["/dev/vdb", "/dev/vdc", "/dev/vdd", "/dev/vde"] - brick_root: "/bricks" - - &server12 - host: server-vm12 - devices: ["/dev/vdb", "/dev/vdc", "/dev/vdd", "/dev/vde"] - brick_root: "/bricks" - -clients: - - &client1 - host: client-vm1 - - &client2 - host: client-vm2 - -gluster: - cluster_config: - smb: - enable: False - user: 'root' - passwd: 'foobar' - ctdb_servers: [] - ctdb_vips: - - vip: vip1 - routing_prefix: '23' - interface: 'eth0' - - vip: vip2 - routing_prefix: '22' - interface: 'eth0' - ctdb_metavol_brick_path: '' - - nfs_ganesha: - enable: False - num_of_nfs_ganesha_nodes: 4 - vips: [] - - volume_types: - distribute: &distribute - type: distribute - dist_count: 4 - transport: tcp - replicate: &replicate - type: replicate - replica_count: 3 - transport: tcp - dist_rep: &dist_rep - type: dist_rep - dist_count: 2 - replica_count: 2 - transport: tcp - disperse: &disperse - type: disperse - disperse_count: 4 - redundancy_count: 2 - transport: tcp - dist_disperse: &dist_disperse - type: dist_disperse - dist_count: 2 - disperse_count: 4 - redundancy_count: 2 - transport: tcp - - slave_volumes: - - &slave_vol1 - voltype: *dist_rep - servers: [ *server5, *server6, *server7, *server8 ] - peers: [] - quota: - enable: False - limit_usage: - path: "/" - size: 100GB - percent: - limit_objects: - path: "/" - number: - percent: - alert_time: - soft_timeout: - hard_timeout: - inode_quota: - enable: False - bitrot: - enable: False - scrub_throttle: - scrub_frequency: - - volumes: - - &vol1 - name: hosdu - voltype: *dist_disperse - servers: [ *server1, *server2, *server3, *server4 ] - peers: [ *server9, *server10, *server11, *server12 ] - tier: - create_tier: False - type: *dist_rep - quota: - enable: False - limit_usage: - path: "/" - size: 100GB - percent: - limit_objects: - path: "/" - number: - percent: - alert_time: 0 - soft_timeout: 0 - hard_timeout: 0 - inode_quota: - enable: False - bitrot: - enable: False - scrub_throttle: 'aggressive' - scrub_frequency: 'hourly' - geo_rep: - create_geo_rep_session: False - slave_volumes: [ *slave_vol1 ] - user: 'root' - group: 'geogroup' - sync_mode: 'rsync' - options: - performance.readdir-ahead: on - snapshot: - use_snapshot: True - snap_jobname: 'snap_job' - snap_schedule: 2 - - mounts: - - &mount1 - protocol: 'glusterfs' - server: '' - volname: - client: *client1 - mountpoint: '' - options: '' - - &mount2 - protocol: 'nfs' - server: '' - volname: '' - client: *client2 - mountpoint: '' - options: '' - -global_mode: True diff --git a/tests/distaf/tests_d/examples/__init__.py b/tests/distaf/tests_d/examples/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/tests/distaf/tests_d/examples/test_basic_gluster_tests.py b/tests/distaf/tests_d/examples/test_basic_gluster_tests.py deleted file mode 100644 index d981c0b8ab5..00000000000 --- a/tests/distaf/tests_d/examples/test_basic_gluster_tests.py +++ /dev/null @@ -1,64 +0,0 @@ -# This file is part of DiSTAF -# Copyright (C) 2015-2016 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 distaf.util import tc, testcase -from distaflibs.gluster.gluster_base_class import GlusterBaseClass -from distaflibs.gluster.mount_ops import mount_volume, umount_volume - - -@testcase("gluster_basic_test") -class gluster_basic_test(GlusterBaseClass): - """ - runs_on_volumes: ALL - runs_on_protocol: [ glusterfs, nfs ] - reuse_setup: False - """ - def run(self): - _rc = True - client = self.clients[0] - tc.run(self.mnode, "gluster volume status %s" % self.volname) - ret, _, _ = mount_volume(self.volname, self.mount_proto, - self.mountpoint, mclient=client) - if ret != 0: - tc.logger.error("Unable to mount the volume %s in %s" - "Please check the logs" % (self.volname, client)) - return False - ret, _, _ = tc.run(client, "cp -r /etc %s" % self.mountpoint) - if ret != 0: - tc.logger.error("cp failed in %s. Please check the logs" % client) - _rc = False - tc.run(client, "rm -rf %s/etc" % self.mountpoint) - umount_volume(client, self.mountpoint) - return _rc - - -@testcase("dummy_testcase") -class dummy_testcase(GlusterBaseClass): - """ - runs_on_volumes: ALL - runs_on_protocol: [ glusterfs, nfs ] - reuse_setup: False - """ - def run(self): - _rc = True - ret, _, _ = tc.run(self.mnode, "gluster volume status %s" % self.volname) - if ret != 0: - tc.logger.error("Unable to thet the status of %s", self.volname) - _rc = False - - return _rc diff --git a/tests/distaf/tests_d/examples/test_docstring.py b/tests/distaf/tests_d/examples/test_docstring.py deleted file mode 100644 index a939da8da9e..00000000000 --- a/tests/distaf/tests_d/examples/test_docstring.py +++ /dev/null @@ -1,130 +0,0 @@ -# This file is part of DiSTAF -# Copyright (C) 2015-2016 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 distaf.util import tc, testcase -from distaflibs.gluster.gluster_base_class import GlusterBaseClass - - -# An example with both doc and config in docstring -@testcase("doc_and_config_test") -class DocAndConfig(GlusterBaseClass): - """ Testing docstring configuration options - This is an example of a basic distaf test with mixed comment and config - Any necessary description doc string text goes here and can include any - plain text normally found in a docstring. - Distaf specific config yaml can be included using the yaml standard - document triple-dash separator below. - --- - runs_on_volumes: [ distributed ] - runs_on_protocol: [ glusterfs ] - reuse_setup: False - tags: - - tag1 - - tag2 - - tag3 - """ - def run(self): - tc.logger.info("Running with doc and config in docstring") - config = self.config_data - tc.logger.debug("Tag 2 is %s" % config["tags"][1]) - tag2 = config["tags"][1] - if tag2 == "tag2": - return True - - return False - - def setup(self): - return True - - def cleanup(self): - return True - - def teardown(self): - return True - - -# An example with only config in docstring -@testcase("config_only_test") -class ConfigOnly(GlusterBaseClass): - """ - runs_on_volumes: [ distributed ] - runs_on_protocol: [ glusterfs, cifs ] - reuse_setup: False - tags: - - tag1 - - tag2 - - tag3 - """ - def run(self): - tc.logger.info("Running with only config in docstring") - config = self.config_data - tc.logger.debug("Tag 2 is %s" % config["tags"][1]) - tag2 = config["tags"][1] - if tag2 == "tag2": - return True - - return False - - def setup(self): - return True - - def cleanup(self): - return True - - def teardown(self): - return True - - -# An example with only doc in docstring -@testcase("doc_only_test") -class DocOnly(GlusterBaseClass): - """ Testing docstring configuration options - This is an example of a basic distaf test with mixed comment and config - Any necessary description doc string text goes here and can include any - plain text normally found in a docstring. - """ - def run(self): - tc.logger.info("Running with only doc in docstring") - return True - - def setup(self): - return True - - def cleanup(self): - return True - - def teardown(self): - return True - - -# An example without a docstring -@testcase("no_docstring_test") -class NoDocstring(GlusterBaseClass): - def run(self): - tc.logger.info("Running with no docstring") - - return True - - def setup(self): - return True - - def cleanup(self): - return True - - def teardown(self): - return True diff --git a/tests/distaf/tests_d/examples/test_passfail.py b/tests/distaf/tests_d/examples/test_passfail.py deleted file mode 100644 index 78396349fc4..00000000000 --- a/tests/distaf/tests_d/examples/test_passfail.py +++ /dev/null @@ -1,97 +0,0 @@ -# This file is part of DiSTAF -# Copyright (C) 2015-2016 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 distaf.util import tc, testcase -from distaflibs.gluster.gluster_base_class import GlusterBaseClass - - -@testcase("this_should_pass") -class GoingToPass(GlusterBaseClass): - """ Testing connectivity and framework pass - This is an example of a basic distaf test with mixed comment and config - Any necessary description doc string text goes here and can include any - plain text normally found in a docstring. - Distaf specific config yaml can be included using the yaml standard - document triple-dash separator below. - --- - runs_on_volumes: [ distributed ] - runs_on_protocol: [ glusterfs ] - reuse_setup: False - tags: - - tag1 - - tag2 - - tag3 - """ - def setup(self): - return True - - def run(self): - config = self.config_data - tc.logger.info("Testing connection and command exec") - tc.logger.debug("Tag 1 is %s" % config["tags"][0]) - ret, _, _ = tc.run(self.servers[0], "hostname") - if ret != 0: - tc.logger.error("hostname command failed") - return False - else: - return True - - def setup(self): - return True - - def cleanup(self): - return True - - def teardown(self): - return True - - -@testcase("this_should_fail") -class GoingToFail(GlusterBaseClass): - """ Testing connectivity and fail - --- - runs_on_volumes: [ distributed ] - runs_on_protocol: [ glusterfs, cifs ] - reuse_setup: False - tags: - - tag1 - - tag2 - - tag3 - """ - def setup(self): - return True - - def run(self): - config = self.config_data - tc.logger.info("Testing fail output") - tc.logger.debug("Tag 1 is %s" % config["tags"][0]) - ret, _, _ = tc.run(self.servers[0], "false") - if ret != 0: - tc.logger.error("false command failed") - return False - else: - return True - - def setup(self): - return True - - def cleanup(self): - return True - - def teardown(self): - return True diff --git a/tests/distaf/tests_d/nfs_ganesha/__init__.py b/tests/distaf/tests_d/nfs_ganesha/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/tests/distaf/tests_d/nfs_ganesha/test_nfs_ganesha_setup.py b/tests/distaf/tests_d/nfs_ganesha/test_nfs_ganesha_setup.py deleted file mode 100644 index b95d3c9af90..00000000000 --- a/tests/distaf/tests_d/nfs_ganesha/test_nfs_ganesha_setup.py +++ /dev/null @@ -1,63 +0,0 @@ -#!/usr/bin/env python -# This file is part of DiSTAF -# Copyright (C) 2015-2016 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 distaf.util import tc, testcase -from distaflibs.gluster.class_setup_nfs_ganesha_vol import SetupNfsGaneshaVol - - -class TestSetupNfsGaneshaVol(SetupNfsGaneshaVol): - """ - Test case to setup NFS-Ganesha - """ - def __init__(self, config_data, nfs_options="vers=3"): - """ - Initialise the class with the config values - Kwargs: - nfs_options (str): This argument takes the nfs options, - say vers=3 or vers=4. - Default value is vers=3 - """ - tc.logger.info("Testcase to setup NFS-Ganesha volume %s" - % nfs_options) - SetupNfsGaneshaVol.__init__(self, config_data, nfs_options) - - def run(self): - return True - - -@testcase("test_setup_nfs_ganesha_vol_v3") -class TestSetupNfsGaneshaVolV3(TestSetupNfsGaneshaVol): - """ - Test case to setup NFS-Ganesha and - export volume with vers=3 - """ - def ___init__(self, config_data): - TestSetupNfsGaneshaVol.__init__(self, config_data, - nfs_options="vers=3") - - -@testcase("test_setup_nfs_ganesha_vol_v4") -class TestSetupNfsGaneshaVolV4(TestSetupNfsGaneshaVol): - """ - Test case to setup NFS-Ganesha and - export volume with vers=3 - """ - def ___init__(self, config_data): - TestSetupNfsGaneshaVol.__init__(self, config_data, - nfs_options="vers=4") diff --git a/tests/distaf/tests_d/sanity/__init__.py b/tests/distaf/tests_d/sanity/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/tests/distaf/tests_d/sanity/io_config.yml b/tests/distaf/tests_d/sanity/io_config.yml deleted file mode 100644 index 577c43eda09..00000000000 --- a/tests/distaf/tests_d/sanity/io_config.yml +++ /dev/null @@ -1,14 +0,0 @@ -gluster: - tests: - io: - dd_writes: - num_of_files: 1 - num_of_process_per_file: 1 - input_file: /dev/urandom - block_size: random - count: 1 - # oflag: append,direct,nonblock - # conv: fsync - - - diff --git a/tests/distaf/tests_d/sanity/test_dd_writes.py b/tests/distaf/tests_d/sanity/test_dd_writes.py deleted file mode 100644 index 3cff3ef8d82..00000000000 --- a/tests/distaf/tests_d/sanity/test_dd_writes.py +++ /dev/null @@ -1,139 +0,0 @@ -from distaf.util import tc, testcase, globl_configs -from distaflibs.gluster.gluster_base_class import GlusterBaseClass -from distaflibs.gluster.mount_ops import mount_volume, umount_volume -import os -import random -import yaml - -@testcase("test_dd_writes") -class TestDdWrites(GlusterBaseClass): - """ - runs_on_volumes: [ distribute, replicate, dist_rep ] - runs_on_protocol: [ glusterfs, nfs ] - reuse_setup: True - """ - def __init__(self, globl_configs): - GlusterBaseClass.__init__(self, globl_configs) - self.filename = "dd_testfile" - io_config_file = os.path.join(os.path.dirname - (os.path.realpath(__file__)), - "io_config.yml") - dd_writes_config = yaml.load(open(io_config_file)) - # Num of dd's to start per client/per file - self.num_of_dd_writes_process = (dd_writes_config['gluster']['tests'] - ['io']['dd_writes'] - ['num_of_process_per_file']) - - # Num of files to create - self.num_of_files = (dd_writes_config['gluster']['tests'] - ['io']['dd_writes']['num_of_files']) - - # Input file for dd command - self.dd_input_file = (dd_writes_config['gluster']['tests'] - ['io']['dd_writes']['input_file']) - - # Block size - self.block_size = (dd_writes_config['gluster']['tests'] - ['io']['dd_writes']['block_size']) - if "random" in self.block_size: - self.block_size = ["1k", "10k", "256k", "512k" ,"1M", - "10M", "100M", "256M", "512M", "1G"] - - # dd count - self.dd_count = (dd_writes_config['gluster']['tests'] - ['io']['dd_writes']['count']) - - # dd CONV - if (dd_writes_config['gluster']['tests']['io'] - ['dd_writes']).has_key('conv'): - self.dd_conv = (dd_writes_config['gluster']['tests'] - ['io']['dd_writes']['conv']) - else: - self.dd_conv = None - - # dd OFLAG - if (dd_writes_config['gluster']['tests']['io'] - ['dd_writes']).has_key('oflag'): - self.dd_oflag = (dd_writes_config['gluster']['tests'] - ['io']['dd_writes']['oflag']) - else: - self.dd_oflag = None - - - def setup(self): - ret = GlusterBaseClass.setup(self) - if not ret: - return False - - if self.mounts: - for mount_obj in self.mounts: - ret = mount_obj.mount() - if not ret: - tc.logger.error("Mounting Volume %s failed on %s:%s" % - (mount_obj.volname, - mount_obj.client_system, - mount_obj.mountpoint)) - return False - return True - - - def run(self): - rc = True - dd_cmd = "dd if=%s count=%s " % (self.dd_input_file, self.dd_count) - if self.dd_conv is not None: - dd_cmd += "conv=%s " % self.dd_conv - - if self.dd_oflag is not None: - dd_cmd += "oflag=%s " % self.dd_oflag - - all_mounts_cmd_runs = [] - for mount_obj in self.mounts: - all_cmd_runs = [] - for i in range(1, (self.num_of_files + 1)): - cmd_runs = [] - for j in range(1, (self.num_of_dd_writes_process + 1)): - cmd = dd_cmd + ("of=%s bs=%s" % - (os.path.join(mount_obj.mountpoint, - self.filename + "_" + str(i)), - random.choice(self.block_size))) - tc.logger.info("Executing Command: %s", cmd) - ret = tc.run_async(mount_obj.client_system, cmd) - cmd_runs.append(ret) - all_cmd_runs.append(cmd_runs) - all_mounts_cmd_runs.append(all_cmd_runs) - - for all_cmd_runs in all_mounts_cmd_runs: - for cmd_runs in all_cmd_runs: - for each_cmd_run in cmd_runs: - each_cmd_run.wait() - - rc = True - for i, all_cmd_runs in enumerate(all_mounts_cmd_runs): - for j, cmd_runs in enumerate(all_cmd_runs): - for k, each_cmd_run in enumerate(cmd_runs): - ret, _, _ = each_cmd_run.value() - if ret != 0: - tc.logger.error("DD Writes failed on: %s/%s/%s:%d" % - (self.mounts[i].client_system, - self.mounts[i].mountpoint, - (self.filename + "_" + str(j)), k)) - rc = False - if not rc: - tc.logger.error("DD Write failed on atleast one file") - return False - else: - tc.logger.info("DD Write successfully passed on all the files") - return True - - def teardown(self): - for mount_obj in self.mounts: - cleanup_mount_cmd = "rm -rf %s/*" % mount_obj.mountpoint - ret, out, err = tc.run(mount_obj.client_system, - cleanup_mount_cmd) - for mount_obj in self.mounts: - mount_obj.unmount() - ret = GlusterBaseClass.teardown(self) - if not ret: - return False - return True - -- cgit