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