From 1ed8609a6818d99133bf56483adb9bce8c886fd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elvira=20Garc=C3=ADa?= Date: Fri, 9 Aug 2024 18:16:59 +0200 Subject: [PATCH] Get ips from system dns resolver without scope MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently, is_valid_ipv6 accepts ipv6 addresses with scope. However netaddr library won't accept an address with scope. Now, get_noscope_ipv6() can be used to avoid this situation. In a future we will be able to use the same function which is also being defined on oslo.utils. https://review.opendev.org/c/openstack/oslo.utils/+/925469 Closes-Bug: #2073894 Signed-off-by: Elvira GarcĂ­a Change-Id: I27f25f90c54d7aaa3c4a7b5317b4b8a4122e4068 --- neutron/common/ipv6_utils.py | 18 ++++++++++++++++++ neutron/common/ovn/utils.py | 3 +++ neutron/tests/unit/common/test_ipv6_utils.py | 13 +++++++++++++ 3 files changed, 34 insertions(+) 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:::')