Add support for configuring split-stack networks

Some clouds, like OSIC and v1 of DreamCompute, have a split stack
network. This means that a single Neutron Network has both an IPv4 and
an IPv6 subnet, but that the IPv4 subnet is a private/RFC-1918 and the
IPv6 subnet is a Global network. As any inferrance information is
attached to the Network, it's impossible to properly categorize IP
addresses that are on the Server in such a scenario.

Add support for ipv4 and ipv6 versions of the current routes_externally
config value, with each of them defaulting to the value of the
un-specialized routes_externally.

Change-Id: I1e87a1423d20eac31175f44f5f7b38dfcf3a11cb
This commit is contained in:
Monty Taylor 2016-08-18 11:35:50 -05:00
parent a6840f69ff
commit 9d757b3a9a
No known key found for this signature in database
GPG Key ID: 7BAE94BC7141A594
5 changed files with 65 additions and 4 deletions

View File

@ -19,9 +19,15 @@ allows configuring a list of network metadata.
default_interface: true
- name: green
routes_externally: false
- name: purple
- name: yellow
routes_externally: false
nat_destination: true
- name: chartreuse
routes_externally: false
routes_ipv6_externally: true
- name: aubergine
routes_ipv4_externally: false
routes_ipv6_externally: true
Every entry must have a name field, which can hold either the name or the id
of the network.
@ -33,6 +39,11 @@ be an RFC1918 address. In either case, it's provides IPs to servers that
things not on the cloud can use. This value defaults to `false`, which
indicates only servers on the same network can talk to it.
`routes_ipv4_externally` and `routes_ipv6_externally` are boolean fields to
help handle `routes_externally` in the case where a network has a split stack
with different values for IPv4 and IPv6. Either entry, if not given, defaults
to the value of `routes_externally`.
`default_interface` is a boolean field that indicates that the network is the
one that programs should use. It defaults to false. An example of needing to
use this value is a cloud with two private networks, and where a user is

View File

@ -452,12 +452,36 @@ class CloudConfig(object):
net['name'] for net in self.config['networks']
if net['routes_externally']]
def get_external_ipv4_networks(self):
"""Get list of network names for external IPv4 networks."""
return [
net['name'] for net in self.config['networks']
if net['routes_ipv4_externally']]
def get_external_ipv6_networks(self):
"""Get list of network names for external IPv6 networks."""
return [
net['name'] for net in self.config['networks']
if net['routes_ipv6_externally']]
def get_internal_networks(self):
"""Get list of network names for internal networks."""
return [
net['name'] for net in self.config['networks']
if not net['routes_externally']]
def get_internal_ipv4_networks(self):
"""Get list of network names for internal IPv4 networks."""
return [
net['name'] for net in self.config['networks']
if not net['routes_ipv4_externally']]
def get_internal_ipv6_networks(self):
"""Get list of network names for internal IPv6 networks."""
return [
net['name'] for net in self.config['networks']
if not net['routes_ipv6_externally']]
def get_default_network(self):
"""Get network used for default interactions."""
for net in self.config['networks']:

View File

@ -520,6 +520,14 @@ class OpenStackConfig(object):
nat_destination=get_boolean(net.get('nat_destination')),
default_interface=get_boolean(net.get('default_interface')),
)
# routes_ipv4_externally defaults to the value of routes_externally
network['routes_ipv4_externally'] = get_boolean(
net.get(
'routes_ipv4_externally', network['routes_externally']))
# routes_ipv6_externally defaults to the value of routes_externally
network['routes_ipv6_externally'] = get_boolean(
net.get(
'routes_ipv6_externally', network['routes_externally']))
networks.append(network)
for key in ('external_network', 'internal_network'):

View File

@ -113,6 +113,14 @@ USER_CONF = {
'name': 'another-private',
'routes_externally': False,
'nat_destination': True,
}, {
'name': 'split-default',
'routes_externally': True,
'routes_ipv4_externally': False,
}, {
'name': 'split-no-default',
'routes_ipv6_externally': False,
'routes_ipv4_externally': True,
}],
'region_name': 'test-region',
},

View File

@ -194,11 +194,19 @@ class TestConfig(base.TestCase):
vendor_files=[self.vendor_yaml])
cc = c.get_one_cloud('_test-cloud-networks_')
self.assertEqual(
['a-public', 'another-public'], cc.get_external_networks())
['a-public', 'another-public', 'split-default'],
cc.get_external_networks())
self.assertEqual(
['a-private', 'another-private'], cc.get_internal_networks())
['a-private', 'another-private', 'split-no-default'],
cc.get_internal_networks())
self.assertEqual('another-private', cc.get_nat_destination())
self.assertEqual('another-public', cc.get_default_network())
self.assertEqual(
['a-public', 'another-public', 'split-no-default'],
cc.get_external_ipv4_networks())
self.assertEqual(
['a-public', 'another-public', 'split-default'],
cc.get_external_ipv6_networks())
def test_get_one_cloud_no_networks(self):
c = config.OpenStackConfig(config_files=[self.cloud_yaml],
@ -875,7 +883,9 @@ class TestBackwardsCompatibility(base.TestCase):
expected = {
'networks': [
{'name': 'private', 'routes_externally': False,
'nat_destination': False, 'default_interface': False},
'nat_destination': False, 'default_interface': False,
'routes_ipv4_externally': False,
'routes_ipv6_externally': False},
]
}
self.assertEqual(expected, result)