Return IPv6 address for interface_ip on request
If the local host looks like it can route IPv6 and we have an IPv6 address, and the user has not indicated that they must use IPv4 for some reason, return it to them in the interface_ip field. Also, always return something in interface_ip if possible. Change-Id: I3544280cab7abfa6b4154244f4c4588bc65c7347 Depends-On: Ib0c4c4e8b3b7b4bcee5fa3414719969274929b9a Co-Authored-By: James E. Blair <jeblair@linux.vnet.ibm.com>
This commit is contained in:
parent
0a06226863
commit
5a420350db
@ -3,10 +3,11 @@ pbr>=0.11,<2.0
|
||||
bunch
|
||||
decorator
|
||||
jsonpatch
|
||||
os-client-config>=1.7.4
|
||||
os-client-config>=1.8.0
|
||||
six
|
||||
|
||||
keystoneauth1>=1.0.0
|
||||
netifaces>=0.10.4
|
||||
python-novaclient>=2.21.0,!=2.27.0
|
||||
python-keystoneclient>=0.11.0
|
||||
python-glanceclient>=1.0.0
|
||||
|
@ -246,6 +246,7 @@ class OpenStackCloud(object):
|
||||
self.api_timeout = cloud_config.config['api_timeout']
|
||||
self.image_api_use_tasks = cloud_config.config['image_api_use_tasks']
|
||||
self.secgroup_source = cloud_config.config['secgroup_source']
|
||||
self.force_ipv4 = cloud_config.force_ipv4
|
||||
|
||||
self._external_network = None
|
||||
self._external_network_name_or_id = cloud_config.config.get(
|
||||
@ -295,6 +296,8 @@ class OpenStackCloud(object):
|
||||
self._swift_service = None
|
||||
self._trove_client = None
|
||||
|
||||
self._local_ipv6 = _utils.localhost_supports_ipv6()
|
||||
|
||||
self.cloud_config = cloud_config
|
||||
|
||||
@contextlib.contextmanager
|
||||
|
@ -15,6 +15,7 @@
|
||||
import re
|
||||
import time
|
||||
|
||||
import netifaces
|
||||
from socket import inet_aton
|
||||
from struct import unpack
|
||||
|
||||
@ -273,3 +274,14 @@ def normalize_neutron_floating_ips(ips):
|
||||
ip.get('port_id') != ''),
|
||||
status=ip['status']
|
||||
) for ip in ips]
|
||||
|
||||
|
||||
def localhost_supports_ipv6():
|
||||
"""Determine whether the local host supports IPv6
|
||||
|
||||
We look for a default route that supports the IPv6 address family,
|
||||
and assume that if it is present, this host has globally routable
|
||||
IPv6 connectivity.
|
||||
"""
|
||||
|
||||
return netifaces.AF_INET6 in netifaces.gateways()['default']
|
||||
|
@ -265,10 +265,15 @@ def get_hostvars_from_server(cloud, server, mounts=None):
|
||||
server_vars['public_v4'] = get_server_external_ipv4(cloud, server) or ''
|
||||
server_vars['public_v6'] = get_server_external_ipv6(server) or ''
|
||||
server_vars['private_v4'] = get_server_private_ip(server, cloud) or ''
|
||||
if cloud.private:
|
||||
interface_ip = None
|
||||
if cloud.private and server_vars['private_v4']:
|
||||
interface_ip = server_vars['private_v4']
|
||||
else:
|
||||
interface_ip = server_vars['public_v4']
|
||||
if (server_vars['public_v6'] and cloud._local_ipv6
|
||||
and not cloud.force_ipv4):
|
||||
interface_ip = server_vars['public_v6']
|
||||
else:
|
||||
interface_ip = server_vars['public_v4']
|
||||
if interface_ip:
|
||||
server_vars['interface_ip'] = interface_ip
|
||||
|
||||
@ -276,7 +281,10 @@ def get_hostvars_from_server(cloud, server, mounts=None):
|
||||
# server record. Since we know them, go ahead and set them. In the case
|
||||
# where they were set previous, we use the values, so this will not break
|
||||
# clouds that provide the information
|
||||
server_vars['accessIPv4'] = server_vars['public_v4']
|
||||
if cloud.private and server_vars['private_v4']:
|
||||
server_vars['accessIPv4'] = server_vars['private_v4']
|
||||
else:
|
||||
server_vars['accessIPv4'] = server_vars['public_v4']
|
||||
server_vars['accessIPv6'] = server_vars['public_v6']
|
||||
|
||||
server_vars['region'] = cloud.region_name
|
||||
|
@ -32,8 +32,10 @@ class FakeCloud(object):
|
||||
region_name = 'test-region'
|
||||
name = 'test-name'
|
||||
private = False
|
||||
force_ipv4 = False
|
||||
service_val = True
|
||||
_unused = "useless"
|
||||
_local_ipv6 = True
|
||||
|
||||
def get_flavor_name(self, id):
|
||||
return 'test-flavor-name'
|
||||
@ -319,7 +321,7 @@ class TestMeta(testtools.TestCase):
|
||||
self.assertEqual(PRIVATE_V4, hostvars['private_v4'])
|
||||
self.assertEqual(PUBLIC_V4, hostvars['public_v4'])
|
||||
self.assertEqual(PUBLIC_V6, hostvars['public_v6'])
|
||||
self.assertEqual(PUBLIC_V4, hostvars['interface_ip'])
|
||||
self.assertEqual(PUBLIC_V6, hostvars['interface_ip'])
|
||||
self.assertEquals(FakeCloud.region_name, hostvars['region'])
|
||||
self.assertEquals(FakeCloud.name, hostvars['cloud'])
|
||||
self.assertEquals("test-image-name", hostvars['image']['name'])
|
||||
@ -332,6 +334,20 @@ class TestMeta(testtools.TestCase):
|
||||
# test volume exception
|
||||
self.assertEquals([], hostvars['volumes'])
|
||||
|
||||
@mock.patch.object(shade.meta, 'get_server_external_ipv6')
|
||||
@mock.patch.object(shade.meta, 'get_server_external_ipv4')
|
||||
def test_ipv4_hostvars(
|
||||
self, mock_get_server_external_ipv4,
|
||||
mock_get_server_external_ipv6):
|
||||
mock_get_server_external_ipv4.return_value = PUBLIC_V4
|
||||
mock_get_server_external_ipv6.return_value = PUBLIC_V6
|
||||
|
||||
fake_cloud = FakeCloud()
|
||||
fake_cloud.force_ipv4 = True
|
||||
hostvars = meta.get_hostvars_from_server(
|
||||
fake_cloud, meta.obj_to_dict(FakeServer()))
|
||||
self.assertEqual(PUBLIC_V4, hostvars['interface_ip'])
|
||||
|
||||
@mock.patch.object(shade.meta, 'get_server_external_ipv4')
|
||||
def test_private_interface_ip(self, mock_get_server_external_ipv4):
|
||||
mock_get_server_external_ipv4.return_value = PUBLIC_V4
|
||||
|
2
tox.ini
2
tox.ini
@ -32,7 +32,7 @@ commands = python setup.py testr --coverage --testr-args='{posargs}'
|
||||
|
||||
[flake8]
|
||||
# Infra does not follow hacking, nor the broken E12* things
|
||||
ignore = E123,E125,H
|
||||
ignore = E123,E125,E129,H
|
||||
show-source = True
|
||||
builtins = _
|
||||
exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,build
|
||||
|
Loading…
x
Reference in New Issue
Block a user