Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[enh] Simplify error management #574

Merged
merged 21 commits into from Dec 15, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
189 changes: 69 additions & 120 deletions src/yunohost/app.py

Large diffs are not rendered by default.

122 changes: 43 additions & 79 deletions src/yunohost/backup.py

Large diffs are not rendered by default.

62 changes: 21 additions & 41 deletions src/yunohost/certificate.py
Expand Up @@ -24,7 +24,6 @@

import os
import sys
import errno
import shutil
import pwd
import grp
Expand All @@ -37,7 +36,7 @@

from yunohost.vendor.acme_tiny.acme_tiny import get_crt as sign_certificate

from moulinette.core import MoulinetteError
from yunohost.utils.error import YunohostError
from moulinette.utils.log import getActionLogger

from yunohost.utils.network import get_public_ip
Expand Down Expand Up @@ -106,8 +105,7 @@ def certificate_status(auth, domain_list, full=False):
for domain in domain_list:
# Is it in Yunohost domain list?
if domain not in yunohost_domains_list:
raise MoulinetteError(errno.EINVAL, m18n.n(
'certmanager_domain_unknown', domain=domain))
raise YunohostError('certmanager_domain_unknown', domain=domain)

certificates = {}

Expand Down Expand Up @@ -172,8 +170,7 @@ def _certificate_install_selfsigned(domain_list, force=False):
status = _get_status(domain)

if status["summary"]["code"] in ('good', 'great'):
raise MoulinetteError(errno.EINVAL, m18n.n(
'certmanager_attempt_to_replace_valid_cert', domain=domain))
raise YunohostError('certmanager_attempt_to_replace_valid_cert', domain=domain)

operation_logger.start()

Expand Down Expand Up @@ -203,8 +200,7 @@ def _certificate_install_selfsigned(domain_list, force=False):

if p.returncode != 0:
logger.warning(out)
raise MoulinetteError(
errno.EIO, m18n.n('domain_cert_gen_failed'))
raise YunohostError('domain_cert_gen_failed')
else:
logger.debug(out)

Expand Down Expand Up @@ -262,14 +258,12 @@ def _certificate_install_letsencrypt(auth, domain_list, force=False, no_checks=F
for domain in domain_list:
yunohost_domains_list = yunohost.domain.domain_list(auth)['domains']
if domain not in yunohost_domains_list:
raise MoulinetteError(errno.EINVAL, m18n.n(
'certmanager_domain_unknown', domain=domain))
raise YunohostError('certmanager_domain_unknown', domain=domain)

# Is it self-signed?
status = _get_status(domain)
if not force and status["CA_type"]["code"] != "self-signed":
raise MoulinetteError(errno.EINVAL, m18n.n(
'certmanager_domain_cert_not_selfsigned', domain=domain))
raise YunohostError('certmanager_domain_cert_not_selfsigned', domain=domain)

if staging:
logger.warning(
Expand Down Expand Up @@ -349,25 +343,21 @@ def certificate_renew(auth, domain_list, force=False, no_checks=False, email=Fal

# Is it in Yunohost dmomain list?
if domain not in yunohost.domain.domain_list(auth)['domains']:
raise MoulinetteError(errno.EINVAL, m18n.n(
'certmanager_domain_unknown', domain=domain))
raise YunohostError('certmanager_domain_unknown', domain=domain)

status = _get_status(domain)

# Does it expire soon?
if status["validity"] > VALIDITY_LIMIT and not force:
raise MoulinetteError(errno.EINVAL, m18n.n(
'certmanager_attempt_to_renew_valid_cert', domain=domain))
raise YunohostError('certmanager_attempt_to_renew_valid_cert', domain=domain)

# Does it have a Let's Encrypt cert?
if status["CA_type"]["code"] != "lets-encrypt":
raise MoulinetteError(errno.EINVAL, m18n.n(
'certmanager_attempt_to_renew_nonLE_cert', domain=domain))
raise YunohostError('certmanager_attempt_to_renew_nonLE_cert', domain=domain)

# Check ACME challenge configured for given domain
if not _check_acme_challenge_configuration(domain):
raise MoulinetteError(errno.EINVAL, m18n.n(
'certmanager_acme_not_configured_for_domain', domain=domain))
raise YunohostError('certmanager_acme_not_configured_for_domain', domain=domain)

if staging:
logger.warning(
Expand Down Expand Up @@ -484,8 +474,7 @@ def _configure_for_acme_challenge(auth, domain):
contents = f.read()

if '/.well-known/acme-challenge' in contents:
raise MoulinetteError(errno.EINVAL, m18n.n(
'certmanager_conflicting_nginx_file', filepath=path))
raise YunohostError('certmanager_conflicting_nginx_file', filepath=path)

# Write the conf
if os.path.exists(nginx_conf_file):
Expand Down Expand Up @@ -563,25 +552,22 @@ def _fetch_and_enable_new_certificate(domain, staging=False, no_checks=False):
CA=certification_authority)
except ValueError as e:
if "urn:acme:error:rateLimited" in str(e):
raise MoulinetteError(errno.EINVAL, m18n.n(
'certmanager_hit_rate_limit', domain=domain))
raise YunohostError('certmanager_hit_rate_limit', domain=domain)
else:
logger.error(str(e))
_display_debug_information(domain)
raise MoulinetteError(errno.EINVAL, m18n.n(
'certmanager_cert_signing_failed'))
raise YunohostError('certmanager_cert_signing_failed')

except Exception as e:
logger.error(str(e))

raise MoulinetteError(errno.EINVAL, m18n.n(
'certmanager_cert_signing_failed'))
raise YunohostError('certmanager_cert_signing_failed')

import requests # lazy loading this module for performance reasons
try:
intermediate_certificate = requests.get(INTERMEDIATE_CERTIFICATE_URL, timeout=30).text
except requests.exceptions.Timeout as e:
raise MoulinetteError(errno.EINVAL, m18n.n('certmanager_couldnt_fetch_intermediate_cert'))
raise YunohostError('certmanager_couldnt_fetch_intermediate_cert')

# Now save the key and signed certificate
logger.debug("Saving the key and signed certificate...")
Expand Down Expand Up @@ -624,8 +610,7 @@ def _fetch_and_enable_new_certificate(domain, staging=False, no_checks=False):
status_summary = _get_status(domain)["summary"]

if status_summary["code"] != "great":
raise MoulinetteError(errno.EINVAL, m18n.n(
'certmanager_certificate_fetching_or_enabling_failed', domain=domain))
raise YunohostError('certmanager_certificate_fetching_or_enabling_failed', domain=domain)


def _prepare_certificate_signing_request(domain, key_file, output_folder):
Expand Down Expand Up @@ -658,8 +643,7 @@ def _get_status(domain):
cert_file = os.path.join(CERT_FOLDER, domain, "crt.pem")

if not os.path.isfile(cert_file):
raise MoulinetteError(errno.EINVAL, m18n.n(
'certmanager_no_cert_file', domain=domain, file=cert_file))
raise YunohostError('certmanager_no_cert_file', domain=domain, file=cert_file)

from OpenSSL import crypto # lazy loading this module for performance reasons
try:
Expand All @@ -668,8 +652,7 @@ def _get_status(domain):
except Exception as exception:
import traceback
traceback.print_exc(file=sys.stdout)
raise MoulinetteError(errno.EINVAL, m18n.n(
'certmanager_cannot_read_cert', domain=domain, file=cert_file, reason=exception))
raise YunohostError('certmanager_cannot_read_cert', domain=domain, file=cert_file, reason=exception)

cert_subject = cert.get_subject().CN
cert_issuer = cert.get_issuer().CN
Expand Down Expand Up @@ -830,13 +813,11 @@ def _check_domain_is_ready_for_ACME(domain):

# Check if IP from DNS matches public IP
if not _dns_ip_match_public_ip(public_ip, domain):
raise MoulinetteError(errno.EINVAL, m18n.n(
'certmanager_domain_dns_ip_differs_from_public_ip', domain=domain))
raise YunohostError('certmanager_domain_dns_ip_differs_from_public_ip', domain=domain)

# Check if domain seems to be accessible through HTTP?
if not _domain_is_accessible_through_HTTP(public_ip, domain):
raise MoulinetteError(errno.EINVAL, m18n.n(
'certmanager_domain_http_not_working', domain=domain))
raise YunohostError('certmanager_domain_http_not_working', domain=domain)


def _get_dns_ip(domain):
Expand All @@ -845,8 +826,7 @@ def _get_dns_ip(domain):
resolver.nameservers = DNS_RESOLVERS
answers = resolver.query(domain, "A")
except (dns.resolver.NoAnswer, dns.resolver.NXDOMAIN):
raise MoulinetteError(errno.EINVAL, m18n.n(
'certmanager_error_no_A_record', domain=domain))
raise YunohostError('certmanager_error_no_A_record', domain=domain)

return str(answers[0])

Expand Down
11 changes: 5 additions & 6 deletions src/yunohost/data_migrations/0002_migrate_to_tsig_sha256.py
Expand Up @@ -4,10 +4,9 @@
import base64
import time
import json
import errno

from moulinette import m18n
from moulinette.core import MoulinetteError
from yunohost.utils.error import YunohostError
from moulinette.utils.log import getActionLogger

from yunohost.tools import Migration
Expand All @@ -29,7 +28,7 @@ def migrate(self, dyn_host="dyndns.yunohost.org", domain=None, private_key_path=
try:
(domain, private_key_path) = _guess_current_dyndns_domain(dyn_host)
assert "+157" in private_key_path
except (MoulinetteError, AssertionError):
except (YunohostError, AssertionError):
logger.info(m18n.n("migrate_tsig_not_needed"))
return

Expand All @@ -52,7 +51,7 @@ def migrate(self, dyn_host="dyndns.yunohost.org", domain=None, private_key_path=
'public_key_sha512': base64.b64encode(public_key_sha512),
}, timeout=30)
except requests.ConnectionError:
raise MoulinetteError(errno.ENETUNREACH, m18n.n('no_internet_connection'))
raise YunohostError('no_internet_connection')

if r.status_code != 201:
try:
Expand All @@ -70,8 +69,8 @@ def migrate(self, dyn_host="dyndns.yunohost.org", domain=None, private_key_path=
# Migration didn't succeed, so we rollback and raise an exception
os.system("mv /etc/yunohost/dyndns/*+165* /tmp")

raise MoulinetteError(m18n.n('migrate_tsig_failed', domain=domain,
error_code=str(r.status_code), error=error))
raise YunohostError('migrate_tsig_failed', domain=domain,
error_code=str(r.status_code), error=error)

# remove old certificates
os.system("mv /etc/yunohost/dyndns/*+157* /tmp")
Expand Down
12 changes: 6 additions & 6 deletions src/yunohost/data_migrations/0003_migrate_to_stretch.py
Expand Up @@ -3,7 +3,7 @@
from shutil import copy2

from moulinette import m18n, msettings
from moulinette.core import MoulinetteError
from yunohost.utils.error import YunohostError
from moulinette.utils.log import getActionLogger
from moulinette.utils.process import check_output, call_async_output
from moulinette.utils.filesystem import read_file
Expand All @@ -30,7 +30,7 @@ class MyMigration(Migration):

def backward(self):

raise MoulinetteError(m18n.n("migration_0003_backward_impossible"))
raise YunohostError("migration_0003_backward_impossible")

def migrate(self):

Expand All @@ -57,7 +57,7 @@ def migrate(self):
self.apt_dist_upgrade(conf_flags=["old", "miss", "def"])
_run_service_command("start", "mysql")
if self.debian_major_version() == 8:
raise MoulinetteError(m18n.n("migration_0003_still_on_jessie_after_main_upgrade", log=self.logfile))
raise YunohostError("migration_0003_still_on_jessie_after_main_upgrade", log=self.logfile)

# Specific upgrade for fail2ban...
logger.info(m18n.n("migration_0003_fail2ban_upgrade"))
Expand Down Expand Up @@ -107,11 +107,11 @@ def check_assertions(self):
# would still be in 2.x...
if not self.debian_major_version() == 8 \
and not self.yunohost_major_version() == 2:
raise MoulinetteError(m18n.n("migration_0003_not_jessie"))
raise YunohostError("migration_0003_not_jessie")

# Have > 1 Go free space on /var/ ?
if free_space_in_directory("/var/") / (1024**3) < 1.0:
raise MoulinetteError(m18n.n("migration_0003_not_enough_free_space"))
raise YunohostError("migration_0003_not_enough_free_space")

# Check system is up to date
# (but we don't if 'stretch' is already in the sources.list ...
Expand All @@ -120,7 +120,7 @@ def check_assertions(self):
self.apt_update()
apt_list_upgradable = check_output("apt list --upgradable -a")
if "upgradable" in apt_list_upgradable:
raise MoulinetteError(m18n.n("migration_0003_system_not_fully_up_to_date"))
raise YunohostError("migration_0003_system_not_fully_up_to_date")

@property
def disclaimer(self):
Expand Down
6 changes: 3 additions & 3 deletions src/yunohost/data_migrations/0005_postgresql_9p4_to_9p6.py
@@ -1,7 +1,7 @@
import subprocess

from moulinette import m18n
from moulinette.core import MoulinetteError
from yunohost.utils.error import YunohostError
from moulinette.utils.log import getActionLogger

from yunohost.tools import Migration
Expand All @@ -20,10 +20,10 @@ def migrate(self):
return

if not self.package_is_installed("postgresql-9.6"):
raise MoulinetteError(m18n.n("migration_0005_postgresql_96_not_installed"))
raise YunohostError("migration_0005_postgresql_96_not_installed")

if not space_used_by_directory("/var/lib/postgresql/9.4") > free_space_in_directory("/var/lib/postgresql"):
raise MoulinetteError(m18n.n("migration_0005_not_enough_space", path="/var/lib/postgresql/"))
raise YunohostError("migration_0005_not_enough_space", path="/var/lib/postgresql/")

subprocess.check_call("service postgresql stop", shell=True)
subprocess.check_call("pg_dropcluster --stop 9.6 main", shell=True)
Expand Down
Expand Up @@ -5,7 +5,7 @@
import subprocess

from moulinette import m18n
from moulinette.core import MoulinetteError
from yunohost.utils.error import YunohostError
from moulinette.utils.log import getActionLogger
from moulinette.utils.process import run_commands, check_output
from moulinette.utils.filesystem import append_to_file
Expand Down
Expand Up @@ -4,14 +4,14 @@
from shutil import copyfile

from moulinette import m18n
from moulinette.core import MoulinetteError
from moulinette.utils.log import getActionLogger
from moulinette.utils.filesystem import mkdir, rm

from yunohost.tools import Migration
from yunohost.service import service_regen_conf, _get_conf_hashes, \
_calculate_hash, _run_service_command
from yunohost.settings import settings_set
from yunohost.utils.error import YunohostError

logger = getActionLogger('yunohost.migration')

Expand Down Expand Up @@ -67,11 +67,11 @@ def migrate(self):
# Restart ssh and backward if it fail
if not _run_service_command('restart', 'ssh'):
self.backward()
raise MoulinetteError(m18n.n("migration_0007_cancel"))
raise YunohostError("migration_0007_cancel")

def backward(self):

# We don't backward completely but it should be enough
copyfile('/etc/ssh/sshd_config.bkp', SSHD_CONF)
if not _run_service_command('restart', 'ssh'):
raise MoulinetteError(m18n.n("migration_0007_cannot_restart"))
raise YunohostError("migration_0007_cannot_restart")
@@ -1,13 +1,12 @@
import re

from moulinette import m18n
from moulinette.core import MoulinetteError
from moulinette.utils.log import getActionLogger

from yunohost.tools import Migration
from yunohost.service import service_regen_conf, _get_conf_hashes, \
_calculate_hash
from yunohost.settings import settings_set, settings_get
from yunohost.utils.error import YunohostError

logger = getActionLogger('yunohost.migration')

Expand All @@ -33,7 +32,7 @@ def migrate(self):

def backward(self):

raise MoulinetteError(m18n.n("migration_0008_backward_impossible"))
raise YunohostError("migration_0008_backward_impossible")

@property
def mode(self):
Expand Down