summaryrefslogtreecommitdiffstats
path: root/cns-libs
diff options
context:
space:
mode:
Diffstat (limited to 'cns-libs')
-rw-r--r--cns-libs/cnslibs/common/heketi_libs.py22
-rw-r--r--cns-libs/cnslibs/common/openshift_ops.py166
-rw-r--r--cns-libs/cnslibs/common/utils.py44
3 files changed, 232 insertions, 0 deletions
diff --git a/cns-libs/cnslibs/common/heketi_libs.py b/cns-libs/cnslibs/common/heketi_libs.py
index 868b7281..0e913c29 100644
--- a/cns-libs/cnslibs/common/heketi_libs.py
+++ b/cns-libs/cnslibs/common/heketi_libs.py
@@ -12,6 +12,8 @@ from cnslibs.common.exceptions import ExecutionError, ConfigError
from cnslibs.common.heketi_ops import (setup_heketi_ssh_key,
modify_heketi_executor,
export_heketi_cli_server, hello_heketi)
+from cnslibs.common.openshift_ops import (oc_login, switch_oc_project,
+ get_ocp_gluster_pod_names)
class HeketiBaseClass(unittest.TestCase):
@@ -29,6 +31,12 @@ class HeketiBaseClass(unittest.TestCase):
super(HeketiBaseClass, cls).setUpClass()
# Initializes heketi config variables
+ cls.cns_username = g.config['cns']['setup']['cns_username']
+ cls.cns_password = g.config['cns']['setup']['cns_password']
+ cls.cns_project_name = g.config['cns']['setup']['cns_project_name']
+ cls.ocp_master_nodes = g.config['ocp_servers']['master'].keys()
+ cls.ocp_master_node = cls.ocp_master_nodes[0]
+
cls.deployment_type = g.config['cns']['deployment_type']
cls.executor = g.config['cns']['executor']
cls.executor_user = g.config['cns']['executor_user']
@@ -67,6 +75,20 @@ class HeketiBaseClass(unittest.TestCase):
raise ConfigError("Heketi server %s is not alive"
% cls.heketi_server_url)
+ if cls.deployment_type == "cns":
+ if not oc_login(cls.ocp_master_node, cls.cns_username,
+ cls.cns_password):
+ raise ExecutionError("Failed to do oc login on node %s"
+ % cls.ocp_master_node)
+
+ if not switch_oc_project(cls.ocp_master_node,
+ cls.cns_project_name):
+ raise ExecutionError("Failed to switch oc project on node %s"
+ % cls.ocp_master_node)
+
+ cls.gluster_pods = get_ocp_gluster_pod_names(cls.ocp_master_node)
+ g.pod_name = cls.gluster_pods[0]
+
# Have a unique string to recognize the test run for logging
if 'glustotest_run_id' not in g.config:
g.config['glustotest_run_id'] = (
diff --git a/cns-libs/cnslibs/common/openshift_ops.py b/cns-libs/cnslibs/common/openshift_ops.py
new file mode 100644
index 00000000..beff3272
--- /dev/null
+++ b/cns-libs/cnslibs/common/openshift_ops.py
@@ -0,0 +1,166 @@
+"""Library for openshift operations.
+
+Various utility functions for interacting with OCP/OpenShift.
+"""
+
+import re
+import types
+
+import yaml
+
+from glusto.core import Glusto as g
+
+
+PODS_WIDE_RE = re.compile(
+ '(\S+)\s+(\S+)\s+(\w+)\s+(\d+)\s+(\S+)\s+(\S+)\s+(\S+)\n')
+
+
+def oc_get_pods(ocp_node):
+ """Gets the pods info with 'wide' option in the current project.
+
+ Args:
+ ocp_node (str): Node in which ocp command will be executed.
+
+ Returns:
+ dict : dict of pods info in the current project.
+ """
+
+ cmd = "oc get -o wide --no-headers=true pods"
+ ret, out, err = g.run(ocp_node, cmd)
+ if ret != 0:
+ g.log.error("Failed to get ocp pods on node %s" % ocp_node)
+ raise AssertionError('failed to get pods: %r' % (err,))
+ return _parse_wide_pods_output(out)
+
+
+def _parse_wide_pods_output(output):
+ """Parse the output of `oc get -o wide pods`.
+ """
+ # Interestingly, the output of get pods is "cooked" in such a way that
+ # the values in the ready, status, & restart fields are not accessible
+ # from YAML/JSON/templating forcing us to scrape the output for
+ # these values
+ # (at the time of this writing the logic is in
+ # printPodBase in kubernetes/pkg/printers/internalversion/printers.go )
+ # Possibly obvious, but if you don't need those values you can
+ # use the YAML output directly.
+ #
+ # TODO: Add unit tests for this parser
+ pods_info = {}
+ for each_pod_info in PODS_WIDE_RE.findall(output):
+ pods_info[each_pod_info[0]] = {
+ 'ready': each_pod_info[1],
+ 'status': each_pod_info[2],
+ 'restarts': each_pod_info[3],
+ 'age': each_pod_info[4],
+ 'ip': each_pod_info[5],
+ 'node': each_pod_info[6],
+ }
+ return pods_info
+
+
+def oc_get_pods_full(ocp_node):
+ """Gets all the pod info via YAML in the current project.
+
+ Args:
+ ocp_node (str): Node in which ocp command will be executed.
+
+ Returns:
+ dict: The YAML output converted to python objects
+ (a top-level dict)
+ """
+
+ cmd = "oc get -o yaml pods"
+ ret, out, err = g.run(ocp_node, cmd)
+ if ret != 0:
+ g.log.error("Failed to get ocp pods on node %s" % ocp_node)
+ raise AssertionError('failed to get pods: %r' % (err,))
+ return yaml.load(out)
+
+
+def get_ocp_gluster_pod_names(ocp_node):
+ """Gets the gluster pod names in the current project.
+
+ Args:
+ ocp_node (str): Node in which ocp command will be executed.
+
+ Returns:
+ list : list of gluster pod names in the current project.
+ Empty list, if there are no gluster pods.
+
+ Example:
+ get_ocp_gluster_pod_names(ocp_node)
+ """
+
+ pod_names = oc_get_pods(ocp_node).keys()
+ return [pod for pod in pod_names if pod.startswith('glusterfs-')]
+
+
+def oc_login(ocp_node, username, password):
+ """Login to ocp master node.
+
+ Args:
+ ocp_node (str): Node in which ocp command will be executed.
+ username (str): username of ocp master node to login.
+ password (str): password of ocp master node to login.
+
+ Returns:
+ bool : True on successful login to ocp master node.
+ False otherwise
+
+ Example:
+ oc_login(ocp_node, "test","test")
+ """
+
+ cmd = "oc login --username=%s --password=%s" % (username, password)
+ ret, _, _ = g.run(ocp_node, cmd)
+ if ret != 0:
+ g.log.error("Failed to login to ocp master node %s" % ocp_node)
+ return False
+ return True
+
+
+def switch_oc_project(ocp_node, project_name):
+ """Switch to the given project.
+
+ Args:
+ ocp_node (str): Node in which ocp command will be executed.
+ project_name (str): Project name.
+ Returns:
+ bool : True on switching to given project.
+ False otherwise
+
+ Example:
+ switch_oc_project(ocp_node, "storage-project")
+ """
+
+ cmd = "oc project %s" % project_name
+ ret, _, _ = g.run(ocp_node, cmd)
+ if ret != 0:
+ g.log.error("Failed to switch to project %s" % project_name)
+ return False
+ return True
+
+
+def oc_rsh(ocp_node, pod_name, command):
+ """Run a command in the ocp pod using `oc rsh`.
+
+ Args:
+ ocp_node (str): Node on which oc rsh command will be executed.
+ pod_name (str): Name of the pod on which the command will
+ be executed.
+ command (str|list): command to run.
+
+ Returns:
+ A tuple consisting of the command return code, stdout, and stderr.
+ """
+ prefix = ['oc', 'rsh', pod_name]
+ if isinstance(command, types.StringTypes):
+ cmd = ' '.join(prefix + [command])
+ else:
+ cmd = prefix + command
+
+ # unpack the tuple to make sure our return value exactly matches
+ # our docstring
+ ret, stdout, stderr = g.run(ocp_node, cmd)
+ return (ret, stdout, stderr)
diff --git a/cns-libs/cnslibs/common/utils.py b/cns-libs/cnslibs/common/utils.py
new file mode 100644
index 00000000..a47ccafa
--- /dev/null
+++ b/cns-libs/cnslibs/common/utils.py
@@ -0,0 +1,44 @@
+"""Generic host utility functions.
+
+Generic utility functions not specifc to a larger suite of tools.
+For example, not specific to OCP, Gluster, Heketi, etc.
+"""
+
+import re
+
+from glusto.core import Glusto as g
+
+
+ONE_GB_BYTES = 1073741824.0
+
+
+def get_device_size(host, device_name):
+ """Gets device size for the given device name.
+
+ Args:
+ host (str): Node in command will be executed.
+ device_name (str): device name for which the size has to
+ be calculated.
+
+ Returns:
+ str : returns device size in GB on success
+ False otherwise
+
+ Example:
+ get_device_size(host, device_name)
+ """
+
+ cmd = "fdisk -l %s " % device_name
+ ret, out, _ = g.run(host, cmd)
+ if ret != 0:
+ g.log.error("Failed to execute fdisk -l command "
+ "on node %s" % host)
+ return False
+
+ regex = 'Disk\s' + device_name + '.*?,\s(\d+)\sbytes\,.*'
+ match = re.search(regex, out)
+ if match is None:
+ g.log.error("Regex mismatch while parsing fdisk -l output")
+ return False
+
+ return str(int(int(match.group(1))/ONE_GB_BYTES))