BIND 10 trac811_new, updated. b6982ea32af206b6ef661b492eea7b274af97bd2 [trac811] addressed review comments
BIND 10 source code commits
bind10-changes at lists.isc.org
Mon May 16 14:05:29 UTC 2011
The branch, trac811_new has been updated
via b6982ea32af206b6ef661b492eea7b274af97bd2 (commit)
from cd79c2fae07f7b1a8d2e2f501488de7a2d11eac5 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit b6982ea32af206b6ef661b492eea7b274af97bd2
Author: Jelte Jansen <jelte at isc.org>
Date: Mon May 16 16:05:08 2011 +0200
[trac811] addressed review comments
-----------------------------------------------------------------------
Summary of changes:
src/bin/xfrin/tests/xfrin_test.py | 183 ++++++++++++++++++++++++++----
src/bin/xfrin/xfrin.py.in | 149 ++++++++++++++++++-------
src/lib/python/isc/config/config_data.py | 9 ++
3 files changed, 278 insertions(+), 63 deletions(-)
-----------------------------------------------------------------------
diff --git a/src/bin/xfrin/tests/xfrin_test.py b/src/bin/xfrin/tests/xfrin_test.py
index c9e25ba..e2ad329 100644
--- a/src/bin/xfrin/tests/xfrin_test.py
+++ b/src/bin/xfrin/tests/xfrin_test.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2009 Internet Systems Consortium.
+# Copyright (C) 2011 Internet Systems Consortium.
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
@@ -20,8 +20,10 @@ from xfrin import *
#
# Commonly used (mostly constant) test parameters
#
-TEST_ZONE_NAME = "example.com"
+TEST_ZONE_NAME_STR = "example.com."
+TEST_ZONE_NAME = Name(TEST_ZONE_NAME_STR)
TEST_RRCLASS = RRClass.IN()
+TEST_RRCLASS_STR = 'IN'
TEST_DB_FILE = 'db_file'
TEST_MASTER_IPV4_ADDRESS = '127.0.0.1'
TEST_MASTER_IPV4_ADDRINFO = (socket.AF_INET, socket.SOCK_STREAM,
@@ -40,12 +42,12 @@ TSIG_KEY = TSIGKey("example.com:SFuWd/q99SzF8Yzd1QbB9g==")
soa_rdata = Rdata(RRType.SOA(), TEST_RRCLASS,
'master.example.com. admin.example.com ' +
'1234 3600 1800 2419200 7200')
-soa_rrset = RRset(Name(TEST_ZONE_NAME), TEST_RRCLASS, RRType.SOA(),
+soa_rrset = RRset(TEST_ZONE_NAME, TEST_RRCLASS, RRType.SOA(),
RRTTL(3600))
soa_rrset.add_rdata(soa_rdata)
-example_axfr_question = Question(Name(TEST_ZONE_NAME), TEST_RRCLASS,
+example_axfr_question = Question(TEST_ZONE_NAME, TEST_RRCLASS,
RRType.AXFR())
-example_soa_question = Question(Name(TEST_ZONE_NAME), TEST_RRCLASS,
+example_soa_question = Question(TEST_ZONE_NAME, TEST_RRCLASS,
RRType.SOA())
default_questions = [example_axfr_question]
default_answers = [soa_rrset]
@@ -60,6 +62,13 @@ def strip_mutable_tsig_data(data):
# Time Signed.
return data[0:-32] + data[-26:-22] + data[-6:]
+class MockCC():
+ def get_default_value(self, identifier):
+ if identifier == "zones/master_port":
+ return TEST_MASTER_PORT
+ if identifier == "zones/class":
+ return 'IN'
+
class MockXfrin(Xfrin):
# This is a class attribute of a callable object that specifies a non
# default behavior triggered in _cc_check_command(). Specific test methods
@@ -70,6 +79,7 @@ class MockXfrin(Xfrin):
def _cc_setup(self):
self._tsig_key_str = None
+ self._module_cc = MockCC()
pass
def _get_db_file(self):
@@ -80,6 +90,19 @@ class MockXfrin(Xfrin):
if MockXfrin.check_command_hook:
MockXfrin.check_command_hook()
+ def xfrin_start(self, zone_name, rrclass, db_file, master_addrinfo, tsig_key_str,
+ check_soa = True):
+ # store some of the arguments for verification, then call this
+ # method in the superclass
+ self.xfrin_started_zone_name = zone_name
+ self.xfrin_started_rrclass = rrclass
+ self.xfrin_started_master_addr = master_addrinfo[2][0]
+ self.xfrin_started_master_port = master_addrinfo[2][1]
+ self.xfrin_started_tsig_key_str = tsig_key_str
+ return Xfrin.xfrin_start(self, zone_name, rrclass, db_file,
+ master_addrinfo, tsig_key_str,
+ check_soa = True)
+
class MockXfrinConnection(XfrinConnection):
def __init__(self, sock_map, zone_name, rrclass, db_file, shutdown_event,
master_addr):
@@ -450,7 +473,7 @@ class TestXfrin(unittest.TestCase):
sys.stderr = open(os.devnull, 'w')
self.xfr = MockXfrin()
self.args = {}
- self.args['zone_name'] = TEST_ZONE_NAME
+ self.args['zone_name'] = TEST_ZONE_NAME_STR
self.args['port'] = TEST_MASTER_PORT
self.args['master'] = TEST_MASTER_IPV4_ADDRESS
self.args['db_file'] = TEST_DB_FILE
@@ -502,8 +525,7 @@ class TestXfrin(unittest.TestCase):
def test_parse_cmd_params_nomaster(self):
# master address is mandatory.
del self.args['master']
- master_addrinfo = self._do_parse_master_port()
- self.assertEqual(master_addrinfo[2][0], DEFAULT_MASTER)
+ self.assertRaises(XfrinException, self._do_parse_master_port)
def test_parse_cmd_params_bad_ip4(self):
self.args['master'] = '3.3.3.3.3'
@@ -533,28 +555,30 @@ class TestXfrin(unittest.TestCase):
def test_command_handler_retransfer(self):
self.assertEqual(self.xfr.command_handler("retransfer",
self.args)['result'][0], 0)
+ self.assertEqual(self.args['master'], self.xfr.xfrin_started_master_addr)
+ self.assertEqual(int(self.args['port']), self.xfr.xfrin_started_master_port)
def test_command_handler_retransfer_short_command1(self):
# try it when only specifying the zone name (of unknown zone)
short_args = {}
- short_args['zone_name'] = TEST_ZONE_NAME
+ short_args['zone_name'] = TEST_ZONE_NAME_STR
self.assertEqual(self.xfr.command_handler("retransfer",
- short_args)['result'][0], 0)
+ short_args)['result'][0], 1)
def test_command_handler_retransfer_short_command2(self):
# try it when only specifying the zone name (of unknown zone)
short_args = {}
- short_args['zone_name'] = TEST_ZONE_NAME + "."
+ short_args['zone_name'] = TEST_ZONE_NAME_STR
self.assertEqual(self.xfr.command_handler("retransfer",
- short_args)['result'][0], 0)
+ short_args)['result'][0], 1)
def test_command_handler_retransfer_short_command3(self):
# try it when only specifying the zone name (of known zone)
short_args = {}
- short_args['zone_name'] = TEST_ZONE_NAME
+ short_args['zone_name'] = TEST_ZONE_NAME_STR
zones = { 'zones': [
- { 'name': TEST_ZONE_NAME,
+ { 'name': TEST_ZONE_NAME_STR,
'master_addr': TEST_MASTER_IPV4_ADDRESS,
'master_port': TEST_MASTER_PORT
}
@@ -562,6 +586,10 @@ class TestXfrin(unittest.TestCase):
self.xfr.config_handler(zones)
self.assertEqual(self.xfr.command_handler("retransfer",
short_args)['result'][0], 0)
+ self.assertEqual(TEST_MASTER_IPV4_ADDRESS,
+ self.xfr.xfrin_started_master_addr)
+ self.assertEqual(int(TEST_MASTER_PORT),
+ self.xfr.xfrin_started_master_port)
def test_command_handler_retransfer_badcommand(self):
self.args['master'] = 'invalid'
@@ -569,13 +597,15 @@ class TestXfrin(unittest.TestCase):
self.args)['result'][0], 1)
def test_command_handler_retransfer_quota(self):
+ self.args['master'] = '127.0.0.1'
+
for i in range(self.xfr._max_transfers_in - 1):
- self.xfr.recorder.increment(str(i) + TEST_ZONE_NAME)
+ self.xfr.recorder.increment(Name(str(i) + TEST_ZONE_NAME_STR))
# there can be one more outstanding transfer.
self.assertEqual(self.xfr.command_handler("retransfer",
self.args)['result'][0], 0)
# make sure the # xfrs would excceed the quota
- self.xfr.recorder.increment(str(self.xfr._max_transfers_in) + TEST_ZONE_NAME)
+ self.xfr.recorder.increment(Name(str(self.xfr._max_transfers_in) + TEST_ZONE_NAME_STR))
# this one should fail
self.assertEqual(self.xfr.command_handler("retransfer",
self.args)['result'][0], 1)
@@ -599,6 +629,10 @@ class TestXfrin(unittest.TestCase):
self.args['master'] = TEST_MASTER_IPV6_ADDRESS
self.assertEqual(self.xfr.command_handler("refresh",
self.args)['result'][0], 0)
+ self.assertEqual(TEST_MASTER_IPV6_ADDRESS,
+ self.xfr.xfrin_started_master_addr)
+ self.assertEqual(int(TEST_MASTER_PORT),
+ self.xfr.xfrin_started_master_port)
def test_command_handler_notify(self):
# at this level, refresh is no different than retransfer.
@@ -611,8 +645,9 @@ class TestXfrin(unittest.TestCase):
# try it with a known zone
self.args['master'] = TEST_MASTER_IPV6_ADDRESS
+ # but use a different address in the actual command
zones = { 'zones': [
- { 'name': TEST_ZONE_NAME,
+ { 'name': TEST_ZONE_NAME_STR,
'master_addr': TEST_MASTER_IPV4_ADDRESS,
'master_port': TEST_MASTER_PORT
}
@@ -621,6 +656,16 @@ class TestXfrin(unittest.TestCase):
self.assertEqual(self.xfr.command_handler("notify",
self.args)['result'][0], 0)
+ # and see if we used the address from the command, and not from
+ # the config
+ # This is actually NOT the address given in the command, which
+ # would at this point not make sense, see the TODO in
+ # xfrin.py.in:542)
+ self.assertEqual(TEST_MASTER_IPV4_ADDRESS,
+ self.xfr.xfrin_started_master_addr)
+ self.assertEqual(int(TEST_MASTER_PORT),
+ self.xfr.xfrin_started_master_port)
+
def test_command_handler_unknown(self):
self.assertEqual(self.xfr.command_handler("xxx", None)['result'][0], 1)
@@ -629,37 +674,127 @@ class TestXfrin(unittest.TestCase):
self.assertEqual(self.xfr.config_handler({'transfers_in': 3})['result'][0], 0)
self.assertEqual(self.xfr._max_transfers_in, 3)
+ def _check_zones_config(self, config_given):
+ for zone_config in config_given['zones']:
+ zone_name = zone_config['name']
+ zone_info = self.xfr._get_zone_info(Name(zone_name), RRClass.IN())
+ self.assertEqual(zone_info.master_addr_str, zone_config['master_addr'])
+ self.assertEqual(zone_info.master_port_str, zone_config['master_port'])
+ if 'tsig_key' in zone_config:
+ self.assertEqual(zone_info.tsig_key_str, zone_config['tsig_key'])
+ else:
+ self.assertIsNone(zone_info.tsig_key_str)
+
def test_command_handler_zones(self):
+ zones1 = { 'zones': [
+ { 'name': 'test.example.',
+ 'master_addr': '192.0.2.1',
+ 'master_port': 53
+ }
+ ]}
+ self.assertEqual(self.xfr.config_handler(zones1)['result'][0], 0)
+ self._check_zones_config(zones1)
+
+ zones2 = { 'zones': [
+ { 'name': 'test.example.',
+ 'master_addr': '192.0.2.2',
+ 'master_port': 53,
+ 'tsig_key': "example.com:SFuWd/q99SzF8Yzd1QbB9g=="
+ }
+ ]}
+ self.assertEqual(self.xfr.config_handler(zones2)['result'][0], 0)
+ self._check_zones_config(zones2)
+
+ # test that configuring the zone multiple times fails
+ zones = { 'zones': [
+ { 'name': 'test.example.',
+ 'master_addr': '192.0.2.1',
+ 'master_port': 53
+ },
+ { 'name': 'test.example.',
+ 'master_addr': '192.0.2.2',
+ 'master_port': 53
+ }
+ ]}
+ self.assertEqual(self.xfr.config_handler(zones)['result'][0], 1)
+ # since this has failed, we should still have the previous config
+ self._check_zones_config(zones2)
+
+ zones = { 'zones': [
+ { 'name': 'test.example.',
+ 'master_addr': '192.0.2.3',
+ 'master_port': 53,
+ 'class': 'BADCLASS'
+ }
+ ]}
+ self.assertEqual(self.xfr.config_handler(zones)['result'][0], 1)
+ self._check_zones_config(zones2)
+
+ zones = { 'zones': [
+ { 'master_addr': '192.0.2.4',
+ 'master_port': 53
+ }
+ ]}
+ self.assertEqual(self.xfr.config_handler(zones)['result'][0], 1)
+ # since this has failed, we should still have the previous config
+ self._check_zones_config(zones2)
+
zones = { 'zones': [
- { 'name': 'test.com.',
- 'master_addr': '1.1.1.1',
+ { 'name': 'bad..zone.',
+ 'master_addr': '192.0.2.5',
'master_port': 53
}
]}
- self.assertEqual(self.xfr.config_handler(zones)['result'][0], 0)
+ self.assertEqual(self.xfr.config_handler(zones)['result'][0], 1)
+ # since this has failed, we should still have the previous config
+ self._check_zones_config(zones2)
zones = { 'zones': [
- { 'master_addr': '1.1.1.1',
+ { 'name': '',
+ 'master_addr': '192.0.2.6',
'master_port': 53
}
]}
self.assertEqual(self.xfr.config_handler(zones)['result'][0], 1)
+ # since this has failed, we should still have the previous config
+ self._check_zones_config(zones2)
zones = { 'zones': [
- { 'name': 'test.com',
+ { 'name': 'test.example',
'master_addr': 'badaddress',
'master_port': 53
}
]}
self.assertEqual(self.xfr.config_handler(zones)['result'][0], 1)
+ # since this has failed, we should still have the previous config
+ self._check_zones_config(zones2)
zones = { 'zones': [
- { 'name': 'test.com',
- 'master_addr': '1.1.1.1',
+ { 'name': 'test.example',
+ 'master_addr': '192.0.2.7',
'master_port': 'bad_port'
}
]}
self.assertEqual(self.xfr.config_handler(zones)['result'][0], 1)
+ # since this has failed, we should still have the previous config
+ self._check_zones_config(zones2)
+
+ # let's also add a zone that is correct too, and make sure
+ # that the new config is not partially taken
+ zones = { 'zones': [
+ { 'name': 'test.example.',
+ 'master_addr': '192.0.2.8',
+ 'master_port': 53
+ },
+ { 'name': 'test2.example.',
+ 'master_addr': '192.0.2.9',
+ 'master_port': 53,
+ 'tsig_key': 'badkey'
+ }
+ ]}
+ self.assertEqual(self.xfr.config_handler(zones)['result'][0], 1)
+ # since this has failed, we should still have the previous config
+ self._check_zones_config(zones2)
def raise_interrupt():
diff --git a/src/bin/xfrin/xfrin.py.in b/src/bin/xfrin/xfrin.py.in
index 0d112f5..a9871a7 100755
--- a/src/bin/xfrin/xfrin.py.in
+++ b/src/bin/xfrin/xfrin.py.in
@@ -1,6 +1,6 @@
#!@PYTHON@
-# Copyright (C) 2010 Internet Systems Consortium.
+# Copyright (C) 2011 Internet Systems Consortium.
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
@@ -56,14 +56,12 @@ XFROUT_MODULE_NAME = 'Xfrout'
ZONE_MANAGER_MODULE_NAME = 'Zonemgr'
REFRESH_FROM_ZONEMGR = 'refresh_from_zonemgr'
ZONE_XFRIN_FAILED = 'zone_xfrin_failed'
+DEFAULT_MASTER_PORT = 53
__version__ = 'BIND10'
# define xfrin rcode
XFRIN_OK = 0
XFRIN_FAIL = 1
-DEFAULT_MASTER_PORT = '53'
-DEFAULT_MASTER = '127.0.0.1'
-
def log_error(msg):
sys.stderr.write("[b10-xfrin] %s\n" % str(msg))
@@ -71,8 +69,34 @@ class XfrinException(Exception):
pass
class XfrinConfigException(Exception):
+ """This exception is raised if there is an error in the given
+ configuration (part), for instance when the zone's master
+ address is not a valid IP address, when the zone does not
+ have a name, or when multiple settings are given for the same
+ zone."""
pass
+def _check_zone_name(zone_name_str):
+ """Checks if the given zone name is a valid domain name, and returns it as a Name object.
+ Raises an XfrinException if it is not."""
+ try:
+ return Name(zone_name_str)
+ except (EmptyLabel, TooLongLabel, BadLabelType, BadEscape,
+ TooLongName, IncompleteName) as ne:
+ raise XfrinConfigException("bad zone name: " + zone_name_str + " (" + str(ne) + ")")
+
+def _check_zone_class(zone_class_str):
+ """If the given argument is a string: checks if the given class is
+ a valid one, and returns an RRClass object if so.
+ Raises XfrinConfigException if not.
+ If it is None, this function returns the default RRClass.IN()"""
+ if zone_class_str is None:
+ return RRClass.IN()
+ try:
+ return RRClass(zone_class_str)
+ except InvalidRRClass as irce:
+ raise XfrinConfigException("bad zone class: " + zone_class_str + " (" + str(irce) + ")")
+
class XfrinConnection(asyncore.dispatcher):
'''Do xfrin in this class. '''
@@ -382,22 +406,31 @@ class XfrinRecorder:
return ret
class ZoneInfo:
- def __init__(self, config_data):
+ def __init__(self, config_data, module_cc = None):
"""Creates a zone_info with the config data element as
- specified by the 'zones' list in xfrin.spec"""
- self.name = config_data.get('name')
- self.class_str = config_data.get('class') or 'IN'
+ specified by the 'zones' list in xfrin.spec. Module_cc is
+ needed to get the defaults from the specification"""
+ self.name_str = config_data.get('name')
+ self.class_str = config_data.get('class') or \
+ module_cc.get_default_value("zones/class")
- if self.name is None:
+ if self.name_str is None:
raise XfrinConfigException("Configuration zones list "
"element does not contain "
"'name' attribute")
- # add the root dot if the user forgot
- if len(self.name) > 0 and self.name[-1] != '.':
- self.name += '.'
- self.master_addr_str = config_data.get('master_addr') or DEFAULT_MASTER
- self.master_port_str = config_data.get('master_port') or DEFAULT_MASTER_PORT
+ self.master_addr_str = config_data.get('master_addr')
+ self.master_port_str = config_data.get('master_port') or \
+ str(module_cc.get_default_value("zones/master_port"))
+
+ try:
+ self.name = Name(self.name_str)
+ except (EmptyLabel, TooLongLabel, BadLabelType, BadEscape,
+ TooLongName, IncompleteName) as ne:
+ errmsg = "bad zone name: " + self.name_str + " (" + str(ne) + ")"
+ log_error(errmsg)
+ raise XfrinConfigException(errmsg)
+
try:
self.master_addr = isc.net.parse.addr_parse(self.master_addr_str)
self.master_port = isc.net.parse.port_parse(self.master_port_str)
@@ -406,7 +439,21 @@ class ZoneInfo:
log_error(errmsg)
raise XfrinConfigException(errmsg)
+ try:
+ self.rrclass = RRClass(self.class_str)
+ except InvalidRRClass:
+ errmsg = "invalid class: " + self.class_str
+ log_error(errmsg)
+ raise XfrinConfigException(errmsg)
+
self.tsig_key_str = config_data.get('tsig_key') or None
+ if self.tsig_key_str is not None:
+ try:
+ tsig_key = TSIGKey(self.tsig_key_str)
+ except InvalidParameter as ipe:
+ errmsg = "bad TSIG key string: " + self.tsig_key_str
+ log_error(errmsg)
+ raise XfrinConfigException(errmsg)
def get_master_addr_info(self):
return (self.master_addr.family, socket.SOCK_STREAM,
@@ -442,33 +489,50 @@ class Xfrin:
of unit tests.'''
self._module_cc.check_command(False)
- def _get_zone_info(self, name, class_str = "IN"):
+ def _get_zone_info(self, name, rrclass):
"""Returns the ZoneInfo object containing the configured data
for the given zone name. If the zone name did not have any
data, returns None"""
- # add the root dot if the user forgot
- if len(name) > 0 and name[-1] != '.':
- name += '.'
- if (name, class_str) in self._zones:
- return self._zones[(name, class_str)]
+ key = (name.to_text(), rrclass.to_text())
+ if key in self._zones:
+ return self._zones[key]
else:
return None
- def _clear_zone_info(self):
- self._zones = {}
+ def _get_all_zone_info(self):
+ """Returns the structure used to store ZoneInfo objects. This
+ method can be used (together with _set_all_zone_info()) to
+ revert to the previous zone info configuration when one
+ of the new config items turns out to be bad"""
+ return self._zones
def _add_zone_info(self, zone_info):
- self._zones[(zone_info.name, zone_info.class_str)] = zone_info
+ """Add the zone info. Raises a XfrinConfigException if a zone
+ with the same name and class is already configured"""
+ key = (zone_info.name.to_text(), zone_info.class_str)
+ if key in self._zones:
+ raise XfrinConfigException("zone " + str(key) +
+ " configured multiple times")
+ self._zones[key] = zone_info
+
+ def _set_all_zone_info(self, zones):
+ self._zones = zones
+
+ def _clear_zone_info(self):
+ self._zones = {}
def config_handler(self, new_config):
self._max_transfers_in = new_config.get("transfers_in") or self._max_transfers_in
+
if 'zones' in new_config:
+ zones_backup = self._get_all_zone_info()
self._clear_zone_info()
for zone_config in new_config.get('zones'):
try:
- zone_info = ZoneInfo(zone_config)
+ zone_info = ZoneInfo(zone_config, self._module_cc)
self._add_zone_info(zone_info)
except XfrinConfigException as xce:
+ self._set_all_zone_info(zones_backup)
return create_answer(1, str(xce))
return create_answer(0)
@@ -494,11 +558,14 @@ class Xfrin:
# notify command maybe has the parameters which
# specify the notifyfrom address and port, according the RFC1996, zone
# transfer should starts first from the notifyfrom, but now, let 'TODO' it.
+ # (using the value now, while we can only set one master address, would be
+ # a security hole. Once we add the ability to have multiple master addresses,
+ # we should check if it matches one of them, and then use it.)
(zone_name, rrclass) = self._parse_zone_name_and_class(args)
- zone_info = self._get_zone_info(zone_name)
+ zone_info = self._get_zone_info(zone_name, rrclass)
if zone_info is None:
# TODO what to do? no info known about zone. defaults?
- errmsg = "Got notification to retransfer unknown zone " + zone_name
+ errmsg = "Got notification to retransfer unknown zone " + zone_name.to_text()
log_error(errmsg)
answer = create_answer(1, errmsg)
else:
@@ -517,7 +584,7 @@ class Xfrin:
# master address, or else do transfer from the configured masters.
(zone_name, rrclass) = self._parse_zone_name_and_class(args)
master_addr = self._parse_master_and_port(args)
- zone_info = self._get_zone_info(zone_name)
+ zone_info = self._get_zone_info(zone_name, rrclass)
tsig_key_str = None
if zone_info:
tsig_key_str = zone_info.tsig_key_str
@@ -538,8 +605,8 @@ class Xfrin:
return answer
def _parse_zone_name_and_class(self, args):
- zone_name = args.get('zone_name')
- if not zone_name:
+ zone_name_str = args.get('zone_name')
+ if not zone_name_str:
raise XfrinException('zone name should be provided')
rrclass = args.get('zone_class')
@@ -551,12 +618,22 @@ class Xfrin:
except InvalidRRClass as e:
raise XfrinException('invalid RRClass: ' + rrclass)
- return zone_name, rrclass
+ return _check_zone_name(zone_name_str), rrclass
def _parse_master_and_port(self, args):
# check if we have configured info about this zone, in case
# port or master are not specified
- zone_info = self._get_zone_info(args.get('zone_name'))
+ zone_name = _check_zone_name(args.get('zone_name'))
+ zone_class = _check_zone_class(args.get('class'))
+ zone_info = self._get_zone_info(zone_name, zone_class)
+
+ master = args.get('master')
+ if master is None:
+ if zone_info is not None:
+ master = zone_info.master_addr_str
+ else:
+ raise XfrinException("Master address not given or "
+ "configured for " + zone_name.to_text())
port = args.get('port')
if port is None:
@@ -565,13 +642,6 @@ class Xfrin:
else:
port = DEFAULT_MASTER_PORT
- master = args.get('master')
- if master is None:
- if zone_info is not None:
- master = zone_info.master_addr_str
- else:
- master = DEFAULT_MASTER
-
return build_addr_info(master, port)
def _get_db_file(self):
@@ -650,7 +720,8 @@ class Xfrin:
xfrin_thread = threading.Thread(target = process_xfrin,
args = (self,
self.recorder,
- zone_name, rrclass,
+ zone_name.to_text(),
+ rrclass,
db_file,
self._shutdown_event,
master_addrinfo, check_soa,
diff --git a/src/lib/python/isc/config/config_data.py b/src/lib/python/isc/config/config_data.py
index cee1d34..cc3f484 100644
--- a/src/lib/python/isc/config/config_data.py
+++ b/src/lib/python/isc/config/config_data.py
@@ -213,6 +213,15 @@ class ConfigData:
return spec['item_default'], True
return None, False
+ def get_default_value(self, identifier):
+ """Returns the default from the specification, or None if there
+ is no default"""
+ spec = find_spec_part(self.specification.get_config_spec(), identifier)
+ if spec and 'item_default' in spec:
+ return spec['item_default']
+ else:
+ return None
+
def get_module_spec(self):
"""Returns the ModuleSpec object associated with this ConfigData"""
return self.specification
More information about the bind10-changes
mailing list