summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Mellado <dmellado@redhat.com>2017-10-10 09:42:27 +0000
committerDaniel Mellado <dmellado@redhat.com>2017-10-27 09:28:58 +0000
commit0a820212fe0681300044c7259afa227d214ef5a3 (patch)
treeb8f43bc254d00a3a957bc1c760c3b5d80b5e339f
parent8883d324baff9ec571344e52ebfa0bbe0a092bc7 (diff)
Add scenario test manager
This commit adds a scenario test manager and an example scenario test using it for cross-connectivity between pods and vms. Change-Id: I890f5b35847a7b874659c52b172a5af7da26a147
Notes
Notes (review): Code-Review+1: MichaƂ Dulko <mdulko@redhat.com> Code-Review+2: Luis Tomas Bolivar <ltomasbo@redhat.com> Code-Review+2: Berezovsky Irena <irenab.dev@gmail.com> Workflow+1: Berezovsky Irena <irenab.dev@gmail.com> Verified+2: Zuul Submitted-by: Zuul Submitted-at: Sun, 29 Oct 2017 06:00:16 +0000 Reviewed-on: https://review.openstack.org/510896 Project: openstack/kuryr-tempest-plugin Branch: refs/heads/master
-rw-r--r--README.rst3
-rw-r--r--doc/source/index.rst8
l---------doc/source/scenario_tests/scenario.rst1
-rw-r--r--kuryr_tempest_plugin/tests/scenario/README.rst13
-rw-r--r--kuryr_tempest_plugin/tests/scenario/__init__.py0
-rw-r--r--kuryr_tempest_plugin/tests/scenario/base.py122
-rw-r--r--kuryr_tempest_plugin/tests/scenario/test_cross_ping.py66
7 files changed, 213 insertions, 0 deletions
diff --git a/README.rst b/README.rst
index a1d1173..b4e3307 100644
--- a/README.rst
+++ b/README.rst
@@ -2,6 +2,9 @@
2Tempest Integration of Kuryr 2Tempest Integration of Kuryr
3============================ 3============================
4 4
5Overview
6========
7
5This project defines a tempest plugin containing tests used to verify the 8This project defines a tempest plugin containing tests used to verify the
6functionality of a kuryr installation. The plugin will automatically load 9functionality of a kuryr installation. The plugin will automatically load
7these tests into tempest. 10these tests into tempest.
diff --git a/doc/source/index.rst b/doc/source/index.rst
index a6210d3..a3bf757 100644
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -1 +1,9 @@
1.. include:: ../../README.rst 1.. include:: ../../README.rst
2
3Scenario Tests
4==============
5
6.. toctree::
7 :maxdepth: 1
8
9 scenario_tests/scenario
diff --git a/doc/source/scenario_tests/scenario.rst b/doc/source/scenario_tests/scenario.rst
new file mode 120000
index 0000000..443cf66
--- /dev/null
+++ b/doc/source/scenario_tests/scenario.rst
@@ -0,0 +1 @@
../../../kuryr_tempest_plugin/tests/scenario/README.rst \ No newline at end of file
diff --git a/kuryr_tempest_plugin/tests/scenario/README.rst b/kuryr_tempest_plugin/tests/scenario/README.rst
new file mode 100644
index 0000000..1c9c61d
--- /dev/null
+++ b/kuryr_tempest_plugin/tests/scenario/README.rst
@@ -0,0 +1,13 @@
1
2What are these tests?
3---------------------
4
5As stated in the tempest developer guide, scenario tests are meant to be used to
6test the interaction between several OpenStack services to perform a real-life
7use case.
8
9In the case of the Kuryr Tempest Plugin it also involves interaction with
10Kubernetes pods, so its manager class includes handlers to its python bindings.
11
12A developer using this manager would be able to perform, among others, CRUD
13operations with pods, alongside Kuryr-K8s added funcionality.
diff --git a/kuryr_tempest_plugin/tests/scenario/__init__.py b/kuryr_tempest_plugin/tests/scenario/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/kuryr_tempest_plugin/tests/scenario/__init__.py
diff --git a/kuryr_tempest_plugin/tests/scenario/base.py b/kuryr_tempest_plugin/tests/scenario/base.py
new file mode 100644
index 0000000..ca13bc0
--- /dev/null
+++ b/kuryr_tempest_plugin/tests/scenario/base.py
@@ -0,0 +1,122 @@
1# Copyright 2017 Red Hat, Inc.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15import time
16
17from kubernetes import client as k8s_client
18from kubernetes import config as k8s_config
19
20from tempest.scenario import manager
21from tempest.lib.common.utils import data_utils
22from tempest import config
23
24CONF = config.CONF
25
26
27class BaseKuryrScenarioTest(manager.NetworkScenarioTest):
28
29 @classmethod
30 def skip_checks(cls):
31 super(BaseKuryrScenarioTest, cls).skip_checks()
32 if not CONF.service_available.kuryr:
33 raise cls.skipException('Kuryr support is required')
34
35 @classmethod
36 def setup_clients(cls):
37 super(BaseKuryrScenarioTest, cls).setup_clients()
38 cls.k8s_client = k8s_client
39
40 @classmethod
41 def resource_setup(cls):
42 super(BaseKuryrScenarioTest, cls).resource_setup()
43 cls.pod_fips = []
44 # TODO (dmellado): Config k8s client in a cleaner way
45 k8s_config.load_kube_config()
46
47 @classmethod
48 def resource_cleanup(cls):
49 super(BaseKuryrScenarioTest, cls).resource_cleanup()
50 for fip in cls.pod_fips:
51 cls.os_admin.floating_ips_client.delete_floatingip(
52 fip['floatingip']['id'])
53
54 def create_pod(self, name=None, image='celebdor/kuryr-demo',
55 namespace="default"):
56 name = data_utils.rand_name(prefix='kuryr-pod')
57 pod = self.k8s_client.V1Pod()
58 pod.metadata = self.k8s_client.V1ObjectMeta(name=name)
59
60 container = self.k8s_client.V1Container()
61 container.image = image
62 container.args = ["sleep", "3600"]
63 container.name = name
64
65 spec = self.k8s_client.V1PodSpec()
66 spec.containers = [container]
67
68 pod.spec = spec
69 self.k8s_client.CoreV1Api().create_namespaced_pod(namespace=namespace,
70 body=pod)
71 status = ""
72 while status != "Running":
73 # TODO (dmellado) add timeout config to tempest plugin
74 time.sleep(1)
75 status = self.get_pod_status(name, namespace)
76
77 return name, pod
78
79 def delete_pod(self, pod_name, body=None, namespace="default"):
80 if body is None:
81 body = {}
82 self.k8s_client.CoreV1Api().delete_namespaced_pod(
83 name=pod_name,
84 body=body,
85 namespace=namespace)
86
87 def get_pod_ip(self, pod_name, namespace="default"):
88 pod_list = self.k8s_client.CoreV1Api().list_namespaced_pod(
89 namespace=namespace)
90 for pod in pod_list.items:
91 if pod.metadata.name == pod_name:
92 return pod.status.pod_ip
93
94 def get_pod_status(self, pod_name, namespace="default"):
95 pod_list = self.k8s_client.CoreV1Api().list_namespaced_pod(
96 namespace=namespace)
97 for pod in pod_list.items:
98 if pod.metadata.name == pod_name:
99 return pod.status.phase
100
101 def get_pod_port(self, pod_name, namespace="default"):
102 # TODO(gcheresh) get pod port using container id, as kuryr this would
103 # depend on port_debug kuryr feature
104 port_list = self.os_admin.ports_client.list_ports()
105 for port in port_list['ports']:
106 if pod_name == port['name']:
107 return port
108
109 def assign_fip_to_pod(self, pod_name, namespace="default"):
110 ext_net_id = CONF.network.public_network_id
111 pod_fip = self.os_admin.floating_ips_client.create_floatingip(
112 floating_network_id=ext_net_id,
113 tenant_id=self.get_project_id(),
114 port_id=self.get_pod_port(pod_name)['id'])
115 self.pod_fips.append(pod_fip)
116 return pod_fip
117
118 def get_project_id(self, project_name='k8s'):
119 projects_list = self.os_admin.projects_client.list_projects()
120 for project in projects_list['projects']:
121 if project_name == project['name']:
122 return project['id']
diff --git a/kuryr_tempest_plugin/tests/scenario/test_cross_ping.py b/kuryr_tempest_plugin/tests/scenario/test_cross_ping.py
new file mode 100644
index 0000000..5687df2
--- /dev/null
+++ b/kuryr_tempest_plugin/tests/scenario/test_cross_ping.py
@@ -0,0 +1,66 @@
1# Copyright 2017 Red Hat, Inc.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15import testtools
16
17from oslo_log import log as logging
18from tempest import config
19from tempest.lib import decorators
20from tempest.lib import exceptions
21from tempest.lib.common.utils import data_utils
22
23from kuryr_tempest_plugin.tests.scenario import base
24
25LOG = logging.getLogger(__name__)
26CONF = config.CONF
27
28
29class TestCrossPingScenario(base.BaseKuryrScenarioTest):
30
31 @classmethod
32 def skip_checks(cls):
33 super(TestCrossPingScenario, cls).skip_checks()
34 if not CONF.network_feature_enabled.floating_ips:
35 raise cls.skipException("Floating ips are not available")
36
37 @decorators.idempotent_id('bddf5441-1244-449d-a125-b5fddfb1a1a8')
38 def test_vm_pod_ping(self):
39 keypair = self.create_keypair()
40 security_groups = [
41 {'name': self._create_security_group()['name']}
42 ]
43 server = self.create_server(name=data_utils.rand_name(prefix='kuryr'),
44 key_name=keypair['name'],
45 security_groups=security_groups)
46 fip = self.create_floating_ip(server)
47
48 pod_name, pod = self.create_pod()
49 self.addCleanup(self.delete_pod, pod_name, pod)
50 pod_fip = self.assign_fip_to_pod(pod_name)
51
52 ssh_client = self.get_remote_client(fip['floating_ip_address'],
53 private_key=keypair['private_key'])
54 cmd = ("ping -c1 -w1 %s &> /dev/null; echo $?" %
55 pod_fip['floatingip']['floating_ip_address'])
56
57 try:
58 result = ssh_client.exec_command(cmd)
59 if result:
60 msg = ('Failed while trying to ping. Could not ping '
61 'from host "%s" to "%s".' % (
62 fip['floating_ip_address'],
63 pod_fip['floatingip']['floating_ip_address']))
64 self.assertEqual('0', result.rstrip('\n'))
65 except exceptions.SSHExecCommandFailed:
66 LOG.error("Couldn't ping server")