summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/generate_glusto_config/README.md34
-rw-r--r--tools/generate_glusto_config/examples/sample_glusto_config.yaml20
-rw-r--r--tools/generate_glusto_config/generate_glusto_config.py74
-rw-r--r--tools/generate_glusto_config/glusto_config_template.jinja40
-rw-r--r--tools/generate_glusto_config/setup.py32
-rw-r--r--tools/get_sosreports/README.md45
-rw-r--r--tools/get_sosreports/get_sosreports.py190
-rw-r--r--tools/get_sosreports/setup.py33
-rw-r--r--tools/log_splitter/README.md37
-rw-r--r--tools/log_splitter/log_splitter.py100
-rw-r--r--tools/log_splitter/setup.py33
-rw-r--r--tools/setup_passwordless_ssh/README.md47
-rw-r--r--tools/setup_passwordless_ssh/setup.py31
-rw-r--r--tools/setup_passwordless_ssh/setup_passwordless_ssh.py147
-rw-r--r--tools/verify_test_execution/README.md38
-rw-r--r--tools/verify_test_execution/verify_test_execution.py157
16 files changed, 1058 insertions, 0 deletions
diff --git a/tools/generate_glusto_config/README.md b/tools/generate_glusto_config/README.md
new file mode 100644
index 000000000..ce0455d69
--- /dev/null
+++ b/tools/generate_glusto_config/README.md
@@ -0,0 +1,34 @@
+# generate_glusto_config
+Tool to generate config file for executing glusto tests.
+
+## Prerequisites
+Python 3.x
+
+## Installation
+1. Change directory to the project directory.
+
+```
+# cd tools/generate_glusto_config
+```
+
+2. Now run the installation script.
+
+```
+# python3 setup.py install
+```
+
+3. To check run:
+
+```
+# generate_glusto_config --help
+```
+
+## Usage
+Pass arguments to the script as shown below:
+
+```
+# generate_glusto_config -c examples/sample_glusto_config.yaml -t glusto_config_template.jinja -o output_config.yml
+```
+
+## Licence
+[GPLv3](https://github.com/gluster/glusto-tests/blob/master/LICENSE)
diff --git a/tools/generate_glusto_config/examples/sample_glusto_config.yaml b/tools/generate_glusto_config/examples/sample_glusto_config.yaml
new file mode 100644
index 000000000..4991b2204
--- /dev/null
+++ b/tools/generate_glusto_config/examples/sample_glusto_config.yaml
@@ -0,0 +1,20 @@
+# 'clients' is list of Hostnames/IP's of clients in the cluster.
+clients: [client_hostname1, client_hostname2]
+
+# 'servers' is list of Hostnames/IP's of servers in the cluster.
+# Each item in list is a dict with 'Hostname/IP' of the server as key.
+# The info should contain the devices to use
+# for creating bricks, brick_root i.e dirname of brick mount point.
+
+servers:
+ - server_hostname1:
+ devices: ["/dev/vdb", "/dev/vdc", "/dev/vdd", "/dev/vde", "/dev/vdf"]
+ brick_root: "/bricks"
+ - server_hostname2:
+ devices: ["/dev/vdb", "/dev/vdc", "/dev/vdd", "/dev/vde", "/dev/vdf"]
+ brick_root: "/bricks"
+
+logfile: "/var/log/glusto_tests.log"
+
+# Mount protocol to use in the current run
+mount_type: ["glusterfs"]
diff --git a/tools/generate_glusto_config/generate_glusto_config.py b/tools/generate_glusto_config/generate_glusto_config.py
new file mode 100644
index 000000000..ca63b1d5a
--- /dev/null
+++ b/tools/generate_glusto_config/generate_glusto_config.py
@@ -0,0 +1,74 @@
+# Copyright (C) 2020 Red Hat, Inc. <http://www.redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 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 argparse
+
+from glusto.core import Glusto as g
+
+
+def handle_configs(config_list):
+ """Load user configuration files"""
+
+ # load user specified configs
+ if config_list:
+ config_files = config_list.split()
+ g.config = g.load_configs(config_files)
+ return True
+
+ return False
+
+
+def parse_args():
+ """Parse arguments with newer argparse module
+ (adds built-in required parm)
+ """
+ parser = argparse.ArgumentParser(
+ formatter_class=argparse.ArgumentDefaultsHelpFormatter,
+ description='Create output file based on template and config files')
+ parser.add_argument("-c", "--config",
+ help="Config file(s) to read.",
+ action="store", dest="config_list",
+ default=None)
+ parser.add_argument("-t", "--template",
+ help="Template file to render",
+ action="store", dest="template_file",
+ default=None)
+ parser.add_argument("-o", "--output",
+ help="Output file for rendered template",
+ action="store", dest="output_file",
+ default=None)
+ return parser.parse_args()
+
+
+def main():
+ """Main function"""
+
+ args = parse_args()
+
+ if args.config_list:
+ handle_configs(args.config_list)
+ g.show_config(g.config)
+
+ output_file = "rendered_template.txt"
+ if args.output_file:
+ output_file = args.output_file
+
+ if args.template_file:
+ g.render_template(args.template_file, g.config, output_file)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/tools/generate_glusto_config/glusto_config_template.jinja b/tools/generate_glusto_config/glusto_config_template.jinja
new file mode 100644
index 000000000..3146586d8
--- /dev/null
+++ b/tools/generate_glusto_config/glusto_config_template.jinja
@@ -0,0 +1,40 @@
+log_file: {{logfile}}
+log_level: DEBUG
+remote_user: root
+
+# 'servers' is list of Hostnames/IP's of servers in the cluster.
+servers: &servers_list{% for server_item in servers %}{% for server, value in server_item.items() %}
+ - {{server}}{% endfor %}{% endfor %}
+
+# 'clients' is list of Hostnames/IP's of clients in the cluster.
+clients:{% for client in clients %}
+ - {{client}}{% endfor %}
+
+# 'servers_info' is info about each server in the cluster.
+# each server_info is a dict with 'Hostname/IP' of the server as key.
+# The info should contain the host(Hostname/IP) of server, devices to use
+# for creating bricks, brick_root i.e dirname of brick mount point.
+# Note: Use the same Hostname/IP used in the above 'servers' section.
+
+servers_info:{% for server_item in servers %}
+ {% set outer_loop = loop %}
+ {% for server, value in server_item.items() %}
+ {{server}}: &server{{ outer_loop.index }}
+ host: {{server}}
+ devices: {{ value["devices"] }}
+ brick_root: {{ value["brick_root"] }}{% endfor %}{% endfor %}
+
+# 'clients_info' is info about each client in the cluster.
+# each client_info is a dict with 'Hostname/IP' of the client as key.
+# The info should contain the host(Hostname/IP) of client.
+
+clients_info: {% for client in clients %}
+ {{client}}: &client{{ loop.index }}
+ host: {{client}}{% endfor %}
+
+# This is to define what volume types and mount protocols will be run
+# in this current test run.
+
+gluster:
+ running_on_volumes: []
+ running_on_mounts: {{mount_type}}
diff --git a/tools/generate_glusto_config/setup.py b/tools/generate_glusto_config/setup.py
new file mode 100644
index 000000000..f6dcab180
--- /dev/null
+++ b/tools/generate_glusto_config/setup.py
@@ -0,0 +1,32 @@
+#!/usr/bin/python3
+# Copyright (C) 2020 Red Hat, Inc. <http://www.redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 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 setuptools import setup
+
+setup(
+ name='generate_glusto_config',
+ author='Red Hat, Inc.',
+ author_email='gluster-devel@gluster.org',
+ url='http://www.gluster.org',
+ license='GPLv3+',
+ description=("Tool to generate config file for executing glusto tests."),
+ py_modules=['generate_glusto_config'],
+ entry_points="""
+ [console_scripts]
+ generate_glusto_config = generate_glusto_config:main
+ """
+)
diff --git a/tools/get_sosreports/README.md b/tools/get_sosreports/README.md
new file mode 100644
index 000000000..57176f27f
--- /dev/null
+++ b/tools/get_sosreports/README.md
@@ -0,0 +1,45 @@
+# get_sosreports
+Tool to collect sosreports from all servers and clients.
+
+## Prerequisites
+1. Python 3.x
+2. Passwordless ssh should be setup.
+
+## Installation
+1. Change directory to the project directory.
+
+```
+# cd tools/get_sosreports
+```
+
+2. Now run the installation script.
+
+```
+# python3 setup.py install
+```
+
+3. To check run:
+
+```
+# get_sosreports --help
+```
+
+## Usage
+There are 2 ways of using the tool.
+1. Passing IP addresses through command line seperated by comma(,):
+
+```
+# get_sosreports -m machine_1,machine_2,machine_3
+```
+
+2. Passing a glusto-tests config file:
+
+```
+# get_sosreports -f config_file
+```
+
+**Note**:
+The default destination directory is `.` (present dir) `-d` or `--dist-dir` option.
+
+## Licence
+[GPLv3](https://github.com/gluster/glusto-tests/blob/master/LICENSE)
diff --git a/tools/get_sosreports/get_sosreports.py b/tools/get_sosreports/get_sosreports.py
new file mode 100644
index 000000000..962fa6d7f
--- /dev/null
+++ b/tools/get_sosreports/get_sosreports.py
@@ -0,0 +1,190 @@
+# Copyright (C) 2020 Red Hat, Inc. <http://www.redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 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.
+
+# Imports needed by the script.
+import argparse
+import os
+import sys
+from yaml import safe_load
+
+
+def read_config_file(config_file):
+ """
+ A function to read the yaml file given to the script.
+
+ Args:
+ config_file(str): A config file used to run glusto-tests.
+
+ Return:
+ dict: A dictornary with all the details from config file.
+ """
+ return safe_load(open(config_file, 'r'))
+
+
+def remove_previous_sosreports(server):
+ """
+ A function to remove old sosreports.
+
+ Args:
+ server: hostname/IP server from which sosreport
+ has to be removed.
+
+ Returns:
+ bool: True if successful else false.
+ """
+ cmd = ("ssh root@{} \"rm -rf /var/tmp/sosreport-*\""
+ .format(server))
+ ret = os.system(cmd)
+ if ret:
+ return False
+ return True
+
+
+def collect_new_sosreports(server):
+ """
+ A function to generate sosreports.
+
+ Args:
+ server: hostname/IP server from which sosreport
+ has to be collected.
+
+ Returns:
+ bool: True if successful else false.
+ """
+ cmd = ("ssh root@{} \"sosreport --batch --name=$HOSTNAME\""
+ .format(server))
+ ret = os.system(cmd)
+ if ret:
+ return False
+ return True
+
+
+def copy_sosreports_to_dir(server, directory):
+ """
+ A function to copy sosreports to local dir.
+
+ Args:
+ server: hostname/IP of server for passwordless ssh
+ has to be configured.
+ directory: Directory to be used to store sosreports.
+
+ Returns:
+ bool: True if successful else false.
+ """
+ cmd = ("scp root@{}:/var/tmp/sosreport-* {}"
+ .format(server, directory))
+ ret = os.system(cmd)
+ if ret:
+ return False
+ return True
+
+
+def check_and_create_dir_if_not_present(directory):
+ """
+ A function to check and create directory if not present.
+
+ Args:
+ directory: Directory to be checked/created.
+
+ Returns:
+ bool: True if successful else false.
+ """
+ if not os.path.isdir(directory):
+ cmd = ("mkdir -p {}".format(directory))
+ ret = os.system(cmd)
+ if ret:
+ return False
+ else:
+ print("[INFO]:The dir already exists.")
+ return True
+
+
+def main():
+ """
+ Main function of the tool.
+ """
+ # Setting up command line arguments.
+ parser = argparse.ArgumentParser(
+ description="Tool to collect sosreports from servers and clients."
+ )
+ parser.add_argument("-f",
+ "--config_file",
+ type=str,
+ dest="config_file",
+ help="A glusto-tests configuration file.")
+ parser.add_argument("-m", "--servers", type=str,
+ dest="servers",
+ help=("A list of hostnames/ips of"
+ " servers seperated by comma(',')."))
+ parser.add_argument("-d", "--dist-dir", type=str, default=".",
+ dest="directory",
+ help=("Directory where reports are to be stored."
+ "(Default:.)"))
+ args = parser.parse_args()
+
+ # Getting list of hostname/IP.
+ if args.servers:
+ servers = args.servers.split(',')
+
+ # Reading the config file.
+ if args.config_file:
+ config = read_config_file(args.config_file)
+ servers = []
+ servers += config.get('clients', [])
+ servers += config.get('servers', [])
+
+ # Fetching other parameters from command line.
+ directory = args.directory
+
+ # Checking and creating dir if not present.
+ ret = check_and_create_dir_if_not_present(directory)
+ if not ret:
+ sys.exit("[ERROR]:Unable to create dir for storing sosreports.")
+
+ try:
+ for server in servers:
+
+ # Removing old sosreports from the server.
+ ret = remove_previous_sosreports(server)
+ if not ret:
+ sys.exit("[ERROR]:Unable to remove old sosreports on {}!"
+ .format(server))
+ print("[INFO]:Successfully removed old sosreports on {}."
+ .format(server))
+
+ # Collecting sosreport on the server.
+ ret = collect_new_sosreports(server)
+ if not ret:
+ sys.exit("[ERROR]:Unable to collect sosreport on {}!"
+ .format(server))
+ print("[INFO]:Successfully collected sosreport on {}."
+ .format(server))
+
+ # Downloading sosreport to local machine.
+ ret = copy_sosreports_to_dir(server, directory)
+ if not ret:
+ sys.exit("[ERROR]:Unable download sosreport from {}."
+ .format(server))
+ print("[INFO]:Successfully copied sosreports from {}."
+ .format(server))
+
+ # If servers aren't provided.
+ except UnboundLocalError:
+ sys.exit("[ERROR]:servers were not provided")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/tools/get_sosreports/setup.py b/tools/get_sosreports/setup.py
new file mode 100644
index 000000000..79392e7ec
--- /dev/null
+++ b/tools/get_sosreports/setup.py
@@ -0,0 +1,33 @@
+# Copyright (C) 2020 Red Hat, Inc. <http://www.redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 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 setuptools import setup
+
+setup(
+ name='get_sosreports',
+ version="1.0",
+ author='Red Hat, Inc.',
+ author_email='gluster-devel@gluster.org',
+ url='http://www.gluster.org',
+ licens="GPLv3+",
+ description=("Tool to collect sosreports"
+ " from all servers and clients"),
+ py_modules=['get_sosreports'],
+ entry_points="""
+ [console_scripts]
+ get_sosreports = get_sosreports:main
+ """
+)
diff --git a/tools/log_splitter/README.md b/tools/log_splitter/README.md
new file mode 100644
index 000000000..e44aaecd3
--- /dev/null
+++ b/tools/log_splitter/README.md
@@ -0,0 +1,37 @@
+# log_splitter
+Tool to split glusto logs to individual testcase logs.
+
+## Prerequisites
+Python 3.x
+
+## Installation
+1. Change directory to the project directory.
+
+```
+# cd tools/log_splitter
+```
+
+2. Now run the installation script.
+
+```
+# python3 setup.py install
+```
+
+3. To check run:
+
+```
+# log_splitter --help
+```
+
+## Usage
+Just pass glusto_test.log file to the script as shown below:
+
+```
+# log_splitter -f glusto_test.log
+```
+
+**Note**:
+The default destination directory is `.` (present dir) `-d` or `--dist-dir` option.
+
+## Licence
+[GPLv3](https://github.com/gluster/glusto-tests/blob/master/LICENSE)
diff --git a/tools/log_splitter/log_splitter.py b/tools/log_splitter/log_splitter.py
new file mode 100644
index 000000000..e433b3ee1
--- /dev/null
+++ b/tools/log_splitter/log_splitter.py
@@ -0,0 +1,100 @@
+# Copyright (C) 2020 Red Hat, Inc. <http://www.redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 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.
+
+# Imports needed by the script.
+import argparse
+import os
+import sys
+
+
+def check_and_create_dir_if_not_present(directory):
+ """
+ A function to check and create directory if not present
+
+ Args:
+ directory(str): Directory to be created if not present
+
+ Retuns:
+ bool: True if successful else False
+ """
+ if not os.path.isdir(directory):
+ cmd = "mkdir -p {}".format(directory)
+ ret = os.system(cmd)
+ if ret:
+ return False
+ print("[INFO]: Dir created successfully")
+ else:
+ print("[INFO]: The dir already exists")
+ return True
+
+
+def main():
+ """
+ Main function of the tool.
+ """
+ # Setting up command line arguments.
+ parser = argparse.ArgumentParser(
+ description="Tool to split glusto logs to individual testcase logs."
+ )
+ parser.add_argument(
+ '-f', '--log_file', type=str, dest='log_file', required=True,
+ help="Glusto test log file")
+ parser.add_argument(
+ '-d', '--dist-dir', type=str, default=".", dest="destination_dir",
+ help="Path were individual test logs are to be stored.")
+ args = parser.parse_args()
+
+ # Fetching the values from command line.
+ log_file = args.log_file
+ destination_dir = args.destination_dir
+
+ # Check and create dir if not present
+ if not check_and_create_dir_if_not_present(destination_dir):
+ sys.exit("[ERROR]: Unable to create dir")
+
+ with open(log_file, 'r', encoding="ISO-8859-1") as log_file_fd:
+
+ # Read lines and set flag to check if
+ # file is open
+ file_open_flag = False
+ while True:
+ line = log_file_fd.readline()
+ if not line:
+ break
+
+ # Check if line is starting line.
+ if '(setUp) Starting Test : ' in line:
+ if file_open_flag:
+ file_open_flag = False
+
+ # Open new fd for individual test
+ # file
+ filename = line.split(' ')[7]
+ if destination_dir != '.':
+ filename = os.path.join(destination_dir,
+ filename)
+ file_open_flag = True
+
+ # Write lines to individual test file
+ if file_open_flag:
+ with open(filename, 'w') as test_file:
+ test_file.write(line)
+
+ print("[INFO]: Log file split completed")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/tools/log_splitter/setup.py b/tools/log_splitter/setup.py
new file mode 100644
index 000000000..2d922f30a
--- /dev/null
+++ b/tools/log_splitter/setup.py
@@ -0,0 +1,33 @@
+# Copyright (C) 2020 Red Hat, Inc. <http://www.redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 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 setuptools import setup
+
+setup(
+ name='log_splitter',
+ version="1.0",
+ author='Red Hat, Inc.',
+ author_email='gluster-devel@gluster.org',
+ url='http://www.gluster.org',
+ licens="GPLv3+",
+ description=("Tool to split glusto logs to "
+ "individual testcase logs."),
+ py_modules=['log_splitter'],
+ entry_points="""
+ [console_scripts]
+ log_splitter = log_splitter:main
+ """
+)
diff --git a/tools/setup_passwordless_ssh/README.md b/tools/setup_passwordless_ssh/README.md
new file mode 100644
index 000000000..c122d3703
--- /dev/null
+++ b/tools/setup_passwordless_ssh/README.md
@@ -0,0 +1,47 @@
+# setup_passwordless_ssh
+This is a tool to setup passwordless ssh to all nodes. It takes a glusto-tests
+config file and password as input.
+
+## Prerequisites
+1. Python 3.x
+2. All the servers should have the same password.
+3. Install sshpass on the control node.
+
+```
+# yum install sshpass
+```
+
+## Installation
+Download the project files from github.
+
+```
+# git clone https://github.com/gluster/glusto-tests.git
+```
+Change directory to the project directory.
+
+```
+# cd glusto-tests/tool/setup_passwordless_ssh/
+```
+Now run the installation script.
+
+```
+# python3 setup.py install
+```
+To check run:
+
+```
+setup_passwordless_ssh --help
+```
+
+## Usage
+To use this you need to have a valid glusto-tests config file([Sample file](https://github.com/gluster/glusto-tests/tree/master/tests/))
+after which just run the tool as shown below:
+
+```
+# setup_passwordless_ssh -c <Config file> -p <Password>
+```
+If you wish to establish passwordless ssh for a non-root user use `-u` or
+`--username` option followed by the username.
+
+## License
+[GPLv3](https://github.com/gluster/glusto-tests/blob/master/LICENSE) \ No newline at end of file
diff --git a/tools/setup_passwordless_ssh/setup.py b/tools/setup_passwordless_ssh/setup.py
new file mode 100644
index 000000000..6a8a49936
--- /dev/null
+++ b/tools/setup_passwordless_ssh/setup.py
@@ -0,0 +1,31 @@
+#!/usr/bin/python3
+# Copyright (C) 2019 Red Hat, Inc. <http://www.redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 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 setuptools import setup
+
+setup(
+ name='setup_passwordless_ssh',
+ author='Red Hat, Inc.',
+ author_email='gluster-devel@gluster.org',
+ url='http://www.gluster.org',
+ license='GPLv3+',
+ description=("Tool to setup passwordless ssh to all nodes."),
+ py_modules=['setup_passwordless_ssh'],
+ entry_points="""
+ [console_scripts]
+ setup_passwordless_ssh = setup_passwordless_ssh:main
+ """
+)
diff --git a/tools/setup_passwordless_ssh/setup_passwordless_ssh.py b/tools/setup_passwordless_ssh/setup_passwordless_ssh.py
new file mode 100644
index 000000000..e9a619c50
--- /dev/null
+++ b/tools/setup_passwordless_ssh/setup_passwordless_ssh.py
@@ -0,0 +1,147 @@
+#!/usr/bin/env python3
+# Copyright (C) 2019 Red Hat, Inc. <http://www.redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 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 argparse
+import sys
+from os import system
+from yaml import safe_load
+
+
+def read_config_file(config_file):
+ """
+ A function to read the yaml file given to the script.
+ Args:
+ config_file(str): A config file used to run glusto-tests.
+ Return:
+ dict: A dictornary with all the details from config file.
+ """
+ return safe_load(open(config_file, 'r'))
+
+
+def setup_passwordless_ssh(server, username, password):
+ """
+ A function to setup passwordless ssh to all servers.
+ Args:
+ server(str): hostname/IP of server for
+ passwordless ssh has to be configured.
+ username(str): User to be used to login.
+ password(str): password to be used to login.
+ Returns:
+ bool: True if successful else false.
+ """
+ command = ("sshpass -p %s ssh-copy-id -o StrictHostKeyChecking=no %s@%s"
+ % (password, username, server))
+ ret = system(command)
+ return not ret
+
+
+def check_passwordless_ssh_setup(server, username):
+ """
+ A function to check if passwordless ssh setup was successfull or not.
+ Args:
+ server(str): hostname/IP of server for
+ passwordless ssh has to be configured.
+ username(str): User to be used to login.
+ Returns:
+ bool: True if successful else false.
+ """
+ command = ("ssh %s@%s hostname" % (username, server))
+ ret = system(command)
+ return not ret
+
+
+def main():
+ """
+ Main function of the tool.
+ """
+
+ # Setting up command line arguments.
+ parser = argparse.ArgumentParser(
+ description="Tool to setup passwordless ssh to all nodes."
+ )
+ parser.add_argument("-c", "--config_file",
+ type=str, dest="config_file",
+ help="A glusto-tests configuration file.")
+ parser.add_argument("-p", "--password", dest="password",
+ type=str, help="Password of servers.")
+ parser.add_argument("-u", "--username", dest="username",
+ type=str, default="root",
+ help="User to be used to setup"
+ " passwordless ssh.")
+ args = parser.parse_args()
+
+ # Reading the config file.
+ if args.config_file:
+ config = read_config_file(args.config_file)
+ else:
+ sys.exit("[ERROR]:Config file not provided.")
+
+ # Checking if password was provided.
+ if args.password:
+ password = args.password
+ else:
+ sys.exit("[ERROR]:Password not provided.")
+
+ # Configuring passwordless ssh to all servers.
+ for server in config.get('servers', []):
+ ret = setup_passwordless_ssh(server, args.username,
+ password)
+ if not ret:
+ sys.exit("[ERROR]:Unable to setup "
+ "passwordless ssh to %s."
+ % server)
+ ret = check_passwordless_ssh_setup(server,
+ args.username)
+ if ret:
+ print("[INFO]:Passwordless ssh setup "
+ "completed to %s." % server)
+
+ # Configuring passwordless ssh to all clients.
+ for server in config.get('clients', []):
+ ret = setup_passwordless_ssh(server,
+ args.username,
+ password)
+
+ if not ret:
+ sys.exit("[ERROR]:Unable to setup "
+ "passwordless ssh to %s."
+ % server)
+
+ ret = check_passwordless_ssh_setup(server,
+ args.username)
+ if ret:
+ print("[INFO]:Passwordless ssh setup "
+ "completed to %s." % server)
+
+ # Configure paswordless ssh to all geo-rep slaves nodes.
+ for server in config.get('slaves', []):
+ ret = setup_passwordless_ssh(server,
+ args.username,
+ password)
+ if not ret:
+ sys.exit("[ERROR]:Unable to setup "
+ "passwordless ssh to %s."
+ % server)
+ ret = check_passwordless_ssh_setup(server,
+ args.username)
+ if ret:
+ print("[INFO]:Passwordless ssh setup "
+ "completed to %s." % server)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/tools/verify_test_execution/README.md b/tools/verify_test_execution/README.md
new file mode 100644
index 000000000..d78819515
--- /dev/null
+++ b/tools/verify_test_execution/README.md
@@ -0,0 +1,38 @@
+# verify_test_execution
+This tool verifies the stability of a given set of testcase(s) by executing it
+consecutively for a pre-defined number of times. This ensures that the written
+code is stable and also helps the user to identify unexpected failures or errors
+that may arise while executing it multiple times. It also checks the given code
+for any pylint/flake8 issues.
+
+## Prerequisites
+Python 3.x
+
+To use this you need to have a valid glusto-tests config file
+
+## Usage
+- Download the project files from github.
+
+ ```
+ # git clone https://github.com/gluster/glusto-tests.git
+ ```
+- Change directory to the project directory.
+ ```
+ # cd glusto-tests/tool/verify_test_execution/
+ ```
+- To get help run:
+ ```
+ # python3 verify_test_execution.py --help
+ ```
+- To run the test(s):
+ ```
+ # python3 verify_test_execution.py --config < Config file> --test <test_path>
+ ```
+
+If you wish to specify the commands for flake8 and pylint (optional) use
+`--flake8 <flake8 cmd> `and `--pylint <pylint command>` arguments.
+Also, use `--iterations` to specify the number of times the test(s)
+should be run (by default its 5) eg. `-- iterations 10 `
+
+## License
+GPLv3
diff --git a/tools/verify_test_execution/verify_test_execution.py b/tools/verify_test_execution/verify_test_execution.py
new file mode 100644
index 000000000..1cfc3143e
--- /dev/null
+++ b/tools/verify_test_execution/verify_test_execution.py
@@ -0,0 +1,157 @@
+# Copyright (C) 2020 Red Hat, Inc. <http://www.redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 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 argparse
+import subprocess
+import sys
+from datetime import datetime
+
+
+class TestVerify:
+
+ def __init__(self):
+ self.parser = argparse.ArgumentParser()
+ self.config = None
+ self.test_path = None
+ self.test_run_count = None
+ self.pre_run_check = False
+ iter_value_default = 5
+ flake8_default = "flake8"
+ pylint_default = "pylint"
+ # Set the arguments
+ self.parser.add_argument('-c', '--config',
+ help='Path to config file',
+ required=True)
+ self.parser.add_argument('-t', '--test',
+ help='path to test file/folder',
+ required=True)
+ self.parser.add_argument('-f', '--flake8',
+ default=flake8_default,
+ help='command to invoke flake8 '
+ '(by default <flake8 path_to_py_file>)')
+ self.parser.add_argument('-p', '--pylint',
+ default=pylint_default,
+ help='command to invoke pylint '
+ '(by default <pylint path_to_py_file>)')
+ self.parser.add_argument('-i', '--iterations',
+ type=int,
+ default=iter_value_default,
+ help='Iterations to runs the tests '
+ '(by default its 5)')
+ args = self.parser.parse_args()
+
+ # Get config file path
+ self.config = args.config
+
+ # Get test file or folder
+ self.test_path = args.test
+
+ # Get the pylint command
+ self.pylint_cmd = args.pylint
+
+ # Get the falke8 command
+ self.flake8_cmd = args.flake8
+
+ # Get the iteration count
+ self.test_run_count = args.iterations
+
+ # Verify flake8
+ self.verify_flake8()
+
+ # Verify Pylint
+ self.verify_pylint()
+
+ # Verify test run for user defined number of times
+ self.execute_tests()
+
+ def verify_pylint(self):
+ """
+ Verifies the given file has pylint issues or not.
+ In case the path given for the test to execute is a folder, the pylint
+ command returns all the issues in all the files present in the folder.
+ Verifies the return code of pylint.
+ """
+ print("o Pylint Verification:")
+ result = subprocess.run([self.pylint_cmd, self.test_path],
+ stdout=subprocess.PIPE)
+ if result.returncode != 0:
+ self._print_error(result.stdout)
+ print("\t Pylint validation failed")
+ self.pre_run_check = False
+ else:
+ print("\t Pylint validation successful")
+ self.pre_run_check = True
+
+ def verify_flake8(self):
+ """
+ Verifies the given file for falke8 issues. Executes the flake8 command
+ and verifies the return code.
+ """
+ print("o Flake8 Verification:")
+ result = subprocess.run([self.flake8_cmd, self.test_path],
+ stdout=subprocess.PIPE)
+ if result.returncode != 0:
+ self._print_error(result.stdout)
+ sys.exit("[ERROR]: Flake8 validation Failed")
+ print("\t Flake8 validation successful")
+
+ def execute_tests(self):
+ """
+ Runs the given test for user defined number of times.
+ """
+ start_time = datetime.now()
+ if not self.pre_run_check:
+ print("========= WARNING =========")
+ decision = input("There were some errors in the pre-check for "
+ "the given code. It is advised to fix all those "
+ "issues and the start executing the tests. To "
+ "continue to test execution press Y. To exit "
+ "press any other key : ")
+ if decision.lower() != "y":
+ sys.exit("[ERROR]: Aborted by user")
+ cmd = ("glusto -c '{config_path}' --pytest='-v -x {test_path}'"
+ .format(config_path=self.config, test_path=self.test_path))
+ print("\no Run Tests")
+ print("\t ==>[ ", cmd, " ]")
+ for counter in range(1, self.test_run_count+1):
+ print("\t Iteration : %s" % counter)
+ process = subprocess.Popen(cmd, shell=True,
+ stdout=subprocess.PIPE)
+ process.wait()
+ if process.returncode != 0:
+ self._print_error(process.stdout.read())
+ sys.exit("[ERROR]: Test Execution Failed")
+ print("\n\t\t Status : PASS")
+ end_time = datetime.now()
+ print("[INFO] : Test Execution succeeded")
+ print("\t Test : {test_name}".format(test_name=self.test_path))
+ print("\t Iterations : {iter}".format(iter=str(self.test_run_count)))
+ print("\t Completed in {time}".format(time=str(end_time-start_time)))
+
+ @staticmethod
+ def _print_error(err):
+ """
+ Prints the error from the stdout
+ """
+ print("\t [Error] \n\t", "-" * 100)
+ output = err.decode("utf-8").split("\n")
+ for line in output:
+ if line:
+ print("\t", str(line))
+ print("\t", "-" * 100)
+
+
+if __name__ == "__main__":
+ TestVerify()