From 8aa64a06414779ac21e3012e5ba1fd4e49a256d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Lebleu?= Date: Tue, 8 Mar 2016 11:08:57 +0100 Subject: [PATCH] [enh] Use a common method to retrieve public IP address --- data/actionsmap/yunohost.yml | 2 +- src/yunohost/domain.py | 31 ++++++++++++--------- src/yunohost/dyndns.py | 52 ++++++++++++++++-------------------- src/yunohost/monitor.py | 9 ++++--- 4 files changed, 48 insertions(+), 46 deletions(-) diff --git a/data/actionsmap/yunohost.yml b/data/actionsmap/yunohost.yml index eaf3a746f..4e09d68dc 100644 --- a/data/actionsmap/yunohost.yml +++ b/data/actionsmap/yunohost.yml @@ -1169,7 +1169,7 @@ dyndns: full: --key help: Public DNS key -i: - full: --ip + full: --ipv4 help: IP address to send -6: full: --ipv6 diff --git a/src/yunohost/domain.py b/src/yunohost/domain.py index a16dd593f..9535b01c5 100644 --- a/src/yunohost/domain.py +++ b/src/yunohost/domain.py @@ -82,10 +82,7 @@ def domain_add(auth, domain, dyndns=False): from yunohost.hook import hook_callback attr_dict = { 'objectClass' : ['mailDomain', 'top'] } - try: - ip = str(urlopen('https://ip.yunohost.org').read()) - except IOError: - ip = "127.0.0.1" + now = datetime.datetime.now() timestamp = str(now.year) + str(now.month) + str(now.day) @@ -232,20 +229,16 @@ def domain_dns_conf(domain, ttl=None): ip4 = ip6 = None # A/AAAA records - try: - ip4 = urlopen("https://ip.yunohost.org").read().strip() - except IOError: - raise MoulinetteError(errno.ENETUNREACH, - m18n.n('no_internet_connection')) + ip4 = get_public_ip() result = ( "@ {ttl} IN A {ip4}\n" "* {ttl} IN A {ip4}\n" ).format(ttl=ttl, ip4=ip4) try: - ip6 = urlopen("http://ip6.yunohost.org").read().strip() - except IOError: - logger.debug('cannot retrieve IPv6', exc_info=1) + ip6 = get_public_ip(6) + except: + pass else: result += ( "@ {ttl} IN AAAA {ip6}\n" @@ -295,3 +288,17 @@ def domain_dns_conf(domain, ttl=None): ) return result + + +def get_public_ip(protocol=4): + """Retrieve the public IP address from ip.yunohost.org""" + if protocol not in [4, 6]: + raise ValueError("invalid protocol version") + try: + return urlopen("https://ip{protocol}.yunohost.org".format( + protocol=('' if protocol == 4 else 'v6') + )).read().strip() + except IOError: + logger.debug('cannot retrieve public IPv%d' % protocol, exc_info=1) + raise MoulinetteError(errno.ENETUNREACH, + m18n.n('no_internet_connection')) diff --git a/src/yunohost/dyndns.py b/src/yunohost/dyndns.py index a296185e2..97826062f 100644 --- a/src/yunohost/dyndns.py +++ b/src/yunohost/dyndns.py @@ -35,6 +35,8 @@ import subprocess from moulinette.core import MoulinetteError from moulinette.utils.log import getActionLogger +from yunohost.domain import get_public_ip + logger = getActionLogger('yunohost.dyndns') @@ -112,7 +114,8 @@ def dyndns_subscribe(subscribe_host="dyndns.yunohost.org", domain=None, key=None dyndns_installcron() -def dyndns_update(dyn_host="dynhost.yunohost.org", domain=None, key=None, ip=None, ipv6=None): +def dyndns_update(dyn_host="dynhost.yunohost.org", domain=None, key=None, + ipv4=None, ipv6=None): """ Update IP on DynDNS platform @@ -120,7 +123,7 @@ def dyndns_update(dyn_host="dynhost.yunohost.org", domain=None, key=None, ip=Non domain -- Full domain to subscribe with dyn_host -- Dynette DNS server to inform key -- Public DNS key - ip -- IP address to send + ipv4 -- IP address to send ipv6 -- IPv6 address to send """ @@ -129,13 +132,8 @@ def dyndns_update(dyn_host="dynhost.yunohost.org", domain=None, key=None, ip=Non domain = f.readline().rstrip() # IPv4 - if ip is None: - try: - new_ip = requests.get('https://ip.yunohost.org').text - except requests.ConnectionError: - raise MoulinetteError(errno.ENETUNREACH, m18n.n('no_internet_connection')) - else: - new_ip = ip + if ipv4 is None: + ipv4 = get_public_ip() try: with open('/etc/yunohost/dyndns/old_ip', 'r') as f: @@ -145,7 +143,6 @@ def dyndns_update(dyn_host="dynhost.yunohost.org", domain=None, key=None, ip=Non # IPv6 if ipv6 is None: - new_ipv6 = None try: ip_route_out = subprocess.check_output( ['ip', 'route', 'get', '2000::']).split('\n') @@ -153,7 +150,7 @@ def dyndns_update(dyn_host="dynhost.yunohost.org", domain=None, key=None, ip=Non if len(ip_route_out) > 0: route = IPRouteLine(ip_route_out[0]) if not route.unreachable: - new_ipv6 = route.src_addr + ipv6 = route.src_addr except (OSError, ValueError) as e: # Unlikely case "ip route" does not return status 0 @@ -161,11 +158,8 @@ def dyndns_update(dyn_host="dynhost.yunohost.org", domain=None, key=None, ip=Non raise MoulinetteError(errno.EBADMSG, "ip route cmd error : {}".format(e)) - if new_ipv6 is None: - logger.warning(m18n.n('no_ipv6_connectivity')) - - else: - new_ipv6 = ipv6 + if ipv6 is None: + logger.info(m18n.n('no_ipv6_connectivity')) try: with open('/etc/yunohost/dyndns/old_ipv6', 'r') as f: @@ -173,7 +167,7 @@ def dyndns_update(dyn_host="dynhost.yunohost.org", domain=None, key=None, ip=Non except IOError: old_ipv6 = '0000:0000:0000:0000:0000:0000:0000:0000' - if old_ip != new_ip or old_ipv6 != new_ipv6: + if old_ip != ipv4 or old_ipv6 != ipv6: host = domain.split('.')[1:] host = '.'.join(host) lines = [ @@ -191,21 +185,21 @@ def dyndns_update(dyn_host="dynhost.yunohost.org", domain=None, key=None, ip=Non 'update delete vjud.%s. AAAA' % domain, 'update delete _xmpp-client._tcp.%s. SRV' % domain, 'update delete _xmpp-server._tcp.%s. SRV' % domain, - 'update add %s. 1800 A %s' % (domain, new_ip), + 'update add %s. 1800 A %s' % (domain, ipv4), 'update add %s. 14400 MX 5 %s.' % (domain, domain), 'update add %s. 14400 TXT "v=spf1 a mx -all"' % domain, - 'update add pubsub.%s. 1800 A %s' % (domain, new_ip), - 'update add muc.%s. 1800 A %s' % (domain, new_ip), - 'update add vjud.%s. 1800 A %s' % (domain, new_ip), + 'update add pubsub.%s. 1800 A %s' % (domain, ipv4), + 'update add muc.%s. 1800 A %s' % (domain, ipv4), + 'update add vjud.%s. 1800 A %s' % (domain, ipv4), 'update add _xmpp-client._tcp.%s. 14400 SRV 0 5 5222 %s.' % (domain, domain), 'update add _xmpp-server._tcp.%s. 14400 SRV 0 5 5269 %s.' % (domain, domain) ] - if new_ipv6 is not None: + if ipv6 is not None: lines += [ - 'update add %s. 1800 AAAA %s' % (domain, new_ipv6), - 'update add pubsub.%s. 1800 AAAA %s' % (domain, new_ipv6), - 'update add muc.%s. 1800 AAAA %s' % (domain, new_ipv6), - 'update add vjud.%s. 1800 AAAA %s' % (domain, new_ipv6), + 'update add %s. 1800 AAAA %s' % (domain, ipv6), + 'update add pubsub.%s. 1800 AAAA %s' % (domain, ipv6), + 'update add muc.%s. 1800 AAAA %s' % (domain, ipv6), + 'update add vjud.%s. 1800 AAAA %s' % (domain, ipv6), ] lines += [ 'show', @@ -222,10 +216,10 @@ def dyndns_update(dyn_host="dynhost.yunohost.org", domain=None, key=None, ip=Non if os.system('/usr/bin/nsupdate -k %s /etc/yunohost/dyndns/zone' % private_key_file) == 0: logger.success(m18n.n('dyndns_ip_updated')) with open('/etc/yunohost/dyndns/old_ip', 'w') as f: - f.write(new_ip) - if new_ipv6 is not None: + f.write(ipv4) + if ipv6 is not None: with open('/etc/yunohost/dyndns/old_ipv6', 'w') as f: - f.write(new_ipv6) + f.write(ipv6) else: os.system('rm -f /etc/yunohost/dyndns/old_ip') os.system('rm -f /etc/yunohost/dyndns/old_ipv6') diff --git a/src/yunohost/monitor.py b/src/yunohost/monitor.py index 35337dae4..542455dd7 100644 --- a/src/yunohost/monitor.py +++ b/src/yunohost/monitor.py @@ -35,12 +35,13 @@ import errno import os import dns.resolver import cPickle as pickle -from urllib import urlopen from datetime import datetime, timedelta from moulinette.core import MoulinetteError from moulinette.utils.log import getActionLogger +from yunohost.domain import get_public_ip + logger = getActionLogger('yunohost.monitor') glances_uri = 'http://127.0.0.1:61209' @@ -210,9 +211,9 @@ def monitor_network(units=None, human_readable=False): logger.debug('interface name %s was not found', iname) elif u == 'infos': try: - p_ip = str(urlopen('https://ip.yunohost.org').read()) + p_ipv4 = get_public_ip() except: - p_ip = 'unknown' + p_ipv4 = 'unknown' l_ip = 'unknown' for name, addrs in devices.items(): @@ -231,7 +232,7 @@ def monitor_network(units=None, human_readable=False): proto, gateway = addr.popitem() result[u] = { - 'public_ip': p_ip, + 'public_ip': p_ipv4, 'local_ip': l_ip, 'gateway': gateway, }