mirror of
https://github.com/YunoHost/yunohost.git
synced 2024-09-03 20:06:10 +02:00
[fix] Clean madness related to DynDNS (#353)
* Add a function to check if a dyndns provider provides a domain * Add a function to check a domain availability from a dyndns provider * Use new functions in dyndns_subscribe * Replace complete madness by _dyndns_available in dyndns_update * This regex is only used in dyndns_update, no need to define it at the whole file scope level * Try to clarify management of old ipv4/ipv6 ... * Add a nice helper to get both ipv4 and ipv6... * Clarify the dyndns_update madness to get current ipv4/v6 * Remove now useless IPRouteLine * Change default values of old ipv4/v6 to None, otherwise shit gets update just because IPv6 = None * Rearrange thing a bit, move path to global variable * Copypasta typo * Dyndns zone file as a global variable * Use helper to write zone content to file * Adding some debugs/info messages * Move the domain guessing to a dedicated function... * Adding comments.. * Using subprocess check_call instead of os.system for nsupdate * Removing dump of the zone update because it's kinda duplicated from what nsupdate already does * Ignore error if old_ipvx file is non existent * Add docstring for _dyndns_available * Remove parenthesis otherwise this gonna displease Bram-sama :P * Start working on postinstall .. use _dyndns_provides to check if domain is a .nohost.me or .nohost.st * Use _dyndns_available to cleanly check for domain availability * Forget about the weird 'domain split' check... * Clean dyndns stuff in domain.py * Missing argument for string
This commit is contained in:
parent
0086c8c16a
commit
5ae558edc9
4 changed files with 198 additions and 124 deletions
|
@ -158,6 +158,7 @@
|
||||||
"domains_available": "Available domains:",
|
"domains_available": "Available domains:",
|
||||||
"done": "Done",
|
"done": "Done",
|
||||||
"downloading": "Downloading...",
|
"downloading": "Downloading...",
|
||||||
|
"dyndns_could_not_check_provide": "Could not check if {provider:s} can provide {domain:s}.",
|
||||||
"dyndns_cron_installed": "The DynDNS cron job has been installed",
|
"dyndns_cron_installed": "The DynDNS cron job has been installed",
|
||||||
"dyndns_cron_remove_failed": "Unable to remove the DynDNS cron job",
|
"dyndns_cron_remove_failed": "Unable to remove the DynDNS cron job",
|
||||||
"dyndns_cron_removed": "The DynDNS cron job has been removed",
|
"dyndns_cron_removed": "The DynDNS cron job has been removed",
|
||||||
|
@ -168,7 +169,8 @@
|
||||||
"dyndns_no_domain_registered": "No domain has been registered with DynDNS",
|
"dyndns_no_domain_registered": "No domain has been registered with DynDNS",
|
||||||
"dyndns_registered": "The DynDNS domain has been registered",
|
"dyndns_registered": "The DynDNS domain has been registered",
|
||||||
"dyndns_registration_failed": "Unable to register DynDNS domain: {error:s}",
|
"dyndns_registration_failed": "Unable to register DynDNS domain: {error:s}",
|
||||||
"dyndns_unavailable": "Unavailable DynDNS subdomain",
|
"dyndns_domain_not_provided": "Dyndns provider {provider:s} cannot provide domain {domain:s}.",
|
||||||
|
"dyndns_unavailable": "Domain {domain:s} is not available.",
|
||||||
"executing_command": "Executing command '{command:s}'...",
|
"executing_command": "Executing command '{command:s}'...",
|
||||||
"executing_script": "Executing script '{script:s}'...",
|
"executing_script": "Executing script '{script:s}'...",
|
||||||
"extracting": "Extracting...",
|
"extracting": "Extracting...",
|
||||||
|
|
|
@ -82,28 +82,23 @@ def domain_add(auth, domain, dyndns=False):
|
||||||
|
|
||||||
# DynDNS domain
|
# DynDNS domain
|
||||||
if dyndns:
|
if dyndns:
|
||||||
if len(domain.split('.')) < 3:
|
|
||||||
raise MoulinetteError(errno.EINVAL, m18n.n('domain_dyndns_invalid'))
|
|
||||||
|
|
||||||
|
# Do not allow to subscribe to multiple dyndns domains...
|
||||||
if os.path.exists('/etc/cron.d/yunohost-dyndns'):
|
if os.path.exists('/etc/cron.d/yunohost-dyndns'):
|
||||||
raise MoulinetteError(errno.EPERM,
|
raise MoulinetteError(errno.EPERM,
|
||||||
m18n.n('domain_dyndns_already_subscribed'))
|
m18n.n('domain_dyndns_already_subscribed'))
|
||||||
try:
|
|
||||||
r = requests.get('https://dyndns.yunohost.org/domains', timeout=30)
|
|
||||||
except requests.ConnectionError as e:
|
|
||||||
raise MoulinetteError(errno.EHOSTUNREACH,
|
|
||||||
m18n.n('domain_dyndns_dynette_is_unreachable', error=str(e)))
|
|
||||||
|
|
||||||
from yunohost.dyndns import dyndns_subscribe
|
from yunohost.dyndns import dyndns_subscribe, _dyndns_provides
|
||||||
|
|
||||||
dyndomains = json.loads(r.text)
|
# Check that this domain can effectively be provided by
|
||||||
dyndomain = '.'.join(domain.split('.')[1:])
|
# dyndns.yunohost.org. (i.e. is it a nohost.me / noho.st)
|
||||||
if dyndomain in dyndomains:
|
if not _dyndns_provides("dyndns.yunohost.org", domain):
|
||||||
dyndns_subscribe(domain=domain)
|
|
||||||
else:
|
|
||||||
raise MoulinetteError(errno.EINVAL,
|
raise MoulinetteError(errno.EINVAL,
|
||||||
m18n.n('domain_dyndns_root_unknown'))
|
m18n.n('domain_dyndns_root_unknown'))
|
||||||
|
|
||||||
|
# Actually subscribe
|
||||||
|
dyndns_subscribe(domain=domain)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
yunohost.certificate._certificate_install_selfsigned([domain], False)
|
yunohost.certificate._certificate_install_selfsigned([domain], False)
|
||||||
|
|
||||||
|
@ -281,6 +276,25 @@ def get_public_ip(protocol=4):
|
||||||
raise MoulinetteError(errno.ENETUNREACH,
|
raise MoulinetteError(errno.ENETUNREACH,
|
||||||
m18n.n('no_internet_connection'))
|
m18n.n('no_internet_connection'))
|
||||||
|
|
||||||
|
def get_public_ips():
|
||||||
|
"""
|
||||||
|
Retrieve the public IPv4 and v6 from ip. and ip6.yunohost.org
|
||||||
|
|
||||||
|
Returns a 2-tuple (ipv4, ipv6). ipv4 or ipv6 can be None if they were not
|
||||||
|
found.
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
ipv4 = get_public_ip()
|
||||||
|
except:
|
||||||
|
ipv4 = None
|
||||||
|
try:
|
||||||
|
ipv6 = get_public_ip(6)
|
||||||
|
except:
|
||||||
|
ipv6 = None
|
||||||
|
|
||||||
|
return (ipv4, ipv6)
|
||||||
|
|
||||||
|
|
||||||
def _get_maindomain():
|
def _get_maindomain():
|
||||||
with open('/etc/yunohost/current_host', 'r') as f:
|
with open('/etc/yunohost/current_host', 'r') as f:
|
||||||
|
|
|
@ -35,37 +35,72 @@ import subprocess
|
||||||
from moulinette import m18n
|
from moulinette import m18n
|
||||||
from moulinette.core import MoulinetteError
|
from moulinette.core import MoulinetteError
|
||||||
from moulinette.utils.log import getActionLogger
|
from moulinette.utils.log import getActionLogger
|
||||||
|
from moulinette.utils.filesystem import read_file, write_to_file, rm
|
||||||
|
from moulinette.utils.network import download_json
|
||||||
|
|
||||||
from yunohost.domain import get_public_ip, _get_maindomain, _build_dns_conf
|
from yunohost.domain import get_public_ips, _get_maindomain, _build_dns_conf
|
||||||
|
|
||||||
logger = getActionLogger('yunohost.dyndns')
|
logger = getActionLogger('yunohost.dyndns')
|
||||||
|
|
||||||
|
OLD_IPV4_FILE = '/etc/yunohost/dyndns/old_ip'
|
||||||
|
OLD_IPV6_FILE = '/etc/yunohost/dyndns/old_ipv6'
|
||||||
|
DYNDNS_ZONE = '/etc/yunohost/dyndns/zone'
|
||||||
|
|
||||||
class IPRouteLine(object):
|
|
||||||
""" Utility class to parse an ip route output line
|
|
||||||
|
|
||||||
The output of ip ro is variable and hard to parse completly, it would
|
def _dyndns_provides(provider, domain):
|
||||||
require a real parser, not just a regexp, so do minimal parsing here...
|
|
||||||
|
|
||||||
>>> a = IPRouteLine('2001:: from :: via fe80::c23f:fe:1e:cafe dev eth0 src 2000:de:beef:ca:0:fe:1e:cafe metric 0')
|
|
||||||
>>> a.src_addr
|
|
||||||
"2000:de:beef:ca:0:fe:1e:cafe"
|
|
||||||
"""
|
"""
|
||||||
regexp = re.compile(
|
Checks if a provider provide/manage a given domain.
|
||||||
r'(?P<unreachable>unreachable)?.*src\s+(?P<src_addr>[0-9a-f:]+).*')
|
|
||||||
|
|
||||||
def __init__(self, line):
|
Keyword arguments:
|
||||||
self.m = self.regexp.match(line)
|
provider -- The url of the provider, e.g. "dyndns.yunohost.org"
|
||||||
if not self.m:
|
domain -- The full domain that you'd like.. e.g. "foo.nohost.me"
|
||||||
raise ValueError("Not a valid ip route get line")
|
|
||||||
|
|
||||||
# make regexp group available as object attributes
|
Returns:
|
||||||
for k, v in self.m.groupdict().items():
|
True if the provider provide/manages the domain. False otherwise.
|
||||||
setattr(self, k, v)
|
"""
|
||||||
|
|
||||||
re_dyndns_private_key = re.compile(
|
logger.debug("Checking if %s is managed by %s ..." % (domain, provider))
|
||||||
r'.*/K(?P<domain>[^\s\+]+)\.\+157.+\.private$'
|
|
||||||
)
|
try:
|
||||||
|
# Dyndomains will be a list of domains supported by the provider
|
||||||
|
# e.g. [ "nohost.me", "noho.st" ]
|
||||||
|
dyndomains = download_json('https://%s/domains' % provider, timeout=30)
|
||||||
|
except MoulinetteError as e:
|
||||||
|
logger.error(str(e))
|
||||||
|
raise MoulinetteError(errno.EIO,
|
||||||
|
m18n.n('dyndns_could_not_check_provide',
|
||||||
|
domain=domain, provider=provider))
|
||||||
|
|
||||||
|
# Extract 'dyndomain' from 'domain', e.g. 'nohost.me' from 'foo.nohost.me'
|
||||||
|
dyndomain = '.'.join(domain.split('.')[1:])
|
||||||
|
|
||||||
|
return dyndomain in dyndomains
|
||||||
|
|
||||||
|
|
||||||
|
def _dyndns_available(provider, domain):
|
||||||
|
"""
|
||||||
|
Checks if a domain is available from a given provider.
|
||||||
|
|
||||||
|
Keyword arguments:
|
||||||
|
provider -- The url of the provider, e.g. "dyndns.yunohost.org"
|
||||||
|
domain -- The full domain that you'd like.. e.g. "foo.nohost.me"
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
True if the domain is avaible, False otherwise.
|
||||||
|
"""
|
||||||
|
logger.debug("Checking if domain %s is available on %s ..."
|
||||||
|
% (domain, provider))
|
||||||
|
|
||||||
|
try:
|
||||||
|
r = download_json('https://%s/test/%s' % (provider, domain),
|
||||||
|
expected_status_code=None)
|
||||||
|
except MoulinetteError as e:
|
||||||
|
logger.error(str(e))
|
||||||
|
raise MoulinetteError(errno.EIO,
|
||||||
|
m18n.n('dyndns_could_not_check_available',
|
||||||
|
domain=domain, provider=provider))
|
||||||
|
|
||||||
|
return r == u"Domain %s is available" % domain
|
||||||
|
|
||||||
|
|
||||||
def dyndns_subscribe(subscribe_host="dyndns.yunohost.org", domain=None, key=None):
|
def dyndns_subscribe(subscribe_host="dyndns.yunohost.org", domain=None, key=None):
|
||||||
|
@ -81,12 +116,16 @@ def dyndns_subscribe(subscribe_host="dyndns.yunohost.org", domain=None, key=None
|
||||||
if domain is None:
|
if domain is None:
|
||||||
domain = _get_maindomain()
|
domain = _get_maindomain()
|
||||||
|
|
||||||
|
# Verify if domain is provided by subscribe_host
|
||||||
|
if not _dyndns_provides(subscribe_host, domain):
|
||||||
|
raise MoulinetteError(errno.ENOENT,
|
||||||
|
m18n.n('dyndns_domain_not_provided',
|
||||||
|
domain=domain, provider=subscribe_host))
|
||||||
|
|
||||||
# Verify if domain is available
|
# Verify if domain is available
|
||||||
try:
|
if not _dyndns_available(subscribe_host, domain):
|
||||||
if requests.get('https://%s/test/%s' % (subscribe_host, domain)).status_code != 200:
|
raise MoulinetteError(errno.ENOENT,
|
||||||
raise MoulinetteError(errno.EEXIST, m18n.n('dyndns_unavailable'))
|
m18n.n('dyndns_unavailable', domain=domain))
|
||||||
except requests.ConnectionError:
|
|
||||||
raise MoulinetteError(errno.ENETUNREACH, m18n.n('no_internet_connection'))
|
|
||||||
|
|
||||||
if key is None:
|
if key is None:
|
||||||
if len(glob.glob('/etc/yunohost/dyndns/*.key')) == 0:
|
if len(glob.glob('/etc/yunohost/dyndns/*.key')) == 0:
|
||||||
|
@ -133,73 +172,40 @@ def dyndns_update(dyn_host="dyndns.yunohost.org", domain=None, key=None,
|
||||||
ipv6 -- IPv6 address to send
|
ipv6 -- IPv6 address to send
|
||||||
|
|
||||||
"""
|
"""
|
||||||
# IPv4
|
# Get old ipv4/v6
|
||||||
|
|
||||||
|
old_ipv4, old_ipv6 = (None, None) # (default values)
|
||||||
|
|
||||||
|
if os.path.isfile(OLD_IPV4_FILE):
|
||||||
|
old_ipv4 = read_file(OLD_IPV4_FILE).rstrip()
|
||||||
|
|
||||||
|
if os.path.isfile(OLD_IPV6_FILE):
|
||||||
|
old_ipv6 = read_file(OLD_IPV6_FILE).rstrip()
|
||||||
|
|
||||||
|
# Get current IPv4 and IPv6
|
||||||
|
(ipv4_, ipv6_) = get_public_ips()
|
||||||
|
|
||||||
if ipv4 is None:
|
if ipv4 is None:
|
||||||
ipv4 = get_public_ip()
|
ipv4 = ipv4_
|
||||||
|
|
||||||
try:
|
|
||||||
with open('/etc/yunohost/dyndns/old_ip', 'r') as f:
|
|
||||||
old_ip = f.readline().rstrip()
|
|
||||||
except IOError:
|
|
||||||
old_ip = '0.0.0.0'
|
|
||||||
|
|
||||||
# IPv6
|
|
||||||
if ipv6 is None:
|
|
||||||
try:
|
|
||||||
ip_route_out = subprocess.check_output(
|
|
||||||
['ip', 'route', 'get', '2000::']).split('\n')
|
|
||||||
|
|
||||||
if len(ip_route_out) > 0:
|
|
||||||
route = IPRouteLine(ip_route_out[0])
|
|
||||||
if not route.unreachable:
|
|
||||||
ipv6 = route.src_addr
|
|
||||||
|
|
||||||
except (OSError, ValueError) as e:
|
|
||||||
# Unlikely case "ip route" does not return status 0
|
|
||||||
# or produces unexpected output
|
|
||||||
raise MoulinetteError(errno.EBADMSG,
|
|
||||||
"ip route cmd error : {}".format(e))
|
|
||||||
|
|
||||||
if ipv6 is None:
|
if ipv6 is None:
|
||||||
logger.info(m18n.n('no_ipv6_connectivity'))
|
ipv6 = ipv6_
|
||||||
|
|
||||||
try:
|
logger.debug("Old IPv4/v6 are (%s, %s)" % (old_ipv4, old_ipv6))
|
||||||
with open('/etc/yunohost/dyndns/old_ipv6', 'r') as f:
|
logger.debug("Requested IPv4/v6 are (%s, %s)" % (ipv4, ipv6))
|
||||||
old_ipv6 = f.readline().rstrip()
|
|
||||||
except IOError:
|
|
||||||
old_ipv6 = '0000:0000:0000:0000:0000:0000:0000:0000'
|
|
||||||
|
|
||||||
# no need to update
|
# no need to update
|
||||||
if old_ip == ipv4 and old_ipv6 == ipv6:
|
if old_ipv4 == ipv4 and old_ipv6 == ipv6:
|
||||||
|
logger.info("No updated needed.")
|
||||||
return
|
return
|
||||||
|
else:
|
||||||
|
logger.info("Updated needed, going on...")
|
||||||
|
|
||||||
|
# If domain is not given, try to guess it from keys available...
|
||||||
if domain is None:
|
if domain is None:
|
||||||
# Retrieve the first registered domain
|
(domain, key) = _guess_current_dyndns_domain(dyn_host)
|
||||||
for path in glob.iglob('/etc/yunohost/dyndns/K*.private'):
|
# If key is not given, pick the first file we find with the domain given
|
||||||
match = re_dyndns_private_key.match(path)
|
elif key is None:
|
||||||
if not match:
|
|
||||||
continue
|
|
||||||
_domain = match.group('domain')
|
|
||||||
|
|
||||||
try:
|
|
||||||
# Check if domain is registered
|
|
||||||
request_url = 'https://{0}/test/{1}'.format(dyn_host, _domain)
|
|
||||||
if requests.get(request_url, timeout=30).status_code == 200:
|
|
||||||
continue
|
|
||||||
except requests.ConnectionError:
|
|
||||||
raise MoulinetteError(errno.ENETUNREACH,
|
|
||||||
m18n.n('no_internet_connection'))
|
|
||||||
except requests.exceptions.Timeout:
|
|
||||||
logger.warning("Correction timed out on {}, skip it".format(
|
|
||||||
request_url))
|
|
||||||
domain = _domain
|
|
||||||
key = path
|
|
||||||
break
|
|
||||||
if not domain:
|
|
||||||
raise MoulinetteError(errno.EINVAL,
|
|
||||||
m18n.n('dyndns_no_domain_registered'))
|
|
||||||
|
|
||||||
if key is None:
|
|
||||||
keys = glob.glob('/etc/yunohost/dyndns/K{0}.+*.private'.format(domain))
|
keys = glob.glob('/etc/yunohost/dyndns/K{0}.+*.private'.format(domain))
|
||||||
|
|
||||||
if not keys:
|
if not keys:
|
||||||
|
@ -207,9 +213,12 @@ def dyndns_update(dyn_host="dyndns.yunohost.org", domain=None, key=None,
|
||||||
|
|
||||||
key = keys[0]
|
key = keys[0]
|
||||||
|
|
||||||
|
# Extract 'host', e.g. 'nohost.me' from 'foo.nohost.me'
|
||||||
host = domain.split('.')[1:]
|
host = domain.split('.')[1:]
|
||||||
host = '.'.join(host)
|
host = '.'.join(host)
|
||||||
|
|
||||||
|
logger.debug("Building zone update file ...")
|
||||||
|
|
||||||
lines = [
|
lines = [
|
||||||
'server %s' % dyn_host,
|
'server %s' % dyn_host,
|
||||||
'zone %s' % host,
|
'zone %s' % host,
|
||||||
|
@ -246,21 +255,27 @@ def dyndns_update(dyn_host="dyndns.yunohost.org", domain=None, key=None,
|
||||||
'send'
|
'send'
|
||||||
]
|
]
|
||||||
|
|
||||||
with open('/etc/yunohost/dyndns/zone', 'w') as zone:
|
# Write the actions to do to update to a file, to be able to pass it
|
||||||
zone.write('\n'.join(lines))
|
# to nsupdate as argument
|
||||||
|
write_to_file(DYNDNS_ZONE, '\n'.join(lines))
|
||||||
|
|
||||||
if os.system('/usr/bin/nsupdate -k %s /etc/yunohost/dyndns/zone' % key) != 0:
|
logger.info("Now pushing new conf to DynDNS host...")
|
||||||
os.system('rm -f /etc/yunohost/dyndns/old_ip')
|
|
||||||
os.system('rm -f /etc/yunohost/dyndns/old_ipv6')
|
try:
|
||||||
|
command = ["/usr/bin/nsupdate", "-k", key, DYNDNS_ZONE]
|
||||||
|
subprocess.check_call(command)
|
||||||
|
except subprocess.CalledProcessError:
|
||||||
|
rm(OLD_IPV4_FILE, force=True) # Remove file (ignore if non-existent)
|
||||||
|
rm(OLD_IPV6_FILE, force=True) # Remove file (ignore if non-existent)
|
||||||
raise MoulinetteError(errno.EPERM,
|
raise MoulinetteError(errno.EPERM,
|
||||||
m18n.n('dyndns_ip_update_failed'))
|
m18n.n('dyndns_ip_update_failed'))
|
||||||
|
|
||||||
logger.success(m18n.n('dyndns_ip_updated'))
|
logger.success(m18n.n('dyndns_ip_updated'))
|
||||||
with open('/etc/yunohost/dyndns/old_ip', 'w') as f:
|
|
||||||
f.write(ipv4)
|
if ipv4 is not None:
|
||||||
|
write_to_file(OLD_IPV4_FILE, ipv4)
|
||||||
if ipv6 is not None:
|
if ipv6 is not None:
|
||||||
with open('/etc/yunohost/dyndns/old_ipv6', 'w') as f:
|
write_to_file(OLD_IPV6_FILE, ipv6)
|
||||||
f.write(ipv6)
|
|
||||||
|
|
||||||
|
|
||||||
def dyndns_installcron():
|
def dyndns_installcron():
|
||||||
|
@ -287,3 +302,34 @@ def dyndns_removecron():
|
||||||
raise MoulinetteError(errno.EIO, m18n.n('dyndns_cron_remove_failed'))
|
raise MoulinetteError(errno.EIO, m18n.n('dyndns_cron_remove_failed'))
|
||||||
|
|
||||||
logger.success(m18n.n('dyndns_cron_removed'))
|
logger.success(m18n.n('dyndns_cron_removed'))
|
||||||
|
|
||||||
|
|
||||||
|
def _guess_current_dyndns_domain(dyn_host):
|
||||||
|
"""
|
||||||
|
This function tries to guess which domain should be updated by
|
||||||
|
"dyndns_update()" because there's not proper management of the current
|
||||||
|
dyndns domain :/ (and at the moment the code doesn't support having several
|
||||||
|
dyndns domain, which is sort of a feature so that people don't abuse the
|
||||||
|
dynette...)
|
||||||
|
"""
|
||||||
|
|
||||||
|
re_dyndns_private_key = re.compile(
|
||||||
|
r'.*/K(?P<domain>[^\s\+]+)\.\+157.+\.private$'
|
||||||
|
)
|
||||||
|
|
||||||
|
# Retrieve the first registered domain
|
||||||
|
for path in glob.iglob('/etc/yunohost/dyndns/K*.private'):
|
||||||
|
match = re_dyndns_private_key.match(path)
|
||||||
|
if not match:
|
||||||
|
continue
|
||||||
|
_domain = match.group('domain')
|
||||||
|
|
||||||
|
# Verify if domain is registered (i.e., if it's available, skip
|
||||||
|
# current domain beause that's not the one we want to update..)
|
||||||
|
if _dyndns_available(dyn_host, _domain):
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
return (_domain, path)
|
||||||
|
|
||||||
|
raise MoulinetteError(errno.EINVAL,
|
||||||
|
m18n.n('dyndns_no_domain_registered'))
|
||||||
|
|
|
@ -45,7 +45,7 @@ from moulinette.utils.log import getActionLogger
|
||||||
from moulinette.utils.filesystem import read_json, write_to_json
|
from moulinette.utils.filesystem import read_json, write_to_json
|
||||||
from yunohost.app import app_fetchlist, app_info, app_upgrade, app_ssowatconf, app_list, _install_appslist_fetch_cron
|
from yunohost.app import app_fetchlist, app_info, app_upgrade, app_ssowatconf, app_list, _install_appslist_fetch_cron
|
||||||
from yunohost.domain import domain_add, domain_list, get_public_ip, _get_maindomain, _set_maindomain
|
from yunohost.domain import domain_add, domain_list, get_public_ip, _get_maindomain, _set_maindomain
|
||||||
from yunohost.dyndns import dyndns_subscribe
|
from yunohost.dyndns import _dyndns_available, _dyndns_provides
|
||||||
from yunohost.firewall import firewall_upnp
|
from yunohost.firewall import firewall_upnp
|
||||||
from yunohost.service import service_status, service_regen_conf, service_log
|
from yunohost.service import service_status, service_regen_conf, service_log
|
||||||
from yunohost.monitor import monitor_disk, monitor_system
|
from yunohost.monitor import monitor_disk, monitor_system
|
||||||
|
@ -253,27 +253,39 @@ def tools_postinstall(domain, password, ignore_dyndns=False):
|
||||||
password -- YunoHost admin password
|
password -- YunoHost admin password
|
||||||
|
|
||||||
"""
|
"""
|
||||||
dyndns = not ignore_dyndns
|
dyndns_provider = "dyndns.yunohost.org"
|
||||||
|
|
||||||
# Do some checks at first
|
# Do some checks at first
|
||||||
if os.path.isfile('/etc/yunohost/installed'):
|
if os.path.isfile('/etc/yunohost/installed'):
|
||||||
raise MoulinetteError(errno.EPERM,
|
raise MoulinetteError(errno.EPERM,
|
||||||
m18n.n('yunohost_already_installed'))
|
m18n.n('yunohost_already_installed'))
|
||||||
if len(domain.split('.')) >= 3 and not ignore_dyndns:
|
|
||||||
try:
|
|
||||||
r = requests.get('https://dyndns.yunohost.org/domains')
|
|
||||||
except requests.ConnectionError:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
dyndomains = json.loads(r.text)
|
|
||||||
dyndomain = '.'.join(domain.split('.')[1:])
|
|
||||||
|
|
||||||
if dyndomain in dyndomains:
|
if not ignore_dyndns:
|
||||||
if requests.get('https://dyndns.yunohost.org/test/%s' % domain).status_code == 200:
|
# Check if yunohost dyndns can handle the given domain
|
||||||
|
# (i.e. is it a .nohost.me ? a .noho.st ?)
|
||||||
|
try:
|
||||||
|
is_nohostme_or_nohost = _dyndns_provides(dyndns_provider, domain)
|
||||||
|
# If an exception is thrown, most likely we don't have internet
|
||||||
|
# connectivity or something. Assume that this domain isn't manageable
|
||||||
|
# and inform the user that we could not contact the dyndns host server.
|
||||||
|
except:
|
||||||
|
logger.warning(m18n.n('dyndns_provider_unreachable',
|
||||||
|
provider=dyndns_provider))
|
||||||
|
is_nohostme_or_nohost = False
|
||||||
|
|
||||||
|
# If this is a nohost.me/noho.st, actually check for availability
|
||||||
|
if is_nohostme_or_nohost:
|
||||||
|
# (Except if the user explicitly said he/she doesn't care about dyndns)
|
||||||
|
if ignore_dyndns:
|
||||||
|
dyndns = False
|
||||||
|
# Check if the domain is available...
|
||||||
|
elif _dyndns_available(dyndns_provider, domain):
|
||||||
dyndns = True
|
dyndns = True
|
||||||
|
# If not, abort the postinstall
|
||||||
else:
|
else:
|
||||||
raise MoulinetteError(errno.EEXIST,
|
raise MoulinetteError(errno.EEXIST,
|
||||||
m18n.n('dyndns_unavailable'))
|
m18n.n('dyndns_unavailable',
|
||||||
|
domain=domain))
|
||||||
else:
|
else:
|
||||||
dyndns = False
|
dyndns = False
|
||||||
else:
|
else:
|
||||||
|
|
Loading…
Add table
Reference in a new issue