From 889566aa9735cade0842af45b2e040c23a60c8a1 Mon Sep 17 00:00:00 2001 From: Ihar Hrachyshka <ihrachys@redhat.com> Date: Thu, 22 Aug 2024 18:08:29 +0000 Subject: [PATCH] Implement nested snat validation test scenario It's disabled for ovn because it's not, yet, implemented for the driver. See: https://review.opendev.org/c/openstack/neutron/+/926495 (The feature also requires special configuration for the driver that we probably won't enable in the gate. This can be discussed though.) Related-Bug: #2051935 Change-Id: Ie2e49a53857009446e22300e2fff292355cef058 --- neutron_tempest_plugin/config.py | 5 ++ .../scenario/test_floatingip.py | 54 +++++++++++++++++++ zuul.d/master_jobs.yaml | 6 +++ 3 files changed, 65 insertions(+) diff --git a/neutron_tempest_plugin/config.py b/neutron_tempest_plugin/config.py index a6d5c090..d2592017 100644 --- a/neutron_tempest_plugin/config.py +++ b/neutron_tempest_plugin/config.py @@ -77,6 +77,11 @@ NeutronPluginOptions = [ default='openstackgate.local', help='dns_domain value configured at neutron.conf, which will ' 'be used for the DNS configuration of the instances'), + cfg.BoolOpt('snat_rules_apply_to_nested_networks', + default=False, + help='Whether SNAT rules apply recursively to all connected ' + 'networks. This is the default behavior for ovs and ' + 'linuxbridge drivers.'), # Multicast tests settings cfg.StrOpt('multicast_group_range', diff --git a/neutron_tempest_plugin/scenario/test_floatingip.py b/neutron_tempest_plugin/scenario/test_floatingip.py index f2223967..24e58203 100644 --- a/neutron_tempest_plugin/scenario/test_floatingip.py +++ b/neutron_tempest_plugin/scenario/test_floatingip.py @@ -204,6 +204,60 @@ class DefaultSnatToExternal(FloatingIpTestCasesMixin, gateway_external_ip, servers=[proxy, src_server]) + @decorators.idempotent_id('b911b124-b6cb-449d-83d9-b34f3665741d') + @utils.requires_ext(extension='extraroute', service='network') + @testtools.skipUnless( + CONF.neutron_plugin_options.snat_rules_apply_to_nested_networks, + "Backend doesn't enable nested SNAT.") + def test_nested_snat_external_ip(self): + """Check connectivity to an external IP from a nested network.""" + gateway_external_ip = self._get_external_gateway() + + if not gateway_external_ip: + raise self.skipTest("IPv4 gateway is not configured for public " + "network or public_network_id is not " + "configured") + proxy = self._create_server() + proxy_client = ssh.Client(proxy['fip']['floating_ip_address'], + CONF.validation.image_ssh_user, + pkey=self.keypair['private_key']) + + # Create a nested router + router = self.create_router( + router_name=data_utils.rand_name('router'), + admin_state_up=True) + + # Attach outer subnet to it + outer_port = self.create_port(self.network) + self.client.add_router_interface_with_port_id(router['id'], + outer_port['id']) + + # Attach a nested subnet to it + network = self.create_network() + subnet = self.create_subnet(network) + self.create_router_interface(router['id'], subnet['id']) + + # Set up static routes in both directions + self.client.update_extra_routes( + self.router['id'], + outer_port['fixed_ips'][0]['ip_address'], subnet['cidr']) + self.client.update_extra_routes( + router['id'], self.subnet['gateway_ip'], '0.0.0.0/0') + + # Create a server inside the nested network + src_server = self._create_server(create_floating_ip=False, + network=network) + + # Validate that it can access external gw ip (via nested snat) + src_server_ip = src_server['port']['fixed_ips'][0]['ip_address'] + ssh_client = ssh.Client(src_server_ip, + CONF.validation.image_ssh_user, + pkey=self.keypair['private_key'], + proxy_client=proxy_client) + self.check_remote_connectivity(ssh_client, + gateway_external_ip, + servers=[proxy, src_server]) + class FloatingIPPortDetailsTest(FloatingIpTestCasesMixin, base.BaseTempestTestCase): diff --git a/zuul.d/master_jobs.yaml b/zuul.d/master_jobs.yaml index 90379a1b..36955658 100644 --- a/zuul.d/master_jobs.yaml +++ b/zuul.d/master_jobs.yaml @@ -194,6 +194,7 @@ image_is_advanced: true available_type_drivers: flat,geneve,vlan,gre,local,vxlan provider_net_base_segm_id: 1 + snat_rules_apply_to_nested_networks: true irrelevant-files: - ^\.pylintrc$ - ^(test-|)requirements.txt$ @@ -285,6 +286,7 @@ neutron_plugin_options: available_type_drivers: flat,vlan,local,vxlan firewall_driver: openvswitch + snat_rules_apply_to_nested_networks: true irrelevant-files: - ^\.pylintrc$ - ^(test-|)requirements.txt$ @@ -400,6 +402,7 @@ neutron_plugin_options: available_type_drivers: flat,vlan,local,vxlan firewall_driver: iptables_hybrid + snat_rules_apply_to_nested_networks: true irrelevant-files: - ^\.pylintrc$ - ^(test-|)requirements.txt$ @@ -575,6 +578,7 @@ available_type_drivers: flat,vlan,local,vxlan q_agent: linuxbridge firewall_driver: iptables + snat_rules_apply_to_nested_networks: true irrelevant-files: - ^\.pylintrc$ - ^(test-|)requirements.txt$ @@ -715,6 +719,7 @@ available_type_drivers: local,flat,vlan,geneve is_igmp_snooping_enabled: True firewall_driver: ovn + snat_rules_apply_to_nested_networks: false zuul_copy_output: '{{ devstack_base_dir }}/data/ovs': 'logs' '{{ devstack_base_dir }}/data/ovn': 'logs' @@ -937,6 +942,7 @@ available_type_drivers: flat,geneve,vlan,gre,local,vxlan l3_agent_mode: dvr_snat firewall_driver: openvswitch + snat_rules_apply_to_nested_networks: true group-vars: subnode: devstack_services: