Add util functions to extract network interfaces and gateway

This commit is contained in:
Alexandre Aubin 2018-06-13 19:39:56 +02:00
parent 3681e6adfc
commit 8b08de665a
2 changed files with 78 additions and 0 deletions

View file

@ -164,6 +164,7 @@ def monitor_network(units=None, human_readable=False):
units = ['check', 'usage', 'infos']
# Get network devices and their addresses
# TODO / FIXME : use functions in utils/network.py to manage this
devices = {}
output = subprocess.check_output('ip addr show'.split())
for d in re.split('^(?:[0-9]+: )', output, flags=re.MULTILINE):
@ -213,6 +214,7 @@ def monitor_network(units=None, human_readable=False):
elif u == 'infos':
p_ipv4 = get_public_ip() or 'unknown'
# TODO / FIXME : use functions in utils/network.py to manage this
l_ip = 'unknown'
for name, addrs in devices.items():
if name == 'lo':

View file

@ -19,10 +19,13 @@
"""
import logging
import re
import subprocess
from urllib import urlopen
logger = logging.getLogger('yunohost.utils.network')
def get_public_ip(protocol=4):
"""Retrieve the public IP address from ip.yunohost.org"""
@ -37,3 +40,76 @@ def get_public_ip(protocol=4):
return urlopen(url).read().strip()
except IOError:
return None
def get_network_interfaces():
# Get network devices and their addresses (raw infos from 'ip addr')
devices_raw = {}
output = subprocess.check_output('ip addr show'.split())
for d in re.split('^(?:[0-9]+: )', output, flags=re.MULTILINE):
# Extract device name (1) and its addresses (2)
m = re.match('([^\s@]+)(?:@[\S]+)?: (.*)', d, flags=re.DOTALL)
if m:
devices_raw[m.group(1)] = m.group(2)
# Parse relevant informations for each of them
devices = {name: _extract_inet(addrs) for name, addrs in devices_raw.items() if name != "lo"}
return devices or "unknown"
def get_gateway():
output = subprocess.check_output('ip route show'.split())
m = re.search('default via (.*) dev ([a-z]+[0-9]?)', output)
if not m:
return "unknown"
addr = _extract_inet(m.group(1), True)
return addr.popitem()[1] if len(addr) == 1 else "unknown"
###############################################################################
def _extract_inet(string, skip_netmask=False, skip_loopback=True):
"""
Extract IP addresses (v4 and/or v6) from a string limited to one
address by protocol
Keyword argument:
string -- String to search in
skip_netmask -- True to skip subnet mask extraction
skip_loopback -- False to include addresses reserved for the
loopback interface
Returns:
A dict of {protocol: address} with protocol one of 'ipv4' or 'ipv6'
"""
ip4_pattern = '((25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}'
ip6_pattern = '(((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)::((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)'
ip4_pattern += '/[0-9]{1,2})' if not skip_netmask else ')'
ip6_pattern += '/[0-9]{1,3})' if not skip_netmask else ')'
result = {}
for m in re.finditer(ip4_pattern, string):
addr = m.group(1)
if skip_loopback and addr.startswith('127.'):
continue
# Limit to only one result
result['ipv4'] = addr
break
for m in re.finditer(ip6_pattern, string):
addr = m.group(1)
if skip_loopback and addr == '::1':
continue
# Limit to only one result
result['ipv6'] = addr
break
return result