diff --git a/octavia_tempest_plugin/tests/scenario/v2/test_traffic_ops.py b/octavia_tempest_plugin/tests/scenario/v2/test_traffic_ops.py index 627c261d..edc2cbcc 100644 --- a/octavia_tempest_plugin/tests/scenario/v2/test_traffic_ops.py +++ b/octavia_tempest_plugin/tests/scenario/v2/test_traffic_ops.py @@ -620,3 +620,66 @@ class TrafficOperationsScenarioTest(test_base.LoadBalancerBaseTestWithCompute): self.assertConsistentResponse((403, None), url_for_member1, headers={'reject': 'true'}) + + @testtools.skipIf(CONF.load_balancer.test_with_noop, + 'Traffic tests will not work in noop mode.') + @testtools.skipUnless(CONF.load_balancer.test_with_ipv6, + 'Mixed IPv4/IPv6 member test requires IPv6.') + @decorators.idempotent_id('20b6b671-0101-4bed-a249-9af6ee3aa6d9') + def test_mixed_ipv4_ipv6_members_traffic(self): + """Tests traffic through a loadbalancer with IPv4 and IPv6 members. + + * Set up members on a loadbalancer. + * Test traffic to ensure it is balanced properly. + """ + # Set up Member 1 for Webserver 1 + member1_name = data_utils.rand_name("lb_member_member1-traffic") + member1_kwargs = { + const.POOL_ID: self.pool_id, + const.NAME: member1_name, + const.ADMIN_STATE_UP: True, + const.ADDRESS: self.webserver1_ip, + const.PROTOCOL_PORT: 80, + } + if self.lb_member_1_subnet: + member1_kwargs[const.SUBNET_ID] = self.lb_member_1_subnet[const.ID] + + member1 = self.mem_member_client.create_member( + **member1_kwargs) + self.addCleanup( + self.mem_member_client.cleanup_member, + member1[const.ID], pool_id=self.pool_id, + lb_client=self.mem_lb_client, lb_id=self.lb_id) + waiters.wait_for_status( + self.mem_lb_client.show_loadbalancer, self.lb_id, + const.PROVISIONING_STATUS, const.ACTIVE, + CONF.load_balancer.check_interval, + CONF.load_balancer.check_timeout) + + # Set up Member 2 for Webserver 2 + member2_name = data_utils.rand_name("lb_member_member2-traffic") + member2_kwargs = { + const.POOL_ID: self.pool_id, + const.NAME: member2_name, + const.ADMIN_STATE_UP: True, + const.ADDRESS: self.webserver2_ipv6, + const.PROTOCOL_PORT: 80, + } + if self.lb_member_2_ipv6_subnet: + member2_kwargs[const.SUBNET_ID] = ( + self.lb_member_2_ipv6_subnet[const.ID]) + + member2 = self.mem_member_client.create_member( + **member2_kwargs) + self.addCleanup( + self.mem_member_client.cleanup_member, + member2[const.ID], pool_id=self.pool_id, + lb_client=self.mem_lb_client, lb_id=self.lb_id) + waiters.wait_for_status( + self.mem_lb_client.show_loadbalancer, self.lb_id, + const.PROVISIONING_STATUS, const.ACTIVE, + CONF.load_balancer.check_interval, + CONF.load_balancer.check_timeout) + + # Send some traffic + self.check_members_balanced(self.lb_vip_address) diff --git a/octavia_tempest_plugin/tests/test_base.py b/octavia_tempest_plugin/tests/test_base.py index c70c2f1f..825b7581 100644 --- a/octavia_tempest_plugin/tests/test_base.py +++ b/octavia_tempest_plugin/tests/test_base.py @@ -305,6 +305,10 @@ class LoadBalancerBaseTest(test.BaseTestCase): 'cidr': CONF.load_balancer.member_1_ipv6_subnet_cidr, 'ip_version': 6} result = cls.lb_mem_subnet_client.create_subnet(**subnet_kwargs) + cls.lb_member_1_subnet_prefix = ( + CONF.load_balancer.member_1_ipv6_subnet_cidr.rpartition('/')[2] + ) + assert(cls.lb_member_1_subnet_prefix.isdigit()) cls.lb_member_1_ipv6_subnet = result['subnet'] LOG.info('lb_member_1_ipv6_subnet: {}'.format( cls.lb_member_1_ipv6_subnet)) @@ -354,6 +358,10 @@ class LoadBalancerBaseTest(test.BaseTestCase): 'cidr': CONF.load_balancer.member_2_ipv6_subnet_cidr, 'ip_version': 6} result = cls.lb_mem_subnet_client.create_subnet(**subnet_kwargs) + cls.lb_member_2_subnet_prefix = ( + CONF.load_balancer.member_2_ipv6_subnet_cidr.rpartition('/')[2] + ) + assert(cls.lb_member_2_subnet_prefix.isdigit()) cls.lb_member_2_ipv6_subnet = result['subnet'] LOG.info('lb_member_2_ipv6_subnet: {}'.format( cls.lb_member_2_ipv6_subnet)) @@ -520,6 +528,17 @@ class LoadBalancerBaseTestWithCompute(LoadBalancerBaseTest): LOG.debug('Octavia Setup: webserver2_public_ip = {}'.format( cls.webserver2_public_ip)) + if CONF.load_balancer.test_with_ipv6: + # Enable the IPv6 nic in webserver 1 + cls._enable_ipv6_nic_webserver( + cls.webserver1_public_ip, cls.lb_member_keypair['private_key'], + cls.webserver1_ipv6, cls.lb_member_1_subnet_prefix) + + # Enable the IPv6 nic in webserver 2 + cls._enable_ipv6_nic_webserver( + cls.webserver2_public_ip, cls.lb_member_keypair['private_key'], + cls.webserver2_ipv6, cls.lb_member_2_subnet_prefix) + # Set up serving on webserver 1 cls._install_start_webserver(cls.webserver1_public_ip, cls.lb_member_keypair['private_key'], @@ -710,6 +729,19 @@ class LoadBalancerBaseTestWithCompute(LoadBalancerBaseTest): linux_client.exec_command('sudo screen -d -m {0} -port 81 ' '-id {1}'.format(dest_file, start_id + 1)) + # Cirros does not configure the assigned IPv6 address by default + # so enable it manually like tempest does here: + # tempest/scenario/test_netowrk_v6.py turn_nic6_on() + @classmethod + def _enable_ipv6_nic_webserver(cls, ip_address, ssh_key, + ipv6_address, ipv6_prefix): + linux_client = remote_client.RemoteClient( + ip_address, CONF.validation.image_ssh_user, pkey=ssh_key) + linux_client.validate_authentication() + + linux_client.exec_command('sudo ip address add {0}/{1} dev ' + 'eth0'.format(ipv6_address, ipv6_prefix)) + @classmethod def _validate_webserver(cls, ip_address, start_id): URL = 'http://{0}'.format(ip_address)