From 105cf6666f51017d59521250698697f5ff60f1a4 Mon Sep 17 00:00:00 2001 From: Sean Fisk Date: Fri, 4 Sep 2015 16:12:20 -0400 Subject: [PATCH 1/2] Detect internal_ip interface from default gateway Add the option to specify `interface='default_gateway'` to the `internal_ip` segment, which displays the IP address of the interface connected to the default gateway. --- powerline/segments/common/net.py | 14 +++++++++++++- tests/test_segments.py | 23 +++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/powerline/segments/common/net.py b/powerline/segments/common/net.py index 0af5762d..85bf737b 100644 --- a/powerline/segments/common/net.py +++ b/powerline/segments/common/net.py @@ -101,15 +101,22 @@ else: return 0 def internal_ip(pl, interface='auto', ipv=4): + family = netifaces.AF_INET6 if ipv == 6 else netifaces.AF_INET if interface == 'auto': try: interface = next(iter(sorted(netifaces.interfaces(), key=_interface_key, reverse=True))) except StopIteration: pl.info('No network interfaces found') return None + elif interface == 'default_gateway': + try: + interface = netifaces.gateways()['default'][family][1] + except KeyError: + pl.info('No default gateway found for IPv{0}', ipv) + return None addrs = netifaces.ifaddresses(interface) try: - return addrs[netifaces.AF_INET6 if ipv == 6 else netifaces.AF_INET][0]['addr'] + return addrs[family][0]['addr'] except (KeyError, IndexError): return None @@ -130,6 +137,11 @@ Requires ``netifaces`` module to work properly. #. ``teredo`` followed by number or the end of string. #. Any other interface that is not ``lo*``. #. ``lo`` followed by number or the end of string. + + Use ``default_gateway`` to detect the interface based on the machine's + `default gateway `_ (i.e., + the router to which it is connected). + :param int ipv: 4 or 6 for ipv4 and ipv6 respectively, depending on which IP address you need exactly. diff --git a/tests/test_segments.py b/tests/test_segments.py index b3c77029..58292909 100644 --- a/tests/test_segments.py +++ b/tests/test_segments.py @@ -397,6 +397,29 @@ class TestNet(TestCommon): interfaces[:] = () self.assertEqual(self.module.internal_ip(pl=pl, ipv=6), None) + gateways = { + 'default': { + netifaces.AF_INET: ('192.168.100.1', 'enp2s0'), + netifaces.AF_INET6: ('feff::5446:5eff:fe5a:0001', 'enp2s0') + } + } + + with replace_module_module( + self.module, 'netifaces', + interfaces=(lambda: interfaces), + ifaddresses=(lambda interface: addr[interface]), + gateways=(lambda: gateways), + AF_INET=netifaces.AF_INET, + AF_INET6=netifaces.AF_INET6, + ): + # default gateway has specified address family + self.assertEqual(self.module.internal_ip(pl=pl, interface='default_gateway', ipv=4), '192.168.100.200') + self.assertEqual(self.module.internal_ip(pl=pl, interface='default_gateway', ipv=6), 'feff::5446:5eff:fe5a:7777%enp2s0') + # default gateway doesn't have specified address family + gateways['default'] = {} + self.assertEqual(self.module.internal_ip(pl=pl, interface='default_gateway', ipv=4), None) + self.assertEqual(self.module.internal_ip(pl=pl, interface='default_gateway', ipv=6), None) + def test_network_load(self): def gb(interface): return None From 2c1213116ed68fff15169a61d94852c97840dd3c Mon Sep 17 00:00:00 2001 From: Sean Fisk Date: Sat, 5 Sep 2015 18:02:11 -0400 Subject: [PATCH 2/2] Log when IP address family not found for interface --- powerline/segments/common/net.py | 1 + 1 file changed, 1 insertion(+) diff --git a/powerline/segments/common/net.py b/powerline/segments/common/net.py index 85bf737b..eb5b4bcf 100644 --- a/powerline/segments/common/net.py +++ b/powerline/segments/common/net.py @@ -118,6 +118,7 @@ else: try: return addrs[family][0]['addr'] except (KeyError, IndexError): + pl.info("No IPv{0} address found for interface {1}", ipv, interface) return None