summaryrefslogtreecommitdiffstats
path: root/cns-libs/cnslibs
diff options
context:
space:
mode:
authorValerii Ponomarov <vponomar@redhat.com>2018-07-19 22:12:50 +0530
committerValerii Ponomarov <vponomar@redhat.com>2018-07-26 20:54:40 +0530
commit072e610ce6e667f8b4b32200035bdbce5fea4a53 (patch)
tree29587ac8329bdc66800007d69168e25ac92abf4d /cns-libs/cnslibs
parent6d9338fc1d00c2ea5c77febd0a8a71dc4c5a80b5 (diff)
[CNS-533] Add test for glusterblock logs verification
Also, 3 new library functions for: - secret creation - storage class creation - pvc creation Which use "stdin" creation approach without files. Change-Id: Ifba768deba11048ede207d72af4d480898e8f5fc
Diffstat (limited to 'cns-libs/cnslibs')
-rw-r--r--cns-libs/cnslibs/common/dynamic_provisioning.py53
-rw-r--r--cns-libs/cnslibs/common/openshift_ops.py123
-rw-r--r--cns-libs/cnslibs/common/utils.py7
3 files changed, 175 insertions, 8 deletions
diff --git a/cns-libs/cnslibs/common/dynamic_provisioning.py b/cns-libs/cnslibs/common/dynamic_provisioning.py
index c02c499b..5743bf6c 100644
--- a/cns-libs/cnslibs/common/dynamic_provisioning.py
+++ b/cns-libs/cnslibs/common/dynamic_provisioning.py
@@ -7,6 +7,7 @@ from glusto.core import Glusto as g
from glustolibs.misc.misc_libs import upload_scripts
import rtyaml
+from cnslibs.common import exceptions
from cnslibs.common.waiter import Waiter
@@ -334,3 +335,55 @@ def get_pvc_status(hostname, pvc_name):
return False, err
output = out.strip().split("\n")[0].strip()
return True, output
+
+
+def verify_pvc_status_is_bound(hostname, pvc_name, timeout=120, wait_step=3):
+ """Verify that PVC gets 'Bound' status in required time.
+
+ Args:
+ hostname (str): hostname on which we will execute oc commands
+ pvc_name (str): name of PVC to check status of
+ timeout (int): total time in seconds we are ok to wait
+ for 'Bound' status of a PVC
+ wait_step (int): time in seconds we will sleep before checking a PVC
+ status again.
+ Returns: None
+ Raises: exceptions.ExecutionError in case of errors.
+ """
+ pvc_not_found_counter = 0
+ for w in Waiter(timeout, wait_step):
+ ret, output = get_pvc_status(hostname, pvc_name)
+ if ret is not True:
+ msg = ("Failed to execute 'get' command for '%s' PVC. "
+ "Got following responce: %s" % (pvc_name, output))
+ g.log.error(msg)
+ raise exceptions.ExecutionError(msg)
+ if output == "":
+ g.log.info("PVC '%s' not found, sleeping for %s "
+ "sec." % (pvc_name, wait_step))
+ if pvc_not_found_counter > 0:
+ msg = ("PVC '%s' has not been found 2 times already. "
+ "Make sure you provided correct PVC name." % pvc_name)
+ else:
+ pvc_not_found_counter += 1
+ continue
+ elif output == "Pending":
+ g.log.info("PVC '%s' is in Pending state, sleeping for %s "
+ "sec" % (pvc_name, wait_step))
+ continue
+ elif output == "Bound":
+ g.log.info("PVC '%s' is in Bound state." % pvc_name)
+ return pvc_name
+ elif output == "Error":
+ msg = "PVC '%s' is in 'Error' state." % pvc_name
+ g.log.error(msg)
+ else:
+ msg = "PVC %s has different status - %s" % (pvc_name, output)
+ g.log.error(msg)
+ if msg:
+ raise exceptions.ExecutionError(msg)
+ if w.expired:
+ msg = ("Exceeded timeout of '%s' seconds for verifying PVC '%s' "
+ "to reach the 'Bound' status." % (timeout, pvc_name))
+ g.log.error(msg)
+ raise exceptions.ExecutionError(msg)
diff --git a/cns-libs/cnslibs/common/openshift_ops.py b/cns-libs/cnslibs/common/openshift_ops.py
index 84edfdd6..2a61f6ac 100644
--- a/cns-libs/cnslibs/common/openshift_ops.py
+++ b/cns-libs/cnslibs/common/openshift_ops.py
@@ -3,6 +3,8 @@
Various utility functions for interacting with OCP/OpenShift.
"""
+import base64
+import json
import re
import types
@@ -10,6 +12,7 @@ from glusto.core import Glusto as g
import yaml
from cnslibs.common import exceptions
+from cnslibs.common import utils
from cnslibs.common import waiter
@@ -170,22 +173,126 @@ def oc_rsh(ocp_node, pod_name, command, log_level=None):
return (ret, stdout, stderr)
-def oc_create(ocp_node, filename):
+def oc_create(ocp_node, value, value_type='file'):
"""Create a resource based on the contents of the given file name.
Args:
ocp_node (str): Node on which the ocp command will run
- filename (str): Filename (on remote) to be passed to oc create
- command
+ value (str): Filename (on remote) or file data
+ to be passed to oc create command.
+ value_type (str): either 'file' or 'stdin'.
Raises:
AssertionError: Raised when resource fails to create.
"""
- ret, out, err = g.run(ocp_node, ['oc', 'create', '-f', filename])
+ if value_type == 'file':
+ cmd = ['oc', 'create', '-f', value]
+ else:
+ cmd = ['echo', '\'%s\'' % value, '|', 'oc', 'create', '-f', '-']
+ ret, out, err = g.run(ocp_node, cmd)
if ret != 0:
- g.log.error('Failed to create resource: %r; %r', out, err)
- raise AssertionError('failed to create resource: %r; %r' % (out, err))
- g.log.info('Created resource from file (%s)', filename)
- return
+ msg = 'Failed to create resource: %r; %r' % (out, err)
+ g.log.error(msg)
+ raise AssertionError(msg)
+ g.log.info('Created resource from %s.' % value_type)
+
+
+def oc_create_secret(hostname, secret_name_prefix="autotests-secret-",
+ namespace="default",
+ data_key="password",
+ secret_type="kubernetes.io/glusterfs"):
+ """Create secret using data provided as stdin input.
+
+ Args:
+ hostname (str): Node on which 'oc create' command will be executed.
+ secret_name_prefix (str): secret name will consist of this prefix and
+ random str.
+ namespace (str): name of a namespace to create a secret in
+ data_key (str): plain text value for secret which will be transformed
+ into base64 string automatically.
+ secret_type (str): type of the secret, which will be created.
+ Returns: name of a secret
+ """
+ secret_name = "%s-%s" % (secret_name_prefix, utils.get_random_str())
+ secret_data = json.dumps({
+ "apiVersion": "v1",
+ "data": {"key": base64.b64encode(data_key)},
+ "kind": "Secret",
+ "metadata": {
+ "name": secret_name,
+ "namespace": namespace,
+ },
+ "type": secret_type,
+ })
+ oc_create(hostname, secret_data, 'stdin')
+ return secret_name
+
+
+def oc_create_sc(hostname, sc_name_prefix="autotests-sc",
+ provisioner="kubernetes.io/glusterfs",
+ allow_volume_expansion=False, **parameters):
+ """Create storage class using data provided as stdin input.
+
+ Args:
+ hostname (str): Node on which 'oc create' command will be executed.
+ sc_name_prefix (str): sc name will consist of this prefix and
+ random str.
+ provisioner (str): name of the provisioner
+ allow_volume_expansion (bool): Set it to True if need to allow
+ volume expansion.
+ Kvargs:
+ All the keyword arguments are expected to be key and values of
+ 'parameters' section for storage class.
+ """
+ allowed_parameters = (
+ 'resturl', 'secretnamespace', 'restuser', 'secretname',
+ 'restauthenabled', 'restsecretnamespace', 'restsecretname',
+ 'hacount', 'clusterids', 'chapauthenabled', 'volumenameprefix',
+ 'volumeoptions',
+ )
+ for parameter in parameters.keys():
+ if parameter.lower() not in allowed_parameters:
+ parameters.pop(parameter)
+ sc_name = "%s-%s" % (sc_name_prefix, utils.get_random_str())
+ sc_data = json.dumps({
+ "kind": "StorageClass",
+ "apiVersion": "storage.k8s.io/v1",
+ "metadata": {"name": sc_name},
+ "provisioner": provisioner,
+ "parameters": parameters,
+ "allowVolumeExpansion": allow_volume_expansion,
+ })
+ oc_create(hostname, sc_data, 'stdin')
+ return sc_name
+
+
+def oc_create_pvc(hostname, sc_name, pvc_name_prefix="autotests-pvc",
+ pvc_size=1):
+ """Create PVC using data provided as stdin input.
+
+ Args:
+ hostname (str): Node on which 'oc create' command will be executed.
+ sc_name (str): name of a storage class to create PVC in.
+ pvc_name_prefix (str): PVC name will consist of this prefix and
+ random str.
+ pvc_size (int/str): size of PVC in Gb
+ """
+ pvc_name = "%s-%s" % (pvc_name_prefix, utils.get_random_str())
+ pvc_data = json.dumps({
+ "kind": "PersistentVolumeClaim",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": pvc_name,
+ "annotations": {
+ "volume.beta.kubernetes.io/storage-class": sc_name,
+ },
+ },
+ "spec": {
+ "accessModes": ["ReadWriteOnce"],
+ "resources": {"requests": {"storage": "%sGi" % pvc_size}}
+ },
+ })
+ oc_create(hostname, pvc_data, 'stdin')
+ return pvc_name
def oc_delete(ocp_node, rtype, name):
diff --git a/cns-libs/cnslibs/common/utils.py b/cns-libs/cnslibs/common/utils.py
index a47ccafa..7d1f6d6f 100644
--- a/cns-libs/cnslibs/common/utils.py
+++ b/cns-libs/cnslibs/common/utils.py
@@ -4,7 +4,9 @@ Generic utility functions not specifc to a larger suite of tools.
For example, not specific to OCP, Gluster, Heketi, etc.
"""
+import random
import re
+import string
from glusto.core import Glusto as g
@@ -42,3 +44,8 @@ def get_device_size(host, device_name):
return False
return str(int(int(match.group(1))/ONE_GB_BYTES))
+
+
+def get_random_str(size=14):
+ chars = string.ascii_lowercase + string.digits
+ return ''.join(random.choice(chars) for _ in range(size))