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']