Move default router to external network stack

Change-Id: I3a8d443e4c36f6ed345a9edac236311ebd0822df
This commit is contained in:
Federico Ressi 2022-04-25 13:05:27 +02:00
parent 1d7b9ae547
commit bbf99d35be
9 changed files with 179 additions and 102 deletions

View File

@ -71,8 +71,7 @@ def create_floating_ip(network: _network.NetworkIdType = None,
if 'floating_network_id' not in params:
if network is None:
from tobiko.openstack import stacks
network_id = tobiko.setup_fixture(
stacks.FloatingNetworkStackFixture).external_id
network_id = stacks.get_floating_network_id()
else:
network_id = _network.get_network_id(network)

View File

@ -56,8 +56,7 @@ def create_router(client: _client.NeutronClientType = None,
if 'external_gateway_info' not in params:
if network is None:
from tobiko.openstack import stacks
network_id = tobiko.setup_fixture(
stacks.FloatingNetworkStackFixture).external_id
network_id = stacks.get_floating_network_id()
else:
network_id = _network.get_network_id(network)
params['external_gateway_info'] = dict(network_id=network_id)

View File

@ -65,7 +65,7 @@ L3haDifferentHostServerStackFixture = _l3ha.L3haDifferentHostServerStackFixture
L3haSameHostServerStackFixture = _l3ha.L3haSameHostServerStackFixture
NetworkStackFixture = _neutron.NetworkStackFixture
FloatingNetworkStackFixture = _neutron.FloatingNetworkStackFixture
RouterStackFixture = _neutron.RouterStackFixture
NetworkWithNetMtuWriteStackFixture = (
_neutron.NetworkWithNetMtuWriteStackFixture)
SecurityGroupsFixture = _neutron.SecurityGroupsFixture
@ -73,9 +73,15 @@ SecurityGroupsFixture = _neutron.SecurityGroupsFixture
get_external_network = _neutron.get_external_network
has_external_network = _neutron.has_external_network
skip_unless_has_external_network = _neutron.skip_unless_has_external_network
get_floating_network_id = _neutron.get_floating_network_id
get_floating_network = _neutron.get_floating_network
has_floating_network = _neutron.has_floating_network
skip_unless_has_floating_network = _neutron.skip_unless_has_floating_network
get_router_id = _neutron.get_router_id
get_router = _neutron.get_router
has_router = _neutron.has_router
skip_unless_has_router = _neutron.skip_unless_has_router
ServerStackFixture = _nova.ServerStackFixture
KeyPairStackFixture = _nova.KeyPairStackFixture

View File

@ -21,10 +21,15 @@ from tobiko.openstack.stacks import _nova
@neutron.skip_if_missing_networking_extensions('l3-ha')
class L3haNetworkStackFixture(_neutron.NetworkStackFixture):
class L3haRouterStackFixture(_neutron.RouterStackFixture):
ha = True
@neutron.skip_if_missing_networking_extensions('l3-ha')
class L3haNetworkStackFixture(_neutron.NetworkStackFixture):
gateway_stack = tobiko.required_fixture(L3haRouterStackFixture)
@neutron.skip_if_missing_networking_extensions('l3-ha')
class L3haServerStackFixture(_cirros.CirrosServerStackFixture):
#: Heat stack for creating internal network with L3HA enabled

View File

@ -34,23 +34,21 @@ from tobiko.shell import ssh
CONF = config.CONF
LOG = log.getLogger(__name__)
NeutronNetworkType = typing.Dict[str, typing.Any]
class ExternalNetworkStackFixture(heat.HeatStackFixture):
template = _hot.heat_template_file('neutron/external_network.yaml')
@property
def external_name(self):
def external_name(self) -> typing.Optional[str]:
return tobiko.tobiko_config().neutron.external_network
subnet_enable_dhcp: typing.Optional[bool] = False
_external_network: typing.Optional[NeutronNetworkType] = None
_external_network: typing.Optional[neutron.NetworkType] = None
@property
def external_network(self) -> typing.Optional[NeutronNetworkType]:
def external_network(self) -> typing.Optional[neutron.NetworkType]:
external_network = self._external_network
if external_network is None:
subnet_parameters = {}
@ -84,29 +82,73 @@ class ExternalNetworkStackFixture(heat.HeatStackFixture):
return external_network
@property
def external_id(self):
def external_id(self) -> typing.Optional[str]:
network = self.external_network
return network and network['id'] or None
if network is None:
return None
else:
return network['id']
@property
def has_external_id(self):
return bool(self.external_id)
return bool(self.external_network)
@property
def network_details(self):
def network_details(self) -> neutron.NetworkType:
return neutron.get_network(self.network_id)
@property
def has_network(self) -> bool:
return bool(self.network_id)
has_gateway = False
class FloatingNetworkStackFixture(ExternalNetworkStackFixture):
@property
def create_router(self) -> bool:
return False
@property
def external_name(self):
def has_l3_ha(self):
"""Whenever can obtain gateway router HA value"""
return neutron.has_networking_extensions('l3-ha')
ha = False
@property
def router_value_specs(self) -> typing.Dict[str, typing.Any]:
value_specs: typing.Dict[str, typing.Any] = {}
if self.has_l3_ha:
value_specs.update(ha=bool(self.ha))
return value_specs
@property
def has_router(self) -> bool:
return bool(self.router_id)
@property
def router_details(self) -> neutron.RouterType:
return neutron.get_router(self.router_id)
class RouterStackFixture(ExternalNetworkStackFixture):
@property
def external_name(self) -> typing.Optional[str]:
return tobiko.tobiko_config().neutron.floating_network
subnet_enable_dhcp = None
@property
def create_router(self) -> bool:
return self.has_external_id
@property
def neutron_required_quota_set(self) -> typing.Dict[str, int]:
requirements = super().neutron_required_quota_set
if self.create_router:
requirements['router'] += 1
return requirements
@neutron.skip_if_missing_networking_extensions('port-security')
class NetworkStackFixture(heat.HeatStackFixture):
@ -147,27 +189,25 @@ class NetworkStackFixture(heat.HeatStackFixture):
"""Extra network creation parameters"""
return {}
floating_network_stack = tobiko.required_fixture(
FloatingNetworkStackFixture)
gateway_stack = tobiko.required_fixture(RouterStackFixture)
@property
def ha(self) -> bool:
return self.gateway_stack.ha
@property
def floating_network(self):
"""Network ID where the Neutron floating IPs are created"""
return self.floating_network_stack.network_id
return self.gateway_stack.network_id
@property
def gateway_network(self):
"""Network ID where gateway routes packages to"""
return self.floating_network
ha = False
@property
def gateway_value_specs(self):
value_specs = {}
if self.has_l3_ha:
value_specs.update(ha=(self.ha or False))
return value_specs
def gateway(self) -> str:
return self.gateway_stack.router_id
@property
def has_gateway(self):
@ -287,8 +327,6 @@ class NetworkStackFixture(heat.HeatStackFixture):
requirements['subnet'] += 1
if self.has_ipv6:
requirements['subnet'] += 1
if self.has_gateway:
requirements['router'] += 1
return requirements
def is_router_distributed(self) -> bool:
@ -330,9 +368,9 @@ class SecurityGroupsFixture(heat.HeatStackFixture):
template = _hot.heat_template_file('neutron/security_groups.yaml')
def list_external_networks(name: typing.Optional[str] = None) -> \
tobiko.Selection[NeutronNetworkType]:
networks = tobiko.Selection[NeutronNetworkType]()
def list_external_networks(name: str = None) -> \
tobiko.Selection[neutron.NetworkType]:
networks = tobiko.Selection[neutron.NetworkType]()
if name is not None:
try:
network = neutron.get_network(name)
@ -367,22 +405,38 @@ skip_unless_has_external_network = tobiko.skip_unless(
'External network not found', has_external_network)
def get_floating_network_id():
return tobiko.setup_fixture(FloatingNetworkStackFixture).network_id
def get_floating_network_id() -> str:
return tobiko.setup_fixture(RouterStackFixture).network_id
def get_floating_network():
return tobiko.setup_fixture(FloatingNetworkStackFixture).network_details
def get_floating_network() -> neutron.NetworkType:
return tobiko.setup_fixture(RouterStackFixture).network_details
def has_floating_network():
return tobiko.setup_fixture(FloatingNetworkStackFixture).has_network
def has_floating_network() -> bool:
return tobiko.setup_fixture(RouterStackFixture).has_network
skip_unless_has_floating_network = tobiko.skip_unless(
'Floating network not found', has_floating_network)
def get_router_id() -> str:
return tobiko.setup_fixture(RouterStackFixture).router_id
def get_router() -> neutron.RouterType:
return tobiko.setup_fixture(RouterStackFixture).router_details
def has_router() -> bool:
return tobiko.setup_fixture(RouterStackFixture).has_router
skip_unless_has_router = tobiko.skip_unless(
'External router not created', has_router)
class DefaultNameserversFixture(tobiko.SharedFixture):
remove_local_ips = True

View File

@ -2,39 +2,63 @@ heat_template_version: newton
description: |
Creates an network with a subnet and a gateway router to an external network
if given
It references to an external network and creates a router attached to it
parameters:
external_id:
description: Default value to be assigned to network ports
description: default value to be assigned to network ports
type: string
default: '<no-external-id>'
has_external_id:
description: Extra network creation parameters
description: whenever has external network
type: boolean
default: false
default: true
router_value_specs:
description: extra router creation parameters
type: json
default: {}
create_router:
description: whatever to attach a router to external interface
type: boolean
default: true
conditions:
has_network:
has_external_id:
get_param: has_external_id
create_router:
and:
- get_param: has_external_id
- get_param: create_router
resources:
network:
_network:
type: OS::Neutron::Net
condition: has_external_id
external_id: {get_param: external_id}
condition: has_network
_router:
type: OS::Neutron::Router
condition: create_router
properties:
external_gateway_info:
network: {get_resource: _network}
value_specs: {get_param: router_value_specs}
outputs:
network_id:
description: Network ID
value: {get_resource: network}
description: network ID
condition: has_external_id
value: {get_resource: _network}
has_network:
description: Whenever has a floating network
value: {get_param: has_external_id}
router_id:
description: router ID
condition: create_router
value: {get_resource: _router}

View File

@ -68,26 +68,16 @@ parameters:
type: boolean
default: false
gateway_network:
description: Optional gateway network to route packages to
gateway:
description: Optional gateway to route packages to
type: string
default: '<no-gateway-network>'
gateway_value_specs:
description: Extra gateway router creation parameters
type: json
default: {}
default: '<no-gateway-id>'
has_net_mtu:
description: whenever net-mtu extension is available
type: boolean
default: false
has_l3_ha:
description: whenever l3-ha extension is available
type: boolean
default: false
has_qos_policy:
description: whether qos policy is attached to the network
type: boolean
@ -117,101 +107,94 @@ conditions:
has_net_mtu:
get_param: has_net_mtu
has_l3_ha:
and:
- get_param: has_l3_ha
- get_param: has_gateway
has_qos_policy:
get_param: has_qos_policy
resources:
network:
_network:
type: OS::Neutron::Net
properties:
port_security_enabled: {get_param: port_security_enabled}
value_specs: {get_param: network_value_specs}
ipv4_subnet:
_ipv4_subnet:
type: OS::Neutron::Subnet
condition: has_ipv4
properties:
network: {get_resource: network}
network: {get_resource: _network}
ip_version: 4
cidr: {get_param: ipv4_cidr}
dns_nameservers: {get_param: ipv4_dns_nameservers}
ipv6_subnet:
_ipv6_subnet:
type: OS::Neutron::Subnet
condition: has_ipv6
properties:
network: {get_resource: network}
network: {get_resource: _network}
ip_version: 6
cidr: {get_param: ipv6_cidr}
dns_nameservers: {get_param: ipv6_dns_nameservers}
ipv6_address_mode: {get_param: ipv6_address_mode}
ipv6_ra_mode: {get_param: ipv6_ra_mode}
gateway:
_gateway:
type: OS::Neutron::Router
condition: has_gateway
properties:
external_gateway_info:
network: {get_param: gateway_network}
value_specs: {get_param: gateway_value_specs}
external_id: {get_param: gateway}
ipv4_gateway_interface:
_ipv4_gateway_interface:
type: OS::Neutron::RouterInterface
condition: has_ipv4_gateway
properties:
router: {get_resource: gateway}
subnet: {get_resource: ipv4_subnet}
router: {get_resource: _gateway}
subnet: {get_resource: _ipv4_subnet}
ipv6_gateway_interface:
_ipv6_gateway_interface:
type: OS::Neutron::RouterInterface
condition: has_ipv6_gateway
properties:
router: {get_resource: gateway}
subnet: {get_resource: ipv6_subnet}
router: {get_resource: _gateway}
subnet: {get_resource: _ipv6_subnet}
outputs:
network_id:
description: Network ID
value: {get_resource: network}
value: {get_resource: _network}
port_security_enabled:
description: whenever port security has been enabled on created network
value: {get_attr: [network, port_security_enabled]}
value: {get_attr: [_network, port_security_enabled]}
ipv4_subnet_id:
description: IPv4 subnet ID
value: {get_resource: ipv4_subnet}
value: {get_resource: _ipv4_subnet}
condition: has_ipv4
ipv6_subnet_id:
description: IPv6 subnet ID
value: {get_resource: ipv6_subnet}
value: {get_resource: _ipv6_subnet}
condition: has_ipv6
gateway_id:
description: Gateway router ID
value: {get_resource: gateway}
value: {get_resource: _gateway}
condition: has_gateway
gateway_network_id:
description: Gateway network ID
value: {get_attr: [gateway, external_gateway_info, network_id]}
value: {get_attr: [_gateway, external_gateway_info, network_id]}
condition: has_gateway
mtu:
description: Network MTU value (integer)
value: {get_attr: [network, mtu]}
value: {get_attr: [_network, mtu]}
condition: has_net_mtu
qos_policy_id:
description: QoS Policy ID attached to the network
value: {get_attr: [network, qos_policy_id]}
value: {get_attr: [_network, qos_policy_id]}
condition: has_qos_policy

View File

@ -28,16 +28,13 @@ class FloatingIpTest(testtools.TestCase):
server = tobiko.required_fixture(stacks.CirrosServerStackFixture)
floating_network_stack = tobiko.required_fixture(
stacks.FloatingNetworkStackFixture)
@property
def floating_network_id(self) -> str:
return self.floating_network_stack.external_id
return stacks.get_floating_network_id()
@property
def floating_network_details(self) -> neutron.NetworkType:
return neutron.get_network(self.floating_network_stack.external_id)
return stacks.get_floating_network()
def test_create_floating_ip(self,
network: neutron.NetworkIdType = None) -> \

View File

@ -104,7 +104,7 @@ class L3HaNetworkTest(NetworkTest):
@keystone.skip_unless_has_keystone_credentials()
@stacks.skip_unless_has_external_network
class ExternalNetworkStackTest(testtools.TestCase):
class ExternalNetworkTest(testtools.TestCase):
def test_get_external_network(self):
network = stacks.get_external_network()
@ -120,7 +120,7 @@ class ExternalNetworkStackTest(testtools.TestCase):
@keystone.skip_unless_has_keystone_credentials()
@stacks.skip_unless_has_floating_network
class FloatingNetworkStackTest(testtools.TestCase):
class RouterTest(testtools.TestCase):
def test_get_floating_network(self):
network = stacks.get_floating_network()
@ -129,4 +129,14 @@ class FloatingNetworkStackTest(testtools.TestCase):
self.assertEqual('ACTIVE', network['status'])
def test_has_floating_network(self):
self.assertIs(True, stacks.has_floating_network())
self.assertTrue(stacks.has_floating_network())
def test_get_router(self):
router = stacks.get_router()
self.assertIsNotNone(router)
self.assertEqual(
stacks.get_floating_network_id(),
router['external_gateway_info']['network_id'])
def test_has_router(self):
self.assertTrue(stacks.has_router())