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))