Support dual-stack neutron networks
It is totally possible for a neutron network to have a network with a globally routable IPv6 subnet and an RFC-1918 IPv4 subnet. In fact, the existing OSIC Cloud1 does this, and the original region of Dreamhost did this. The trouble is, it's not possible in a reasonable way to _infer_ this setup, so we rely on brand-new config functions in os-client-config to allow a user to express that a network is external for ipv4 or for ipv6. Depends-On: I40f5165d36060643943bcb91df14e5e34cd5e3fa Change-Id: I12c491ac31b950dde4c1ac55860043fd9d05ece8
This commit is contained in:
parent
18aa5d1e28
commit
6832f734d0
@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- Added support for dual stack networks where the IPv4 subnet and the
|
||||||
|
IPv6 subnet have opposite public/private qualities. It is now possible
|
||||||
|
to add configuration to clouds.yaml that will indicate that a network
|
||||||
|
is public for v6 and private for v4, which is otherwise very difficult
|
||||||
|
to correctly infer while setting server attributes like private_v4,
|
||||||
|
public_v4 and public_v6.
|
@ -4,7 +4,7 @@ munch
|
|||||||
decorator
|
decorator
|
||||||
jsonpatch
|
jsonpatch
|
||||||
ipaddress
|
ipaddress
|
||||||
os-client-config>=1.17.0,!=1.19.0
|
os-client-config>=1.20.0
|
||||||
requestsexceptions>=1.1.1
|
requestsexceptions>=1.1.1
|
||||||
six
|
six
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ def get_server_private_ip(server, cloud=None):
|
|||||||
# Short circuit the ports/networks search below with a heavily cached
|
# Short circuit the ports/networks search below with a heavily cached
|
||||||
# and possibly pre-configured network name
|
# and possibly pre-configured network name
|
||||||
if cloud:
|
if cloud:
|
||||||
int_nets = cloud.get_internal_networks()
|
int_nets = cloud.get_internal_ipv4_networks()
|
||||||
for int_net in int_nets:
|
for int_net in int_nets:
|
||||||
int_ip = get_server_ip(server, key_name=int_net['name'])
|
int_ip = get_server_ip(server, key_name=int_net['name'])
|
||||||
if int_ip is not None:
|
if int_ip is not None:
|
||||||
@ -123,7 +123,7 @@ def get_server_external_ipv4(cloud, server):
|
|||||||
|
|
||||||
# Short circuit the ports/networks search below with a heavily cached
|
# Short circuit the ports/networks search below with a heavily cached
|
||||||
# and possibly pre-configured network name
|
# and possibly pre-configured network name
|
||||||
ext_nets = cloud.get_external_networks()
|
ext_nets = cloud.get_external_ipv4_networks()
|
||||||
for ext_net in ext_nets:
|
for ext_net in ext_nets:
|
||||||
ext_ip = get_server_ip(server, key_name=ext_net['name'])
|
ext_ip = get_server_ip(server, key_name=ext_net['name'])
|
||||||
if ext_ip is not None:
|
if ext_ip is not None:
|
||||||
|
@ -147,8 +147,19 @@ class OpenStackCloud(object):
|
|||||||
self.secgroup_source = cloud_config.config['secgroup_source']
|
self.secgroup_source = cloud_config.config['secgroup_source']
|
||||||
self.force_ipv4 = cloud_config.force_ipv4
|
self.force_ipv4 = cloud_config.force_ipv4
|
||||||
|
|
||||||
|
# The first two aren't useful to us anymore, but we still do them
|
||||||
|
# because there are two methods that won't work without them
|
||||||
self._external_network_names = cloud_config.get_external_networks()
|
self._external_network_names = cloud_config.get_external_networks()
|
||||||
self._internal_network_names = cloud_config.get_internal_networks()
|
self._internal_network_names = cloud_config.get_internal_networks()
|
||||||
|
|
||||||
|
# Provide better error message for people with stale OCC
|
||||||
|
if cloud_config.get_external_ipv4_networks is None:
|
||||||
|
raise OpenStackCloudException(
|
||||||
|
"shade requires at least version 1.20.0 of os-client-config")
|
||||||
|
self._external_ipv4_names = cloud_config.get_external_ipv4_networks()
|
||||||
|
self._internal_ipv4_names = cloud_config.get_internal_ipv4_networks()
|
||||||
|
self._external_ipv6_names = cloud_config.get_external_ipv6_networks()
|
||||||
|
self._internal_ipv6_names = cloud_config.get_internal_ipv6_networks()
|
||||||
self._nat_destination = cloud_config.get_nat_destination()
|
self._nat_destination = cloud_config.get_nat_destination()
|
||||||
self._default_network = cloud_config.get_default_network()
|
self._default_network = cloud_config.get_default_network()
|
||||||
|
|
||||||
@ -1596,6 +1607,10 @@ class OpenStackCloud(object):
|
|||||||
with self._networks_lock:
|
with self._networks_lock:
|
||||||
self._external_networks = []
|
self._external_networks = []
|
||||||
self._internal_networks = []
|
self._internal_networks = []
|
||||||
|
self._external_ipv4_networks = []
|
||||||
|
self._internal_ipv4_networks = []
|
||||||
|
self._external_ipv6_networks = []
|
||||||
|
self._internal_ipv6_networks = []
|
||||||
self._nat_destination_network = None
|
self._nat_destination_network = None
|
||||||
self._default_network_network = None
|
self._default_network_network = None
|
||||||
self._network_list_stamp = False
|
self._network_list_stamp = False
|
||||||
@ -1603,6 +1618,10 @@ class OpenStackCloud(object):
|
|||||||
def _set_interesting_networks(self):
|
def _set_interesting_networks(self):
|
||||||
external_networks = []
|
external_networks = []
|
||||||
internal_networks = []
|
internal_networks = []
|
||||||
|
external_ipv4_networks = []
|
||||||
|
internal_ipv4_networks = []
|
||||||
|
external_ipv6_networks = []
|
||||||
|
internal_ipv6_networks = []
|
||||||
nat_destination = None
|
nat_destination = None
|
||||||
default_network = None
|
default_network = None
|
||||||
|
|
||||||
@ -1623,7 +1642,7 @@ class OpenStackCloud(object):
|
|||||||
return
|
return
|
||||||
|
|
||||||
for network in all_networks:
|
for network in all_networks:
|
||||||
# External networks
|
# Old External networks
|
||||||
if (network['name'] in self._external_network_names
|
if (network['name'] in self._external_network_names
|
||||||
or network['id'] in self._external_network_names):
|
or network['id'] in self._external_network_names):
|
||||||
external_networks.append(network)
|
external_networks.append(network)
|
||||||
@ -1634,7 +1653,7 @@ class OpenStackCloud(object):
|
|||||||
network['id'] not in self._internal_network_names):
|
network['id'] not in self._internal_network_names):
|
||||||
external_networks.append(network)
|
external_networks.append(network)
|
||||||
|
|
||||||
# Internal networks
|
# Old Internal networks
|
||||||
if (network['name'] in self._internal_network_names
|
if (network['name'] in self._internal_network_names
|
||||||
or network['id'] in self._internal_network_names):
|
or network['id'] in self._internal_network_names):
|
||||||
internal_networks.append(network)
|
internal_networks.append(network)
|
||||||
@ -1644,6 +1663,45 @@ class OpenStackCloud(object):
|
|||||||
network['id'] not in self._external_network_names):
|
network['id'] not in self._external_network_names):
|
||||||
internal_networks.append(network)
|
internal_networks.append(network)
|
||||||
|
|
||||||
|
# External IPv4 networks
|
||||||
|
if (network['name'] in self._external_ipv4_names
|
||||||
|
or network['id'] in self._external_ipv4_names):
|
||||||
|
external_ipv4_networks.append(network)
|
||||||
|
elif ((('router:external' in network
|
||||||
|
and network['router:external']) or
|
||||||
|
network.get('provider:physical_network')) and
|
||||||
|
network['name'] not in self._internal_ipv4_names and
|
||||||
|
network['id'] not in self._internal_ipv4_names):
|
||||||
|
external_ipv4_networks.append(network)
|
||||||
|
|
||||||
|
# Internal networks
|
||||||
|
if (network['name'] in self._internal_ipv4_names
|
||||||
|
or network['id'] in self._internal_ipv4_names):
|
||||||
|
internal_ipv4_networks.append(network)
|
||||||
|
elif (not network.get('router:external', False) and
|
||||||
|
not network.get('provider:physical_network') and
|
||||||
|
network['name'] not in self._external_ipv4_names and
|
||||||
|
network['id'] not in self._external_ipv4_names):
|
||||||
|
internal_ipv4_networks.append(network)
|
||||||
|
|
||||||
|
# External networks
|
||||||
|
if (network['name'] in self._external_ipv6_names
|
||||||
|
or network['id'] in self._external_ipv6_names):
|
||||||
|
external_ipv6_networks.append(network)
|
||||||
|
elif (network.get('router:external') and
|
||||||
|
network['name'] not in self._internal_ipv6_names and
|
||||||
|
network['id'] not in self._internal_ipv6_names):
|
||||||
|
external_ipv6_networks.append(network)
|
||||||
|
|
||||||
|
# Internal networks
|
||||||
|
if (network['name'] in self._internal_ipv6_names
|
||||||
|
or network['id'] in self._internal_ipv6_names):
|
||||||
|
internal_ipv6_networks.append(network)
|
||||||
|
elif (not network.get('router:external', False) and
|
||||||
|
network['name'] not in self._external_ipv6_names and
|
||||||
|
network['id'] not in self._external_ipv6_names):
|
||||||
|
internal_ipv6_networks.append(network)
|
||||||
|
|
||||||
# NAT Destination
|
# NAT Destination
|
||||||
if self._nat_destination in (
|
if self._nat_destination in (
|
||||||
network['name'], network['id']):
|
network['name'], network['id']):
|
||||||
@ -1707,6 +1765,34 @@ class OpenStackCloud(object):
|
|||||||
" access and those networks could not be found".format(
|
" access and those networks could not be found".format(
|
||||||
network=net_name))
|
network=net_name))
|
||||||
|
|
||||||
|
for net_name in self._external_ipv4_names:
|
||||||
|
if net_name not in [net['name'] for net in external_ipv4_networks]:
|
||||||
|
raise OpenStackCloudException(
|
||||||
|
"Networks: {network} was provided for external IPv4"
|
||||||
|
" access and those networks could not be found".format(
|
||||||
|
network=net_name))
|
||||||
|
|
||||||
|
for net_name in self._internal_ipv4_names:
|
||||||
|
if net_name not in [net['name'] for net in internal_ipv4_networks]:
|
||||||
|
raise OpenStackCloudException(
|
||||||
|
"Networks: {network} was provided for internal IPv4"
|
||||||
|
" access and those networks could not be found".format(
|
||||||
|
network=net_name))
|
||||||
|
|
||||||
|
for net_name in self._external_ipv6_names:
|
||||||
|
if net_name not in [net['name'] for net in external_ipv6_networks]:
|
||||||
|
raise OpenStackCloudException(
|
||||||
|
"Networks: {network} was provided for external IPv6"
|
||||||
|
" access and those networks could not be found".format(
|
||||||
|
network=net_name))
|
||||||
|
|
||||||
|
for net_name in self._internal_ipv6_names:
|
||||||
|
if net_name not in [net['name'] for net in internal_ipv6_networks]:
|
||||||
|
raise OpenStackCloudException(
|
||||||
|
"Networks: {network} was provided for internal IPv6"
|
||||||
|
" access and those networks could not be found".format(
|
||||||
|
network=net_name))
|
||||||
|
|
||||||
if self._nat_destination and not nat_destination:
|
if self._nat_destination and not nat_destination:
|
||||||
raise OpenStackCloudException(
|
raise OpenStackCloudException(
|
||||||
'Network {network} was configured to be the'
|
'Network {network} was configured to be the'
|
||||||
@ -1723,6 +1809,10 @@ class OpenStackCloud(object):
|
|||||||
|
|
||||||
self._external_networks = external_networks
|
self._external_networks = external_networks
|
||||||
self._internal_networks = internal_networks
|
self._internal_networks = internal_networks
|
||||||
|
self._external_ipv4_networks = external_ipv4_networks
|
||||||
|
self._internal_ipv4_networks = internal_ipv4_networks
|
||||||
|
self._external_ipv6_networks = external_ipv6_networks
|
||||||
|
self._internal_ipv6_networks = internal_ipv6_networks
|
||||||
self._nat_destination_network = nat_destination
|
self._nat_destination_network = nat_destination
|
||||||
self._default_network_network = default_network
|
self._default_network_network = default_network
|
||||||
|
|
||||||
@ -1761,6 +1851,9 @@ class OpenStackCloud(object):
|
|||||||
def get_external_networks(self):
|
def get_external_networks(self):
|
||||||
"""Return the networks that are configured to route northbound.
|
"""Return the networks that are configured to route northbound.
|
||||||
|
|
||||||
|
This should be avoided in favor of the specific ipv4/ipv6 method,
|
||||||
|
but is here for backwards compatibility.
|
||||||
|
|
||||||
:returns: A list of network ``munch.Munch`` if one is found
|
:returns: A list of network ``munch.Munch`` if one is found
|
||||||
"""
|
"""
|
||||||
self._find_interesting_networks()
|
self._find_interesting_networks()
|
||||||
@ -1769,11 +1862,46 @@ class OpenStackCloud(object):
|
|||||||
def get_internal_networks(self):
|
def get_internal_networks(self):
|
||||||
"""Return the networks that are configured to not route northbound.
|
"""Return the networks that are configured to not route northbound.
|
||||||
|
|
||||||
|
This should be avoided in favor of the specific ipv4/ipv6 method,
|
||||||
|
but is here for backwards compatibility.
|
||||||
|
|
||||||
:returns: A list of network ``munch.Munch`` if one is found
|
:returns: A list of network ``munch.Munch`` if one is found
|
||||||
"""
|
"""
|
||||||
self._find_interesting_networks()
|
self._find_interesting_networks()
|
||||||
return self._internal_networks
|
return self._internal_networks
|
||||||
|
|
||||||
|
def get_external_ipv4_networks(self):
|
||||||
|
"""Return the networks that are configured to route northbound.
|
||||||
|
|
||||||
|
:returns: A list of network ``munch.Munch`` if one is found
|
||||||
|
"""
|
||||||
|
self._find_interesting_networks()
|
||||||
|
return self._external_ipv4_networks
|
||||||
|
|
||||||
|
def get_internal_ipv4_networks(self):
|
||||||
|
"""Return the networks that are configured to not route northbound.
|
||||||
|
|
||||||
|
:returns: A list of network ``munch.Munch`` if one is found
|
||||||
|
"""
|
||||||
|
self._find_interesting_networks()
|
||||||
|
return self._internal_ipv4_networks
|
||||||
|
|
||||||
|
def get_external_ipv6_networks(self):
|
||||||
|
"""Return the networks that are configured to route northbound.
|
||||||
|
|
||||||
|
:returns: A list of network ``munch.Munch`` if one is found
|
||||||
|
"""
|
||||||
|
self._find_interesting_networks()
|
||||||
|
return self._external_ipv6_networks
|
||||||
|
|
||||||
|
def get_internal_ipv6_networks(self):
|
||||||
|
"""Return the networks that are configured to not route northbound.
|
||||||
|
|
||||||
|
:returns: A list of network ``munch.Munch`` if one is found
|
||||||
|
"""
|
||||||
|
self._find_interesting_networks()
|
||||||
|
return self._internal_ipv6_networks
|
||||||
|
|
||||||
def _has_floating_ips(self):
|
def _has_floating_ips(self):
|
||||||
if not self._floating_ip_source:
|
if not self._floating_ip_source:
|
||||||
return False
|
return False
|
||||||
@ -3393,7 +3521,7 @@ class OpenStackCloud(object):
|
|||||||
# Use given list to get first matching external network
|
# Use given list to get first matching external network
|
||||||
floating_network_id = None
|
floating_network_id = None
|
||||||
for net in network:
|
for net in network:
|
||||||
for ext_net in self.get_external_networks():
|
for ext_net in self.get_external_ipv4_networks():
|
||||||
if net in (ext_net['name'], ext_net['id']):
|
if net in (ext_net['name'], ext_net['id']):
|
||||||
floating_network_id = ext_net['id']
|
floating_network_id = ext_net['id']
|
||||||
break
|
break
|
||||||
@ -3406,8 +3534,8 @@ class OpenStackCloud(object):
|
|||||||
net=network)
|
net=network)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# Get first existing external network
|
# Get first existing external IPv4 network
|
||||||
networks = self.get_external_networks()
|
networks = self.get_external_ipv4_networks()
|
||||||
if not networks:
|
if not networks:
|
||||||
raise OpenStackCloudResourceNotFound(
|
raise OpenStackCloudResourceNotFound(
|
||||||
"unable to find an external network")
|
"unable to find an external network")
|
||||||
@ -3549,7 +3677,7 @@ class OpenStackCloud(object):
|
|||||||
"unable to find network for floating ips with id "
|
"unable to find network for floating ips with id "
|
||||||
"{0}".format(network_name_or_id))
|
"{0}".format(network_name_or_id))
|
||||||
else:
|
else:
|
||||||
networks = self.get_external_networks()
|
networks = self.get_external_ipv4_networks()
|
||||||
if not networks:
|
if not networks:
|
||||||
raise OpenStackCloudResourceNotFound(
|
raise OpenStackCloudResourceNotFound(
|
||||||
"Unable to find an external network in this cloud"
|
"Unable to find an external network in this cloud"
|
||||||
@ -4185,8 +4313,7 @@ class OpenStackCloud(object):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
# No external IPv4 network - no FIPs
|
# No external IPv4 network - no FIPs
|
||||||
# TODO(mordred) THIS IS get_external_ipv4_networks IN THE NEXT PATCH
|
networks = self.get_external_ipv4_networks()
|
||||||
networks = self.get_external_networks()
|
|
||||||
if not networks:
|
if not networks:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -214,6 +214,9 @@ class TestFloatingIP(base.TestCase):
|
|||||||
|
|
||||||
mock_nova_client.servers.get.return_value = server
|
mock_nova_client.servers.get.return_value = server
|
||||||
# TODO(mordred) REMOVE THIS MOCK WHEN THE NEXT PATCH LANDS
|
# TODO(mordred) REMOVE THIS MOCK WHEN THE NEXT PATCH LANDS
|
||||||
|
# SERIOUSLY THIS TIME. NEXT PATCH - WHICH SHOULD ADD MOCKS FOR
|
||||||
|
# list_ports AND list_networks AND list_subnets. BUT THAT WOULD
|
||||||
|
# BE NOT ACTUALLY RELATED TO THIS PATCH. SO DO IT NEXT PATCH
|
||||||
mock_needs_floating_ip.return_value = True
|
mock_needs_floating_ip.return_value = True
|
||||||
|
|
||||||
self.cloud.add_ips_to_server(server_dict)
|
self.cloud.add_ips_to_server(server_dict)
|
||||||
|
@ -303,7 +303,7 @@ class TestFloatingIP(base.TestCase):
|
|||||||
@patch.object(_utils, '_filter_list')
|
@patch.object(_utils, '_filter_list')
|
||||||
@patch.object(OpenStackCloud, '_neutron_create_floating_ip')
|
@patch.object(OpenStackCloud, '_neutron_create_floating_ip')
|
||||||
@patch.object(OpenStackCloud, '_neutron_list_floating_ips')
|
@patch.object(OpenStackCloud, '_neutron_list_floating_ips')
|
||||||
@patch.object(OpenStackCloud, 'get_external_networks')
|
@patch.object(OpenStackCloud, 'get_external_ipv4_networks')
|
||||||
@patch.object(OpenStackCloud, 'keystone_session')
|
@patch.object(OpenStackCloud, 'keystone_session')
|
||||||
def test__neutron_available_floating_ips(
|
def test__neutron_available_floating_ips(
|
||||||
self,
|
self,
|
||||||
@ -340,7 +340,7 @@ class TestFloatingIP(base.TestCase):
|
|||||||
@patch.object(_utils, '_filter_list')
|
@patch.object(_utils, '_filter_list')
|
||||||
@patch.object(OpenStackCloud, '_neutron_create_floating_ip')
|
@patch.object(OpenStackCloud, '_neutron_create_floating_ip')
|
||||||
@patch.object(OpenStackCloud, '_neutron_list_floating_ips')
|
@patch.object(OpenStackCloud, '_neutron_list_floating_ips')
|
||||||
@patch.object(OpenStackCloud, 'get_external_networks')
|
@patch.object(OpenStackCloud, 'get_external_ipv4_networks')
|
||||||
@patch.object(OpenStackCloud, 'keystone_session')
|
@patch.object(OpenStackCloud, 'keystone_session')
|
||||||
def test__neutron_available_floating_ips_network(
|
def test__neutron_available_floating_ips_network(
|
||||||
self,
|
self,
|
||||||
@ -375,7 +375,7 @@ class TestFloatingIP(base.TestCase):
|
|||||||
server=None
|
server=None
|
||||||
)
|
)
|
||||||
|
|
||||||
@patch.object(OpenStackCloud, 'get_external_networks')
|
@patch.object(OpenStackCloud, 'get_external_ipv4_networks')
|
||||||
@patch.object(OpenStackCloud, 'keystone_session')
|
@patch.object(OpenStackCloud, 'keystone_session')
|
||||||
def test__neutron_available_floating_ips_invalid_network(
|
def test__neutron_available_floating_ips_invalid_network(
|
||||||
self,
|
self,
|
||||||
@ -621,7 +621,7 @@ class TestFloatingIP(base.TestCase):
|
|||||||
|
|
||||||
@patch.object(OpenStackCloud, '_submit_create_fip')
|
@patch.object(OpenStackCloud, '_submit_create_fip')
|
||||||
@patch.object(OpenStackCloud, '_nat_destination_port')
|
@patch.object(OpenStackCloud, '_nat_destination_port')
|
||||||
@patch.object(OpenStackCloud, 'get_external_networks')
|
@patch.object(OpenStackCloud, 'get_external_ipv4_networks')
|
||||||
def test_create_floating_ip_no_port(
|
def test_create_floating_ip_no_port(
|
||||||
self, mock_get_ext_nets, mock_nat_destination_port,
|
self, mock_get_ext_nets, mock_nat_destination_port,
|
||||||
mock_submit_create_fip):
|
mock_submit_create_fip):
|
||||||
|
@ -61,6 +61,18 @@ class FakeCloud(object):
|
|||||||
def get_external_networks(self):
|
def get_external_networks(self):
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
def get_internal_ipv4_networks(self):
|
||||||
|
return []
|
||||||
|
|
||||||
|
def get_external_ipv4_networks(self):
|
||||||
|
return []
|
||||||
|
|
||||||
|
def get_internal_ipv6_networks(self):
|
||||||
|
return []
|
||||||
|
|
||||||
|
def get_external_ipv6_networks(self):
|
||||||
|
return []
|
||||||
|
|
||||||
def list_server_security_groups(self, server):
|
def list_server_security_groups(self, server):
|
||||||
return []
|
return []
|
||||||
|
|
||||||
@ -107,6 +119,116 @@ SUBNETS_WITH_NAT = [
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
OSIC_NETWORKS = [
|
||||||
|
{
|
||||||
|
u'admin_state_up': True,
|
||||||
|
u'id': u'7004a83a-13d3-4dcd-8cf5-52af1ace4cae',
|
||||||
|
u'mtu': 0,
|
||||||
|
u'name': u'GATEWAY_NET',
|
||||||
|
u'router:external': True,
|
||||||
|
u'shared': True,
|
||||||
|
u'status': u'ACTIVE',
|
||||||
|
u'subnets': [u'cf785ee0-6cc9-4712-be3d-0bf6c86cf455'],
|
||||||
|
u'tenant_id': u'7a1ca9f7cc4e4b13ac0ed2957f1e8c32'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
u'admin_state_up': True,
|
||||||
|
u'id': u'405abfcc-77dc-49b2-a271-139619ac9b26',
|
||||||
|
u'mtu': 0,
|
||||||
|
u'name': u'openstackjenkins-network1',
|
||||||
|
u'router:external': False,
|
||||||
|
u'shared': False,
|
||||||
|
u'status': u'ACTIVE',
|
||||||
|
u'subnets': [u'a47910bc-f649-45db-98ec-e2421c413f4e'],
|
||||||
|
u'tenant_id': u'7e9c4d5842b3451d94417bd0af03a0f4'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
u'admin_state_up': True,
|
||||||
|
u'id': u'54753d2c-0a58-4928-9b32-084c59dd20a6',
|
||||||
|
u'mtu': 0,
|
||||||
|
u'name': u'GATEWAY_NET_V6',
|
||||||
|
u'router:external': True,
|
||||||
|
u'shared': True,
|
||||||
|
u'status': u'ACTIVE',
|
||||||
|
u'subnets': [u'9c21d704-a8b9-409a-b56d-501cb518d380',
|
||||||
|
u'7cb0ce07-64c3-4a3d-92d3-6f11419b45b9'],
|
||||||
|
u'tenant_id': u'7a1ca9f7cc4e4b13ac0ed2957f1e8c32'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
OSIC_SUBNETS = [
|
||||||
|
{
|
||||||
|
u'allocation_pools': [{
|
||||||
|
u'end': u'172.99.106.254',
|
||||||
|
u'start': u'172.99.106.5'}],
|
||||||
|
u'cidr': u'172.99.106.0/24',
|
||||||
|
u'dns_nameservers': [u'69.20.0.164', u'69.20.0.196'],
|
||||||
|
u'enable_dhcp': True,
|
||||||
|
u'gateway_ip': u'172.99.106.1',
|
||||||
|
u'host_routes': [],
|
||||||
|
u'id': u'cf785ee0-6cc9-4712-be3d-0bf6c86cf455',
|
||||||
|
u'ip_version': 4,
|
||||||
|
u'ipv6_address_mode': None,
|
||||||
|
u'ipv6_ra_mode': None,
|
||||||
|
u'name': u'GATEWAY_NET',
|
||||||
|
u'network_id': u'7004a83a-13d3-4dcd-8cf5-52af1ace4cae',
|
||||||
|
u'subnetpool_id': None,
|
||||||
|
u'tenant_id': u'7a1ca9f7cc4e4b13ac0ed2957f1e8c32'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
u'allocation_pools': [{
|
||||||
|
u'end': u'10.0.1.254', u'start': u'10.0.1.2'}],
|
||||||
|
u'cidr': u'10.0.1.0/24',
|
||||||
|
u'dns_nameservers': [u'8.8.8.8', u'8.8.4.4'],
|
||||||
|
u'enable_dhcp': True,
|
||||||
|
u'gateway_ip': u'10.0.1.1',
|
||||||
|
u'host_routes': [],
|
||||||
|
u'id': u'a47910bc-f649-45db-98ec-e2421c413f4e',
|
||||||
|
u'ip_version': 4,
|
||||||
|
u'ipv6_address_mode': None,
|
||||||
|
u'ipv6_ra_mode': None,
|
||||||
|
u'name': u'openstackjenkins-subnet1',
|
||||||
|
u'network_id': u'405abfcc-77dc-49b2-a271-139619ac9b26',
|
||||||
|
u'subnetpool_id': None,
|
||||||
|
u'tenant_id': u'7e9c4d5842b3451d94417bd0af03a0f4'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
u'allocation_pools': [{
|
||||||
|
u'end': u'10.255.255.254', u'start': u'10.0.0.2'}],
|
||||||
|
u'cidr': u'10.0.0.0/8',
|
||||||
|
u'dns_nameservers': [u'8.8.8.8', u'8.8.4.4'],
|
||||||
|
u'enable_dhcp': True,
|
||||||
|
u'gateway_ip': u'10.0.0.1',
|
||||||
|
u'host_routes': [],
|
||||||
|
u'id': u'9c21d704-a8b9-409a-b56d-501cb518d380',
|
||||||
|
u'ip_version': 4,
|
||||||
|
u'ipv6_address_mode': None,
|
||||||
|
u'ipv6_ra_mode': None,
|
||||||
|
u'name': u'GATEWAY_SUBNET_V6V4',
|
||||||
|
u'network_id': u'54753d2c-0a58-4928-9b32-084c59dd20a6',
|
||||||
|
u'subnetpool_id': None,
|
||||||
|
u'tenant_id': u'7a1ca9f7cc4e4b13ac0ed2957f1e8c32'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
u'allocation_pools': [{
|
||||||
|
u'end': u'2001:4800:1ae1:18:ffff:ffff:ffff:ffff',
|
||||||
|
u'start': u'2001:4800:1ae1:18::2'}],
|
||||||
|
u'cidr': u'2001:4800:1ae1:18::/64',
|
||||||
|
u'dns_nameservers': [u'2001:4860:4860::8888'],
|
||||||
|
u'enable_dhcp': True,
|
||||||
|
u'gateway_ip': u'2001:4800:1ae1:18::1',
|
||||||
|
u'host_routes': [],
|
||||||
|
u'id': u'7cb0ce07-64c3-4a3d-92d3-6f11419b45b9',
|
||||||
|
u'ip_version': 6,
|
||||||
|
u'ipv6_address_mode': u'dhcpv6-stateless',
|
||||||
|
u'ipv6_ra_mode': None,
|
||||||
|
u'name': u'GATEWAY_SUBNET_V6V6',
|
||||||
|
u'network_id': u'54753d2c-0a58-4928-9b32-084c59dd20a6',
|
||||||
|
u'subnetpool_id': None,
|
||||||
|
u'tenant_id': u'7a1ca9f7cc4e4b13ac0ed2957f1e8c32'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class TestMeta(base.TestCase):
|
class TestMeta(base.TestCase):
|
||||||
def test_find_nova_addresses_key_name(self):
|
def test_find_nova_addresses_key_name(self):
|
||||||
@ -394,6 +516,61 @@ class TestMeta(base.TestCase):
|
|||||||
mock_list_networks.assert_not_called()
|
mock_list_networks.assert_not_called()
|
||||||
mock_list_floating_ips.assert_not_called()
|
mock_list_floating_ips.assert_not_called()
|
||||||
|
|
||||||
|
@mock.patch.object(shade.OpenStackCloud, 'list_floating_ips')
|
||||||
|
@mock.patch.object(shade.OpenStackCloud, 'list_subnets')
|
||||||
|
@mock.patch.object(shade.OpenStackCloud, 'list_server_security_groups')
|
||||||
|
@mock.patch.object(shade.OpenStackCloud, 'get_image_name')
|
||||||
|
@mock.patch.object(shade.OpenStackCloud, 'get_flavor_name')
|
||||||
|
@mock.patch.object(shade.OpenStackCloud, 'has_service')
|
||||||
|
@mock.patch.object(shade.OpenStackCloud, 'list_networks')
|
||||||
|
def test_get_server_cloud_osic_split(
|
||||||
|
self, mock_list_networks, mock_has_service,
|
||||||
|
mock_get_flavor_name, mock_get_image_name,
|
||||||
|
mock_list_server_security_groups,
|
||||||
|
mock_list_subnets,
|
||||||
|
mock_list_floating_ips):
|
||||||
|
self.cloud._floating_ip_source = None
|
||||||
|
self.cloud.force_ipv4 = False
|
||||||
|
self.cloud._local_ipv6 = True
|
||||||
|
self.cloud._external_ipv4_names = ['GATEWAY_NET']
|
||||||
|
self.cloud._external_ipv6_names = ['GATEWAY_NET_V6']
|
||||||
|
self.cloud._internal_ipv4_names = ['GATEWAY_NET_V6']
|
||||||
|
self.cloud._internal_ipv6_names = []
|
||||||
|
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_list_subnets.return_value = OSIC_SUBNETS
|
||||||
|
mock_list_networks.return_value = OSIC_NETWORKS
|
||||||
|
|
||||||
|
srv = self.cloud.get_openstack_vars(meta.obj_to_dict(fakes.FakeServer(
|
||||||
|
id='test-id', name='test-name', status='ACTIVE',
|
||||||
|
flavor={u'id': u'1'},
|
||||||
|
image={
|
||||||
|
'name': u'cirros-0.3.4-x86_64-uec',
|
||||||
|
u'id': u'f93d000b-7c29-4489-b375-3641a1758fe1'},
|
||||||
|
addresses={
|
||||||
|
'private': [{
|
||||||
|
'addr': "10.223.160.141",
|
||||||
|
'version': 4
|
||||||
|
}],
|
||||||
|
'public': [{
|
||||||
|
'addr': "104.130.246.91",
|
||||||
|
'version': 4
|
||||||
|
}, {
|
||||||
|
'addr': "2001:4800:7819:103:be76:4eff:fe05:8525",
|
||||||
|
'version': 6
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
)))
|
||||||
|
|
||||||
|
self.assertEqual("10.223.160.141", srv['private_v4'])
|
||||||
|
self.assertEqual("104.130.246.91", srv['public_v4'])
|
||||||
|
self.assertEqual(
|
||||||
|
"2001:4800:7819:103:be76:4eff:fe05:8525", srv['public_v6'])
|
||||||
|
self.assertEqual(
|
||||||
|
"2001:4800:7819:103:be76:4eff:fe05:8525", srv['interface_ip'])
|
||||||
|
mock_list_floating_ips.assert_not_called()
|
||||||
|
|
||||||
@mock.patch.object(shade.OpenStackCloud, 'has_service')
|
@mock.patch.object(shade.OpenStackCloud, 'has_service')
|
||||||
@mock.patch.object(shade.OpenStackCloud, 'list_subnets')
|
@mock.patch.object(shade.OpenStackCloud, 'list_subnets')
|
||||||
@mock.patch.object(shade.OpenStackCloud, 'list_networks')
|
@mock.patch.object(shade.OpenStackCloud, 'list_networks')
|
||||||
|
Loading…
x
Reference in New Issue
Block a user