Merge "Find an external network when no one is provided"
This commit is contained in:
commit
1fe5dc5726
@ -142,12 +142,8 @@ function configure_tobiko_neutron {
|
|||||||
# Write floating network
|
# Write floating network
|
||||||
local floating_network=${TOBIKO_NEUTRON_FLOATING_NETWORK}
|
local floating_network=${TOBIKO_NEUTRON_FLOATING_NETWORK}
|
||||||
if [ "${floating_network}" != "" ]; then
|
if [ "${floating_network}" != "" ]; then
|
||||||
local floating_network=$(openstack network show -f value -c name "${floating_network}")
|
|
||||||
else
|
|
||||||
local networks=( $( openstack network list -f value -c Name --enable --external) )
|
|
||||||
local floating_network=${networks[0]}
|
|
||||||
fi
|
|
||||||
iniset "${tobiko_conf_file}" neutron floating_network "${floating_network}"
|
iniset "${tobiko_conf_file}" neutron floating_network "${floating_network}"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ def filter_by_items(dictionaries, exclude=False, **items):
|
|||||||
|
|
||||||
|
|
||||||
class ObjectNotFound(_exception.TobikoException):
|
class ObjectNotFound(_exception.TobikoException):
|
||||||
"Object not found."
|
"Object not found"
|
||||||
|
|
||||||
|
|
||||||
class MultipleObjectsFound(_exception.TobikoException):
|
class MultipleObjectsFound(_exception.TobikoException):
|
||||||
|
@ -38,6 +38,10 @@ get_port = _client.get_port
|
|||||||
get_subnet = _client.get_subnet
|
get_subnet = _client.get_subnet
|
||||||
list_l3_agent_hosting_routers = _client.list_l3_agent_hosting_routers
|
list_l3_agent_hosting_routers = _client.list_l3_agent_hosting_routers
|
||||||
find_l3_agent_hosting_router = _client.find_l3_agent_hosting_router
|
find_l3_agent_hosting_router = _client.find_l3_agent_hosting_router
|
||||||
|
NoSuchNetwork = _client.NoSuchNetwork
|
||||||
|
NoSuchPort = _client.NoSuchPort
|
||||||
|
NoSuchRouter = _client.NoSuchRouter
|
||||||
|
NoSuchSubnet = _client.NoSuchSubnet
|
||||||
|
|
||||||
new_ipv4_cidr = _cidr.new_ipv4_cidr
|
new_ipv4_cidr = _cidr.new_ipv4_cidr
|
||||||
new_ipv6_cidr = _cidr.new_ipv6_cidr
|
new_ipv6_cidr = _cidr.new_ipv6_cidr
|
||||||
|
@ -136,19 +136,32 @@ def get_floating_ip(floating_ip, client=None, **params):
|
|||||||
|
|
||||||
|
|
||||||
def get_network(network, client=None, **params):
|
def get_network(network, client=None, **params):
|
||||||
return neutron_client(client).show_network(network, **params)['network']
|
try:
|
||||||
|
return neutron_client(client).show_network(network,
|
||||||
|
**params)['network']
|
||||||
|
except neutronclient.exceptions.NotFound:
|
||||||
|
raise NoSuchNetwork(id=network)
|
||||||
|
|
||||||
|
|
||||||
def get_port(port, client=None, **params):
|
def get_port(port, client=None, **params):
|
||||||
|
try:
|
||||||
return neutron_client(client).show_port(port, **params)['port']
|
return neutron_client(client).show_port(port, **params)['port']
|
||||||
|
except neutronclient.exceptions.NotFound:
|
||||||
|
raise NoSuchPort(id=port)
|
||||||
|
|
||||||
|
|
||||||
def get_router(router, client=None, **params):
|
def get_router(router, client=None, **params):
|
||||||
|
try:
|
||||||
return neutron_client(client).show_router(router, **params)['router']
|
return neutron_client(client).show_router(router, **params)['router']
|
||||||
|
except neutronclient.exceptions.NotFound:
|
||||||
|
raise NoSuchRouter(id=router)
|
||||||
|
|
||||||
|
|
||||||
def get_subnet(subnet, client=None, **params):
|
def get_subnet(subnet, client=None, **params):
|
||||||
|
try:
|
||||||
return neutron_client(client).show_subnet(subnet, **params)['subnet']
|
return neutron_client(client).show_subnet(subnet, **params)['subnet']
|
||||||
|
except neutronclient.exceptions.NotFound:
|
||||||
|
raise NoSuchSubnet(id=subnet)
|
||||||
|
|
||||||
|
|
||||||
def list_l3_agent_hosting_routers(router, client=None, **params):
|
def list_l3_agent_hosting_routers(router, client=None, **params):
|
||||||
@ -170,3 +183,19 @@ def find_l3_agent_hosting_router(router, client=None, unique=False,
|
|||||||
return agents.first
|
return agents.first
|
||||||
else:
|
else:
|
||||||
return default
|
return default
|
||||||
|
|
||||||
|
|
||||||
|
class NoSuchNetwork(tobiko.ObjectNotFound):
|
||||||
|
message = "No such network found for {id!r}"
|
||||||
|
|
||||||
|
|
||||||
|
class NoSuchPort(tobiko.ObjectNotFound):
|
||||||
|
message = "No such port found for {id!r}"
|
||||||
|
|
||||||
|
|
||||||
|
class NoSuchRouter(tobiko.ObjectNotFound):
|
||||||
|
message = "No such router found for {id!r}"
|
||||||
|
|
||||||
|
|
||||||
|
class NoSuchSubnet(tobiko.ObjectNotFound):
|
||||||
|
message = "No such subnet found for {id!r}"
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
# Copyright 2019 Red Hat
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
|
||||||
# not use this file except in compliance with the License. You may obtain
|
|
||||||
# a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
# License for the specific language governing permissions and limitations
|
|
||||||
# under the License.
|
|
||||||
from __future__ import absolute_import
|
|
||||||
|
|
||||||
import tobiko
|
|
||||||
|
|
||||||
|
|
||||||
class NoSuchNetwork(tobiko.TobikoException):
|
|
||||||
message = "No such network found for {network!r}"
|
|
||||||
|
|
||||||
|
|
||||||
class MoreNetworksFound(tobiko.TobikoException):
|
|
||||||
message = "More than one network found for {network!r}: {network_ids!s}"
|
|
@ -49,6 +49,10 @@ NetworkWithNetMtuWriteStackFixture = (
|
|||||||
_neutron.NetworkWithNetMtuWriteStackFixture)
|
_neutron.NetworkWithNetMtuWriteStackFixture)
|
||||||
SecurityGroupsFixture = _neutron.SecurityGroupsFixture
|
SecurityGroupsFixture = _neutron.SecurityGroupsFixture
|
||||||
|
|
||||||
|
get_floating_network = _neutron.get_floating_network
|
||||||
|
has_floating_network = _neutron.has_floating_network
|
||||||
|
skip_if_missing_floating_network = _neutron.skip_if_missing_floating_network
|
||||||
|
|
||||||
ServerStackFixture = _nova.ServerStackFixture
|
ServerStackFixture = _nova.ServerStackFixture
|
||||||
KeyPairStackFixture = _nova.KeyPairStackFixture
|
KeyPairStackFixture = _nova.KeyPairStackFixture
|
||||||
FlavorStackFixture = _nova.FlavorStackFixture
|
FlavorStackFixture = _nova.FlavorStackFixture
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
|
|
||||||
|
import json
|
||||||
|
|
||||||
import netaddr
|
import netaddr
|
||||||
from oslo_log import log
|
from oslo_log import log
|
||||||
|
|
||||||
@ -25,10 +27,45 @@ from tobiko.openstack import neutron
|
|||||||
from tobiko.openstack.stacks import _hot
|
from tobiko.openstack.stacks import _hot
|
||||||
|
|
||||||
|
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
CONF = config.CONF
|
CONF = config.CONF
|
||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class FloatingNetworkStackFixture(heat.HeatStackFixture):
|
||||||
|
|
||||||
|
template = _hot.heat_template_file('neutron/floating_network.yaml')
|
||||||
|
|
||||||
|
@property
|
||||||
|
def external_name(self):
|
||||||
|
return tobiko.tobiko_config().neutron.floating_network
|
||||||
|
|
||||||
|
_external_network = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def external_network(self):
|
||||||
|
network = self._external_network
|
||||||
|
if network is None:
|
||||||
|
self._external_network = network = find_external_network(
|
||||||
|
name=self.external_name) or {}
|
||||||
|
return network
|
||||||
|
|
||||||
|
@property
|
||||||
|
def external_id(self):
|
||||||
|
network = self.external_network
|
||||||
|
return network and network['id'] or None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def has_external_id(self):
|
||||||
|
return bool(self.external_id)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def network_details(self):
|
||||||
|
return neutron.get_network(self.network_id)
|
||||||
|
|
||||||
|
|
||||||
@neutron.skip_if_missing_networking_extensions('port-security')
|
@neutron.skip_if_missing_networking_extensions('port-security')
|
||||||
class NetworkStackFixture(heat.HeatStackFixture):
|
class NetworkStackFixture(heat.HeatStackFixture):
|
||||||
"""Heat stack for creating internal network with a router to external"""
|
"""Heat stack for creating internal network with a router to external"""
|
||||||
@ -68,10 +105,18 @@ class NetworkStackFixture(heat.HeatStackFixture):
|
|||||||
"""Extra network creation parameters"""
|
"""Extra network creation parameters"""
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
floating_network_stack = tobiko.required_setup_fixture(
|
||||||
|
FloatingNetworkStackFixture)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def floating_network(self):
|
||||||
|
"""Network ID where the Neutron floating IPs are created"""
|
||||||
|
return self.floating_network_stack.network_id
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def gateway_network(self):
|
def gateway_network(self):
|
||||||
"""Floating IP network where the Neutron floating IPs are created"""
|
"""Network ID where gateway routes packages to"""
|
||||||
return CONF.tobiko.neutron.floating_network
|
return self.floating_network
|
||||||
|
|
||||||
ha = False
|
ha = False
|
||||||
|
|
||||||
@ -200,3 +245,48 @@ class SecurityGroupsFixture(heat.HeatStackFixture):
|
|||||||
"""
|
"""
|
||||||
#: Heat template file
|
#: Heat template file
|
||||||
template = _hot.heat_template_file('neutron/security_groups.yaml')
|
template = _hot.heat_template_file('neutron/security_groups.yaml')
|
||||||
|
|
||||||
|
|
||||||
|
def find_external_network(name=None):
|
||||||
|
network = None
|
||||||
|
if name:
|
||||||
|
try:
|
||||||
|
network = neutron.get_network(name)
|
||||||
|
except neutron.NoSuchNetwork:
|
||||||
|
LOG.debug('No such network with ID %r', name)
|
||||||
|
|
||||||
|
if not network:
|
||||||
|
params = {'router:external': True, "status": "ACTIVE"}
|
||||||
|
if name:
|
||||||
|
params['name'] = name
|
||||||
|
try:
|
||||||
|
network = neutron.find_network(**params)
|
||||||
|
except tobiko.ObjectNotFound:
|
||||||
|
LOG.exception('No such network (%s):',
|
||||||
|
json.dumps(params, sort_keys=True))
|
||||||
|
if name:
|
||||||
|
message = ('No such external network with name or ID '
|
||||||
|
'{!r}').format(name)
|
||||||
|
raise ValueError(message)
|
||||||
|
|
||||||
|
if network:
|
||||||
|
LOG.debug('Found external network %r:\n%s',
|
||||||
|
network['name'], json.dumps(network, indent=4,
|
||||||
|
sort_keys=True))
|
||||||
|
return network
|
||||||
|
|
||||||
|
|
||||||
|
def get_floating_network_id():
|
||||||
|
return tobiko.setup_fixture(FloatingNetworkStackFixture).network_id
|
||||||
|
|
||||||
|
|
||||||
|
def get_floating_network():
|
||||||
|
return tobiko.setup_fixture(FloatingNetworkStackFixture).network_details
|
||||||
|
|
||||||
|
|
||||||
|
def has_floating_network():
|
||||||
|
return tobiko.setup_fixture(FloatingNetworkStackFixture).has_network
|
||||||
|
|
||||||
|
|
||||||
|
skip_if_missing_floating_network = tobiko.skip_unless(
|
||||||
|
'Floating network not found', has_floating_network)
|
||||||
|
@ -129,12 +129,13 @@ class ServerStackFixture(heat.HeatStackFixture):
|
|||||||
def network(self):
|
def network(self):
|
||||||
return self.network_stack.network_id
|
return self.network_stack.network_id
|
||||||
|
|
||||||
#: Floating IP network where the Neutron floating IP is created
|
#: Floating IP network where the Neutron floating IP are created
|
||||||
floating_network = CONF.tobiko.neutron.floating_network
|
@property
|
||||||
|
def floating_network(self):
|
||||||
|
return self.network_stack.floating_network
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def has_floating_ip(self):
|
def has_floating_ip(self):
|
||||||
"""Whenever to allocate floating IP for the server"""
|
|
||||||
return bool(self.floating_network)
|
return bool(self.floating_network)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
40
tobiko/openstack/stacks/neutron/floating_network.yaml
Normal file
40
tobiko/openstack/stacks/neutron/floating_network.yaml
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
heat_template_version: newton
|
||||||
|
|
||||||
|
|
||||||
|
description: |
|
||||||
|
Creates an network with a subnet and a gateway router to an external network
|
||||||
|
if given
|
||||||
|
|
||||||
|
|
||||||
|
parameters:
|
||||||
|
external_id:
|
||||||
|
description: Default value to be assigned to network ports
|
||||||
|
type: string
|
||||||
|
default: '<no-external-id>'
|
||||||
|
|
||||||
|
has_external_id:
|
||||||
|
description: Extra network creation parameters
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
|
||||||
|
|
||||||
|
conditions:
|
||||||
|
has_network:
|
||||||
|
get_param: has_external_id
|
||||||
|
|
||||||
|
|
||||||
|
resources:
|
||||||
|
network:
|
||||||
|
type: OS::Neutron::Net
|
||||||
|
external_id: {get_param: external_id}
|
||||||
|
condition: has_network
|
||||||
|
|
||||||
|
|
||||||
|
outputs:
|
||||||
|
network_id:
|
||||||
|
description: Network ID
|
||||||
|
value: {get_resource: network}
|
||||||
|
|
||||||
|
has_network:
|
||||||
|
description: Whenever has a floating network
|
||||||
|
value: {get_param: has_external_id}
|
@ -75,9 +75,7 @@ parameters:
|
|||||||
gateway_network:
|
gateway_network:
|
||||||
description: Optional gateway network to route packages to
|
description: Optional gateway network to route packages to
|
||||||
type: string
|
type: string
|
||||||
default:
|
default: '<no-gateway-network>'
|
||||||
constraints:
|
|
||||||
- custom_constraint: neutron.network
|
|
||||||
|
|
||||||
gateway_value_specs:
|
gateway_value_specs:
|
||||||
description: Extra gateway router creation parameters
|
description: Extra gateway router creation parameters
|
||||||
|
@ -96,3 +96,17 @@ class L3HaNetworkTestCase(NetworkTestCase):
|
|||||||
|
|
||||||
#: Stack of resources with a network with a gateway router
|
#: Stack of resources with a network with a gateway router
|
||||||
stack = tobiko.required_setup_fixture(stacks.L3haNetworkStackFixture)
|
stack = tobiko.required_setup_fixture(stacks.L3haNetworkStackFixture)
|
||||||
|
|
||||||
|
|
||||||
|
class FloatingNetworkStackTest(testtools.TestCase):
|
||||||
|
|
||||||
|
@stacks.skip_if_missing_floating_network
|
||||||
|
def test_get_floating_network(self):
|
||||||
|
network = stacks.get_floating_network()
|
||||||
|
self.assertTrue(network['id'])
|
||||||
|
self.assertIs(True, network['router:external'])
|
||||||
|
self.assertEqual('ACTIVE', network['status'])
|
||||||
|
|
||||||
|
@stacks.skip_if_missing_floating_network
|
||||||
|
def test_has_floating_network(self):
|
||||||
|
self.assertIs(True, stacks.has_floating_network())
|
||||||
|
Loading…
x
Reference in New Issue
Block a user