blob: 0e6eba431dd02271f9db3ba45c5e7b40571e5d3c [file] [log] [blame]
Jude Cross986e3f52017-07-24 14:57:20 -07001# Copyright 2018 Rackspace US Inc. All rights reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may
4# not use this file except in compliance with the License. You may obtain
5# 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, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations
13# under the License.
14
15import ipaddress
16import pkg_resources
17import random
Adam Harwellcd72b562018-05-07 11:37:22 -070018import requests
Jude Cross986e3f52017-07-24 14:57:20 -070019import shlex
20import six
21import string
22import subprocess
23import tempfile
Adam Harwellcd72b562018-05-07 11:37:22 -070024import time
Jude Cross986e3f52017-07-24 14:57:20 -070025
26from oslo_log import log as logging
27from oslo_utils import uuidutils
28from tempest import config
29from tempest.lib.common.utils import data_utils
30from tempest.lib.common.utils.linux import remote_client
Jude Cross986e3f52017-07-24 14:57:20 -070031from tempest.lib import exceptions
32from tempest import test
33
34from octavia_tempest_plugin import clients
35from octavia_tempest_plugin.common import constants as const
36from octavia_tempest_plugin.tests import validators
37from octavia_tempest_plugin.tests import waiters
38
39CONF = config.CONF
40LOG = logging.getLogger(__name__)
41
42
43class LoadBalancerBaseTest(test.BaseTestCase):
44 """Base class for load balancer tests."""
45
46 # Setup cls.os_roles_lb_member. cls.os_primary, cls.os_roles_lb_member,
47 # and cls.os_roles_lb_admin credentials.
48 credentials = ['admin', 'primary',
49 ['lb_member', CONF.load_balancer.member_role],
50 ['lb_member2', CONF.load_balancer.member_role],
51 ['lb_admin', CONF.load_balancer.admin_role]]
52
53 client_manager = clients.ManagerV2
Adam Harwelle029af22018-05-24 17:13:28 -070054 webserver1_response = 1
55 webserver2_response = 5
Jude Cross986e3f52017-07-24 14:57:20 -070056
57 @classmethod
58 def skip_checks(cls):
59 """Check if we should skip all of the children tests."""
60 super(LoadBalancerBaseTest, cls).skip_checks()
61
62 service_list = {
63 'load_balancer': CONF.service_available.load_balancer,
64 }
65
66 live_service_list = {
67 'compute': CONF.service_available.nova,
68 'image': CONF.service_available.glance,
69 'neutron': CONF.service_available.neutron
70 }
71
72 if not CONF.load_balancer.test_with_noop:
73 service_list.update(live_service_list)
74
75 for service, available in service_list.items():
76 if not available:
77 skip_msg = ("{0} skipped as {1} serivce is not "
78 "available.".format(cls.__name__, service))
79 raise cls.skipException(skip_msg)
80
81 # We must be able to reach our VIP and instances
82 if not (CONF.network.project_networks_reachable
83 or CONF.network.public_network_id):
84 msg = ('Either project_networks_reachable must be "true", or '
85 'public_network_id must be defined.')
86 raise cls.skipException(msg)
87
88 @classmethod
89 def setup_credentials(cls):
90 """Setup test credentials and network resources."""
91 # Do not auto create network resources
92 cls.set_network_resources()
93 super(LoadBalancerBaseTest, cls).setup_credentials()
94
95 @classmethod
96 def setup_clients(cls):
97 """Setup client aliases."""
98 super(LoadBalancerBaseTest, cls).setup_clients()
99 cls.lb_mem_float_ip_client = cls.os_roles_lb_member.floating_ips_client
100 cls.lb_mem_keypairs_client = cls.os_roles_lb_member.keypairs_client
101 cls.lb_mem_net_client = cls.os_roles_lb_member.networks_client
102 cls.lb_mem_ports_client = cls.os_roles_lb_member.ports_client
103 cls.lb_mem_routers_client = cls.os_roles_lb_member.routers_client
104 cls.lb_mem_SG_client = cls.os_roles_lb_member.security_groups_client
105 cls.lb_mem_SGr_client = (
106 cls.os_roles_lb_member.security_group_rules_client)
107 cls.lb_mem_servers_client = cls.os_roles_lb_member.servers_client
108 cls.lb_mem_subnet_client = cls.os_roles_lb_member.subnets_client
109 cls.mem_lb_client = cls.os_roles_lb_member.loadbalancer_client
Jude Crossfbbd2b42017-08-09 15:21:04 -0700110 cls.mem_listener_client = cls.os_roles_lb_member.listener_client
Adam Harwell8ffce3e2018-05-01 21:18:44 -0700111 cls.mem_pool_client = cls.os_roles_lb_member.pool_client
Adam Harwellde3e0542018-05-03 18:21:06 -0700112 cls.mem_member_client = cls.os_roles_lb_member.member_client
Adam Harwell60ed9d92018-05-10 13:23:13 -0700113 cls.mem_healthmonitor_client = (
114 cls.os_roles_lb_member.healthmonitor_client)
Adam Harwell446f8be2018-05-24 16:51:03 -0700115 cls.mem_l7policy_client = cls.os_roles_lb_member.l7policy_client
Adam Harwelle029af22018-05-24 17:13:28 -0700116 cls.mem_l7rule_client = cls.os_roles_lb_member.l7rule_client
Adam Harwelldfc11ee2018-05-30 09:38:55 -0700117 cls.mem_amphora_client = cls.os_roles_lb_member.amphora_client
Jude Cross986e3f52017-07-24 14:57:20 -0700118
119 @classmethod
120 def resource_setup(cls):
121 """Setup resources needed by the tests."""
122 super(LoadBalancerBaseTest, cls).resource_setup()
123
124 conf_lb = CONF.load_balancer
125
126 if conf_lb.test_subnet_override and not conf_lb.test_network_override:
127 raise exceptions.InvalidConfiguration(
128 "Configuration value test_network_override must be "
129 "specified if test_subnet_override is used.")
130
131 show_subnet = cls.lb_mem_subnet_client.show_subnet
132 if CONF.load_balancer.test_with_noop:
133 cls.lb_member_vip_net = {'id': uuidutils.generate_uuid()}
134 cls.lb_member_vip_subnet = {'id': uuidutils.generate_uuid()}
135 cls.lb_member_1_net = {'id': uuidutils.generate_uuid()}
136 cls.lb_member_1_subnet = {'id': uuidutils.generate_uuid()}
137 cls.lb_member_2_net = {'id': uuidutils.generate_uuid()}
138 cls.lb_member_2_subnet = {'id': uuidutils.generate_uuid()}
139 if CONF.load_balancer.test_with_ipv6:
140 cls.lb_member_vip_ipv6_subnet = {'id':
141 uuidutils.generate_uuid()}
142 cls.lb_member_1_ipv6_subnet = {'id': uuidutils.generate_uuid()}
143 cls.lb_member_2_ipv6_subnet = {'id': uuidutils.generate_uuid()}
144 return
145 elif CONF.load_balancer.test_network_override:
146 if conf_lb.test_subnet_override:
147 override_subnet = show_subnet(conf_lb.test_subnet_override)
148 else:
149 override_subnet = None
150
151 show_net = cls.lb_mem_net_client.show_network
152 override_network = show_net(conf_lb.test_network_override)
153 override_network = override_network.get('network')
154
155 cls.lb_member_vip_net = override_network
156 cls.lb_member_vip_subnet = override_subnet
157 cls.lb_member_1_net = override_network
158 cls.lb_member_1_subnet = override_subnet
159 cls.lb_member_2_net = override_network
160 cls.lb_member_2_subnet = override_subnet
161
162 if (CONF.load_balancer.test_with_ipv6 and
163 conf_lb.test_IPv6_subnet_override):
164 override_ipv6_subnet = show_subnet(
165 conf_lb.test_IPv6_subnet_override)
166 cls.lb_member_vip_ipv6_subnet = override_ipv6_subnet
167 cls.lb_member_1_ipv6_subnet = override_ipv6_subnet
168 cls.lb_member_2_ipv6_subnet = override_ipv6_subnet
169 else:
170 cls.lb_member_vip_ipv6_subnet = None
171 cls.lb_member_1_ipv6_subnet = None
172 cls.lb_member_2_ipv6_subnet = None
173 else:
174 cls._create_networks()
175
176 LOG.debug('Octavia Setup: lb_member_vip_net = {}'.format(
177 cls.lb_member_vip_net[const.ID]))
178 if cls.lb_member_vip_subnet:
179 LOG.debug('Octavia Setup: lb_member_vip_subnet = {}'.format(
180 cls.lb_member_vip_subnet[const.ID]))
181 LOG.debug('Octavia Setup: lb_member_1_net = {}'.format(
182 cls.lb_member_1_net[const.ID]))
183 if cls.lb_member_1_subnet:
184 LOG.debug('Octavia Setup: lb_member_1_subnet = {}'.format(
185 cls.lb_member_1_subnet[const.ID]))
186 LOG.debug('Octavia Setup: lb_member_2_net = {}'.format(
187 cls.lb_member_2_net[const.ID]))
188 if cls.lb_member_2_subnet:
189 LOG.debug('Octavia Setup: lb_member_2_subnet = {}'.format(
190 cls.lb_member_2_subnet[const.ID]))
191 if cls.lb_member_vip_ipv6_subnet:
192 LOG.debug('Octavia Setup: lb_member_vip_ipv6_subnet = {}'.format(
193 cls.lb_member_vip_ipv6_subnet[const.ID]))
194 if cls.lb_member_1_ipv6_subnet:
195 LOG.debug('Octavia Setup: lb_member_1_ipv6_subnet = {}'.format(
196 cls.lb_member_1_ipv6_subnet[const.ID]))
197 if cls.lb_member_2_ipv6_subnet:
198 LOG.debug('Octavia Setup: lb_member_2_ipv6_subnet = {}'.format(
199 cls.lb_member_2_ipv6_subnet[const.ID]))
200
Jude Cross986e3f52017-07-24 14:57:20 -0700201 @classmethod
202 def _create_networks(cls):
203 """Creates networks, subnets, and routers used in tests.
204
205 The following are expected to be defined and available to the tests:
206 cls.lb_member_vip_net
207 cls.lb_member_vip_subnet
208 cls.lb_member_vip_ipv6_subnet (optional)
209 cls.lb_member_1_net
210 cls.lb_member_1_subnet
211 cls.lb_member_1_ipv6_subnet (optional)
212 cls.lb_member_2_net
213 cls.lb_member_2_subnet
214 cls.lb_member_2_ipv6_subnet (optional)
215 """
216
217 # Create tenant VIP network
218 network_kwargs = {
219 'name': data_utils.rand_name("lb_member_vip_network")}
220 if CONF.network_feature_enabled.port_security:
221 # Note: Allowed Address Pairs requires port security
222 network_kwargs['port_security_enabled'] = True
223 result = cls.lb_mem_net_client.create_network(**network_kwargs)
224 cls.lb_member_vip_net = result['network']
225 LOG.info('lb_member_vip_net: {}'.format(cls.lb_member_vip_net))
226 cls.addClassResourceCleanup(
227 waiters.wait_for_not_found,
228 cls.lb_mem_net_client.delete_network,
229 cls.lb_mem_net_client.show_network,
230 cls.lb_member_vip_net['id'])
231
232 # Create tenant VIP subnet
233 subnet_kwargs = {
234 'name': data_utils.rand_name("lb_member_vip_subnet"),
235 'network_id': cls.lb_member_vip_net['id'],
236 'cidr': CONF.load_balancer.vip_subnet_cidr,
237 'ip_version': 4}
238 result = cls.lb_mem_subnet_client.create_subnet(**subnet_kwargs)
239 cls.lb_member_vip_subnet = result['subnet']
240 LOG.info('lb_member_vip_subnet: {}'.format(cls.lb_member_vip_subnet))
241 cls.addClassResourceCleanup(
242 waiters.wait_for_not_found,
243 cls.lb_mem_subnet_client.delete_subnet,
244 cls.lb_mem_subnet_client.show_subnet,
245 cls.lb_member_vip_subnet['id'])
246
247 # Create tenant VIP IPv6 subnet
248 if CONF.load_balancer.test_with_ipv6:
249 subnet_kwargs = {
250 'name': data_utils.rand_name("lb_member_vip_ipv6_subnet"),
251 'network_id': cls.lb_member_vip_net['id'],
252 'cidr': CONF.load_balancer.vip_ipv6_subnet_cidr,
253 'ip_version': 6}
254 result = cls.lb_mem_subnet_client.create_subnet(**subnet_kwargs)
255 cls.lb_member_vip_ipv6_subnet = result['subnet']
256 LOG.info('lb_member_vip_ipv6_subnet: {}'.format(
257 cls.lb_member_vip_ipv6_subnet))
258 cls.addClassResourceCleanup(
259 waiters.wait_for_not_found,
260 cls.lb_mem_subnet_client.delete_subnet,
261 cls.lb_mem_subnet_client.show_subnet,
262 cls.lb_member_vip_ipv6_subnet['id'])
263
264 # Create tenant member 1 network
265 network_kwargs = {
266 'name': data_utils.rand_name("lb_member_1_network")}
267 if CONF.network_feature_enabled.port_security:
268 if CONF.load_balancer.enable_security_groups:
269 network_kwargs['port_security_enabled'] = True
270 else:
271 network_kwargs['port_security_enabled'] = False
272 result = cls.lb_mem_net_client.create_network(**network_kwargs)
273 cls.lb_member_1_net = result['network']
274 LOG.info('lb_member_1_net: {}'.format(cls.lb_member_1_net))
275 cls.addClassResourceCleanup(
276 waiters.wait_for_not_found,
277 cls.lb_mem_net_client.delete_network,
278 cls.lb_mem_net_client.show_network,
279 cls.lb_member_1_net['id'])
280
281 # Create tenant member 1 subnet
282 subnet_kwargs = {
283 'name': data_utils.rand_name("lb_member_1_subnet"),
284 'network_id': cls.lb_member_1_net['id'],
285 'cidr': CONF.load_balancer.member_1_ipv4_subnet_cidr,
286 'ip_version': 4}
287 result = cls.lb_mem_subnet_client.create_subnet(**subnet_kwargs)
288 cls.lb_member_1_subnet = result['subnet']
289 LOG.info('lb_member_1_subnet: {}'.format(cls.lb_member_1_subnet))
290 cls.addClassResourceCleanup(
291 waiters.wait_for_not_found,
292 cls.lb_mem_subnet_client.delete_subnet,
293 cls.lb_mem_subnet_client.show_subnet,
294 cls.lb_member_1_subnet['id'])
295
296 # Create tenant member 1 ipv6 subnet
297 if CONF.load_balancer.test_with_ipv6:
298 subnet_kwargs = {
299 'name': data_utils.rand_name("lb_member_1_ipv6_subnet"),
300 'network_id': cls.lb_member_1_net['id'],
301 'cidr': CONF.load_balancer.member_1_ipv6_subnet_cidr,
302 'ip_version': 6}
303 result = cls.lb_mem_subnet_client.create_subnet(**subnet_kwargs)
304 cls.lb_member_1_ipv6_subnet = result['subnet']
305 LOG.info('lb_member_1_ipv6_subnet: {}'.format(
306 cls.lb_member_1_ipv6_subnet))
307 cls.addClassResourceCleanup(
308 waiters.wait_for_not_found,
309 cls.lb_mem_subnet_client.delete_subnet,
310 cls.lb_mem_subnet_client.show_subnet,
311 cls.lb_member_1_ipv6_subnet['id'])
312
313 # Create tenant member 2 network
314 network_kwargs = {
315 'name': data_utils.rand_name("lb_member_2_network")}
316 if CONF.network_feature_enabled.port_security:
317 if CONF.load_balancer.enable_security_groups:
318 network_kwargs['port_security_enabled'] = True
319 else:
320 network_kwargs['port_security_enabled'] = False
321 result = cls.lb_mem_net_client.create_network(**network_kwargs)
322 cls.lb_member_2_net = result['network']
323 LOG.info('lb_member_2_net: {}'.format(cls.lb_member_2_net))
324 cls.addClassResourceCleanup(
325 waiters.wait_for_not_found,
326 cls.lb_mem_net_client.delete_network,
327 cls.lb_mem_net_client.show_network,
328 cls.lb_member_2_net['id'])
329
330 # Create tenant member 2 subnet
331 subnet_kwargs = {
332 'name': data_utils.rand_name("lb_member_2_subnet"),
333 'network_id': cls.lb_member_2_net['id'],
334 'cidr': CONF.load_balancer.member_2_ipv4_subnet_cidr,
335 'ip_version': 4}
336 result = cls.lb_mem_subnet_client.create_subnet(**subnet_kwargs)
337 cls.lb_member_2_subnet = result['subnet']
338 LOG.info('lb_member_2_subnet: {}'.format(cls.lb_member_2_subnet))
339 cls.addClassResourceCleanup(
340 waiters.wait_for_not_found,
341 cls.lb_mem_subnet_client.delete_subnet,
342 cls.lb_mem_subnet_client.show_subnet,
343 cls.lb_member_2_subnet['id'])
344
345 # Create tenant member 2 ipv6 subnet
346 if CONF.load_balancer.test_with_ipv6:
347 subnet_kwargs = {
348 'name': data_utils.rand_name("lb_member_2_ipv6_subnet"),
349 'network_id': cls.lb_member_2_net['id'],
350 'cidr': CONF.load_balancer.member_2_ipv6_subnet_cidr,
351 'ip_version': 6}
352 result = cls.lb_mem_subnet_client.create_subnet(**subnet_kwargs)
353 cls.lb_member_2_ipv6_subnet = result['subnet']
354 LOG.info('lb_member_2_ipv6_subnet: {}'.format(
355 cls.lb_member_2_ipv6_subnet))
356 cls.addClassResourceCleanup(
357 waiters.wait_for_not_found,
358 cls.lb_mem_subnet_client.delete_subnet,
359 cls.lb_mem_subnet_client.show_subnet,
360 cls.lb_member_2_ipv6_subnet['id'])
361
Adam Harwellcd72b562018-05-07 11:37:22 -0700362 @classmethod
Adam Harwell60ed9d92018-05-10 13:23:13 -0700363 def _setup_lb_network_kwargs(cls, lb_kwargs, ip_version=None):
364 if not ip_version:
365 ip_version = 6 if CONF.load_balancer.test_with_ipv6 else 4
Adam Harwellcd72b562018-05-07 11:37:22 -0700366 if cls.lb_member_vip_subnet:
367 ip_index = data_utils.rand_int_id(start=10, end=100)
368 if ip_version == 4:
369 network = ipaddress.IPv4Network(
370 six.u(CONF.load_balancer.vip_subnet_cidr))
371 lb_vip_address = str(network[ip_index])
372 subnet_id = cls.lb_member_vip_subnet[const.ID]
373 else:
374 network = ipaddress.IPv6Network(
375 six.u(CONF.load_balancer.vip_ipv6_subnet_cidr))
376 lb_vip_address = str(network[ip_index])
377 subnet_id = cls.lb_member_vip_ipv6_subnet[const.ID]
378 lb_kwargs[const.VIP_SUBNET_ID] = subnet_id
379 lb_kwargs[const.VIP_ADDRESS] = lb_vip_address
380 if CONF.load_balancer.test_with_noop:
381 lb_kwargs[const.VIP_NETWORK_ID] = (
382 cls.lb_member_vip_net[const.ID])
383 else:
384 lb_kwargs[const.VIP_NETWORK_ID] = cls.lb_member_vip_net[const.ID]
385 lb_kwargs[const.VIP_SUBNET_ID] = None
386
387
388class LoadBalancerBaseTestWithCompute(LoadBalancerBaseTest):
389 @classmethod
390 def resource_setup(cls):
391 super(LoadBalancerBaseTestWithCompute, cls).resource_setup()
392 # If validation is disabled in this cloud, we won't be able to
393 # start the webservers, so don't even boot them.
394 if not CONF.validation.run_validation:
395 return
396
397 # Create a keypair for the webservers
398 keypair_name = data_utils.rand_name('lb_member_keypair')
399 result = cls.lb_mem_keypairs_client.create_keypair(
400 name=keypair_name)
401 cls.lb_member_keypair = result['keypair']
402 LOG.info('lb_member_keypair: {}'.format(cls.lb_member_keypair))
403 cls.addClassResourceCleanup(
404 waiters.wait_for_not_found,
405 cls.lb_mem_keypairs_client.delete_keypair,
406 cls.lb_mem_keypairs_client.show_keypair,
407 keypair_name)
408
409 if (CONF.load_balancer.enable_security_groups and
410 CONF.network_feature_enabled.port_security):
411 # Set up the security group for the webservers
412 SG_name = data_utils.rand_name('lb_member_SG')
413 cls.lb_member_sec_group = (
414 cls.lb_mem_SG_client.create_security_group(
415 name=SG_name)['security_group'])
416 cls.addClassResourceCleanup(
417 waiters.wait_for_not_found,
418 cls.lb_mem_SG_client.delete_security_group,
419 cls.lb_mem_SG_client.show_security_group,
420 cls.lb_member_sec_group['id'])
421
422 # Create a security group rule to allow 80-81 (test webservers)
423 SGr = cls.lb_mem_SGr_client.create_security_group_rule(
424 direction='ingress',
425 security_group_id=cls.lb_member_sec_group['id'],
426 protocol='tcp',
427 ethertype='IPv4',
428 port_range_min=80,
429 port_range_max=81)['security_group_rule']
430 cls.addClassResourceCleanup(
431 waiters.wait_for_not_found,
432 cls.lb_mem_SGr_client.delete_security_group_rule,
433 cls.lb_mem_SGr_client.show_security_group_rule,
434 SGr['id'])
435 # Create a security group rule to allow 22 (ssh)
436 SGr = cls.lb_mem_SGr_client.create_security_group_rule(
437 direction='ingress',
438 security_group_id=cls.lb_member_sec_group['id'],
439 protocol='tcp',
440 ethertype='IPv4',
441 port_range_min=22,
442 port_range_max=22)['security_group_rule']
443 cls.addClassResourceCleanup(
444 waiters.wait_for_not_found,
445 cls.lb_mem_SGr_client.delete_security_group_rule,
446 cls.lb_mem_SGr_client.show_security_group_rule,
447 SGr['id'])
448 if CONF.load_balancer.test_with_ipv6:
449 # Create a security group rule to allow 80-81 (test webservers)
450 SGr = cls.lb_mem_SGr_client.create_security_group_rule(
451 direction='ingress',
452 security_group_id=cls.lb_member_sec_group['id'],
453 protocol='tcp',
454 ethertype='IPv6',
455 port_range_min=80,
456 port_range_max=81)['security_group_rule']
457 cls.addClassResourceCleanup(
458 waiters.wait_for_not_found,
459 cls.lb_mem_SGr_client.delete_security_group_rule,
460 cls.lb_mem_SGr_client.show_security_group_rule,
461 SGr['id'])
462 # Create a security group rule to allow 22 (ssh)
463 SGr = cls.lb_mem_SGr_client.create_security_group_rule(
464 direction='ingress',
465 security_group_id=cls.lb_member_sec_group['id'],
466 protocol='tcp',
467 ethertype='IPv6',
468 port_range_min=22,
469 port_range_max=22)['security_group_rule']
470 cls.addClassResourceCleanup(
471 waiters.wait_for_not_found,
472 cls.lb_mem_SGr_client.delete_security_group_rule,
473 cls.lb_mem_SGr_client.show_security_group_rule,
474 SGr['id'])
475
476 LOG.info('lb_member_sec_group: {}'.format(cls.lb_member_sec_group))
477
478 # Create webserver 1 instance
479 server_details = cls._create_webserver('lb_member_webserver1',
480 cls.lb_member_1_net)
481
482 cls.lb_member_webserver1 = server_details['server']
483 cls.webserver1_ip = server_details.get('ipv4_address')
484 cls.webserver1_ipv6 = server_details.get('ipv6_address')
485 cls.webserver1_public_ip = server_details['public_ipv4_address']
486
487 LOG.debug('Octavia Setup: lb_member_webserver1 = {}'.format(
488 cls.lb_member_webserver1[const.ID]))
489 LOG.debug('Octavia Setup: webserver1_ip = {}'.format(
490 cls.webserver1_ip))
491 LOG.debug('Octavia Setup: webserver1_ipv6 = {}'.format(
492 cls.webserver1_ipv6))
493 LOG.debug('Octavia Setup: webserver1_public_ip = {}'.format(
494 cls.webserver1_public_ip))
495
496 # Create webserver 2 instance
497 server_details = cls._create_webserver('lb_member_webserver2',
498 cls.lb_member_2_net)
499
500 cls.lb_member_webserver2 = server_details['server']
501 cls.webserver2_ip = server_details.get('ipv4_address')
502 cls.webserver2_ipv6 = server_details.get('ipv6_address')
503 cls.webserver2_public_ip = server_details['public_ipv4_address']
504
505 LOG.debug('Octavia Setup: lb_member_webserver2 = {}'.format(
506 cls.lb_member_webserver2[const.ID]))
507 LOG.debug('Octavia Setup: webserver2_ip = {}'.format(
508 cls.webserver2_ip))
509 LOG.debug('Octavia Setup: webserver2_ipv6 = {}'.format(
510 cls.webserver2_ipv6))
511 LOG.debug('Octavia Setup: webserver2_public_ip = {}'.format(
512 cls.webserver2_public_ip))
513
514 # Set up serving on webserver 1
515 cls._install_start_webserver(cls.webserver1_public_ip,
Adam Harwelle029af22018-05-24 17:13:28 -0700516 cls.lb_member_keypair['private_key'],
517 cls.webserver1_response)
Adam Harwellcd72b562018-05-07 11:37:22 -0700518
519 # Validate webserver 1
Adam Harwelle029af22018-05-24 17:13:28 -0700520 cls._validate_webserver(cls.webserver1_public_ip,
521 cls.webserver1_response)
Adam Harwellcd72b562018-05-07 11:37:22 -0700522
523 # Set up serving on webserver 2
524 cls._install_start_webserver(cls.webserver2_public_ip,
Adam Harwelle029af22018-05-24 17:13:28 -0700525 cls.lb_member_keypair['private_key'],
526 cls.webserver2_response)
Adam Harwellcd72b562018-05-07 11:37:22 -0700527
528 # Validate webserver 2
Adam Harwelle029af22018-05-24 17:13:28 -0700529 cls._validate_webserver(cls.webserver2_public_ip,
530 cls.webserver2_response)
Adam Harwellcd72b562018-05-07 11:37:22 -0700531
532 @classmethod
533 def _create_networks(cls):
534 super(LoadBalancerBaseTestWithCompute, cls)._create_networks()
Jude Cross986e3f52017-07-24 14:57:20 -0700535 # Create a router for the subnets (required for the floating IP)
536 router_name = data_utils.rand_name("lb_member_router")
537 result = cls.lb_mem_routers_client.create_router(
538 name=router_name, admin_state_up=True,
539 external_gateway_info=dict(
540 network_id=CONF.network.public_network_id))
541 cls.lb_member_router = result['router']
542 LOG.info('lb_member_router: {}'.format(cls.lb_member_router))
543 cls.addClassResourceCleanup(
544 waiters.wait_for_not_found,
545 cls.lb_mem_routers_client.delete_router,
546 cls.lb_mem_routers_client.show_router,
547 cls.lb_member_router['id'])
548
549 # Add VIP subnet to router
550 cls.lb_mem_routers_client.add_router_interface(
551 cls.lb_member_router['id'],
552 subnet_id=cls.lb_member_vip_subnet['id'])
553 cls.addClassResourceCleanup(
554 waiters.wait_for_not_found,
555 cls.lb_mem_routers_client.remove_router_interface,
556 cls.lb_mem_routers_client.remove_router_interface,
557 cls.lb_member_router['id'],
558 subnet_id=cls.lb_member_vip_subnet['id'])
559
560 # Add member subnet 1 to router
561 cls.lb_mem_routers_client.add_router_interface(
562 cls.lb_member_router['id'],
563 subnet_id=cls.lb_member_1_subnet['id'])
564 cls.addClassResourceCleanup(
565 waiters.wait_for_not_found,
Jude Cross986e3f52017-07-24 14:57:20 -0700566 cls.lb_mem_routers_client.remove_router_interface,
567 cls.lb_mem_routers_client.remove_router_interface,
568 cls.lb_member_router['id'], subnet_id=cls.lb_member_1_subnet['id'])
569
570 # Add member subnet 2 to router
571 cls.lb_mem_routers_client.add_router_interface(
572 cls.lb_member_router['id'],
573 subnet_id=cls.lb_member_2_subnet['id'])
574 cls.addClassResourceCleanup(
575 waiters.wait_for_not_found,
576 cls.lb_mem_routers_client.remove_router_interface,
577 cls.lb_mem_routers_client.remove_router_interface,
578 cls.lb_member_router['id'], subnet_id=cls.lb_member_2_subnet['id'])
579
580 @classmethod
581 def _create_webserver(cls, name, network):
582 """Creates a webserver with two ports.
583
584 webserver_details dictionary contains:
585 server - The compute server object
586 ipv4_address - The IPv4 address for the server (optional)
587 ipv6_address - The IPv6 address for the server (optional)
588 public_ipv4_address - The publicly accessible IPv4 address for the
589 server, this may be a floating IP (optional)
590
591 :param name: The name of the server to create.
592 :param network: The network to boot the server on.
593 :returns: webserver_details dictionary.
594 """
595 server_kwargs = {
596 'name': data_utils.rand_name(name),
597 'flavorRef': CONF.compute.flavor_ref,
598 'imageRef': CONF.compute.image_ref,
599 'key_name': cls.lb_member_keypair['name']}
600 if (CONF.load_balancer.enable_security_groups and
601 CONF.network_feature_enabled.port_security):
602 server_kwargs['security_groups'] = [
603 {'name': cls.lb_member_sec_group['name']}]
604 if not CONF.load_balancer.disable_boot_network:
605 server_kwargs['networks'] = [{'uuid': network['id']}]
606
607 # Replace the name for clouds that have limitations
608 if CONF.load_balancer.random_server_name_length:
609 r = random.SystemRandom()
610 server_kwargs['name'] = "m{}".format("".join(
611 [r.choice(string.ascii_uppercase + string.digits)
612 for _ in range(
613 CONF.load_balancer.random_server_name_length - 1)]
614 ))
615 if CONF.load_balancer.availability_zone:
616 server_kwargs['availability_zone'] = (
617 CONF.load_balancer.availability_zone)
618
619 server = cls.lb_mem_servers_client.create_server(
620 **server_kwargs)['server']
621 cls.addClassResourceCleanup(
622 waiters.wait_for_not_found,
623 cls.lb_mem_servers_client.delete_server,
624 cls.lb_mem_servers_client.show_server,
625 server['id'])
626 server = waiters.wait_for_status(
627 cls.lb_mem_servers_client.show_server,
628 server['id'], 'status', 'ACTIVE',
629 CONF.load_balancer.build_interval,
630 CONF.load_balancer.build_timeout,
631 root_tag='server')
632 webserver_details = {'server': server}
633 LOG.info('Created server: {}'.format(server))
634
635 addresses = server['addresses']
636 if CONF.load_balancer.disable_boot_network:
637 instance_network = addresses.values()[0]
638 else:
639 instance_network = addresses[network['name']]
640 for addr in instance_network:
641 if addr['version'] == 4:
642 webserver_details['ipv4_address'] = addr['addr']
643 if addr['version'] == 6:
644 webserver_details['ipv6_address'] = addr['addr']
645
646 if CONF.validation.connect_method == 'floating':
647 result = cls.lb_mem_ports_client.list_ports(
648 network_id=network['id'],
649 mac_address=instance_network[0]['OS-EXT-IPS-MAC:mac_addr'])
650 port_id = result['ports'][0]['id']
651 result = cls.lb_mem_float_ip_client.create_floatingip(
652 floating_network_id=CONF.network.public_network_id,
653 port_id=port_id)
654 floating_ip = result['floatingip']
655 LOG.info('webserver1_floating_ip: {}'.format(floating_ip))
656 cls.addClassResourceCleanup(
657 waiters.wait_for_not_found,
658 cls.lb_mem_float_ip_client.delete_floatingip,
659 cls.lb_mem_float_ip_client.show_floatingip,
660 floatingip_id=floating_ip['id'])
661 webserver_details['public_ipv4_address'] = (
662 floating_ip['floating_ip_address'])
663 else:
664 webserver_details['public_ipv4_address'] = (
665 instance_network[0]['addr'])
666
667 return webserver_details
668
669 @classmethod
Adam Harwellcd72b562018-05-07 11:37:22 -0700670 def _install_start_webserver(cls, ip_address, ssh_key, start_id):
671 local_file = pkg_resources.resource_filename(
672 'octavia_tempest_plugin.contrib.httpd', 'httpd.bin')
673 dest_file = '/dev/shm/httpd.bin'
674
675 linux_client = remote_client.RemoteClient(
676 ip_address, CONF.validation.image_ssh_user, pkey=ssh_key)
677 linux_client.validate_authentication()
678
679 with tempfile.NamedTemporaryFile() as key:
680 key.write(ssh_key.encode('utf-8'))
681 key.flush()
682 cmd = ("scp -v -o UserKnownHostsFile=/dev/null "
683 "-o StrictHostKeyChecking=no "
684 "-o ConnectTimeout={0} -o ConnectionAttempts={1} "
685 "-i {2} {3} {4}@{5}:{6}").format(
686 CONF.load_balancer.scp_connection_timeout,
687 CONF.load_balancer.scp_connection_attempts,
688 key.name, local_file, CONF.validation.image_ssh_user,
689 ip_address, dest_file)
690 args = shlex.split(cmd)
691 subprocess_args = {'stdout': subprocess.PIPE,
692 'stderr': subprocess.STDOUT,
693 'cwd': None}
694 proc = subprocess.Popen(args, **subprocess_args)
695 stdout, stderr = proc.communicate()
696 if proc.returncode != 0:
697 raise exceptions.CommandFailed(proc.returncode, cmd,
698 stdout, stderr)
699 linux_client.exec_command('sudo screen -d -m {0} -port 80 '
700 '-id {1}'.format(dest_file, start_id))
701 linux_client.exec_command('sudo screen -d -m {0} -port 81 '
702 '-id {1}'.format(dest_file, start_id + 1))
703
704 @classmethod
Jude Cross986e3f52017-07-24 14:57:20 -0700705 def _validate_webserver(cls, ip_address, start_id):
706 URL = 'http://{0}'.format(ip_address)
707 validators.validate_URL_response(URL, expected_body=str(start_id))
708 URL = 'http://{0}:81'.format(ip_address)
709 validators.validate_URL_response(URL, expected_body=str(start_id + 1))
710
Adam Harwellcd72b562018-05-07 11:37:22 -0700711 def _wait_for_lb_functional(self, vip_address):
712 session = requests.Session()
713 start = time.time()
714
715 while time.time() - start < CONF.load_balancer.build_timeout:
716 try:
717 session.get("http://{0}".format(vip_address), timeout=2)
718 time.sleep(1)
719 return
720 except Exception:
721 LOG.warning('Server is not passing initial traffic. Waiting.')
722 time.sleep(1)
723 LOG.error('Server did not begin passing traffic within the timeout '
724 'period. Failing test.')
725 raise Exception()
726
Adam Harwelle029af22018-05-24 17:13:28 -0700727 def check_members_balanced(self, vip_address, traffic_member_count=2):
Adam Harwellcd72b562018-05-07 11:37:22 -0700728 session = requests.Session()
729 response_counts = {}
730
731 self._wait_for_lb_functional(vip_address)
732
733 # Send a number requests to lb vip
734 for i in range(20):
735 try:
736 r = session.get('http://{0}'.format(vip_address),
737 timeout=2)
738
739 if r.content in response_counts:
740 response_counts[r.content] += 1
741 else:
742 response_counts[r.content] = 1
743
744 except Exception:
745 LOG.exception('Failed to send request to loadbalancer vip')
746 raise Exception('Failed to connect to lb')
747
748 LOG.debug('Loadbalancer response totals: %s', response_counts)
749 # Ensure the correct number of members
Adam Harwell60ed9d92018-05-10 13:23:13 -0700750 self.assertEqual(traffic_member_count, len(response_counts))
Adam Harwellcd72b562018-05-07 11:37:22 -0700751
752 # Ensure both members got the same number of responses
753 self.assertEqual(1, len(set(response_counts.values())))
Adam Harwelle029af22018-05-24 17:13:28 -0700754
755 def assertConsistentResponse(self, response, url, method='GET', repeat=10,
756 redirect=False, timeout=2, **kwargs):
757 """Assert that a request to URL gets the expected response.
758
759 :param response: Expected response in format (status_code, content).
760 :param url: The URL to request.
761 :param method: The HTTP method to use (GET, POST, PUT, etc)
762 :param repeat: How many times to test the response.
763 :param data: Optional data to send in the request.
764 :param headers: Optional headers to send in the request.
765 :param cookies: Optional cookies to send in the request.
766 :param redirect: Is the request a redirect? If true, assume the passed
767 content should be the next URL in the chain.
768 :return: boolean success status
769
770 :raises: testtools.matchers.MismatchError
771 """
772 session = requests.Session()
773 response_code, response_content = response
774
775 for i in range(0, repeat):
776 req = session.request(method, url, allow_redirects=not redirect,
777 timeout=timeout, **kwargs)
778 if response_code:
779 self.assertEqual(response_code, req.status_code)
780 if redirect:
781 self.assertTrue(req.is_redirect)
782 self.assertEqual(response_content, req.next.url)
783 elif response_content:
784 self.assertEqual(six.text_type(response_content), req.text)