summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErik Olof Gunnar Andersson <eandersson@blizzard.com>2021-10-12 18:33:08 -0700
committerMichael Johnson <johnsomor@gmail.com>2022-06-02 21:05:17 +0000
commit60682ccef6d1133bbc239db94192b999b603c254 (patch)
treed0d875adb7f3d6672b51cb6226f188f2337c4f40
parent2e55c3e24bfaf1b03241aa1a4a538d03c29d69ad (diff)
downloaddesignate-60682ccef6d1133bbc239db94192b999b603c254.tar.gz
Fix dns.query.tcp/udp not always handling ipv6 properly
Created a new generic send_dns_msg that properly handles both ip and hostnames and fully supports ipv4 and ipv6. Also, moved all usage of dns.query.tcp/udp to a central location. Change-Id: I403ed6716b3ceffa1910269adf0e352f75e9dd5b (cherry picked from commit acd930d3429aa30bea449f5fc7246581b0d2eb25)
-rw-r--r--designate/backend/agent.py40
-rw-r--r--designate/dnsutils.py152
-rw-r--r--designate/mdns/notify.py24
-rw-r--r--designate/tests/unit/backend/test_agent.py56
-rw-r--r--designate/tests/unit/mdns/test_notify.py76
-rw-r--r--designate/tests/unit/test_dnsutils.py19
-rw-r--r--designate/tests/unit/workers/test_zone_tasks.py20
-rw-r--r--designate/worker/README.md2
-rw-r--r--designate/worker/tasks/zone.py8
-rw-r--r--designate/worker/utils.py82
10 files changed, 213 insertions, 266 deletions
diff --git a/designate/backend/agent.py b/designate/backend/agent.py
index 72f6ce97..67f8c80c 100644
--- a/designate/backend/agent.py
+++ b/designate/backend/agent.py
@@ -24,25 +24,23 @@
Configured in the [service:pool_manager] section
"""
-import eventlet
import dns
-import dns.rdataclass
-import dns.rdatatype
import dns.exception
import dns.flags
-import dns.rcode
import dns.message
import dns.opcode
+import dns.rcode
+import dns.rdataclass
+import dns.rdatatype
from oslo_config import cfg
from oslo_log import log as logging
from designate.backend import base
+from designate.backend import private_codes
+from designate.conf.agent import DEFAULT_AGENT_PORT
+from designate import dnsutils
from designate import exceptions
from designate.mdns import rpcapi as mdns_api
-from designate.utils import DEFAULT_AGENT_PORT
-import designate.backend.private_codes as pcodes
-
-dns_query = eventlet.import_patched('dns.query')
LOG = logging.getLogger(__name__)
CONF = cfg.CONF
@@ -72,9 +70,9 @@ class AgentPoolBackend(base.Backend):
response, retry = self._make_and_send_dns_message(
zone.name,
self.timeout,
- pcodes.CC,
- pcodes.CREATE,
- pcodes.CLASSCC,
+ private_codes.CC,
+ private_codes.CREATE,
+ private_codes.CLASSCC,
self.host,
self.port
)
@@ -100,9 +98,9 @@ class AgentPoolBackend(base.Backend):
response, retry = self._make_and_send_dns_message(
zone.name,
self.timeout,
- pcodes.CC,
- pcodes.DELETE,
- pcodes.CLASSCC,
+ private_codes.CC,
+ private_codes.DELETE,
+ private_codes.CLASSCC,
self.host,
self.port
)
@@ -134,7 +132,7 @@ class AgentPoolBackend(base.Backend):
'port': dest_port, 'timeout': timeout,
'retry': retry})
response = None
- elif isinstance(response, dns_query.BadResponse):
+ elif isinstance(response, dns.query.BadResponse):
LOG.warning("Got BadResponse while trying to send '%(msg)s' for "
"'%(zone)s' to '%(server)s:%(port)d'. "
"Timeout='%(timeout)d' seconds. Retry='%(retry)d'",
@@ -173,14 +171,10 @@ class AgentPoolBackend(base.Backend):
def _send_dns_message(self, dns_message, dest_ip, dest_port, timeout):
try:
- if not CONF['service:mdns'].all_tcp:
- response = dns_query.udp(
- dns_message, dest_ip, port=dest_port, timeout=timeout)
- else:
- response = dns_query.tcp(
- dns_message, dest_ip, port=dest_port, timeout=timeout)
- return response
+ return dnsutils.send_dns_message(
+ dns_message, dest_ip, port=dest_port, timeout=timeout
+ )
except dns.exception.Timeout as timeout:
return timeout
- except dns_query.BadResponse as badResponse:
+ except dns.query.BadResponse as badResponse:
return badResponse
diff --git a/designate/dnsutils.py b/designate/dnsutils.py
index 6833d542..a3b4d2f9 100644
--- a/designate/dnsutils.py
+++ b/designate/dnsutils.py
@@ -21,9 +21,10 @@ from threading import Lock
import six
import dns
import dns.exception
+import dns.query
+import dns.rdatatype
import dns.zone
import eventlet
-from dns import rdatatype
from oslo_serialization import base64
from oslo_log import log as logging
@@ -313,7 +314,7 @@ def dnspyrecords_to_recordsetlist(dnspython_records):
def dnspythonrecord_to_recordset(rname, rdataset):
- record_type = rdatatype.to_text(rdataset.rdtype)
+ record_type = dns.rdatatype.to_text(rdataset.rdtype)
name = rname.to_text()
if six.PY3 and isinstance(name, bytes):
@@ -347,39 +348,122 @@ def do_axfr(zone_name, servers, timeout=None, source=None):
timeout = timeout or CONF["service:mdns"].xfr_timeout
xfr = None
-
for srv in servers:
- to = eventlet.Timeout(timeout)
- log_info = {'name': zone_name, 'host': srv}
- try:
- LOG.info("Doing AXFR for %(name)s from %(host)s", log_info)
-
- xfr = dns.query.xfr(srv['host'], zone_name, relativize=False,
- timeout=1, port=srv['port'], source=source)
- raw_zone = dns.zone.from_xfr(xfr, relativize=False)
- break
- except eventlet.Timeout as t:
- if t == to:
- LOG.error("AXFR timed out for %(name)s from %(host)s",
- log_info)
- continue
- except dns.exception.FormError:
- LOG.error("Zone %(name)s is not present on %(host)s."
- "Trying next server.", log_info)
- except socket.error:
- LOG.error("Connection error when doing AXFR for %(name)s from "
- "%(host)s", log_info)
- except Exception:
- LOG.exception("Problem doing AXFR %(name)s from %(host)s. "
+ for address in get_ip_addresses(srv['host']):
+ to = eventlet.Timeout(timeout)
+ log_info = {'name': zone_name, 'host': srv, 'address': address}
+ try:
+ LOG.info(
+ 'Doing AXFR for %(name)s from %(host)s %(address)s',
+ log_info
+ )
+ xfr = dns.query.xfr(
+ address, zone_name, relativize=False, timeout=1,
+ port=srv['port'], source=source
+ )
+ raw_zone = dns.zone.from_xfr(xfr, relativize=False)
+ LOG.debug("AXFR Successful for %s", raw_zone.origin.to_text())
+ return raw_zone
+ except eventlet.Timeout as t:
+ if t == to:
+ LOG.error("AXFR timed out for %(name)s from %(host)s",
+ log_info)
+ continue
+ except dns.exception.FormError:
+ LOG.error("Zone %(name)s is not present on %(host)s."
"Trying next server.", log_info)
- finally:
- to.cancel()
- continue
- else:
- raise exceptions.XFRFailure(
- "XFR failed for %(name)s. No servers in %(servers)s was reached." %
- {"name": zone_name, "servers": servers})
+ except socket.error:
+ LOG.error("Connection error when doing AXFR for %(name)s from "
+ "%(host)s", log_info)
+ except Exception:
+ LOG.exception("Problem doing AXFR %(name)s from %(host)s. "
+ "Trying next server.", log_info)
+ finally:
+ to.cancel()
+
+ raise exceptions.XFRFailure(
+ "XFR failed for %(name)s. No servers in %(servers)s was reached." %
+ {"name": zone_name, "servers": servers}
+ )
+
+
+def prepare_msg(zone_name, rdatatype=dns.rdatatype.SOA,
+ dns_opcode=dns.opcode.QUERY):
+ """
+ Do the needful to set up a dns packet with dnspython
+ """
+ dns_message = dns.message.make_query(zone_name, rdatatype)
+ dns_message.set_opcode(dns_opcode)
+
+ return dns_message
+
+
+def dig(zone_name, host, rdatatype, port=53):
+ """
+ Set up and send a regular dns query, datatype configurable
+ """
+ query = prepare_msg(zone_name, rdatatype=rdatatype)
+
+ return send_dns_message(query, host, port=port)
+
+
+def notify(zone_name, host, port=53):
+ """
+ Set up a notify packet and send it
+ """
+ msg = prepare_msg(zone_name, dns_opcode=dns.opcode.NOTIFY)
+
+ return send_dns_message(msg, host, port=port)
- LOG.debug("AXFR Successful for %s", raw_zone.origin.to_text())
- return raw_zone
+def send_dns_message(dns_message, host, port=53, timeout=10):
+ """
+ Send the dns message and return the response
+
+ :return: dns.Message of the response to the dns query
+ """
+ ip_address = get_ip_address(host)
+ # This can raise some exceptions, but we'll catch them elsewhere
+ if not CONF['service:mdns'].all_tcp:
+ return dns.query.udp(
+ dns_message, ip_address, port=port, timeout=timeout)
+ return dns.query.tcp(
+ dns_message, ip_address, port=port, timeout=timeout)
+
+
+def get_serial(zone_name, host, port=53):
+ """
+ Possibly raises dns.exception.Timeout or dns.query.BadResponse.
+ Possibly returns 0 if, e.g., the answer section is empty.
+ """
+ resp = dig(zone_name, host, dns.rdatatype.SOA, port=port)
+ if not resp.answer:
+ return 0
+ rdataset = resp.answer[0].to_rdataset()
+ if not rdataset:
+ return 0
+ return rdataset[0].serial
+
+
+def get_ip_address(ip_address_or_hostname):
+ """
+ Provide an ip or hostname and return a valid ip4 or ipv6 address.
+
+ :return: ip address
+ """
+ addresses = get_ip_addresses(ip_address_or_hostname)
+ if not addresses:
+ return None
+ return addresses[0]
+
+
+def get_ip_addresses(ip_address_or_hostname):
+ """
+ Provide an ip or hostname and return all valid ip4 or ipv6 addresses.
+
+ :return: ip addresses
+ """
+ addresses = []
+ for res in socket.getaddrinfo(ip_address_or_hostname, 0):
+ addresses.append(res[4][0])
+ return list(set(addresses))
diff --git a/designate/mdns/notify.py b/designate/mdns/notify.py
index 0d66970d..0e464960 100644
--- a/designate/mdns/notify.py
+++ b/designate/mdns/notify.py
@@ -28,6 +28,7 @@ import dns.opcode
from oslo_config import cfg
from oslo_log import log as logging
+from designate import dnsutils
from designate.mdns import base
from designate.metrics import metrics
@@ -186,8 +187,9 @@ class NotifyEndpoint(base.BaseEndpoint):
'zone': zone.name, 'server': host,
'port': port})
try:
- response = self._send_dns_message(dns_message, host, port,
- timeout)
+ response = dnsutils.send_dns_message(
+ dns_message, host, port, timeout=timeout
+ )
except socket.error as e:
if e.errno != socket.errno.EAGAIN:
@@ -285,21 +287,3 @@ class NotifyEndpoint(base.BaseEndpoint):
dns_message.flags |= dns.flags.RD
return dns_message
-
- def _send_dns_message(self, dns_message, host, port, timeout):
- """
- Send DNS Message over TCP or UDP, return response.
-
- :param dns_message: The dns message that needs to be sent.
- :param host: The destination ip of dns_message.
- :param port: The destination port of dns_message.
- :param timeout: The timeout in seconds to wait for a response.
- :return: response
- """
- send = dns_query.tcp if CONF['service:mdns'].all_tcp else dns_query.udp
- return send(
- dns_message,
- socket.gethostbyname(host),
- port=port,
- timeout=timeout
- )
diff --git a/designate/tests/unit/backend/test_agent.py b/designate/tests/unit/backend/test_agent.py
index d1e585bf..408544d8 100644
--- a/designate/tests/unit/backend/test_agent.py
+++ b/designate/tests/unit/backend/test_agent.py
@@ -14,11 +14,13 @@
from unittest import mock
import dns
+import dns.query
import dns.rdataclass
import dns.rdatatype
import designate.backend.agent as agent
import designate.backend.private_codes as pcodes
+from designate import dnsutils
from designate import exceptions
from designate import objects
from designate import tests
@@ -130,7 +132,7 @@ class AgentBackendTestCase(tests.TestCase):
def test_make_and_send_dns_message_bad_response(self):
self.backend._make_dns_message = mock.Mock(return_value='')
self.backend._send_dns_message = mock.Mock(
- return_value=agent.dns_query.BadResponse())
+ return_value=dns.query.BadResponse())
out = self.backend._make_and_send_dns_message('h', 123, 1, 2, 3, 4, 5)
@@ -176,50 +178,16 @@ class AgentBackendTestCase(tests.TestCase):
self.assertEqual((response, 0), out)
- @mock.patch.object(agent.dns_query, 'tcp')
- @mock.patch.object(agent.dns_query, 'udp')
- def test_send_dns_message(self, mock_udp, mock_tcp):
+ @mock.patch.object(dnsutils, 'get_ip_address')
+ @mock.patch.object(dns.query, 'tcp')
+ @mock.patch.object(dns.query, 'udp')
+ def test_send_dns_message(self, mock_udp, mock_tcp, mock_get_ip_address):
mock_udp.return_value = 'mock udp resp'
+ mock_get_ip_address.return_value = '10.0.1.39'
- out = self.backend._send_dns_message('msg', 'host', 123, 1)
+ out = self.backend._send_dns_message('msg', '10.0.1.39', 123, 1)
- self.assertFalse(agent.dns_query.tcp.called)
- agent.dns_query.udp.assert_called_with('msg', 'host', port=123,
- timeout=1)
+ self.assertFalse(mock_tcp.called)
+ mock_udp.assert_called_with('msg', '10.0.1.39', port=123,
+ timeout=1)
self.assertEqual('mock udp resp', out)
-
- @mock.patch.object(agent.dns_query, 'tcp')
- @mock.patch.object(agent.dns_query, 'udp')
- def test_send_dns_message_timeout(self, mock_udp, mock_tcp):
- mock_udp.side_effect = dns.exception.Timeout
-
- out = self.backend._send_dns_message('msg', 'host', 123, 1)
-
- agent.dns_query.udp.assert_called_with('msg', 'host', port=123,
- timeout=1)
- self.assertIsInstance(out, dns.exception.Timeout)
-
- @mock.patch.object(agent.dns_query, 'tcp')
- @mock.patch.object(agent.dns_query, 'udp')
- def test_send_dns_message_bad_response(self, mock_udp, mock_tcp):
- mock_udp.side_effect = agent.dns_query.BadResponse
-
- out = self.backend._send_dns_message('msg', 'host', 123, 1)
-
- agent.dns_query.udp.assert_called_with('msg', 'host', port=123,
- timeout=1)
- self.assertIsInstance(out, agent.dns_query.BadResponse)
-
- @mock.patch.object(agent.dns_query, 'tcp')
- @mock.patch.object(agent.dns_query, 'udp')
- def test_send_dns_message_tcp(self, mock_udp, mock_tcp):
- self.CONF.set_override('all_tcp', True, 'service:mdns')
-
- mock_tcp.return_value = 'mock tcp resp'
-
- out = self.backend._send_dns_message('msg', 'host', 123, 1)
-
- self.assertFalse(agent.dns_query.udp.called)
- agent.dns_query.tcp.assert_called_with('msg', 'host', port=123,
- timeout=1)
- self.assertEqual('mock tcp resp', out)
diff --git a/designate/tests/unit/mdns/test_notify.py b/designate/tests/unit/mdns/test_notify.py
index 68b47467..45c82338 100644
--- a/designate/tests/unit/mdns/test_notify.py
+++ b/designate/tests/unit/mdns/test_notify.py
@@ -20,6 +20,7 @@ import dns
import dns.rdataclass
import dns.rdatatype
+from designate import dnsutils
import designate.mdns.notify as notify
import designate.tests
from designate.tests.unit import RoObject
@@ -130,12 +131,11 @@ class MdnsNotifyTest(designate.tests.TestCase):
self.assertEqual(('ERROR', 310, 0), out)
@mock.patch('time.sleep')
- def test_make_and_send_dns_message_timeout(self, mock_sleep):
+ @mock.patch.object(dnsutils, 'send_dns_message')
+ def test_make_and_send_dns_message_timeout(self, mock_send_dns_message,
+ mock_sleep):
zone = RoObject(name='zn')
- self.notify._make_dns_message = mock.Mock(return_value='')
- self.notify._send_dns_message = mock.Mock(
- side_effect=dns.exception.Timeout
- )
+ mock_send_dns_message.side_effect = dns.exception.Timeout
out = self.notify._make_and_send_dns_message(
zone, 'host', 123, 1, 2, 3
@@ -143,12 +143,12 @@ class MdnsNotifyTest(designate.tests.TestCase):
self.assertEqual((None, 3), out)
- def test_make_and_send_dns_message_bad_response(self):
+ @mock.patch.object(dnsutils, 'send_dns_message')
+ def test_make_and_send_dns_message_bad_response(self,
+ mock_send_dns_message):
zone = RoObject(name='zn')
self.notify._make_dns_message = mock.Mock(return_value='')
- self.notify._send_dns_message = mock.Mock(
- side_effect=notify.dns_query.BadResponse
- )
+ mock_send_dns_message.side_effect = notify.dns_query.BadResponse
out = self.notify._make_and_send_dns_message(
zone, 'host', 123, 1, 2, 3
@@ -157,15 +157,14 @@ class MdnsNotifyTest(designate.tests.TestCase):
self.assertEqual((None, 1), out)
@mock.patch('time.sleep')
- def test_make_and_send_dns_message_eagain(self, mock_sleep):
+ @mock.patch.object(dnsutils, 'send_dns_message')
+ def test_make_and_send_dns_message_eagain(self, mock_send_dns_message,
+ mock_sleep):
# bug #1558096
zone = RoObject(name='zn')
- self.notify._make_dns_message = mock.Mock(return_value='')
socket_error = socket.error()
socket_error.errno = socket.errno.EAGAIN
- self.notify._send_dns_message = mock.Mock(
- side_effect=socket_error
- )
+ mock_send_dns_message.side_effect = socket_error
out = self.notify._make_and_send_dns_message(
zone, 'host', 123, 1, 2, 3
@@ -173,15 +172,15 @@ class MdnsNotifyTest(designate.tests.TestCase):
self.assertEqual((None, 3), out)
- def test_make_and_send_dns_message_econnrefused(self):
+ @mock.patch.object(dnsutils, 'send_dns_message')
+ def test_make_and_send_dns_message_econnrefused(self,
+ mock_send_dns_message):
# bug #1558096
zone = RoObject(name='zn')
- self.notify._make_dns_message = mock.Mock(return_value='')
socket_error = socket.error()
socket_error.errno = socket.errno.ECONNREFUSED
# socket errors other than EAGAIN should raise
- self.notify._send_dns_message = mock.Mock(
- side_effect=socket_error)
+ mock_send_dns_message.side_effect = socket_error
self.assertRaises(
socket.error,
@@ -189,11 +188,11 @@ class MdnsNotifyTest(designate.tests.TestCase):
zone, 'host', 123, 1, 2, 3
)
- def test_make_and_send_dns_message_nxdomain(self):
+ @mock.patch.object(dnsutils, 'send_dns_message')
+ def test_make_and_send_dns_message_nxdomain(self, mock_send_dns_message):
zone = RoObject(name='zn')
- self.notify._make_dns_message = mock.Mock(return_value='')
response = RoObject(rcode=mock.Mock(return_value=dns.rcode.NXDOMAIN))
- self.notify._send_dns_message = mock.Mock(return_value=response)
+ mock_send_dns_message.return_value = response
out = self.notify._make_and_send_dns_message(
zone, 'host', 123, 1, 2, 3
@@ -201,17 +200,17 @@ class MdnsNotifyTest(designate.tests.TestCase):
self.assertEqual((response, 1), out)
- def test_make_and_send_dns_message_missing_AA_flags(self):
+ @mock.patch.object(dnsutils, 'send_dns_message')
+ def test_make_and_send_dns_message_missing_AA_flags(self,
+ mock_send_dns_message):
zone = RoObject(name='zn')
- self.notify._make_dns_message = mock.Mock(return_value='')
-
response = RoObject(
rcode=mock.Mock(return_value=dns.rcode.NOERROR),
# rcode is NOERROR but (flags & dns.flags.AA) gives 0
flags=0,
answer=['answer'],
)
- self.notify._send_dns_message = mock.Mock(return_value=response)
+ mock_send_dns_message.return_value = response
out = self.notify._make_and_send_dns_message(
zone, 'host', 123, 1, 2, 3
@@ -219,9 +218,10 @@ class MdnsNotifyTest(designate.tests.TestCase):
self.assertEqual((None, 1), out)
- def test_make_and_send_dns_message_error_flags(self):
+ @mock.patch.object(dnsutils, 'send_dns_message')
+ def test_make_and_send_dns_message_error_flags(self,
+ mock_send_dns_message):
zone = RoObject(name='zn')
- self.notify._make_dns_message = mock.Mock(return_value='')
response = RoObject(
rcode=mock.Mock(return_value=dns.rcode.NOERROR),
# rcode is NOERROR but flags are not NOERROR
@@ -229,7 +229,7 @@ class MdnsNotifyTest(designate.tests.TestCase):
ednsflags=321,
answer=['answer'],
)
- self.notify._send_dns_message = mock.Mock(return_value=response)
+ mock_send_dns_message.return_value = response
out = self.notify._make_and_send_dns_message(
zone, 'host', 123, 1, 2, 3
@@ -266,23 +266,3 @@ class MdnsNotifyTest(designate.tests.TestCase):
';AUTHORITY',
';ADDITIONAL',
], txt)
-
- @mock.patch.object(notify.dns_query, 'udp')
- def test_send_udp_dns_message(self, mock_udp):
- self.CONF.set_override('all_tcp', False, 'service:mdns')
-
- self.notify._send_dns_message('msg', '192.0.2.1', 1234, 1)
-
- mock_udp.assert_called_with(
- 'msg', '192.0.2.1', port=1234, timeout=1
- )
-
- @mock.patch.object(notify.dns_query, 'tcp')
- def test_send_tcp_dns_message(self, mock_tcp):
- self.CONF.set_override('all_tcp', True, 'service:mdns')
-
- self.notify._send_dns_message('msg', '192.0.2.1', 1234, 1)
-
- mock_tcp.assert_called_with(
- 'msg', '192.0.2.1', port=1234, timeout=1
- )
diff --git a/designate/tests/unit/test_dnsutils.py b/designate/tests/unit/test_dnsutils.py
index 8345b8ef..eac016fc 100644
--- a/designate/tests/unit/test_dnsutils.py
+++ b/designate/tests/unit/test_dnsutils.py
@@ -23,6 +23,7 @@ import dns.rcode
import dns.rdatatype
import dns.zone
import eventlet
+from oslo_config import cfg
import oslotest.base
from dns import zone as dnszone
@@ -31,6 +32,8 @@ from designate import dnsutils
from designate import exceptions
from designate import objects
+CONF = cfg.CONF
+
SAMPLES = {
("cname.example.com.", "CNAME"): {
"ttl": 10800,
@@ -320,3 +323,19 @@ class TestDoAfxr(oslotest.base.BaseTestCase):
self.assertTrue(mock_xfr.called)
self.assertTrue(mock_from_xfr.called)
+
+ @mock.patch.object(dns.query, 'udp')
+ def test_send_udp_dns_message(self, mock_udp):
+ CONF.set_override('all_tcp', False, 'service:mdns')
+ dnsutils.send_dns_message('msg', '192.0.2.1', 1234, 1)
+ mock_udp.assert_called_with(
+ 'msg', '192.0.2.1', port=1234, timeout=1
+ )
+
+ @mock.patch.object(dns.query, 'tcp')
+ def test_send_tcp_dns_message(self, mock_tcp):
+ CONF.set_override('all_tcp', True, 'service:mdns')
+ dnsutils.send_dns_message('msg', '192.0.2.1', 1234, 1)
+ mock_tcp.assert_called_with(
+ 'msg', '192.0.2.1', port=1234, timeout=1
+ )
diff --git a/designate/tests/unit/workers/test_zone_tasks.py b/designate/tests/unit/workers/test_zone_tasks.py
index 25b9c41a..47eb7d27 100644
--- a/designate/tests/unit/workers/test_zone_tasks.py
+++ b/designate/tests/unit/workers/test_zone_tasks.py
@@ -20,11 +20,11 @@ import oslotest.base
from oslo_config import cfg
from oslo_config import fixture as cfg_fixture
+from designate import dnsutils
from designate import exceptions
from designate import objects
from designate.tests.unit import utils
from designate.worker import processing
-from designate.worker import utils as wutils
from designate.worker.tasks import zone
CONF = cfg.CONF
@@ -167,7 +167,7 @@ class TestZoneActionOnTarget(oslotest.base.BaseTestCase):
self.context = mock.Mock()
self.executor = mock.Mock()
- @mock.patch.object(wutils, 'notify')
+ @mock.patch.object(dnsutils, 'notify')
def test_call_create(self, mock_notify):
self.zone = objects.Zone(name='example.org.', action='CREATE')
self.actor = zone.ZoneActionOnTarget(
@@ -185,7 +185,7 @@ class TestZoneActionOnTarget(oslotest.base.BaseTestCase):
port=53
)
- @mock.patch.object(wutils, 'notify')
+ @mock.patch.object(dnsutils, 'notify')
def test_call_update(self, mock_notify):
self.zone = objects.Zone(name='example.org.', action='UPDATE')
self.actor = zone.ZoneActionOnTarget(
@@ -203,7 +203,7 @@ class TestZoneActionOnTarget(oslotest.base.BaseTestCase):
port=53
)
- @mock.patch.object(wutils, 'notify')
+ @mock.patch.object(dnsutils, 'notify')
def test_call_delete(self, mock_notify):
self.zone = objects.Zone(name='example.org.', action='DELETE')
self.actor = zone.ZoneActionOnTarget(
@@ -217,7 +217,7 @@ class TestZoneActionOnTarget(oslotest.base.BaseTestCase):
mock_notify.assert_not_called()
- @mock.patch.object(wutils, 'notify')
+ @mock.patch.object(dnsutils, 'notify')
@mock.patch('time.sleep', mock.Mock())
def test_call_exception_raised(self, mock_notify):
self.backend.create_zone.side_effect = exceptions.BadRequest()
@@ -250,7 +250,7 @@ class TestSendNotify(oslotest.base.BaseTestCase):
self.executor = mock.Mock()
- @mock.patch.object(wutils, 'notify')
+ @mock.patch.object(dnsutils, 'notify')
def test_call_notify(self, mock_notify):
self.zone = objects.Zone(name='example.org.')
self.actor = zone.SendNotify(
@@ -267,7 +267,7 @@ class TestSendNotify(oslotest.base.BaseTestCase):
port=53
)
- @mock.patch.object(wutils, 'notify')
+ @mock.patch.object(dnsutils, 'notify')
def test_call_notify_timeout(self, mock_notify):
mock_notify.side_effect = dns.exception.Timeout()
self.zone = objects.Zone(name='example.org.')
@@ -282,7 +282,7 @@ class TestSendNotify(oslotest.base.BaseTestCase):
self.actor
)
- @mock.patch.object(wutils, 'notify')
+ @mock.patch.object(dnsutils, 'notify')
def test_call_dont_notify(self, mock_notify):
CONF.set_override('notify', False, 'service:worker')
@@ -668,11 +668,11 @@ class TestPollForZone(oslotest.base.BaseTestCase):
self.task._max_retries = 3
self.task._retry_interval = 2
- @mock.patch.object(zone.wutils, 'get_serial', mock.Mock(return_value=10))
+ @mock.patch.object(dnsutils, 'get_serial', mock.Mock(return_value=10))
def test_get_serial(self):
self.assertEqual(10, self.task._get_serial())
- zone.wutils.get_serial.assert_called_with(
+ dnsutils.get_serial.assert_called_with(
'example.org.',
'ns.example.org',
port=53
diff --git a/designate/worker/README.md b/designate/worker/README.md
index 9c5d9920..47da1934 100644
--- a/designate/worker/README.md
+++ b/designate/worker/README.md
@@ -29,7 +29,7 @@ class SendNotify(base.Task):
port = int(self.target.options.get('port'))
try:
- wutils.notify(self.zone.name, host, port=port)
+ dnsutils.notify(self.zone.name, host, port=port)
return True
except Exception:
return False
diff --git a/designate/worker/tasks/zone.py b/designate/worker/tasks/zone.py
index 3189de27..f07b591c 100644
--- a/designate/worker/tasks/zone.py
+++ b/designate/worker/tasks/zone.py
@@ -20,10 +20,10 @@ import dns
from oslo_config import cfg
from oslo_log import log as logging
-from designate.worker import utils as wutils
-from designate.worker.tasks import base
+from designate import dnsutils
from designate import exceptions
from designate import utils
+from designate.worker.tasks import base
LOG = logging.getLogger(__name__)
CONF = cfg.CONF
@@ -124,7 +124,7 @@ class SendNotify(base.Task):
port = int(self.target.options.get('port'))
try:
- wutils.notify(self.zone.name, host, port=port)
+ dnsutils.notify(self.zone.name, host, port=port)
LOG.debug('Sent NOTIFY to %(host)s:%(port)s for zone %(zone)s',
{
'host': host,
@@ -311,7 +311,7 @@ class PollForZone(base.Task):
self.ns = ns
def _get_serial(self):
- return wutils.get_serial(
+ return dnsutils.get_serial(
self.zone.name,
self.ns.host,
port=self.ns.port
diff --git a/designate/worker/utils.py b/designate/worker/utils.py
deleted file mode 100644
index f82d5432..00000000
--- a/designate/worker/utils.py
+++ /dev/null
@@ -1,82 +0,0 @@
-# Copyright 2016 Rackspace Inc.
-#
-# Author: Tim Simmons <tim.simmons@rackspace>
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.mport threading
-import dns
-import dns.exception
-import dns.query
-from oslo_config import cfg
-from oslo_log import log as logging
-
-LOG = logging.getLogger(__name__)
-CONF = cfg.CONF
-
-
-def prepare_msg(zone_name, rdatatype=dns.rdatatype.SOA, notify=False):
- """
- Do the needful to set up a dns packet with dnspython
- """
- dns_message = dns.message.make_query(zone_name, rdatatype)
- if notify:
- dns_message.set_opcode(dns.opcode.NOTIFY)
- else:
- dns_message.set_opcode(dns.opcode.QUERY)
- return dns_message
-
-
-def dig(zone_name, host, rdatatype, port=53):
- """
- Set up and send a regular dns query, datatype configurable
- """
- query = prepare_msg(zone_name, rdatatype=rdatatype)
-
- return send_dns_msg(query, host, port=port)
-
-
-def notify(zone_name, host, port=53):
- """
- Set up a notify packet and send it
- """
- msg = prepare_msg(zone_name, notify=True)
-
- return send_dns_msg(msg, host, port=port)
-
-
-def send_dns_msg(dns_message, host, port=53):
- """
- Send the dns message and return the response
-
- :return: dns.Message of the response to the dns query
- """
- # This can raise some exceptions, but we'll catch them elsewhere
- if not CONF['service:mdns'].all_tcp:
- return dns.query.udp(
- dns_message, host, port=port, timeout=10)
- else:
- return dns.query.tcp(
- dns_message, host, port=port, timeout=10)
-
-
-def get_serial(zone_name, host, port=53):
- """
- Possibly raises dns.exception.Timeout or dns.query.BadResponse.
- Possibly returns 0 if, e.g., the answer section is empty.
- """
- resp = dig(zone_name, host, dns.rdatatype.SOA, port=port)
- if not resp.answer:
- return 0
- rdataset = resp.answer[0].to_rdataset()
- if not rdataset:
- return 0
- return rdataset[0].serial