diff options
author | Valerii Ponomarov <vponomar@redhat.com> | 2018-07-19 22:12:50 +0530 |
---|---|---|
committer | Valerii Ponomarov <vponomar@redhat.com> | 2018-07-26 20:54:40 +0530 |
commit | 072e610ce6e667f8b4b32200035bdbce5fea4a53 (patch) | |
tree | 29587ac8329bdc66800007d69168e25ac92abf4d /cns-libs/cnslibs | |
parent | 6d9338fc1d00c2ea5c77febd0a8a71dc4c5a80b5 (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.py | 53 | ||||
-rw-r--r-- | cns-libs/cnslibs/common/openshift_ops.py | 123 | ||||
-rw-r--r-- | cns-libs/cnslibs/common/utils.py | 7 |
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)) |