diff options
author | Valerii Ponomarov <vponomar@redhat.com> | 2018-07-26 19:01:56 +0530 |
---|---|---|
committer | Valerii Ponomarov <vponomar@redhat.com> | 2018-09-24 17:35:40 +0530 |
commit | 1545031a488a7c40830fe00aba79e82b7eea3000 (patch) | |
tree | 72b6f34605d6f31b3d44c0ec6e018983a3f06b44 | |
parent | ab4c4a625ae3defba70230282269079177491239 (diff) |
[CNS-945] Add arbiter test case
Where we create POD with mounted arbiter volume and write data to it.
Change-Id: I3a757f7fd71a0fd3f9f7d3cea463bbba5e399ec4
-rw-r--r-- | cns-libs/cnslibs/cns/cns_baseclass.py | 7 | ||||
-rw-r--r-- | cns-libs/cnslibs/common/openshift_ops.py | 33 | ||||
-rw-r--r-- | tests/functional/common/arbiter/test_arbiter.py | 69 |
3 files changed, 109 insertions, 0 deletions
diff --git a/cns-libs/cnslibs/cns/cns_baseclass.py b/cns-libs/cnslibs/cns/cns_baseclass.py index bffc4122..8809341f 100644 --- a/cns-libs/cnslibs/cns/cns_baseclass.py +++ b/cns-libs/cnslibs/cns/cns_baseclass.py @@ -1,4 +1,5 @@ from collections import OrderedDict +from cnslibs.common import command from cnslibs.common.exceptions import ( ConfigError, ExecutionError) @@ -143,6 +144,12 @@ class CnsBaseClass(unittest.TestCase): msg = "Teardownclass: %s : %s" % (cls.__name__, cls.glustotest_run_id) g.log.info(msg) + def cmd_run(self, cmd, hostname=None, raise_on_error=True): + if not hostname: + hostname = self.ocp_master_node[0] + return command.cmd_run( + cmd=cmd, hostname=hostname, raise_on_error=raise_on_error) + class CnsSetupBaseClass(CnsBaseClass): ''' diff --git a/cns-libs/cnslibs/common/openshift_ops.py b/cns-libs/cnslibs/common/openshift_ops.py index a4877687..4131ea9c 100644 --- a/cns-libs/cnslibs/common/openshift_ops.py +++ b/cns-libs/cnslibs/common/openshift_ops.py @@ -411,6 +411,39 @@ def oc_create_app_dc_with_io( return dc_name +def oc_create_tiny_pod_with_volume(hostname, pvc_name, pod_name_prefix='', + mount_path='/mnt'): + """Create tiny POD from image in 10Mb with attached volume at /mnt""" + pod_name = "%s-%s" % (pod_name_prefix, utils.get_random_str()) + pod_data = json.dumps({ + "apiVersion": "v1", + "kind": "Pod", + "metadata": { + "name": pod_name, + }, + "spec": { + "terminationGracePeriodSeconds": 20, + "containers": [{ + "name": pod_name, + "image": "cirros", # noqa: 10 Mb! linux image + "volumeMounts": [{"mountPath": mount_path, "name": "vol"}], + "command": [ + "/bin/sh", "-ec", + "trap 'exit 0' SIGTERM ; " + "while :; do echo '.'; sleep 5 ; done", + ] + }], + "volumes": [{ + "name": "vol", + "persistentVolumeClaim": {"claimName": pvc_name}, + }], + "restartPolicy": "Never", + } + }) + oc_create(hostname, pod_data, 'stdin') + return pod_name + + def oc_delete(ocp_node, rtype, name): """Delete an OCP resource by name. diff --git a/tests/functional/common/arbiter/test_arbiter.py b/tests/functional/common/arbiter/test_arbiter.py index dc21acee..238f3137 100644 --- a/tests/functional/common/arbiter/test_arbiter.py +++ b/tests/functional/common/arbiter/test_arbiter.py @@ -1,5 +1,6 @@ from cnslibs.cns import cns_baseclass from cnslibs.common.dynamic_provisioning import ( + wait_for_pod_be_ready, verify_pvc_status_is_bound, ) from cnslibs.common import heketi_ops @@ -8,6 +9,7 @@ from cnslibs.common.openshift_ops import ( oc_create_pvc, oc_create_sc, oc_create_secret, + oc_create_tiny_pod_with_volume, oc_delete, wait_for_resource_absence, ) @@ -120,3 +122,70 @@ class TestArbiterVolumeCreateExpandDelete(cns_baseclass.CnsBaseClass): "Arbiter brick amount is '%s', Data brick amount is '%s'." % ( arbiter_brick_amount, data_brick_amount) ) + + def test_arbiter_pvc_mount_on_pod(self): + """Test case CNS-945""" + + # Create sc with gluster arbiter info + self._create_storage_class() + + # Create PVC and wait for it to be in 'Bound' state + self._create_and_wait_for_pvc() + + # Create POD with attached volume + mount_path = "/mnt" + pod_name = oc_create_tiny_pod_with_volume( + self.node, self.pvc_name, "test-arbiter-pvc-mount-on-app-pod", + mount_path=mount_path) + self.addCleanup(oc_delete, self.node, 'pod', pod_name) + + # Wait for POD be up and running + wait_for_pod_be_ready(self.node, pod_name, timeout=60, wait_step=2) + + # Get volume ID + vol_info = get_gluster_vol_info_by_pvc_name(self.node, self.pvc_name) + vol_id = vol_info["gluster_vol_id"] + + # Verify that POD has volume mounted on it + cmd = "oc exec {0} -- df -PT {1} | grep {1}".format( + pod_name, mount_path) + out = self.cmd_run(cmd) + err_msg = ("Failed to get info about mounted '%s' volume. " + "Output is empty." % vol_id) + self.assertTrue(out, err_msg) + + # Verify volume data on POD + # Filesystem Type Size Used Avail Cap Mounted on + # IP:vol_id fuse.glusterfs 1038336 33408 1004928 3% /mnt + data = [s for s in out.strip().split(' ') if s] + actual_vol_id = data[0].split(':')[-1] + self.assertEqual( + vol_id, actual_vol_id, + "Volume ID does not match: expected is " + "'%s' and actual is '%s'." % (vol_id, actual_vol_id)) + self.assertIn( + "gluster", data[1], + "Filesystem type is expected to be of 'glusterfs' type. " + "Actual value is '%s'." % data[1]) + self.assertEqual( + mount_path, data[6], + "Unexpected mount path. Expected is '%s' and actual is '%s'." % ( + mount_path, data[6])) + max_size = 1024 ** 2 + total_size = int(data[2]) + self.assertLessEqual( + total_size, max_size, + "Volume has bigger size '%s' than expected - '%s'." % ( + total_size, max_size)) + min_available_size = int(max_size * 0.95) + available_size = int(data[4]) + self.assertLessEqual( + min_available_size, available_size, + "Minimum available size (%s) not satisfied. Actual is '%s'." % ( + min_available_size, available_size)) + + # Write data on mounted volume + write_data_cmd = ( + "dd if=/dev/zero of=%s/file$i bs=%s count=1; " % ( + mount_path, available_size)) + self.cmd_run(write_data_cmd) |