mirror of
https://github.com/YunoHost/yunohost.git
synced 2024-09-03 20:06:10 +02:00
Add test that we can ping outside before talking to ip.yunohost.org
This commit is contained in:
parent
41c3b054ba
commit
4d5ace06db
3 changed files with 57 additions and 4 deletions
|
@ -1,9 +1,12 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import random
|
||||||
|
|
||||||
from moulinette import m18n
|
from moulinette import m18n
|
||||||
from moulinette.utils.network import download_text
|
from moulinette.utils.network import download_text
|
||||||
|
from moulinette.utils.process import check_output
|
||||||
|
from moulinette.utils.filesystem import read_file
|
||||||
|
|
||||||
from yunohost.diagnosis import Diagnoser
|
from yunohost.diagnosis import Diagnoser
|
||||||
|
|
||||||
|
@ -24,7 +27,12 @@ class IPDiagnoser(Diagnoser):
|
||||||
versions = self.args["versions"]
|
versions = self.args["versions"]
|
||||||
|
|
||||||
if 4 in versions:
|
if 4 in versions:
|
||||||
|
|
||||||
|
if not self.can_ping_outside(4):
|
||||||
|
ipv4 = None
|
||||||
|
else:
|
||||||
ipv4 = self.get_public_ip(4)
|
ipv4 = self.get_public_ip(4)
|
||||||
|
|
||||||
yield dict(meta = {"version": 4},
|
yield dict(meta = {"version": 4},
|
||||||
data = ipv4,
|
data = ipv4,
|
||||||
status = "SUCCESS" if ipv4 else "ERROR",
|
status = "SUCCESS" if ipv4 else "ERROR",
|
||||||
|
@ -32,15 +40,57 @@ class IPDiagnoser(Diagnoser):
|
||||||
else ("diagnosis_network_no_ipv4", {}))
|
else ("diagnosis_network_no_ipv4", {}))
|
||||||
|
|
||||||
if 6 in versions:
|
if 6 in versions:
|
||||||
|
|
||||||
|
if not self.can_ping_outside(4):
|
||||||
|
ipv6 = None
|
||||||
|
else:
|
||||||
ipv6 = self.get_public_ip(6)
|
ipv6 = self.get_public_ip(6)
|
||||||
|
|
||||||
yield dict(meta = {"version": 6},
|
yield dict(meta = {"version": 6},
|
||||||
data = ipv6,
|
data = ipv6,
|
||||||
status = "SUCCESS" if ipv6 else "WARNING",
|
status = "SUCCESS" if ipv6 else "WARNING",
|
||||||
summary = ("diagnosis_network_connected_ipv6", {}) if ipv6 \
|
summary = ("diagnosis_network_connected_ipv6", {}) if ipv6 \
|
||||||
else ("diagnosis_network_no_ipv6", {}))
|
else ("diagnosis_network_no_ipv6", {}))
|
||||||
|
|
||||||
|
|
||||||
|
def can_ping_outside(self, protocol=4):
|
||||||
|
|
||||||
|
assert protocol in [4, 6], "Invalid protocol version, it should be either 4 or 6 and was '%s'" % repr(protocol)
|
||||||
|
|
||||||
|
# We can know that ipv6 is not available directly if this file does not exists
|
||||||
|
if protocol == 6 and not os.path.exists("/proc/net/if_inet6"):
|
||||||
|
return False
|
||||||
|
|
||||||
|
# If we are indeed connected in ipv4 or ipv6, we should find a default route
|
||||||
|
routes = check_output("ip -%s route" % protocol).split("\n")
|
||||||
|
if not [r for r in routes if r.startswith("default")]:
|
||||||
|
return False
|
||||||
|
|
||||||
|
# We use the resolver file as a list of well-known, trustable (ie not google ;)) IPs that we can ping
|
||||||
|
resolver_file = "/usr/share/yunohost/templates/dnsmasq/plain/resolv.dnsmasq.conf"
|
||||||
|
resolvers = [r.split(" ")[1] for r in read_file(resolver_file).split("\n") if r.startswith("nameserver")]
|
||||||
|
|
||||||
|
if protocol == 4:
|
||||||
|
resolvers = [r for r in resolvers if ":" not in r]
|
||||||
|
if protocol == 6:
|
||||||
|
resolvers = [r for r in resolvers if ":" in r]
|
||||||
|
|
||||||
|
assert resolvers != [], "Uhoh, need at least one IPv%s DNS resolver in %s ..." % (protocol, resolver_file)
|
||||||
|
|
||||||
|
# So let's try to ping the first 4~5 resolvers (shuffled)
|
||||||
|
# If we succesfully ping any of them, we conclude that we are indeed connected
|
||||||
|
def ping(protocol, target):
|
||||||
|
return os.system("ping -c1 -%s -W 3 %s >/dev/null 2>/dev/null" % (protocol, target)) == 0
|
||||||
|
|
||||||
|
random.shuffle(resolvers)
|
||||||
|
return any(ping(protocol, resolver) for resolver in resolvers[:5])
|
||||||
|
|
||||||
def get_public_ip(self, protocol=4):
|
def get_public_ip(self, protocol=4):
|
||||||
|
|
||||||
|
# FIXME - TODO : here we assume that DNS resolution for ip.yunohost.org is working
|
||||||
|
# but if we want to be able to diagnose DNS resolution issues independently from
|
||||||
|
# internet connectivity, we gotta rely on fixed IPs first....
|
||||||
|
|
||||||
if protocol == 4:
|
if protocol == 4:
|
||||||
url = 'https://ip.yunohost.org'
|
url = 'https://ip.yunohost.org'
|
||||||
elif protocol == 6:
|
elif protocol == 6:
|
||||||
|
|
|
@ -79,6 +79,9 @@ class DNSRecordsDiagnoser(Diagnoser):
|
||||||
command = "dig +short @%s %s %s" % (self.resolver, type_, domain)
|
command = "dig +short @%s %s %s" % (self.resolver, type_, domain)
|
||||||
else:
|
else:
|
||||||
command = "dig +short @%s %s %s.%s" % (self.resolver, type_, name, domain)
|
command = "dig +short @%s %s %s.%s" % (self.resolver, type_, name, domain)
|
||||||
|
# FIXME : gotta handle case where this command fails ...
|
||||||
|
# e.g. no internet connectivity (dependency mechanism to good result from 'ip' diagosis ?)
|
||||||
|
# or the resolver is unavailable for some reason
|
||||||
output = check_output(command).strip()
|
output = check_output(command).strip()
|
||||||
output = output.replace("\;",";")
|
output = output.replace("\;",";")
|
||||||
if output.startswith('"') and output.endswith('"'):
|
if output.startswith('"') and output.endswith('"'):
|
||||||
|
|
|
@ -159,8 +159,8 @@
|
||||||
"diagnosis_network_no_ipv4": "The server does not have a working IPv4.",
|
"diagnosis_network_no_ipv4": "The server does not have a working IPv4.",
|
||||||
"diagnosis_network_connected_ipv6": "The server is connect to the Internet through IPv6 !",
|
"diagnosis_network_connected_ipv6": "The server is connect to the Internet through IPv6 !",
|
||||||
"diagnosis_network_no_ipv6": "The server does not have a working IPv6.",
|
"diagnosis_network_no_ipv6": "The server does not have a working IPv6.",
|
||||||
"diagnosis_dns_good_conf": "Good DNS configuration for {domain} : {category}.",
|
"diagnosis_dns_good_conf": "Good DNS configuration for domain {domain} (category {category})",
|
||||||
"diagnosis_dns_bad_conf": "Bad DNS configuration for {domain} : {category}.",
|
"diagnosis_dns_bad_conf": "Bad DNS configuration for domain {domain} (category {category})",
|
||||||
"diagnosis_dns_missing_record": "According to the recommended DNS configuration, you should add a DNS record with type {0}, name {1} and value {2}",
|
"diagnosis_dns_missing_record": "According to the recommended DNS configuration, you should add a DNS record with type {0}, name {1} and value {2}",
|
||||||
"diagnosis_dns_discrepancy": "According to the recommended DNS configuration, the value for the DNS record with type {0} and name {1} should be {2}, not {3}.",
|
"diagnosis_dns_discrepancy": "According to the recommended DNS configuration, the value for the DNS record with type {0} and name {1} should be {2}, not {3}.",
|
||||||
"diagnosis_description_ip": "Internet connectivity",
|
"diagnosis_description_ip": "Internet connectivity",
|
||||||
|
|
Loading…
Add table
Reference in a new issue