Browse Source

Add lbaas test

Change-Id: Ie4e1a72af612a00a8d72968f6f0534761aae6bda
Georgy Dyuldin 1 year ago
parent
commit
84cd80fc4b

+ 1
- 0
plugin_test/vapor/vapor/conftest.py View File

@@ -13,6 +13,7 @@ from vapor.fixtures.dns import *  # noqa
13 13
 from vapor.fixtures.images import *  # noqa
14 14
 from vapor.fixtures.instance_ip import *  # noqa
15 15
 from vapor.fixtures.ipams import *  # noqa
16
+from vapor.fixtures.lbaas import *  # noqa
16 17
 from vapor.fixtures.networks import *  # noqa
17 18
 from vapor.fixtures.nodes import *  # noqa
18 19
 from vapor.fixtures.policies import *  # noqa

+ 58
- 0
plugin_test/vapor/vapor/fixtures/lbaas.py View File

@@ -0,0 +1,58 @@
1
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
2
+# not use this file except in compliance with the License. You may obtain
3
+# a copy of the License at
4
+
5
+#     http://www.apache.org/licenses/LICENSE-2.0
6
+
7
+# Unless required by applicable law or agreed to in writing, software
8
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10
+# License for the specific language governing permissions and limitations
11
+# under the License.
12
+
13
+import functools
14
+
15
+import pytest
16
+from stepler.third_party import utils
17
+
18
+from vapor.helpers import lbaas
19
+
20
+
21
+@pytest.fixture
22
+def lbaas_steps(neutron_client):
23
+    return lbaas.LBaaSSteps(neutron_client)
24
+
25
+
26
+@pytest.fixture
27
+def loadbalancer(request, lbaas_steps, net_subnet_router):
28
+    """Fixture to create loadbalancer on default subnet."""
29
+    name = next(utils.generate_ids('lb'))
30
+    request.addfinalizer(
31
+        functools.partial(lbaas_steps.cleanup_lbs, names=[name]))
32
+    return lbaas_steps.create_lb(name, net_subnet_router[1])
33
+
34
+
35
+@pytest.fixture
36
+def lb_listener(request, lbaas_steps, loadbalancer):
37
+    """Fixture to create lbaas HTTP listener."""
38
+    name = next(utils.generate_ids('lb_listener'))
39
+    request.addfinalizer(
40
+        functools.partial(lbaas_steps.cleanup_listeners, names=[name]))
41
+    return lbaas_steps.create_listener(
42
+        name=name,
43
+        loadbalancer=loadbalancer,
44
+        protocol="HTTP",
45
+        protocol_port=80)
46
+
47
+
48
+@pytest.fixture
49
+def lb_pool(request, lbaas_steps, lb_listener):
50
+    """Fixture to create lbaas pool."""
51
+    name = next(utils.generate_ids('lb_pool'))
52
+    request.addfinalizer(
53
+        functools.partial(lbaas_steps.cleanup_pools, names=[name]))
54
+    return lbaas_steps.create_pool(
55
+        name=name,
56
+        listener=lb_listener,
57
+        protocol="HTTP",
58
+        lb_algorithm="ROUND_ROBIN")

+ 191
- 0
plugin_test/vapor/vapor/helpers/lbaas.py View File

@@ -0,0 +1,191 @@
1
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
2
+# not use this file except in compliance with the License. You may obtain
3
+# a copy of the License at
4
+
5
+#     http://www.apache.org/licenses/LICENSE-2.0
6
+
7
+# Unless required by applicable law or agreed to in writing, software
8
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10
+# License for the specific language governing permissions and limitations
11
+# under the License.
12
+
13
+from hamcrest import (assert_that, equal_to, is_, is_not, contains,
14
+                      has_entries, starts_with, has_length)  # noqa: H310
15
+import requests
16
+from stepler import base
17
+from stepler.third_party import waiter
18
+
19
+from vapor import settings
20
+
21
+
22
+class LBaaSSteps(base.BaseSteps):
23
+    """LBaaS steps."""
24
+
25
+    def _check_presence(self, objs, list_method, expected_presence, timeout=0):
26
+        def _check_presence():
27
+            all_objs = list_method()
28
+            matcher = is_
29
+            if not expected_presence:
30
+                matcher = is_not
31
+            return waiter.expect_that(
32
+                all_objs,
33
+                matcher(
34
+                    contains(*[has_entries(id=obj['id']) for obj in objs])))
35
+
36
+        waiter.wait(_check_presence, timeout_seconds=timeout)
37
+
38
+    def create_lb(self, name, subnet, **kwargs):
39
+        """Create loadbalancer and wait it became to online."""
40
+        loadbalancer = self._client.lbaas_loadbalancers.create(
41
+            name=name, vip_subnet_id=subnet['id'], **kwargs)
42
+
43
+        loadbalancer = self.check_lb_provisioning_status(
44
+            loadbalancer, timeout=settings.LBAAS_ONLINE_TIMEOUT)
45
+
46
+        return loadbalancer
47
+
48
+    def delete_lbs(self, loadbalancers):
49
+        """Delete loadbalancer and wait for deletion to be completed."""
50
+        for loadbalancer in loadbalancers:
51
+            self._client.lbaas_loadbalancers.delete(loadbalancer['id'])
52
+
53
+        self.check_lbs_presence(
54
+            loadbalancers, timeout=settings.LBAAS_DELETE_TIMEOUT)
55
+
56
+    def check_lb_provisioning_status(self,
57
+                                     loadbalancer,
58
+                                     expected_status="ACTIVE",
59
+                                     timeout=0):
60
+        """Check that loadbalancer has expected provisioning status."""
61
+
62
+        def _check_status():
63
+            lb = self._client.lbaas_loadbalancers.get(loadbalancer['id'])
64
+            waiter.expect_that(lb['provisioning_status'],
65
+                               is_not(starts_with('PENDING_')))
66
+            return lb
67
+
68
+        loadbalancer = waiter.wait(_check_status, timeout_seconds=timeout)
69
+        assert_that(loadbalancer['provisioning_status'],
70
+                    equal_to(expected_status))
71
+        return loadbalancer
72
+
73
+    def check_lbs_presence(self,
74
+                           loadbalancers,
75
+                           expected_presence=True,
76
+                           timeout=0):
77
+        """Check that loadbalancer is present (or not)."""
78
+        self._check_presence(
79
+            loadbalancers,
80
+            self._client.lbaas_loadbalancers.list,
81
+            expected_presence,
82
+            timeout=timeout)
83
+
84
+    def cleanup_lbs(self, names):
85
+        """Remove all loadbalancers by names list."""
86
+        loadbalancers = []
87
+        for name in names:
88
+            for loadbalancer in self._client.lbaas_loadbalancers.find_all(
89
+                    name=name):
90
+                loadbalancers.append(loadbalancer)
91
+                self._client.lbaas_loadbalancers.delete(loadbalancer['id'])
92
+
93
+        self.check_lbs_presence(
94
+            loadbalancers,
95
+            expected_presence=False,
96
+            timeout=settings.LBAAS_DELETE_TIMEOUT)
97
+
98
+    def create_listener(self, name, loadbalancer, protocol, protocol_port,
99
+                        **kwargs):
100
+        """Create LBaaS listener."""
101
+        listener = self._client.lbaas_listeners.create(
102
+            name=name,
103
+            loadbalancer_id=loadbalancer['id'],
104
+            protocol=protocol,
105
+            protocol_port=protocol_port,
106
+            **kwargs)
107
+
108
+        self.check_lb_provisioning_status(
109
+            loadbalancer, timeout=settings.LBAAS_ONLINE_TIMEOUT)
110
+
111
+        return listener
112
+
113
+    def delete_listener(self, listener):
114
+        """Delete LBaaS listener."""
115
+        listener = self._client.lbaas_listeners.get(listener['id'])
116
+        loadbalancers = listener['loadbalancers']
117
+        self._client.lbaas_listeners.delete(listener['id'])
118
+        for lb in loadbalancers:
119
+            self.check_lb_provisioning_status(
120
+                lb, timeout=settings.LBAAS_ONLINE_TIMEOUT)
121
+
122
+    def cleanup_listeners(self, names):
123
+        """Remove all listeners by names list."""
124
+        for name in names:
125
+            for listener in self._client.lbaas_listeners.find_all(name=name):
126
+                self.delete_listener(listener)
127
+
128
+    def create_pool(self, name, listener, protocol, lb_algorithm, **kwargs):
129
+        """Create LBaaS pool."""
130
+        pool = self._client.lbaas_pools.create(
131
+            name=name,
132
+            listener_id=listener['id'],
133
+            protocol=protocol,
134
+            lb_algorithm=lb_algorithm,
135
+            **kwargs)
136
+
137
+        for loadbalancer in pool['loadbalancers']:
138
+            self.check_lb_provisioning_status(
139
+                loadbalancer, timeout=settings.LBAAS_ONLINE_TIMEOUT)
140
+
141
+        return pool
142
+
143
+    def delete_pool(self, pool):
144
+        """Create LBaaS pool."""
145
+        self._client.lbaas_pools.delete(pool['id'])
146
+        for loadbalancer in pool['loadbalancers']:
147
+            self.check_lb_provisioning_status(
148
+                loadbalancer, timeout=settings.LBAAS_ONLINE_TIMEOUT)
149
+
150
+    def cleanup_pools(self, names):
151
+        """Remove all pools by names list."""
152
+        loadbalancers = []
153
+        for name in names:
154
+            for pool in self._client.lbaas_pools.find_all(name=name):
155
+                self._client.lbaas_pools.delete(pool['id'])
156
+                loadbalancers.extend(pool['loadbalancers'])
157
+
158
+        for loadbalancer in loadbalancers:
159
+            self.check_lb_provisioning_status(
160
+                loadbalancer, timeout=settings.LBAAS_ONLINE_TIMEOUT)
161
+
162
+    def create_member(self, pool, address, protocol_port, subnet, **kwargs):
163
+        """Create LBaaS pool member."""
164
+        member = pool.members.create(
165
+            address=address,
166
+            protocol_port=protocol_port,
167
+            subnet_id=subnet['id'],
168
+            **kwargs)
169
+
170
+        for loadbalancer in pool['loadbalancers']:
171
+            self.check_lb_provisioning_status(
172
+                loadbalancer, timeout=settings.LBAAS_ONLINE_TIMEOUT)
173
+
174
+        return member
175
+
176
+    def delete_member(self, pool, member):
177
+        """Delete LBaaS pool member."""
178
+        pool.members.delete(member['id'])
179
+
180
+        for loadbalancer in pool['loadbalancers']:
181
+            self.check_lb_provisioning_status(
182
+                loadbalancer, timeout=settings.LBAAS_ONLINE_TIMEOUT)
183
+
184
+    def check_balancing(self, ip, port, expected_count):
185
+        """Check that responses contains `expected_counts` variants."""
186
+        responses = set()
187
+        for _ in range(expected_count * 3):
188
+            r = requests.get("http://{}:{}/".format(ip, port))
189
+            r.raise_for_status()
190
+            responses.add(r.text)
191
+        assert_that(responses, has_length(expected_count))

+ 10
- 3
plugin_test/vapor/vapor/settings.py View File

@@ -221,12 +221,19 @@ SECURITY_GROUP_SSH_PING_RULES = (stepler_config.SECURITY_GROUP_SSH_RULES +
221 221
 
222 222
 DPDK_ENABLED_GROUP = u'Network devices using DPDK-compatible driver'
223 223
 
224
-
225
-
226 224
 # Service chaining
227 225
 # TODO(gdyuldin): relace with real URL
228 226
 NAT_SERVICE_IMAGE_URL = os.environ.get('NAT_SERVICE_IMAGE_URL',
229 227
                                        '/home/jenkins/nat.qcow2')
230 228
 SERVICE_INSTANCE_CREATE_TIMEOUT = 2 * 60
231 229
 SERVICE_INSTANCE_BOOT_TIMEOUT = 10 * 60
232
-SERVICE_INSTANCE_BOOT_DONE_PATTERN = 'Cloud-init .+ finished'
230
+SERVICE_INSTANCE_BOOT_DONE_PATTERN = 'Cloud-init .+ finished'
231
+
232
+# LBAAS
233
+LBAAS_ONLINE_TIMEOUT = 5 * 60
234
+LBAAS_DELETE_TIMEOUT = 2 * 60
235
+
236
+HTTP_SERVER_CMD = (
237
+    'while true; do '
238
+    'echo -e "HTTP/1.0 200 OK\\r\\nContent-Length: $(hostname | wc -c)\\r\\n\\r\\n$(hostname)" | nc -l -p {port}; '  # noqa
239
+    'done')

+ 2
- 1
plugin_test/vapor/vapor/tests/test_dpdk.py View File

@@ -70,7 +70,8 @@ def test_contrail_vrouter_dpdk_cpu_usage(os_faults_steps, computes):
70 70
 
71 71
 
72 72
 @pytest.mark.parametrize(
73
-    'flavor', [dict(ram=1024, metadata={"hw:mem_page_size": "large"})], indirect=True)
73
+    'flavor', [dict(ram=1024, metadata={"hw:mem_page_size": "large"})],
74
+    indirect=True)
74 75
 @pytest.mark.usefixtures('flavor')
75 76
 def test_vrouter_create_interface(request, os_faults_steps, computes):
76 77
     """Verify if vRouter creates interface after creation of a virtual machine.

+ 83
- 0
plugin_test/vapor/vapor/tests/test_lbaas.py View File

@@ -0,0 +1,83 @@
1
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
2
+# not use this file except in compliance with the License. You may obtain
3
+# a copy of the License at
4
+
5
+#     http://www.apache.org/licenses/LICENSE-2.0
6
+
7
+# Unless required by applicable law or agreed to in writing, software
8
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10
+# License for the specific language governing permissions and limitations
11
+# under the License.
12
+
13
+from six import moves
14
+from stepler import config as stepler_config
15
+
16
+from vapor import settings
17
+
18
+
19
+def test_loadbalancer_after_deleting_server(
20
+        flavor, cirros_image, net_subnet_router, security_group, loadbalancer,
21
+        create_floating_ip, port_steps, server_steps, lb_listener, lb_pool,
22
+        neutron_security_group_rule_steps, lbaas_steps):
23
+    """Check loadbalancer after deleting server.
24
+
25
+    Steps:
26
+        #. Create network, subnet
27
+        #. Create loadbalancer
28
+        #. Create lbaas listener
29
+        #. Create lbaas pool
30
+        #. Create security group with allow ping rule
31
+        #. Create floating IP on loadbalancer port
32
+        #. Create 2 servers with simple HTTP server
33
+        #. Add servers' IPs to loadbalancer pool
34
+        #. Check that loadbalancer routes HTTP queries between servers
35
+        #. Delete one of servers
36
+        #. Check that loadbalancer pass all HTTP queries to single alive server
37
+    """
38
+    port = 80
39
+    neutron_security_group_rule_steps.add_rule_to_group(
40
+        security_group['id'],
41
+        direction='ingress',
42
+        protocol='tcp',
43
+        port_range_min=port,
44
+        port_range_max=port)
45
+
46
+    http_server_cmd = settings.HTTP_SERVER_CMD.format(port=port)
47
+
48
+    userdata = "\n".join([
49
+        '#!/bin/sh -v',
50
+        'screen -dmS daemon /bin/sh -c {cmd}',
51
+        'screen -ls',
52
+        'echo {done_marker}',
53
+    ]).format(
54
+        cmd=moves.shlex_quote(http_server_cmd),
55
+        done_marker=stepler_config.USERDATA_DONE_MARKER)
56
+    network, subnet, _ = net_subnet_router
57
+    servers = server_steps.create_servers(
58
+        count=2,
59
+        image=cirros_image,
60
+        flavor=flavor,
61
+        networks=[network],
62
+        security_groups=[security_group],
63
+        userdata=userdata)
64
+    for server in servers:
65
+        server_steps.check_server_log_contains_record(
66
+            server,
67
+            stepler_config.USERDATA_DONE_MARKER,
68
+            timeout=stepler_config.USERDATA_EXECUTING_TIMEOUT)
69
+
70
+        ip = server_steps.get_fixed_ip(server)
71
+        lbaas_steps.create_member(lb_pool, ip, port, subnet)
72
+
73
+    vip_port = {'id': loadbalancer['vip_port_id']}
74
+    port_steps.update(vip_port, security_groups=[security_group['id']])
75
+    floating_ip = create_floating_ip(port=vip_port)
76
+
77
+    lbaas_steps.check_balancing(
78
+        floating_ip['floating_ip_address'], port, expected_count=2)
79
+
80
+    server_steps.delete_servers(servers[1:])
81
+
82
+    lbaas_steps.check_balancing(
83
+        floating_ip['floating_ip_address'], port, expected_count=1)

Loading…
Cancel
Save