Merge "Add netutils.get_my_ipv6()"

This commit is contained in:
Zuul 2023-06-09 05:04:33 +00:00 committed by Gerrit Code Review
commit 7c2b949ce9
3 changed files with 83 additions and 17 deletions

View File

@ -414,6 +414,52 @@ def _get_my_ipv4_address():
return LOCALHOST
def get_my_ipv6():
"""Returns the actual IPv6 address of the local machine.
This code figures out what source address would be used if some traffic
were to be sent out to some well known address on the Internet. In this
case, IPv6 from RFC3849 is used, but the specific address does not
matter much. No traffic is actually sent.
.. versionadded:: 6.1
Return ``'::1'`` if there is no default interface.
"""
try:
csock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
csock.connect(('2001:db8::1', 80))
(addr, _, _, _) = csock.getsockname()
csock.close()
return addr
except socket.error:
return _get_my_ipv6_address()
def _get_my_ipv6_address():
"""Figure out the best IPv6 address
"""
LOCALHOST = '::1'
gtw = netifaces.gateways()
try:
interface = gtw['default'][netifaces.AF_INET6][1]
except (KeyError, IndexError):
LOG.info('Could not determine default network interface, '
'using %s for IPv6 address', LOCALHOST)
return LOCALHOST
try:
return netifaces.ifaddresses(interface)[netifaces.AF_INET6][0]['addr']
except (KeyError, IndexError):
LOG.info('Could not determine IPv6 address for interface '
'%(interface)s, using %(address)s',
{'interface': interface, 'address': LOCALHOST})
except Exception as e:
LOG.info('Could not determine IPv6 address for '
'interface %(interface)s: %(error)s',
{'interface': interface, 'error': e})
return LOCALHOST
class _ModifiedSplitResult(parse.SplitResult):
"""Split results class for urlsplit."""

View File

@ -276,13 +276,21 @@ class NetworkUtilsTest(test_base.BaseTestCase):
for input_str in invalid_inputs:
self.assertFalse(netutils.is_valid_port(input_str))
def test_get_my_ip(self):
def test_get_my_ipv4(self):
sock_attrs = {
'return_value.getsockname.return_value': ['1.2.3.4', '']}
with mock.patch('socket.socket', **sock_attrs):
addr = netutils.get_my_ipv4()
self.assertEqual(addr, '1.2.3.4')
def test_get_my_ipv6(self):
sock_attrs = {
'return_value.getsockname.return_value': ['2001:db8::2', '',
'', '']}
with mock.patch('socket.socket', **sock_attrs):
addr = netutils.get_my_ipv6()
self.assertEqual(addr, '2001:db8::2')
def test_is_int_in_range(self):
valid_inputs = [(1, -100, 100),
('1', -100, 100),
@ -323,37 +331,44 @@ class NetworkUtilsTest(test_base.BaseTestCase):
@mock.patch('socket.socket')
@mock.patch('oslo_utils.netutils._get_my_ipv4_address')
def test_get_my_ip_socket_error(self, ip, mock_socket):
def test_get_my_ipv4_socket_error(self, ip, mock_socket):
mock_socket.side_effect = socket.error
ip.return_value = '1.2.3.4'
addr = netutils.get_my_ipv4()
self.assertEqual(addr, '1.2.3.4')
@mock.patch('netifaces.gateways')
@mock.patch('netifaces.ifaddresses')
def test_get_my_ipv4_address_with_default_route(
self, ifaddr, gateways):
with mock.patch.dict(netifaces.__dict__, {'AF_INET': '0'}):
ifaddr.return_value = {'0': [{'addr': '172.18.204.1'}]}
addr = netutils._get_my_ipv4_address()
self.assertEqual('172.18.204.1', addr)
@mock.patch('socket.socket')
@mock.patch('oslo_utils.netutils._get_my_ipv6_address')
def test_get_my_ipv6_socket_error(self, ip, mock_socket):
mock_socket.side_effect = socket.error
ip.return_value = '2001:db8::2'
addr = netutils.get_my_ipv6()
self.assertEqual(addr, '2001:db8::2')
@mock.patch('netifaces.gateways')
@mock.patch('netifaces.ifaddresses')
def test_get_my_ipv4_address_without_default_route(
def test_get_my_ip_address_with_default_route(
self, ifaddr, gateways):
with mock.patch.dict(netifaces.__dict__, {'AF_INET': '0'}):
ifaddr.return_value = {}
addr = netutils._get_my_ipv4_address()
self.assertEqual('127.0.0.1', addr)
ifaddr.return_value = {netifaces.AF_INET: [{'addr': '172.18.204.1'}],
netifaces.AF_INET6: [{'addr': '2001:db8::2'}]}
self.assertEqual('172.18.204.1', netutils._get_my_ipv4_address())
self.assertEqual('2001:db8::2', netutils._get_my_ipv6_address())
@mock.patch('netifaces.gateways')
@mock.patch('netifaces.ifaddresses')
def test_get_my_ip_address_without_default_route(
self, ifaddr, gateways):
ifaddr.return_value = {}
self.assertEqual('127.0.0.1', netutils._get_my_ipv4_address())
self.assertEqual('::1', netutils._get_my_ipv6_address())
@mock.patch('netifaces.gateways')
@mock.patch('netifaces.ifaddresses')
def test_get_my_ipv4_address_without_default_interface(
self, ifaddr, gateways):
gateways.return_value = {}
addr = netutils._get_my_ipv4_address()
self.assertEqual('127.0.0.1', addr)
self.assertEqual('127.0.0.1', netutils._get_my_ipv4_address())
self.assertEqual('::1', netutils._get_my_ipv6_address())
self.assertFalse(ifaddr.called)

View File

@ -0,0 +1,5 @@
---
features:
- |
New method ``netutils.get_my_ipv6()`` returns the IPv6 address
of the local machine.