From 076aaac87f6478a95bfb156bd674dfd0558f6782 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elvira=20Garc=C3=ADa?= Date: Thu, 1 Aug 2024 13:21:42 +0200 Subject: [PATCH] Add a function to trim scope out of ipv6 addr Currently, is_valid_ipv6 accepts ipv6 addresses with scope. However, there are functions that won't accept an address with scope. An example of this would be the netaddress.IPAdress() function used in Neutron. Related-Bug: #2073894 Change-Id: If2757dfc91f5b4c8257dee49d6da1e216b3e7cd8 --- oslo_utils/netutils.py | 25 +++++++++++++++++++ oslo_utils/tests/test_netutils.py | 10 ++++++++ .../notes/bug-2073894-2e11ca85984b7bb7.yaml | 7 ++++++ 3 files changed, 42 insertions(+) create mode 100644 releasenotes/notes/bug-2073894-2e11ca85984b7bb7.yaml diff --git a/oslo_utils/netutils.py b/oslo_utils/netutils.py index 017a416a..6e4c54c1 100644 --- a/oslo_utils/netutils.py +++ b/oslo_utils/netutils.py @@ -17,6 +17,7 @@ Network-related utilities and helper functions. """ +import ipaddress import logging import os import re @@ -148,6 +149,30 @@ def is_valid_ipv6(address): return False +def get_noscope_ipv6(address): + """Take an IPv6 address and trim scope out if present. + + :param address: Value to change + :type address: string + :returns: string + + .. versionadded: 7.3.0: + """ + # TODO(egarciar): Scope was added for IPv6Address on Python 3.9. Same for + # the removesuffix str method. Remove try/except when minimum required + # version for Python is 3.9 + try: + _ipv6 = ipaddress.IPv6Address(address) + if _ipv6.scope_id: + address = address.removesuffix('%' + _ipv6.scope_id) + return address + except (ipaddress.AddressValueError, AttributeError): + if is_valid_ipv6(address): + parts = address.rsplit("%", 1) + return parts[0] + raise + + def is_valid_cidr(address): """Verify that address represents a valid CIDR address. diff --git a/oslo_utils/tests/test_netutils.py b/oslo_utils/tests/test_netutils.py index 82212991..b75f2f95 100644 --- a/oslo_utils/tests/test_netutils.py +++ b/oslo_utils/tests/test_netutils.py @@ -212,6 +212,16 @@ class NetworkUtilsTest(test_base.BaseTestCase): self.assertFalse(netutils.is_valid_ipv6('')) + def test_get_noscope_ipv6(self): + self.assertEqual('2001:db8::ff00:42:8329', + netutils.get_noscope_ipv6('2001:db8::ff00:42:8329%1')) + self.assertEqual('ff02::5678', + netutils.get_noscope_ipv6('ff02::5678%eth0')) + self.assertEqual('fe80::1', netutils.get_noscope_ipv6('fe80::1%eth0')) + self.assertEqual('::1', netutils.get_noscope_ipv6('::1%eth0')) + self.assertEqual('::1', netutils.get_noscope_ipv6('::1')) + self.assertRaises(ValueError, netutils.get_noscope_ipv6, '::132:::') + def test_escape_ipv6(self): self.assertEqual('[1234::1234]', netutils.escape_ipv6('1234::1234')) self.assertEqual('127.0.0.1', netutils.escape_ipv6('127.0.0.1')) diff --git a/releasenotes/notes/bug-2073894-2e11ca85984b7bb7.yaml b/releasenotes/notes/bug-2073894-2e11ca85984b7bb7.yaml new file mode 100644 index 00000000..1e015bfa --- /dev/null +++ b/releasenotes/notes/bug-2073894-2e11ca85984b7bb7.yaml @@ -0,0 +1,7 @@ +--- +features: + - | + `Bug #2073894 `_: + Added the netutils.get_noscope_ipv6() function in order to fix errors + related to IPv6 address formatting that can happen when using an IPv6 + defined with scope.