diff --git a/neutron/common/ipv6_utils.py b/neutron/common/ipv6_utils.py index ee715af0786..a2ab7303a60 100644 --- a/neutron/common/ipv6_utils.py +++ b/neutron/common/ipv6_utils.py @@ -16,6 +16,8 @@ """ IPv6-related utilities and helper functions. """ +import ipaddress + import netaddr from neutron_lib import constants as const from oslo_log import log @@ -56,3 +58,19 @@ def valid_ipv6_url(host, port): else: uri = '%s:%s' % (host, port) return uri + + +# TODO(egarciar): Remove and use oslo.utils version of this function whenever +# it is available for Neutron. +# https://review.opendev.org/c/openstack/oslo.utils/+/925469 +def get_noscope_ipv6(address): + try: + _ipv6 = ipaddress.IPv6Address(address) + if _ipv6.scope_id: + address = address.removesuffix('%' + _ipv6.scope_id) + return address + except (ipaddress.AddressValueError, AttributeError): + if netutils.is_valid_ipv6(address): + parts = address.rsplit("%", 1) + return parts[0] + raise diff --git a/neutron/common/ovn/utils.py b/neutron/common/ovn/utils.py index 9e42a5fe6e8..232079328bb 100644 --- a/neutron/common/ovn/utils.py +++ b/neutron/common/ovn/utils.py @@ -44,6 +44,7 @@ import tenacity from neutron._i18n import _ from neutron.common import _constants as n_const +from neutron.common import ipv6_utils from neutron.common.ovn import constants from neutron.common.ovn import exceptions as ovn_exc from neutron.common import utils as common_utils @@ -675,6 +676,8 @@ def get_system_dns_resolvers(resolver_file=DNS_RESOLVER_FILE): valid_ip = (netutils.is_valid_ipv4(line, strict=True) or netutils.is_valid_ipv6(line)) if valid_ip: + if netutils.is_valid_ipv6(line): + line = ipv6_utils.get_noscope_ipv6(line) resolvers.append(line) return resolvers diff --git a/neutron/tests/unit/common/test_ipv6_utils.py b/neutron/tests/unit/common/test_ipv6_utils.py index 09eda127b70..0041ccbc368 100644 --- a/neutron/tests/unit/common/test_ipv6_utils.py +++ b/neutron/tests/unit/common/test_ipv6_utils.py @@ -98,3 +98,16 @@ class TestValidIpv6URL(base.BaseTestCase): port = 443 self.assertEqual("controller:443", ipv6_utils.valid_ipv6_url(host, port)) + + +class TestNoscopeIpv6(base.BaseTestCase): + def test_get_noscope_ipv6(self): + self.assertEqual('2001:db8::f0:42:8329', + ipv6_utils.get_noscope_ipv6('2001:db8::f0:42:8329%1')) + self.assertEqual('ff02::5678', + ipv6_utils.get_noscope_ipv6('ff02::5678%eth0')) + self.assertEqual('fe80::1', + ipv6_utils.get_noscope_ipv6('fe80::1%eth0')) + self.assertEqual('::1', ipv6_utils.get_noscope_ipv6('::1%eth0')) + self.assertEqual('::1', ipv6_utils.get_noscope_ipv6('::1')) + self.assertRaises(ValueError, ipv6_utils.get_noscope_ipv6, '::132:::')