From 110242796ca854aa5c048bbd49ff922639db0c07 Mon Sep 17 00:00:00 2001 From: Dmitrii Shcherbakov Date: Wed, 7 Jun 2023 23:43:45 +0300 Subject: [PATCH] Allow an optional FIP service subnet to be set up A separate service subnet for FIPs is useful in making sure that connectivity based on the advertised routes really works as opposed to relying on directly connected routes to FIPs in the undercloud network subnet used as an external network. --- .../charm_tests/dragent/configure.py | 5 +++-- zaza/openstack/charm_tests/neutron/setup.py | 21 ++++++++++++++++++- zaza/openstack/configure/network.py | 17 +++++++++++++++ zaza/openstack/utilities/openstack.py | 9 +++++++- 4 files changed, 48 insertions(+), 4 deletions(-) diff --git a/zaza/openstack/charm_tests/dragent/configure.py b/zaza/openstack/charm_tests/dragent/configure.py index b9588d4..79c1720 100644 --- a/zaza/openstack/charm_tests/dragent/configure.py +++ b/zaza/openstack/charm_tests/dragent/configure.py @@ -41,8 +41,9 @@ def setup(): :returns: None :rtype: None """ - # Reuse the existing network configuration code. - basic_overcloud_network() + # Reuse the existing network configuration code but ask for a separate + # service subnet to be created for FIPs. + basic_overcloud_network(use_separate_fip_subnet=True) # Get a keystone session keystone_session = openstack_utils.get_overcloud_keystone_session() diff --git a/zaza/openstack/charm_tests/neutron/setup.py b/zaza/openstack/charm_tests/neutron/setup.py index d6a1ab2..f81590d 100644 --- a/zaza/openstack/charm_tests/neutron/setup.py +++ b/zaza/openstack/charm_tests/neutron/setup.py @@ -68,6 +68,17 @@ DEFAULT_UNDERCLOUD_NETWORK_CONFIG = { "default_gateway": "10.5.0.1", } +# For Neutron Dynamic Tests it is useful to avoid relying on the directly +# connected routes and instead using the advertised routes on the southbound +# path and default routes on the northbound path. To do that, a separate +# service subnet may be optionally created to force Neutron to use that instead +# of the external network subnet without concrete service IPs which is used as +# a fallback only. +DEFAULT_FIP_SERVICE_SUBNET_CONFIG = { + "fip_service_subnet_name": openstack_utils.FIP_SERVICE_SUBNET_NAME, + "fip_service_subnet_cidr": "100.64.0.0/24" +} + def undercloud_and_charm_setup(limit_gws=None): """Perform undercloud and charm setup for network plumbing. @@ -111,7 +122,7 @@ def undercloud_and_charm_setup(limit_gws=None): .format(provider_type)) -def basic_overcloud_network(limit_gws=None): +def basic_overcloud_network(limit_gws=None, use_separate_fip_subnet=False): """Run setup for neutron networking. Configure the following: @@ -119,6 +130,10 @@ def basic_overcloud_network(limit_gws=None): :param limit_gws: Limit the number of gateways that get a port attached :type limit_gws: int + :param use_separate_fip_subnet: Use a separate service subnet for floating + ips instead of relying on the external + network subnet for FIP allocations. + :type use_separate_fip_subnet: bool """ cli_utils.setup_logging() @@ -128,6 +143,10 @@ def basic_overcloud_network(limit_gws=None): network_config.update(OVERCLOUD_NETWORK_CONFIG) # Default undercloud settings network_config.update(DEFAULT_UNDERCLOUD_NETWORK_CONFIG) + + if use_separate_fip_subnet: + network_config.update(DEFAULT_FIP_SERVICE_SUBNET_CONFIG) + # Environment specific settings network_config.update(generic_utils.get_undercloud_env_vars()) diff --git a/zaza/openstack/configure/network.py b/zaza/openstack/configure/network.py index 20cde9f..33fab27 100755 --- a/zaza/openstack/configure/network.py +++ b/zaza/openstack/configure/network.py @@ -132,6 +132,23 @@ def setup_sdn(network_config, keystone_session=None): neutron_client, project_id, network_config["external_net_name"]) + + # If a separate service subnet for FIPs is requested, create one. This is + # useful for testing dynamic routing scenarios to avoid relying on directly + # connected routes to the external network subnet. + if network_config.get('fip_service_subnet_name'): + openstack_utils.create_provider_subnet( + neutron_client, + project_id, + ext_network, + subnet_name=network_config["fip_service_subnet_name"], + cidr=network_config["fip_service_subnet_cidr"], + # Disable DHCP as we don't need a metadata port serving this + # subnet while Neutron would fail to allocate a fixed IP for it + # with a service subnet constraint below. + dhcp=False, + service_types=['network:floatingip'] + ) openstack_utils.create_provider_subnet( neutron_client, project_id, diff --git a/zaza/openstack/utilities/openstack.py b/zaza/openstack/utilities/openstack.py index df540e5..19f8ce9 100644 --- a/zaza/openstack/utilities/openstack.py +++ b/zaza/openstack/utilities/openstack.py @@ -199,6 +199,9 @@ KEYSTONE_REMOTE_CACERT = ( # Network/router names EXT_NET = os.environ.get('TEST_EXT_NET', 'ext_net') EXT_NET_SUBNET = os.environ.get('TEST_EXT_NET_SUBNET', 'ext_net_subnet') +# An optional service subnet for FIPs is necessary. +FIP_SERVICE_SUBNET_NAME = os.environ.get('TEST_FIP_SERVICE_SUBNET_NAME', + 'fip_service_subnet') PRIVATE_NET = os.environ.get('TEST_PRIVATE_NET', 'private') PRIVATE_NET_SUBNET = os.environ.get('TEST_PRIVATE_NET_SUBNET', 'private_subnet') @@ -1301,7 +1304,7 @@ def create_provider_subnet(neutron_client, project_id, network, subnet_name=EXT_NET_SUBNET, default_gateway=None, cidr=None, start_floating_ip=None, end_floating_ip=None, - dhcp=False): + dhcp=False, service_types=None): """Create the provider subnet. :param neutron_client: Authenticated neutronclient @@ -1322,6 +1325,8 @@ def create_provider_subnet(neutron_client, project_id, network, :type end_floating_ip: string or None :param dhcp: Run DHCP on this subnet :type dhcp: boolean + :param service_types: Optional subnet service types + :type service_types: List[str] :returns: Subnet object :rtype: dict """ @@ -1345,6 +1350,8 @@ def create_provider_subnet(neutron_client, project_id, network, 'end': end_floating_ip, } subnet_msg['allocation_pools'] = [allocation_pool] + if service_types: + subnet_msg['service_types'] = service_types logging.info('Creating new subnet') subnet = neutron_client.create_subnet({'subnet': subnet_msg})['subnet']