Better default for my_ip if 8.8.8.8 is unreachable
Run if route/show, extract ipv4 addresses and pick the first one. Fall back to 127.0.0.1 as before if we don't find anything or if we have running the ip route/show commands Fixes LP# 1193013 Change-Id: If73f0f6bf67f858f7506220debab0f74cc9e3cb4
This commit is contained in:
parent
922e7306a4
commit
7b97d36352
@ -21,6 +21,8 @@ import socket
|
|||||||
|
|
||||||
from oslo.config import cfg
|
from oslo.config import cfg
|
||||||
|
|
||||||
|
from nova import utils
|
||||||
|
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
|
|
||||||
|
|
||||||
@ -40,7 +42,7 @@ def _get_my_ip():
|
|||||||
csock.close()
|
csock.close()
|
||||||
return addr
|
return addr
|
||||||
except socket.error:
|
except socket.error:
|
||||||
return "127.0.0.1"
|
return utils.get_my_ipv4_address()
|
||||||
|
|
||||||
|
|
||||||
netconf_opts = [
|
netconf_opts = [
|
||||||
|
@ -193,6 +193,92 @@ class GetFromPathTestCase(test.TestCase):
|
|||||||
self.assertEquals(['b_1'], f(input, "a/b"))
|
self.assertEquals(['b_1'], f(input, "a/b"))
|
||||||
|
|
||||||
|
|
||||||
|
class GetMyIP4AddressTestCase(test.TestCase):
|
||||||
|
def test_get_my_ipv4_address_with_no_ipv4(self):
|
||||||
|
response = """172.16.0.0/16 via 172.16.251.13 dev tun1
|
||||||
|
172.16.251.1 via 172.16.251.13 dev tun1
|
||||||
|
172.16.251.13 dev tun1 proto kernel scope link src 172.16.251.14
|
||||||
|
172.24.0.0/16 via 172.16.251.13 dev tun1
|
||||||
|
192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1"""
|
||||||
|
|
||||||
|
def fake_execute(*args, **kwargs):
|
||||||
|
return response, None
|
||||||
|
|
||||||
|
self.stubs.Set(utils, 'execute', fake_execute)
|
||||||
|
address = utils.get_my_ipv4_address()
|
||||||
|
self.assertEqual(address, '127.0.0.1')
|
||||||
|
|
||||||
|
def test_get_my_ipv4_address_bad_process(self):
|
||||||
|
def fake_execute(*args, **kwargs):
|
||||||
|
raise processutils.ProcessExecutionError()
|
||||||
|
|
||||||
|
self.stubs.Set(utils, 'execute', fake_execute)
|
||||||
|
address = utils.get_my_ipv4_address()
|
||||||
|
self.assertEqual(address, '127.0.0.1')
|
||||||
|
|
||||||
|
def test_get_my_ipv4_address_with_single_interface(self):
|
||||||
|
response_route = """default via 192.168.1.1 dev wlan0 proto static
|
||||||
|
192.168.1.0/24 dev wlan0 proto kernel scope link src 192.168.1.137 metric 9
|
||||||
|
"""
|
||||||
|
response_addr = """
|
||||||
|
1: lo inet 127.0.0.1/8 scope host lo
|
||||||
|
3: wlan0 inet 192.168.1.137/24 brd 192.168.1.255 scope global wlan0
|
||||||
|
"""
|
||||||
|
|
||||||
|
def fake_execute(*args, **kwargs):
|
||||||
|
if 'route' in args:
|
||||||
|
return response_route, None
|
||||||
|
return response_addr, None
|
||||||
|
|
||||||
|
self.stubs.Set(utils, 'execute', fake_execute)
|
||||||
|
address = utils.get_my_ipv4_address()
|
||||||
|
self.assertEqual(address, '192.168.1.137')
|
||||||
|
|
||||||
|
def test_get_my_ipv4_address_with_multi_ipv4_on_single_interface(self):
|
||||||
|
response_route = """
|
||||||
|
172.18.56.0/24 dev customer proto kernel scope link src 172.18.56.22
|
||||||
|
169.254.0.0/16 dev customer scope link metric 1031
|
||||||
|
default via 172.18.56.1 dev customer
|
||||||
|
"""
|
||||||
|
response_addr = (""
|
||||||
|
"31: customer inet 172.18.56.22/24 brd 172.18.56.255 scope global"
|
||||||
|
" customer\n"
|
||||||
|
"31: customer inet 172.18.56.32/24 brd 172.18.56.255 scope global "
|
||||||
|
"secondary customer")
|
||||||
|
|
||||||
|
def fake_execute(*args, **kwargs):
|
||||||
|
if 'route' in args:
|
||||||
|
return response_route, None
|
||||||
|
return response_addr, None
|
||||||
|
|
||||||
|
self.stubs.Set(utils, 'execute', fake_execute)
|
||||||
|
address = utils.get_my_ipv4_address()
|
||||||
|
self.assertEqual(address, '172.18.56.22')
|
||||||
|
|
||||||
|
def test_get_my_ipv4_address_with_multiple_interfaces(self):
|
||||||
|
response_route = """
|
||||||
|
169.1.9.0/24 dev eth1 proto kernel scope link src 169.1.9.10
|
||||||
|
172.17.248.0/21 dev eth0 proto kernel scope link src 172.17.255.9
|
||||||
|
169.254.0.0/16 dev eth0 scope link metric 1002
|
||||||
|
169.254.0.0/16 dev eth1 scope link metric 1003
|
||||||
|
default via 172.17.248.1 dev eth0 proto static
|
||||||
|
"""
|
||||||
|
response_addr = """
|
||||||
|
1: lo inet 127.0.0.1/8 scope host lo
|
||||||
|
2: eth0 inet 172.17.255.9/21 brd 172.17.255.255 scope global eth0
|
||||||
|
3: eth1 inet 169.1.9.10/24 scope global eth1
|
||||||
|
"""
|
||||||
|
|
||||||
|
def fake_execute(*args, **kwargs):
|
||||||
|
if 'route' in args:
|
||||||
|
return response_route, None
|
||||||
|
return response_addr, None
|
||||||
|
|
||||||
|
self.stubs.Set(utils, 'execute', fake_execute)
|
||||||
|
address = utils.get_my_ipv4_address()
|
||||||
|
self.assertEqual(address, '172.17.255.9')
|
||||||
|
|
||||||
|
|
||||||
class GenericUtilsTestCase(test.TestCase):
|
class GenericUtilsTestCase(test.TestCase):
|
||||||
def test_parse_server_string(self):
|
def test_parse_server_string(self):
|
||||||
result = utils.parse_server_string('::1')
|
result = utils.parse_server_string('::1')
|
||||||
|
@ -321,6 +321,62 @@ def last_octet(address):
|
|||||||
return int(address.split('.')[-1])
|
return int(address.split('.')[-1])
|
||||||
|
|
||||||
|
|
||||||
|
def get_my_ipv4_address():
|
||||||
|
"""Run ip route/addr commands to figure out the best ipv4
|
||||||
|
"""
|
||||||
|
LOCALHOST = '127.0.0.1'
|
||||||
|
try:
|
||||||
|
out = execute('ip', '-f', 'inet', '-o', 'route', 'show',
|
||||||
|
run_as_root=True)
|
||||||
|
|
||||||
|
# Find the default route
|
||||||
|
regex_default = ('default\s*via\s*'
|
||||||
|
'(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})'
|
||||||
|
'\s*dev\s*(\w*)\s*')
|
||||||
|
default_routes = re.findall(regex_default, out[0])
|
||||||
|
if not default_routes:
|
||||||
|
return LOCALHOST
|
||||||
|
gateway, iface = default_routes[0]
|
||||||
|
|
||||||
|
# Find the right subnet for the gateway/interface for
|
||||||
|
# the default route
|
||||||
|
route = ('(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\/(\d{1,2})'
|
||||||
|
'\s*dev\s*(\w*)\s*')
|
||||||
|
for match in re.finditer(route, out[0]):
|
||||||
|
subnet = netaddr.IPNetwork(match.group(1) + "/" + match.group(2))
|
||||||
|
if (match.group(3) == iface and
|
||||||
|
netaddr.IPAddress(gateway) in subnet):
|
||||||
|
try:
|
||||||
|
return _get_ipv4_address_for_interface(iface)
|
||||||
|
except exception.NovaException:
|
||||||
|
pass
|
||||||
|
except Exception as ex:
|
||||||
|
LOG.error(_("Couldn't get IPv4 : %(ex)s") % {'ex': ex})
|
||||||
|
return LOCALHOST
|
||||||
|
|
||||||
|
|
||||||
|
def _get_ipv4_address_for_interface(iface):
|
||||||
|
"""Run ip addr show for an interface and grab its ipv4 addresses
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
out = execute('ip', '-f', 'inet', '-o', 'addr', 'show', iface,
|
||||||
|
run_as_root=True)
|
||||||
|
regexp_address = re.compile('inet\s*'
|
||||||
|
'(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})')
|
||||||
|
address = [m.group(1) for m in regexp_address.finditer(out[0])
|
||||||
|
if m.group(1) != '127.0.0.1']
|
||||||
|
if address:
|
||||||
|
return address[0]
|
||||||
|
else:
|
||||||
|
msg = _('IPv4 address is not found.: %s') % out[0]
|
||||||
|
raise exception.NovaException(msg)
|
||||||
|
except Exception as ex:
|
||||||
|
msg = _("Couldn't get IPv4 of %(interface)s"
|
||||||
|
" : %(ex)s") % {'interface': iface, 'ex': ex}
|
||||||
|
LOG.error(msg)
|
||||||
|
raise exception.NovaException(msg)
|
||||||
|
|
||||||
|
|
||||||
def get_my_linklocal(interface):
|
def get_my_linklocal(interface):
|
||||||
try:
|
try:
|
||||||
if_str = execute('ip', '-f', 'inet6', '-o', 'addr', 'show', interface)
|
if_str = execute('ip', '-f', 'inet6', '-o', 'addr', 'show', interface)
|
||||||
|
Loading…
Reference in New Issue
Block a user