Search subnets for gateway_ip to discover NAT dest
The network that should be the target of the NAT of a floatingip should have a subnet that has a gateway_ip. Ignore for a moment the monumental insanity which is that data model ... that a network can have one or more subnets, and a network_id is what a port has and is how you describe what you want to attach to, but even with all of that the gateway_ip is the cogent property and it's needs to be on all of the subnets in the network. Just ignore that ... if you can. Since that is the world we live in, we can discover which network is the netowrk that has one or more subnets that has the gateway_ip set. We'll still fail if there are more than one network that has a subnet with gateway_ip set. But in that case, the config will take care of it. Change-Id: Ib947081a6b7839e1a6f00dcbfd924cc99f19d0fd
This commit is contained in:
@@ -1411,6 +1411,8 @@ class OpenStackCloud(object):
|
||||
nat_destination = None
|
||||
default_network = None
|
||||
|
||||
all_subnets = None
|
||||
|
||||
# Filter locally because we have an or condition
|
||||
try:
|
||||
# TODO(mordred): Rackspace exposes neutron but it does not
|
||||
@@ -1457,6 +1459,25 @@ class OpenStackCloud(object):
|
||||
' by name.'.format(
|
||||
nat_net=self._nat_destination))
|
||||
nat_destination = network
|
||||
elif self._nat_destination is None:
|
||||
# TODO(mordred) need a config value for floating
|
||||
# ips for this cloud so that we can skip this
|
||||
# No configured nat destination, we have to figured
|
||||
# it out.
|
||||
if all_subnets is None:
|
||||
try:
|
||||
all_subnets = self.list_subnets()
|
||||
except OpenStackCloudException:
|
||||
# Thanks Rackspace broken neutron
|
||||
all_subnets = []
|
||||
|
||||
for subnet in all_subnets:
|
||||
# TODO(mordred) trap for detecting more than
|
||||
# one network with a gateway_ip without a config
|
||||
if ('gateway_ip' in subnet and subnet['gateway_ip']
|
||||
and network['id'] == subnet['network_id']):
|
||||
nat_destination = network
|
||||
break
|
||||
|
||||
# Default network
|
||||
if self._default_network in (
|
||||
|
||||
@@ -82,6 +82,29 @@ standard_fake_server = fakes.FakeServer(
|
||||
accessIPv6='',
|
||||
)
|
||||
|
||||
SUBNETS_WITH_NAT = [
|
||||
{
|
||||
u'name': u'',
|
||||
u'enable_dhcp': True,
|
||||
u'network_id': u'5ef0358f-9403-4f7b-9151-376ca112abf7',
|
||||
u'tenant_id': u'29c79f394b2946f1a0f8446d715dc301',
|
||||
u'dns_nameservers': [],
|
||||
u'ipv6_ra_mode': None,
|
||||
u'allocation_pools': [
|
||||
{
|
||||
u'start': u'10.10.10.2',
|
||||
u'end': u'10.10.10.254'
|
||||
}
|
||||
],
|
||||
u'gateway_ip': u'10.10.10.1',
|
||||
u'ipv6_address_mode': None,
|
||||
u'ip_version': 4,
|
||||
u'host_routes': [],
|
||||
u'cidr': u'10.10.10.0/24',
|
||||
u'id': u'14025a85-436e-4418-b0ee-f5b12a50f9b4'
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
class TestMeta(base.TestCase):
|
||||
def test_find_nova_addresses_key_name(self):
|
||||
@@ -131,10 +154,12 @@ class TestMeta(base.TestCase):
|
||||
PUBLIC_V4, meta.get_server_ip(srv, ext_tag='floating'))
|
||||
|
||||
@mock.patch.object(shade.OpenStackCloud, 'has_service')
|
||||
@mock.patch.object(shade.OpenStackCloud, 'list_subnets')
|
||||
@mock.patch.object(shade.OpenStackCloud, 'list_networks')
|
||||
def test_get_server_private_ip(
|
||||
self, mock_list_networks, mock_has_service):
|
||||
self, mock_list_networks, mock_list_subnets, mock_has_service):
|
||||
mock_has_service.return_value = True
|
||||
mock_list_subnets.return_value = SUBNETS_WITH_NAT
|
||||
mock_list_networks.return_value = [{
|
||||
'id': 'test-net-id',
|
||||
'name': 'test-net-name'
|
||||
@@ -155,6 +180,7 @@ class TestMeta(base.TestCase):
|
||||
mock_has_service.assert_called_with('network')
|
||||
mock_list_networks.assert_called_once_with()
|
||||
|
||||
@mock.patch.object(shade.OpenStackCloud, 'list_subnets')
|
||||
@mock.patch.object(shade.OpenStackCloud, 'list_server_security_groups')
|
||||
@mock.patch.object(shade.OpenStackCloud, 'get_volumes')
|
||||
@mock.patch.object(shade.OpenStackCloud, 'get_image_name')
|
||||
@@ -165,11 +191,13 @@ class TestMeta(base.TestCase):
|
||||
self, mock_list_networks, mock_has_service,
|
||||
mock_get_flavor_name, mock_get_image_name,
|
||||
mock_get_volumes,
|
||||
mock_list_server_security_groups):
|
||||
mock_list_server_security_groups,
|
||||
mock_list_subnets):
|
||||
mock_get_image_name.return_value = 'cirros-0.3.4-x86_64-uec'
|
||||
mock_get_flavor_name.return_value = 'm1.tiny'
|
||||
mock_has_service.return_value = True
|
||||
mock_get_volumes.return_value = []
|
||||
mock_list_subnets.return_value = SUBNETS_WITH_NAT
|
||||
mock_list_networks.return_value = [
|
||||
{
|
||||
'id': 'test_pnztt_net',
|
||||
@@ -202,12 +230,14 @@ class TestMeta(base.TestCase):
|
||||
mock_list_networks.assert_called_once_with()
|
||||
|
||||
@mock.patch.object(shade.OpenStackCloud, 'has_service')
|
||||
@mock.patch.object(shade.OpenStackCloud, 'list_subnets')
|
||||
@mock.patch.object(shade.OpenStackCloud, 'list_networks')
|
||||
def test_get_server_external_ipv4_neutron(
|
||||
self, mock_list_networks,
|
||||
self, mock_list_networks, mock_list_subnets,
|
||||
mock_has_service):
|
||||
# Testing Clouds with Neutron
|
||||
mock_has_service.return_value = True
|
||||
mock_list_subnets.return_value = []
|
||||
mock_list_networks.return_value = [{
|
||||
'id': 'test-net-id',
|
||||
'name': 'test-net',
|
||||
@@ -225,12 +255,14 @@ class TestMeta(base.TestCase):
|
||||
self.assertEqual(PUBLIC_V4, ip)
|
||||
|
||||
@mock.patch.object(shade.OpenStackCloud, 'has_service')
|
||||
@mock.patch.object(shade.OpenStackCloud, 'list_subnets')
|
||||
@mock.patch.object(shade.OpenStackCloud, 'list_networks')
|
||||
def test_get_server_external_provider_ipv4_neutron(
|
||||
self, mock_list_networks,
|
||||
self, mock_list_networks, mock_list_subnets,
|
||||
mock_has_service):
|
||||
# Testing Clouds with Neutron
|
||||
mock_has_service.return_value = True
|
||||
mock_list_subnets.return_value = SUBNETS_WITH_NAT
|
||||
mock_list_networks.return_value = [{
|
||||
'id': 'test-net-id',
|
||||
'name': 'test-net',
|
||||
@@ -248,12 +280,14 @@ class TestMeta(base.TestCase):
|
||||
self.assertEqual(PUBLIC_V4, ip)
|
||||
|
||||
@mock.patch.object(shade.OpenStackCloud, 'has_service')
|
||||
@mock.patch.object(shade.OpenStackCloud, 'list_subnets')
|
||||
@mock.patch.object(shade.OpenStackCloud, 'list_networks')
|
||||
def test_get_server_external_none_ipv4_neutron(
|
||||
self, mock_list_networks,
|
||||
self, mock_list_networks, mock_list_subnets,
|
||||
mock_has_service):
|
||||
# Testing Clouds with Neutron
|
||||
mock_has_service.return_value = True
|
||||
mock_list_subnets.return_value = SUBNETS_WITH_NAT
|
||||
mock_list_networks.return_value = [{
|
||||
'id': 'test-net-id',
|
||||
'name': 'test-net',
|
||||
@@ -287,16 +321,18 @@ class TestMeta(base.TestCase):
|
||||
self.assertEqual(PUBLIC_V6, ip)
|
||||
|
||||
@mock.patch.object(shade.OpenStackCloud, 'has_service')
|
||||
@mock.patch.object(shade.OpenStackCloud, 'search_networks')
|
||||
@mock.patch.object(shade.OpenStackCloud, 'list_subnets')
|
||||
@mock.patch.object(shade.OpenStackCloud, 'list_networks')
|
||||
@mock.patch.object(shade.OpenStackCloud, 'search_ports')
|
||||
@mock.patch.object(meta, 'get_server_ip')
|
||||
def test_get_server_external_ipv4_neutron_exception(
|
||||
self, mock_get_server_ip, mock_search_ports,
|
||||
mock_search_networks,
|
||||
mock_list_networks, mock_list_subnets,
|
||||
mock_has_service):
|
||||
# Testing Clouds with a non working Neutron
|
||||
mock_has_service.return_value = True
|
||||
mock_search_networks.return_value = []
|
||||
mock_list_subnets.return_value = []
|
||||
mock_list_networks.return_value = []
|
||||
mock_search_ports.side_effect = neutron_exceptions.NotFound()
|
||||
mock_get_server_ip.return_value = PUBLIC_V4
|
||||
|
||||
|
||||
Reference in New Issue
Block a user