api views: reduce code duplication - _update and _delete were almost identical
This commit is contained in:
parent
ae06bb4f73
commit
6ba6628f60
@ -229,10 +229,7 @@ class NicUpdateView(View):
|
|||||||
if not ipaddr: # None or ''
|
if not ipaddr: # None or ''
|
||||||
ipaddr = normalize_ip(request.META.get('REMOTE_ADDR'))
|
ipaddr = normalize_ip(request.META.get('REMOTE_ADDR'))
|
||||||
secure = request.is_secure()
|
secure = request.is_secure()
|
||||||
if delete:
|
return _update_or_delete(host, ipaddr, secure, logger=logger, _delete=delete)
|
||||||
return _delete(host, ipaddr, secure, logger=logger)
|
|
||||||
else:
|
|
||||||
return _update(host, ipaddr, secure, logger=logger)
|
|
||||||
|
|
||||||
|
|
||||||
class NicDeleteView(NicUpdateView):
|
class NicDeleteView(NicUpdateView):
|
||||||
@ -287,10 +284,7 @@ class AuthorizedNicUpdateView(View):
|
|||||||
if not ipaddr: # None or empty string
|
if not ipaddr: # None or empty string
|
||||||
ipaddr = normalize_ip(request.META.get('REMOTE_ADDR'))
|
ipaddr = normalize_ip(request.META.get('REMOTE_ADDR'))
|
||||||
secure = request.is_secure()
|
secure = request.is_secure()
|
||||||
if delete:
|
return _update_or_delete(host, ipaddr, secure, logger=logger, _delete=delete)
|
||||||
return _delete(host, ipaddr, secure, logger=logger)
|
|
||||||
else:
|
|
||||||
return _update(host, ipaddr, secure, logger=logger)
|
|
||||||
|
|
||||||
|
|
||||||
class AuthorizedNicDeleteView(AuthorizedNicUpdateView):
|
class AuthorizedNicDeleteView(AuthorizedNicUpdateView):
|
||||||
@ -306,28 +300,30 @@ class AuthorizedNicDeleteView(AuthorizedNicUpdateView):
|
|||||||
return super(AuthorizedNicDeleteView, self).get(request, logger=logger, delete=delete)
|
return super(AuthorizedNicDeleteView, self).get(request, logger=logger, delete=delete)
|
||||||
|
|
||||||
|
|
||||||
def _update(host, ipaddr, secure=False, logger=None):
|
def _update_or_delete(host, ipaddr, secure=False, logger=None, _delete=False):
|
||||||
"""
|
"""
|
||||||
common code shared by the 2 update views
|
common code shared by the 2 update/delete views
|
||||||
|
|
||||||
:param host: host object
|
:param host: host object
|
||||||
:param ipaddr: new ip addr (v4 or v6)
|
:param ipaddr: ip addr (v4 or v6)
|
||||||
:param secure: True if we use TLS/https
|
:param secure: True if we use TLS/https
|
||||||
:param logger: a logger object
|
:param logger: a logger object
|
||||||
|
:param _delete: True for delete, False for update
|
||||||
:return: Response object with dyndns2 response
|
:return: Response object with dyndns2 response
|
||||||
"""
|
"""
|
||||||
|
mode = ('update', 'delete')[_delete]
|
||||||
# we are doing abuse / available checks rather late, so the client might
|
# we are doing abuse / available checks rather late, so the client might
|
||||||
# get more specific responses (like 'badagent' or 'notfqdn') by earlier
|
# get more specific responses (like 'badagent' or 'notfqdn') by earlier
|
||||||
# checks. it also avoids some code duplication if done here:
|
# checks. it also avoids some code duplication if done here:
|
||||||
fqdn = host.get_fqdn()
|
fqdn = host.get_fqdn()
|
||||||
if host.abuse or host.abuse_blocked:
|
if host.abuse or host.abuse_blocked:
|
||||||
msg = '%s - received update for host with abuse / abuse_blocked flag set' % (fqdn, )
|
msg = '%s - received %s for host with abuse / abuse_blocked flag set' % (fqdn, mode, )
|
||||||
logger.warning(msg)
|
logger.warning(msg)
|
||||||
host.register_client_result(msg, fault=False)
|
host.register_client_result(msg, fault=False)
|
||||||
return Response('abuse')
|
return Response('abuse')
|
||||||
if not host.available:
|
if not host.available:
|
||||||
# not available is like it doesn't exist
|
# not available is like it doesn't exist
|
||||||
msg = '%s - received update for unavailable host' % (fqdn, )
|
msg = '%s - received %s for unavailable host' % (fqdn, mode, )
|
||||||
logger.warning(msg)
|
logger.warning(msg)
|
||||||
host.register_client_result(msg, fault=False)
|
host.register_client_result(msg, fault=False)
|
||||||
return Response('nohost')
|
return Response('nohost')
|
||||||
@ -337,6 +333,7 @@ def _update(host, ipaddr, secure=False, logger=None):
|
|||||||
# TODO: reproduce and submit traceback to issue 41
|
# TODO: reproduce and submit traceback to issue 41
|
||||||
ipaddr = str(ipaddr)
|
ipaddr = str(ipaddr)
|
||||||
kind = check_ip(ipaddr, ('ipv4', 'ipv6'))
|
kind = check_ip(ipaddr, ('ipv4', 'ipv6'))
|
||||||
|
rdtype = 'A' if kind == 'ipv4' else 'AAAA'
|
||||||
except (ValueError, UnicodeError):
|
except (ValueError, UnicodeError):
|
||||||
# invalid ip address string
|
# invalid ip address string
|
||||||
# some people manage to even give a non-ascii string instead of an ip addr
|
# some people manage to even give a non-ascii string instead of an ip addr
|
||||||
@ -346,7 +343,10 @@ def _update(host, ipaddr, secure=False, logger=None):
|
|||||||
return Response('dnserr') # there should be a better response code for this
|
return Response('dnserr') # there should be a better response code for this
|
||||||
host.poke(kind, secure)
|
host.poke(kind, secure)
|
||||||
try:
|
try:
|
||||||
update(fqdn, ipaddr)
|
if _delete:
|
||||||
|
delete(fqdn, rdtype)
|
||||||
|
else:
|
||||||
|
update(fqdn, ipaddr)
|
||||||
except SameIpError:
|
except SameIpError:
|
||||||
msg = '%s - received no-change update, ip: %s tls: %r' % (fqdn, ipaddr, secure)
|
msg = '%s - received no-change update, ip: %s tls: %r' % (fqdn, ipaddr, secure)
|
||||||
logger.warning(msg)
|
logger.warning(msg)
|
||||||
@ -354,119 +354,75 @@ def _update(host, ipaddr, secure=False, logger=None):
|
|||||||
return Response('nochg %s' % ipaddr)
|
return Response('nochg %s' % ipaddr)
|
||||||
except (DnsUpdateError, NameServerNotAvailable) as e:
|
except (DnsUpdateError, NameServerNotAvailable) as e:
|
||||||
msg = str(e)
|
msg = str(e)
|
||||||
msg = '%s - received update that resulted in a dns error [%s], ip: %s tls: %r' % (
|
msg = '%s - received %s that resulted in a dns error [%s], ip: %s tls: %r' % (
|
||||||
fqdn, msg, ipaddr, secure)
|
fqdn, mode, msg, ipaddr, secure)
|
||||||
logger.error(msg)
|
logger.error(msg)
|
||||||
host.register_server_result(msg, fault=True)
|
host.register_server_result(msg, fault=True)
|
||||||
return Response('dnserr')
|
return Response('dnserr')
|
||||||
else:
|
else:
|
||||||
msg = '%s - received good update -> ip: %s tls: %r' % (fqdn, ipaddr, secure)
|
if _delete:
|
||||||
|
msg = '%s - received delete for record %s, tls: %r' % (fqdn, rdtype, secure)
|
||||||
|
else:
|
||||||
|
msg = '%s - received good update -> ip: %s tls: %r' % (fqdn, ipaddr, secure)
|
||||||
logger.info(msg)
|
logger.info(msg)
|
||||||
host.register_client_result(msg, fault=False)
|
host.register_client_result(msg, fault=False)
|
||||||
# update related hosts
|
if _delete:
|
||||||
for rh in host.relatedhosts.all():
|
# XXX unclear what to do for "other services" we relay updates to
|
||||||
if rh.available:
|
return Response('deleted %s' % rdtype)
|
||||||
if kind == 'ipv4':
|
else: # update
|
||||||
ifid = rh.interface_id_ipv4.strip()
|
_on_update_success(host, fqdn, kind, ipaddr, secure)
|
||||||
netmask = host.netmask_ipv4
|
return Response('good %s' % ipaddr)
|
||||||
else: # kind == 'ipv6':
|
|
||||||
ifid = rh.interface_id_ipv6.strip()
|
|
||||||
netmask = host.netmask_ipv6
|
def _on_update_success(host, fqdn, kind, ipaddr, secure):
|
||||||
if not ifid:
|
"""after updating the host in dns, do related other updates"""
|
||||||
# ifid can be just left blank if no address record of this type is wanted
|
# update related hosts
|
||||||
continue
|
for rh in host.relatedhosts.all():
|
||||||
|
if rh.available:
|
||||||
|
if kind == 'ipv4':
|
||||||
|
ifid = rh.interface_id_ipv4.strip()
|
||||||
|
netmask = host.netmask_ipv4
|
||||||
|
else: # kind == 'ipv6':
|
||||||
|
ifid = rh.interface_id_ipv6.strip()
|
||||||
|
netmask = host.netmask_ipv6
|
||||||
|
if not ifid:
|
||||||
|
# ifid can be just left blank if no address record of this type is wanted
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
ifid = IPAddress(ifid)
|
||||||
|
network = IPNetwork("%s/%d" % (ipaddr, netmask))
|
||||||
|
rh_ipaddr = str(IPAddress(network.network) + int(ifid))
|
||||||
|
rh_fqdn = FQDN(rh.name + '.' + fqdn.host, fqdn.domain)
|
||||||
|
except AddrFormatError as e:
|
||||||
|
logger.warning("trouble computing address of related host %s [%s]" % (rh, e))
|
||||||
|
else:
|
||||||
|
logger.info("updating related host %s -> %s" % (rh_fqdn, rh_ipaddr))
|
||||||
try:
|
try:
|
||||||
ifid = IPAddress(ifid)
|
update(rh_fqdn, rh_ipaddr)
|
||||||
network = IPNetwork("%s/%d" % (ipaddr, netmask))
|
except SameIpError:
|
||||||
rh_ipaddr = str(IPAddress(network.network) + int(ifid))
|
msg = '%s - received no-change update, ip: %s tls: %r' % (rh_fqdn, rh_ipaddr, secure)
|
||||||
rh_fqdn = FQDN(rh.name + '.' + fqdn.host, fqdn.domain)
|
logger.warning(msg)
|
||||||
except AddrFormatError as e:
|
host.register_client_result(msg, fault=True)
|
||||||
logger.warning("trouble computing address of related host %s [%s]" % (rh, e))
|
except (DnsUpdateError, NameServerNotAvailable) as e:
|
||||||
else:
|
msg = str(e)
|
||||||
logger.info("updating related host %s -> %s" % (rh_fqdn, rh_ipaddr))
|
msg = '%s - received update that resulted in a dns error [%s], ip: %s tls: %r' % (
|
||||||
try:
|
rh_fqdn, msg, rh_ipaddr, secure)
|
||||||
update(rh_fqdn, rh_ipaddr)
|
logger.error(msg)
|
||||||
except SameIpError:
|
host.register_server_result(msg, fault=True)
|
||||||
msg = '%s - received no-change update, ip: %s tls: %r' % (rh_fqdn, rh_ipaddr, secure)
|
|
||||||
logger.warning(msg)
|
|
||||||
host.register_client_result(msg, fault=True)
|
|
||||||
except (DnsUpdateError, NameServerNotAvailable) as e:
|
|
||||||
msg = str(e)
|
|
||||||
msg = '%s - received update that resulted in a dns error [%s], ip: %s tls: %r' % (
|
|
||||||
rh_fqdn, msg, rh_ipaddr, secure)
|
|
||||||
logger.error(msg)
|
|
||||||
host.register_server_result(msg, fault=True)
|
|
||||||
|
|
||||||
# now check if there are other services we shall relay updates to:
|
# now check if there are other services we shall relay updates to:
|
||||||
for hc in host.serviceupdaterhostconfigs.all():
|
for hc in host.serviceupdaterhostconfigs.all():
|
||||||
if (kind == 'ipv4' and hc.give_ipv4 and hc.service.accept_ipv4
|
if (kind == 'ipv4' and hc.give_ipv4 and hc.service.accept_ipv4
|
||||||
or
|
or
|
||||||
kind == 'ipv6' and hc.give_ipv6 and hc.service.accept_ipv6):
|
kind == 'ipv6' and hc.give_ipv6 and hc.service.accept_ipv6):
|
||||||
kwargs = dict(
|
kwargs = dict(
|
||||||
name=hc.name, password=hc.password,
|
name=hc.name, password=hc.password,
|
||||||
hostname=hc.hostname, myip=ipaddr,
|
hostname=hc.hostname, myip=ipaddr,
|
||||||
server=hc.service.server, path=hc.service.path, secure=hc.service.secure,
|
server=hc.service.server, path=hc.service.path, secure=hc.service.secure,
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
ddns_client.dyndns2_update(**kwargs)
|
ddns_client.dyndns2_update(**kwargs)
|
||||||
except Exception:
|
except Exception:
|
||||||
# we never want to crash here
|
# we never want to crash here
|
||||||
kwargs.pop('password')
|
kwargs.pop('password')
|
||||||
logger.exception("the dyndns2 updater raised an exception [%r]" % kwargs)
|
logger.exception("the dyndns2 updater raised an exception [%r]" % kwargs)
|
||||||
return Response('good %s' % ipaddr)
|
|
||||||
|
|
||||||
|
|
||||||
def _delete(host, ipaddr, secure=False, logger=None):
|
|
||||||
"""
|
|
||||||
common code shared by the 2 delete views
|
|
||||||
|
|
||||||
:param host: host object
|
|
||||||
:param ipaddr: ip addr (to determine record type A or AAAA)
|
|
||||||
:param secure: True if we use TLS/https
|
|
||||||
:param logger: a logger object
|
|
||||||
:return: Response object with dyndns2 response
|
|
||||||
"""
|
|
||||||
# we are doing abuse / available checks rather late, so the client might
|
|
||||||
# get more specific responses (like 'badagent' or 'notfqdn') by earlier
|
|
||||||
# checks. it also avoids some code duplication if done here:
|
|
||||||
fqdn = host.get_fqdn()
|
|
||||||
if host.abuse or host.abuse_blocked:
|
|
||||||
msg = '%s - received delete for host with abuse / abuse_blocked flag set' % (fqdn, )
|
|
||||||
logger.warning(msg)
|
|
||||||
host.register_client_result(msg, fault=False)
|
|
||||||
return Response('abuse')
|
|
||||||
if not host.available:
|
|
||||||
# not available is like it doesn't exist
|
|
||||||
msg = '%s - received delete for unavailable host' % (fqdn, )
|
|
||||||
logger.warning(msg)
|
|
||||||
host.register_client_result(msg, fault=False)
|
|
||||||
return Response('nohost')
|
|
||||||
try:
|
|
||||||
# bug in dnspython: crashes if ipaddr is unicode, wants a str!
|
|
||||||
# https://github.com/rthalley/dnspython/issues/41
|
|
||||||
# TODO: reproduce and submit traceback to issue 41
|
|
||||||
ipaddr = str(ipaddr)
|
|
||||||
kind = check_ip(ipaddr, ('ipv4', 'ipv6'))
|
|
||||||
except (ValueError, UnicodeError):
|
|
||||||
# invalid ip address string
|
|
||||||
# some people manage to even give a non-ascii string instead of an ip addr
|
|
||||||
msg = '%s - received bad ip address: %r' % (fqdn, ipaddr)
|
|
||||||
logger.warning(msg)
|
|
||||||
host.register_client_result(msg, fault=True)
|
|
||||||
return Response('dnserr') # there should be a better response code for this
|
|
||||||
host.poke(kind, secure)
|
|
||||||
try:
|
|
||||||
rdtype = 'A' if kind == 'ipv4' else 'AAAA'
|
|
||||||
delete(fqdn, rdtype)
|
|
||||||
msg = '%s - received delete for record %s, tls: %r' % (fqdn, rdtype, secure)
|
|
||||||
logger.info(msg)
|
|
||||||
host.register_client_result(msg, fault=False)
|
|
||||||
# XXX unclear what to do for "other services" we relay updates to
|
|
||||||
return Response('deleted %s' % rdtype)
|
|
||||||
except (DnsUpdateError, NameServerNotAvailable) as e:
|
|
||||||
msg = str(e)
|
|
||||||
msg = '%s - received delete for record %s that resulted in a dns error [%s], tls: %r' % (
|
|
||||||
fqdn, rdtype, msg, secure)
|
|
||||||
logger.error(msg)
|
|
||||||
host.register_server_result(msg, fault=True)
|
|
||||||
return Response('dnserr')
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user