summaryrefslogtreecommitdiffstats
path: root/nova
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2013-06-28 05:35:48 +0000
committerGerrit Code Review <review@openstack.org>2013-06-28 05:35:48 +0000
commit35029ec8d584be6eadfbe4ccfb179ac9e99acf03 (patch)
tree9da07f8667bcd4dfe8c916669f046928223d1cbe /nova
parenta11a723ee16e325505851d32466e4615c7d60017 (diff)
parent7b97d363524fbd471289070557d1b8ffe9c06758 (diff)
Merge "Better default for my_ip if 8.8.8.8 is unreachable"
Diffstat (limited to 'nova')
-rw-r--r--nova/netconf.py4
-rw-r--r--nova/tests/test_utils.py86
-rw-r--r--nova/utils.py56
3 files changed, 145 insertions, 1 deletions
diff --git a/nova/netconf.py b/nova/netconf.py
index 78939d586..53130ceab 100644
--- a/nova/netconf.py
+++ b/nova/netconf.py
@@ -21,6 +21,8 @@ import socket
from oslo.config import cfg
+from nova import utils
+
CONF = cfg.CONF
@@ -40,7 +42,7 @@ def _get_my_ip():
csock.close()
return addr
except socket.error:
- return "127.0.0.1"
+ return utils.get_my_ipv4_address()
netconf_opts = [
diff --git a/nova/tests/test_utils.py b/nova/tests/test_utils.py
index 609280261..ada649549 100644
--- a/nova/tests/test_utils.py
+++ b/nova/tests/test_utils.py
@@ -193,6 +193,92 @@ class GetFromPathTestCase(test.TestCase):
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):
def test_parse_server_string(self):
result = utils.parse_server_string('::1')
diff --git a/nova/utils.py b/nova/utils.py
index c2580271d..9976e2858 100644
--- a/nova/utils.py
+++ b/nova/utils.py
@@ -329,6 +329,62 @@ def last_octet(address):
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):
try:
if_str = execute('ip', '-f', 'inet6', '-o', 'addr', 'show', interface)