implement intelligent updater (only sends ns update if IP really changed)

This commit is contained in:
Thomas Waldmann 2013-09-28 17:02:43 +02:00
parent 9be82a5d01
commit be3a124fbc
2 changed files with 46 additions and 2 deletions

View File

@ -4,13 +4,29 @@ Tests for dnstools module.
import pytest import pytest
from ..dnstools import (query_ns, parse_name, update_ns, from ..dnstools import (update, query_ns, parse_name, update_ns, SameIpError,
BASEDOMAIN, NONEXISTING_HOST, BASEDOMAIN, NONEXISTING_HOST,
WWW_HOST, WWW_IPV4_HOST, WWW_IPV4_IP, WWW_IPV6_HOST, WWW_IPV6_IP, ) WWW_HOST, WWW_IPV4_HOST, WWW_IPV4_IP, WWW_IPV6_HOST, WWW_IPV6_IP, )
from dns.resolver import NXDOMAIN from dns.resolver import NXDOMAIN
class TestIntelligentUpdater(object):
def test_double_update(self):
host, ip = 'test0.' + BASEDOMAIN, '1.2.3.4'
# make sure the host is not there
try:
update_ns(host, 'A', action='del')
except NXDOMAIN:
# it is ok if it was never there
pass
# first update with this IP, should work without issue:
update(host, ip)
with pytest.raises(SameIpError):
# trying to update again with same IP should raise
update(host, ip)
class TestQuery(object): class TestQuery(object):
def test_queries_ok(self): def test_queries_ok(self):
assert query_ns(WWW_IPV4_HOST, 'A') == WWW_IPV4_IP # v4 ONLY assert query_ns(WWW_IPV4_HOST, 'A') == WWW_IPV4_IP # v4 ONLY

View File

@ -1,8 +1,10 @@
""" s"""
Misc. DNS related code: query, dynamic update, etc. Misc. DNS related code: query, dynamic update, etc.
""" """
from django.conf import settings from django.conf import settings
import dns.inet
import dns.name import dns.name
import dns.resolver import dns.resolver
import dns.query import dns.query
@ -25,6 +27,32 @@ UPDATE_ALGO = dns.tsig.HMAC_SHA512
UPDATE_KEY = settings.UPDATE_KEY UPDATE_KEY = settings.UPDATE_KEY
class SameIpError(ValueError):
"""
raised if an IP address is already present in DNS and and update was
requested, but is not needed.
"""
def update(fqdn, ipaddr, ttl=60):
af = dns.inet.af_for_address(ipaddr)
rdtype = 'A' if af == dns.inet.AF_INET else 'AAAA'
try:
current_ipaddr = query_ns(fqdn, rdtype)
# check if ip really changed
ok = ipaddr != current_ipaddr
except dns.resolver.NXDOMAIN:
# no dns entry yet, ok
ok = True
if ok:
# only send an update if the ip really changed as the update
# causes write I/O on the nameserver and also traffic to the
# dns slaves (they get a notify if we update the zone).
update_ns(fqdn, rdtype, ipaddr, action='upd', ttl=ttl)
else:
raise SameIpError
def query_ns(qname, rdtype): def query_ns(qname, rdtype):
""" """
query a dns name from our master server query a dns name from our master server