diff --git a/data/hooks/diagnosis/21-web.py b/data/hooks/diagnosis/21-web.py index 270c566cc..c54544aa0 100644 --- a/data/hooks/diagnosis/21-web.py +++ b/data/hooks/diagnosis/21-web.py @@ -48,15 +48,20 @@ class WebDiagnoser(Diagnoser): # is working and therefore we'll do it only if at least one ipv4 domain # works. self.do_hairpinning_test = False + + ipversions = [] ipv4 = Diagnoser.get_cached_report("ip", item={"test": "ipv4"}) or {} if ipv4.get("status") == "SUCCESS": - for item in self.test_http(domains_to_check, ipversion=4): - yield item + ipversions.append(4) + # To be discussed: we could also make this check dependent on the + # existence of an AAAA record... ipv6 = Diagnoser.get_cached_report("ip", item={"test": "ipv6"}) or {} if ipv6.get("status") == "SUCCESS": - for item in self.test_http(domains_to_check, ipversion=6): - yield item + ipversions.append(6) + + for item in self.test_http(domains_to_check, ipversions): + yield item # If at least one domain is correctly exposed to the outside, # attempt to diagnose hairpinning situations. On network with @@ -80,32 +85,44 @@ class WebDiagnoser(Diagnoser): # issue but something else super weird ... pass - def test_http(self, domains, ipversion): + def test_http(self, domains, ipversions): - try: - r = Diagnoser.remote_diagnosis('check-http', - data={'domains': domains, - "nonce": self.nonce}, - ipversion=ipversion) - results = r["http"] - except Exception as e: - raise YunohostError("diagnosis_http_could_not_diagnose", error=e) + results = {} + for ipversion in ipversions: + try: + r = Diagnoser.remote_diagnosis('check-http', + data={'domains': domains, + "nonce": self.nonce}, + ipversion=ipversion) + results[ipversion] = r["http"] + except Exception as e: + raise YunohostError("diagnosis_http_could_not_diagnose", error=e) - assert set(results.keys()) == set(domains) + for domain in domains: - for domain, result in results.items(): - - if result["status"] == "ok": - if ipversion == 4: + # If both IPv4 and IPv6 (if applicable) are good + if all(results[ipversion][domain]["status"] == "ok" for ipversion in ipversions): + if 4 in ipversions: self.do_hairpinning_test = True yield dict(meta={"domain": domain}, status="SUCCESS", summary="diagnosis_http_ok") - else: + # If both IPv4 and IPv6 (if applicable) are failed + elif all(results[ipversion][domain]["status"] != "ok" for ipversion in ipversions): + detail = results[4 if 4 in ipversions else 6][domain]["status"] yield dict(meta={"domain": domain}, status="ERROR", summary="diagnosis_http_unreachable", - details=[result["status"].replace("error_http_check", "diagnosis_http")]) + details=[detail.replace("error_http_check", "diagnosis_http")]) + # If only IPv4 is failed or only IPv6 is failed (if applicable) + else: + passed, failed = (4, 6) if results[4][domain]["status"] == "ok" else (6, 4) + detail = results[failed][domain]["status"] + yield dict(meta={"domain": domain}, + data={"passed": passed, "failed": failed}, + status="ERROR", + summary="diagnosis_http_partially_unreachable", + details=[detail.replace("error_http_check", "diagnosis_http")]) def main(args, env, loggers): diff --git a/locales/en.json b/locales/en.json index 71804af97..96a1f4658 100644 --- a/locales/en.json +++ b/locales/en.json @@ -217,6 +217,7 @@ "diagnosis_http_unknown_error": "An error happened while trying to reach your domain, it's very likely unreachable.", "diagnosis_http_bad_status_code": "Timed-out while trying to contact your server from outside. It might be that another machine answered instead of your server.
1. The most common cause for this issue is that you did not correctly configure port forwarding for port 80.
2. On more complex setups: make sure that a firewall or reverse-proxy is not interfering.", "diagnosis_http_unreachable": "Domain {domain} appears unreachable through HTTP from outside the local network.", + "diagnosis_http_partiallu_unreachable": "Domain {domain} appears unreachable through HTTP from outside the local network in IPv{failed}, though it works in IPv{passed}.", "diagnosis_http_nginx_conf_not_up_to_date": "This domain's nginx configuration appears to have been modified manually, and prevents YunoHost from diagnosing if it's reachable on HTTP.", "diagnosis_http_nginx_conf_not_up_to_date_details": "To fix the situation, inspect the difference with the command line using yunohost tools regen-conf nginx --dry-run --with-diff and if you're ok, apply the changes with yunohost tools regen-conf nginx --force.", "diagnosis_unknown_categories": "The following categories are unknown: {categories}",