Tempest plugin for Octavia
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

test_base.py 37KB

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