diff --git a/oslo/utils/netutils.py b/oslo/utils/netutils.py index 0bfb8346..a435b268 100644 --- a/oslo/utils/netutils.py +++ b/oslo/utils/netutils.py @@ -20,6 +20,7 @@ Network-related utilities and helper functions. import logging import socket +import netaddr from six.moves.urllib import parse from oslo.utils._i18n import _LW @@ -75,6 +76,27 @@ def parse_host_port(address, default_port=None): return (host, None if port is None else int(port)) +def is_valid_ipv4(address): + """Verify that address represents a valid IPv4 address.""" + try: + return netaddr.valid_ipv4(address) + except Exception: + return False + + +def is_valid_ipv6(address): + """Verify that address represents a valid IPv6 address.""" + try: + return netaddr.valid_ipv6(address) + except Exception: + return False + + +def is_valid_ip(address): + """Verify that address represents a valid IP address.""" + return is_valid_ipv4(address) or is_valid_ipv6(address) + + class _ModifiedSplitResult(parse.SplitResult): """Split results class for urlsplit.""" diff --git a/requirements.txt b/requirements.txt index 47780e9b..1f1f75fb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,3 +6,4 @@ Babel>=1.3 six>=1.7.0 iso8601>=0.1.9 oslo.i18n>=1.0.0 # Apache-2.0 +netaddr>=0.7.12 diff --git a/tests/test_netutils.py b/tests/test_netutils.py index e1886c4c..12df9923 100644 --- a/tests/test_netutils.py +++ b/tests/test_netutils.py @@ -149,3 +149,29 @@ class NetworkUtilsTest(test_base.BaseTestCase): mock_sock.reset_mock() netutils.set_tcp_keepalive(mock_sock, False) self.assertEqual(1, len(mock_sock.mock_calls)) + + def test_is_valid_ipv4(self): + self.assertTrue(netutils.is_valid_ipv4('42.42.42.42')) + + self.assertFalse(netutils.is_valid_ipv4('-1.11.11.11')) + + self.assertFalse(netutils.is_valid_ipv4('')) + + def test_is_valid_ipv6(self): + self.assertTrue(netutils.is_valid_ipv6('::1')) + + self.assertFalse(netutils.is_valid_ipv6( + '1fff::a88:85a3::172.31.128.1')) + + self.assertFalse(netutils.is_valid_ipv6('')) + + def test_is_valid_ip(self): + self.assertTrue(netutils.is_valid_ip('127.0.0.1')) + + self.assertTrue(netutils.is_valid_ip('2001:db8::ff00:42:8329')) + + self.assertFalse(netutils.is_valid_ip('256.0.0.0')) + + self.assertFalse(netutils.is_valid_ip('::1.2.3.')) + + self.assertFalse(netutils.is_valid_ip('')) \ No newline at end of file