Get ips from system dns resolver without scope

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 <egarciar@redhat.com>
Change-Id: I27f25f90c54d7aaa3c4a7b5317b4b8a4122e4068
(cherry picked from commit 1ed8609a6818d99133bf56483adb9bce8c886fd6)
This commit is contained in:
Elvira García 2024-08-09 18:16:59 +02:00 committed by Elvira García Ruiz
parent d0f11ca346
commit 6f77c811f7
3 changed files with 34 additions and 0 deletions
neutron
common
tests/unit/common

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

@ -41,6 +41,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
@ -605,6 +606,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

@ -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:::')