From 85588ad38e3a08137f4f7b4be98ce271064eb2f0 Mon Sep 17 00:00:00 2001 From: aojeagarcia Date: Sun, 7 Oct 2018 23:17:08 +0200 Subject: [PATCH] Allow Ipv6 addresses for nova_metadata_host Current logic didn't check if the nova_metadata_host is an IPv6 address causing the proxy request to fail with an exception because the url is not valid. This patchs check if the nova_metadata_host is an IPv6 address and create a valid url enclosing the IPv6 address with brackets Closes-Bug: #1796593 Change-Id: Ibfebffcec2c8860237a1f151084de978a7863bd8 Signed-off-by: aojeagarcia --- neutron/agent/metadata/agent.py | 7 ++++-- neutron/common/ipv6_utils.py | 12 ++++++++++ neutron/tests/unit/common/test_ipv6_utils.py | 25 ++++++++++++++++++++ 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/neutron/agent/metadata/agent.py b/neutron/agent/metadata/agent.py index a129cd9c187..d0b5a83e465 100644 --- a/neutron/agent/metadata/agent.py +++ b/neutron/agent/metadata/agent.py @@ -33,6 +33,7 @@ from neutron.agent.linux import utils as agent_utils from neutron.agent import rpc as agent_rpc from neutron.common import cache_utils as cache from neutron.common import constants as n_const +from neutron.common import ipv6_utils from neutron.common import rpc as n_rpc from neutron.conf.agent.metadata import config @@ -177,8 +178,10 @@ class MetadataProxyHandler(object): 'X-Instance-ID-Signature': self._sign_instance_id(instance_id) } - nova_host_port = '%s:%s' % (self.conf.nova_metadata_host, - self.conf.nova_metadata_port) + nova_host_port = ipv6_utils.valid_ipv6_url( + self.conf.nova_metadata_host, + self.conf.nova_metadata_port) + url = urllib.parse.urlunsplit(( self.conf.nova_metadata_protocol, nova_host_port, diff --git a/neutron/common/ipv6_utils.py b/neutron/common/ipv6_utils.py index bb4f1708dc5..ead55e44ec6 100644 --- a/neutron/common/ipv6_utils.py +++ b/neutron/common/ipv6_utils.py @@ -69,3 +69,15 @@ def is_ipv6_pd_enabled(subnet): constants.IPV6_PD_POOL_ID """ return subnet.get('subnetpool_id') == const.IPV6_PD_POOL_ID + + +def valid_ipv6_url(host, port): + """Given a host and a port returns a valid URL + RFC2732 https://tools.ietf.org/html/rfc2732 + square brackets always required in ipv6 URI. + """ + if netaddr.valid_ipv6(host): + uri = '[%s]:%s' % (host, port) + else: + uri = '%s:%s' % (host, port) + return uri diff --git a/neutron/tests/unit/common/test_ipv6_utils.py b/neutron/tests/unit/common/test_ipv6_utils.py index 28240c941d1..0257a3a20b6 100644 --- a/neutron/tests/unit/common/test_ipv6_utils.py +++ b/neutron/tests/unit/common/test_ipv6_utils.py @@ -113,3 +113,28 @@ class TestIsEui64Address(base.BaseTestCase): 'fffe::0cad:12fe:fe44:5566', 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff') self._test_eui_64(ips, False) + + +class TestValidIpv6URL(base.BaseTestCase): + + def test_valid_ipv6_url(self): + host = "::1" + port = 443 + self.assertEqual("[::1]:443", ipv6_utils.valid_ipv6_url(host, port)) + + def test_invalid_ipv6_url(self): + host = "::1" + port = 443 + self.assertNotEqual("::1:443", ipv6_utils.valid_ipv6_url(host, port)) + + def test_valid_ipv4_url(self): + host = "192.168.1.2" + port = 443 + self.assertEqual("192.168.1.2:443", + ipv6_utils.valid_ipv6_url(host, port)) + + def test_valid_hostname_url(self): + host = "controller" + port = 443 + self.assertEqual("controller:443", + ipv6_utils.valid_ipv6_url(host, port))