[svn] commit: r2736 - in /trunk: ./ src/bin/ src/bin/auth/ src/bin/bind10/ src/bin/xfrin/ src/bin/xfrin/tests/ src/bin/xfrout/ src/bin/zonemgr/ src/lib/cc/ src/lib/cc/tests/ src/lib/datasrc/ src/lib/dns/ src/lib/dns/rdata/generic/ src/lib/dns/tests/ src/lib/dns/util/ src/lib/exceptions/tests/ src/lib/python/isc/ src/lib/python/isc/datasrc/ src/lib/python/isc/notify/ src/lib/python/isc/notify/tests/
BIND 10 source code commits
bind10-changes at lists.isc.org
Mon Aug 16 09:05:53 UTC 2010
Author: chenzhengzhang
Date: Mon Aug 16 09:05:52 2010
New Revision: 2736
Log:
merge trac215(zone manager) and trac289(notify-out)
Added:
trunk/src/bin/zonemgr/
- copied from r2733, branches/trac289/src/bin/zonemgr/
trunk/src/lib/python/isc/notify/
- copied from r2733, branches/trac289/src/lib/python/isc/notify/
Modified:
trunk/ (props changed)
trunk/ChangeLog
trunk/configure.ac
trunk/src/bin/Makefile.am
trunk/src/bin/auth/auth_srv.cc
trunk/src/bin/bind10/bind10.py.in
trunk/src/bin/bind10/run_bind10.sh.in
trunk/src/bin/xfrin/ (props changed)
trunk/src/bin/xfrin/tests/xfrin_test.py
trunk/src/bin/xfrin/xfrin.py.in
trunk/src/bin/xfrin/xfrin.spec.pre.in
trunk/src/bin/xfrout/xfrout.py.in
trunk/src/lib/cc/ (props changed)
trunk/src/lib/cc/tests/ (props changed)
trunk/src/lib/datasrc/ (props changed)
trunk/src/lib/dns/ (props changed)
trunk/src/lib/dns/rdata/generic/rrsig_46.cc (props changed)
trunk/src/lib/dns/tests/ (props changed)
trunk/src/lib/dns/util/ (props changed)
trunk/src/lib/exceptions/tests/ (props changed)
trunk/src/lib/python/isc/Makefile.am
trunk/src/lib/python/isc/datasrc/sqlite3_ds.py
trunk/src/lib/python/isc/notify/tests/notify_out_test.py
Modified: trunk/ChangeLog
==============================================================================
--- trunk/ChangeLog (original)
+++ trunk/ChangeLog Mon Aug 16 09:05:52 2010
@@ -1,3 +1,14 @@
+ 87. [func] zhanglikun
+ lib/python/isc/notifyout: Add the feature of notify-out, when
+ zone axfr/ixfr finishing, the server will notify its slaves.
+ (Trac #289, svn r2735)
+
+ 86. [func] jerry
+ bin/zonemgr: Added zone manager module. The zone manager is one
+ of the co-operating processes of BIND10, which keeps track of
+ timers and other information necessary for BIND10 to act as a
+ slave. (Trac #215, svn r2735)
+
85. [build]* jinmei
Build programs using dynamic link by default. A new configure
option --enable-static-link is provided to force static link for
Modified: trunk/configure.ac
==============================================================================
--- trunk/configure.ac (original)
+++ trunk/configure.ac Mon Aug 16 09:05:52 2010
@@ -411,6 +411,8 @@
src/bin/xfrin/tests/Makefile
src/bin/xfrout/Makefile
src/bin/xfrout/tests/Makefile
+ src/bin/zonemgr/Makefile
+ src/bin/zonemgr/tests/Makefile
src/bin/usermgr/Makefile
src/lib/Makefile
src/lib/bench/Makefile
@@ -427,6 +429,8 @@
src/lib/python/isc/config/tests/Makefile
src/lib/python/isc/log/Makefile
src/lib/python/isc/log/tests/Makefile
+ src/lib/python/isc/notify/Makefile
+ src/lib/python/isc/notify/tests/Makefile
src/lib/config/Makefile
src/lib/config/tests/Makefile
src/lib/dns/Makefile
@@ -453,6 +457,10 @@
src/bin/xfrout/xfrout.spec.pre
src/bin/xfrout/tests/xfrout_test
src/bin/xfrout/run_b10-xfrout.sh
+ src/bin/zonemgr/zonemgr.py
+ src/bin/zonemgr/zonemgr.spec.pre
+ src/bin/zonemgr/tests/zonemgr_test
+ src/bin/zonemgr/run_b10-zonemgr.sh
src/bin/bind10/bind10.py
src/bin/bind10/tests/bind10_test
src/bin/bind10/run_bind10.sh
@@ -474,6 +482,7 @@
src/lib/python/isc/config/tests/config_test
src/lib/python/isc/cc/tests/cc_test
src/lib/python/isc/log/tests/log_test
+ src/lib/python/isc/notify/tests/notify_out_test
src/lib/dns/gen-rdatacode.py
src/lib/python/bind10_config.py
src/lib/dns/tests/testdata/gen-wiredata.py
@@ -482,10 +491,12 @@
chmod +x src/bin/cmdctl/run_b10-cmdctl.sh
chmod +x src/bin/xfrin/run_b10-xfrin.sh
chmod +x src/bin/xfrout/run_b10-xfrout.sh
+ chmod +x src/bin/zonemgr/run_b10-zonemgr.sh
chmod +x src/bin/bind10/run_bind10.sh
chmod +x src/bin/cmdctl/tests/cmdctl_test
chmod +x src/bin/xfrin/tests/xfrin_test
chmod +x src/bin/xfrout/tests/xfrout_test
+ chmod +x src/bin/zonemgr/tests/zonemgr_test
chmod +x src/bin/bindctl/tests/bindctl_test
chmod +x src/bin/bindctl/run_bindctl.sh
chmod +x src/bin/loadzone/run_loadzone.sh
Modified: trunk/src/bin/Makefile.am
==============================================================================
--- trunk/src/bin/Makefile.am (original)
+++ trunk/src/bin/Makefile.am Mon Aug 16 09:05:52 2010
@@ -1,1 +1,1 @@
-SUBDIRS = bind10 bindctl cfgmgr loadzone msgq host cmdctl auth xfrin xfrout usermgr
+SUBDIRS = bind10 bindctl cfgmgr loadzone msgq host cmdctl auth xfrin xfrout usermgr zonemgr
Modified: trunk/src/bin/auth/auth_srv.cc
==============================================================================
--- trunk/src/bin/auth/auth_srv.cc (original)
+++ trunk/src/bin/auth/auth_srv.cc Mon Aug 16 09:05:52 2010
@@ -326,7 +326,6 @@
return (true);
}
-
bool
AuthSrvImpl::processAxfrQuery(const IOMessage& io_message, Message& message,
@@ -423,7 +422,7 @@
static const string command_template_start =
"{\"command\": [\"notify\", {\"zone_name\" : \"";
static const string command_template_master = "\", \"master\" : \"";
- static const string command_template_rrclass = "\", \"rrclass\" : \"";
+ static const string command_template_rrclass = "\", \"zone_class\" : \"";
static const string command_template_end = "\"}]}";
try {
@@ -433,7 +432,7 @@
command_template_rrclass + question->getClass().toText() +
command_template_end);
const unsigned int seq =
- xfrin_session_->group_sendmsg(notify_command, "Xfrin",
+ xfrin_session_->group_sendmsg(notify_command, "Zonemgr",
"*", "*");
ElementPtr env, answer, parsed_answer;
xfrin_session_->group_recvmsg(env, answer, false, seq);
@@ -441,14 +440,14 @@
parsed_answer = parseAnswer(rcode, answer);
if (rcode != 0) {
if (verbose_mode_) {
- cerr << "[b10-auth] failed to notify Xfrin: "
+ cerr << "[b10-auth] failed to notify Zonemgr: "
<< parsed_answer->str() << endl;
}
return (false);
}
} catch (const Exception& ex) {
if (verbose_mode_) {
- cerr << "[b10-auth] failed to notify Xfrin: " << ex.what() << endl;
+ cerr << "[b10-auth] failed to notify Zonemgr: " << ex.what() << endl;
}
return (false);
}
Modified: trunk/src/bin/bind10/bind10.py.in
==============================================================================
--- trunk/src/bin/bind10/bind10.py.in (original)
+++ trunk/src/bin/bind10/bind10.py.in Mon Aug 16 09:05:52 2010
@@ -398,6 +398,26 @@
sys.stdout.write("[bind10] Started b10-xfrin (PID %d)\n" %
xfrind.pid)
+ # start b10-zonemgr
+ zonemgr_args = ['b10-zonemgr']
+ if self.verbose:
+ sys.stdout.write("[bind10] Starting b10-zonemgr\n")
+ zonemgr_args += ['-v']
+ try:
+ zonemgr = ProcessInfo("b10-zonemgr", zonemgr_args,
+ c_channel_env)
+ except Exception as e:
+ c_channel.process.kill()
+ bind_cfgd.process.kill()
+ xfrout.process.kill()
+ auth.process.kill()
+ xfrind.process.kill()
+ return "Unable to start b10-zonemgr; " + str(e)
+ self.processes[zonemgr.pid] = zonemgr
+ if self.verbose:
+ sys.stdout.write("[bind10] Started b10-zonemgr(PID %d)\n" %
+ zonemgr.pid)
+
# start the b10-cmdctl
# XXX: we hardcode port 8080
cmdctl_args = ['b10-cmdctl']
@@ -413,6 +433,7 @@
xfrout.process.kill()
auth.process.kill()
xfrind.process.kill()
+ zonemgr.process.kill()
return "Unable to start b10-cmdctl; " + str(e)
self.processes[cmd_ctrld.pid] = cmd_ctrld
if self.verbose:
@@ -431,6 +452,7 @@
self.cc_session.group_sendmsg(cmd, "Boss", "Auth")
self.cc_session.group_sendmsg(cmd, "Boss", "Xfrout")
self.cc_session.group_sendmsg(cmd, "Boss", "Xfrin")
+ self.cc_session.group_sendmsg(cmd, "Boss", "Zonemgr")
def stop_process(self, process):
"""Stop the given process, friendly-like."""
Modified: trunk/src/bin/bind10/run_bind10.sh.in
==============================================================================
--- trunk/src/bin/bind10/run_bind10.sh.in (original)
+++ trunk/src/bin/bind10/run_bind10.sh.in Mon Aug 16 09:05:52 2010
@@ -20,7 +20,7 @@
BIND10_PATH=@abs_top_builddir@/src/bin/bind10
-PATH=@abs_top_builddir@/src/bin/msgq:@abs_top_builddir@/src/bin/auth:@abs_top_builddir@/src/bin/cfgmgr:@abs_top_builddir@/src/bin/cmdctl:@abs_top_builddir@/src/bin/xfrin:@abs_top_builddir@/src/bin/xfrout:$PATH
+PATH=@abs_top_builddir@/src/bin/msgq:@abs_top_builddir@/src/bin/auth:@abs_top_builddir@/src/bin/cfgmgr:@abs_top_builddir@/src/bin/cmdctl:@abs_top_builddir@/src/bin/xfrin:@abs_top_builddir@/src/bin/xfrout:@abs_top_builddir@/src/bin/zonemgr:$PATH
export PATH
PYTHONPATH=@abs_top_builddir@/src/lib/python:@abs_top_builddir@/src/lib/dns/python/.libs:@abs_top_builddir@/src/lib/xfr/.libs
Modified: trunk/src/bin/xfrin/tests/xfrin_test.py
==============================================================================
--- trunk/src/bin/xfrin/tests/xfrin_test.py (original)
+++ trunk/src/bin/xfrin/tests/xfrin_test.py Mon Aug 16 09:05:52 2010
@@ -63,6 +63,9 @@
def _cc_setup(self):
pass
+
+ def _get_db_file(self):
+ pass
def _cc_check_command(self):
self._shutdown_event.set()
@@ -408,11 +411,16 @@
def tearDown(self):
self.xfr.shutdown()
- def _do_parse(self):
- return self.xfr._parse_cmd_params(self.args)
+ def _do_parse_zone_name_class(self):
+ return self.xfr._parse_zone_name_and_class(self.args)
+
+ def _do_parse_master_port(self):
+ return self.xfr._parse_master_and_port(self.args)
def test_parse_cmd_params(self):
- name, rrclass, master_addrinfo, db_file = self._do_parse()
+ name, rrclass = self._do_parse_zone_name_class()
+ master_addrinfo = self._do_parse_master_port()
+ db_file = self.args.get('db_file')
self.assertEqual(master_addrinfo[4][1], int(TEST_MASTER_PORT))
self.assertEqual(name, TEST_ZONE_NAME)
self.assertEqual(rrclass, TEST_RRCLASS)
@@ -421,49 +429,50 @@
def test_parse_cmd_params_default_port(self):
del self.args['port']
- master_addrinfo = self._do_parse()[2]
+ master_addrinfo = self._do_parse_master_port()
self.assertEqual(master_addrinfo[4][1], 53)
def test_parse_cmd_params_ip6master(self):
self.args['master'] = TEST_MASTER_IPV6_ADDRESS
- master_addrinfo = self._do_parse()[2]
+ master_addrinfo = self._do_parse_master_port()
self.assertEqual(master_addrinfo[4][0], TEST_MASTER_IPV6_ADDRESS)
def test_parse_cmd_params_chclass(self):
- self.args['rrclass'] = 'CH'
- self.assertEqual(self._do_parse()[1], RRClass.CH())
+ self.args['zone_class'] = 'CH'
+ self.assertEqual(self._do_parse_zone_name_class()[1], RRClass.CH())
def test_parse_cmd_params_bogusclass(self):
- self.args['rrclass'] = 'XXX'
- self.assertRaises(XfrinException, self._do_parse)
+ self.args['zone_class'] = 'XXX'
+ self.assertRaises(XfrinException, self._do_parse_zone_name_class)
def test_parse_cmd_params_nozone(self):
# zone name is mandatory.
del self.args['zone_name']
- self.assertRaises(XfrinException, self._do_parse)
+ self.assertRaises(XfrinException, self._do_parse_zone_name_class)
def test_parse_cmd_params_nomaster(self):
# master address is mandatory.
del self.args['master']
- self.assertRaises(XfrinException, self._do_parse)
+ master_addrinfo = self._do_parse_master_port()
+ self.assertEqual(master_addrinfo[4][0], DEFAULT_MASTER)
def test_parse_cmd_params_bad_ip4(self):
self.args['master'] = '3.3.3.3.3'
- self.assertRaises(XfrinException, self._do_parse)
+ self.assertRaises(XfrinException, self._do_parse_master_port)
def test_parse_cmd_params_bad_ip6(self):
self.args['master'] = '1::1::1'
- self.assertRaises(XfrinException, self._do_parse)
+ self.assertRaises(XfrinException, self._do_parse_master_port)
def test_parse_cmd_params_bad_port(self):
self.args['port'] = '-1'
- self.assertRaises(XfrinException, self._do_parse)
+ self.assertRaises(XfrinException, self._do_parse_master_port)
self.args['port'] = '65536'
- self.assertRaises(XfrinException, self._do_parse)
+ self.assertRaises(XfrinException, self._do_parse_master_port)
self.args['port'] = 'http'
- self.assertRaises(XfrinException, self._do_parse)
+ self.assertRaises(XfrinException, self._do_parse_master_port)
def test_command_handler_shutdown(self):
self.assertEqual(self.xfr.command_handler("shutdown",
@@ -518,10 +527,31 @@
self.args['master'] = TEST_MASTER_IPV6_ADDRESS
# ...but right now we disable the feature due to security concerns.
self.assertEqual(self.xfr.command_handler("notify",
- self.args)['result'][0], 1)
+ self.args)['result'][0], 0)
def test_command_handler_unknown(self):
self.assertEqual(self.xfr.command_handler("xxx", None)['result'][0], 1)
+
+ def test_command_handler_transfers_in(self):
+ self.assertEqual(self.xfr.config_handler({})['result'][0], 0)
+ self.assertEqual(self.xfr.config_handler({'transfers_in': 3})['result'][0], 0)
+ self.assertEqual(self.xfr._max_transfers_in, 3)
+
+ def test_command_handler_masters(self):
+ master_info = {'master_addr': '1.1.1.1', 'master_port':53}
+ self.assertEqual(self.xfr.config_handler(master_info)['result'][0], 0)
+
+ master_info = {'master_addr': '1111.1.1.1', 'master_port':53 }
+ self.assertEqual(self.xfr.config_handler(master_info)['result'][0], 1)
+
+ master_info = {'master_addr': '2.2.2.2', 'master_port':530000 }
+ self.assertEqual(self.xfr.config_handler(master_info)['result'][0], 1)
+
+ master_info = {'master_addr': '2.2.2.2', 'master_port':53 }
+ self.xfr.config_handler(master_info)
+ self.assertEqual(self.xfr._master_addr, '2.2.2.2')
+ self.assertEqual(self.xfr._master_port, 53)
+
def raise_interrupt():
raise KeyboardInterrupt()
Modified: trunk/src/bin/xfrin/xfrin.py.in
==============================================================================
--- trunk/src/bin/xfrin/xfrin.py.in (original)
+++ trunk/src/bin/xfrin/xfrin.py.in Mon Aug 16 09:05:52 2010
@@ -28,6 +28,7 @@
import random
from optparse import OptionParser, OptionValueError
from isc.config.ccsession import *
+from isc.notify import notify_out
try:
from libdns_python import *
except ImportError as e:
@@ -49,13 +50,17 @@
SPECFILE_LOCATION = SPECFILE_PATH + "/xfrin.spec"
AUTH_SPECFILE_LOCATION = AUTH_SPECFILE_PATH + "/auth.spec"
-
+XFROUT_MODULE_NAME = 'Xfrout'
+ZONE_MANAGER_MODULE_NAME = 'Zonemgr'
+REFRESH_FROM_ZONEMGR = 'refresh_from_zonemgr'
+ZONE_XFRIN_FAILED = 'zone_xfrin_failed'
__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))
@@ -316,14 +321,15 @@
sys.stdout.write('[b10-xfrin] %s\n' % str(msg))
-def process_xfrin(xfrin_recorder, zone_name, rrclass, db_file,
+def process_xfrin(server, xfrin_recorder, zone_name, rrclass, db_file,
shutdown_event, master_addrinfo, check_soa, verbose):
xfrin_recorder.increment(zone_name)
sock_map = {}
conn = XfrinConnection(sock_map, zone_name, rrclass, db_file,
shutdown_event, master_addrinfo, verbose)
if conn.connect_to_master():
- conn.do_xfrin(check_soa)
+ ret = conn.do_xfrin(check_soa)
+ server.publish_xfrin_news(zone_name, rrclass, ret)
xfrin_recorder.decrement(zone_name)
@@ -358,32 +364,54 @@
class Xfrin:
def __init__(self, verbose = False):
+ self._max_transfers_in = 10
+ #TODO, this is the temp way to set the zone's master.
+ self._master_addr = DEFAULT_MASTER
+ self._master_port = DEFAULT_MASTER_PORT
self._cc_setup()
- self._max_transfers_in = 10
self.recorder = XfrinRecorder()
self._shutdown_event = threading.Event()
self._verbose = verbose
def _cc_setup(self):
- '''
-This method is used only as part of initialization, but is implemented
-separately for convenience of unit tests; by letting the test code override
-this method we can test most of this class without requiring a command channel.
-'''
- self._cc = isc.config.ModuleCCSession(SPECFILE_LOCATION,
+ '''This method is used only as part of initialization, but is
+ implemented separately for convenience of unit tests; by letting
+ the test code override this method we can test most of this class
+ without requiring a command channel.'''
+ # Create one session for sending command to other modules, because the
+ # listening session will block the send operation.
+ self._send_cc_session = isc.cc.Session()
+ self._module_cc = isc.config.ModuleCCSession(SPECFILE_LOCATION,
self.config_handler,
self.command_handler)
- self._cc.start()
+ self._module_cc.start()
+ config_data = self._module_cc.get_full_config()
+ self._max_transfers_in = config_data.get("transfers_in")
+ self._master_addr = config_data.get('master_addr') or self._master_addr
+ self._master_port = config_data.get('master_port') or self._master_port
def _cc_check_command(self):
- '''
-This is a straightforward wrapper for cc.check_command, but provided as
-a separate method for the convenience of unit tests.
-'''
- self._cc.check_command()
+ '''This is a straightforward wrapper for cc.check_command,
+ but provided as a separate method for the convenience
+ of unit tests.'''
+ self._module_cc.check_command()
def config_handler(self, new_config):
- # TODO, process new config data
+ self._max_transfers_in = new_config.get("transfers_in") or self._max_transfers_in
+ if ('master_addr' in new_config) or ('master_port' in new_config):
+ # Check if the new master is valid, there should be library for check it.
+ # and user should change the port and address together.
+ try:
+ addr = new_config.get('master_addr') or self._master_addr
+ port = new_config.get('master_port') or self._master_port
+ check_addr_port(addr, port)
+ self._master_addr = addr
+ self._master_port = port
+ except:
+ errmsg = "bad format for zone's master: " + str(new_config)
+ log_error(errmsg)
+ return create_answer(1, errmsg)
+
return create_answer(0)
def shutdown(self):
@@ -397,95 +425,97 @@
continue
th.join()
-
def command_handler(self, command, args):
answer = create_answer(0)
try:
if command == 'shutdown':
self._shutdown_event.set()
+ elif command == 'notify' or command == REFRESH_FROM_ZONEMGR:
+ # Xfrin receives the refresh/notify command from zone manager.
+ # 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.
+ (zone_name, rrclass) = self._parse_zone_name_and_class(args)
+ (master_addr) = check_addr_port(self._master_addr, self._master_port)
+ ret = self.xfrin_start(zone_name,
+ rrclass,
+ self._get_db_file(),
+ master_addr,
+ True)
+ answer = create_answer(ret[0], ret[1])
+
elif command == 'retransfer' or command == 'refresh':
- (zone_name, rrclass,
- master_addr, db_file) = self._parse_cmd_params(args)
- ret = self.xfrin_start(zone_name, rrclass, db_file,
+ # Xfrin receives the retransfer/refresh from cmdctl(sent by bindctl).
+ # If the command has specified master address, do transfer from the
+ # 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)
+ db_file = args.get('db_file') or self._get_db_file()
+ ret = self.xfrin_start(zone_name,
+ rrclass,
+ db_file,
master_addr,
- False if command == 'retransfer' else True)
+ (False if command == 'retransfer' else True))
answer = create_answer(ret[0], ret[1])
- elif command == 'notify':
- # This is the temporary implementation for notify.
- # actually the notfiy command should be sent to the
- # Zone Manager module. Being temporary, we separate this case
- # from refresh/retransfer while we could (and should otherwise)
- # share the code.
- (zone_name, rrclass,
- master_addr, db_file) = self._parse_cmd_params(args)
-
- # XXX: master_addr is the sender of the notify message.
- # It's very dangerous to naively trust it as the source of
- # subsequent zone transfer; any remote node can easily exploit
- # it to mount zone poisoning or DoS attacks. We should
- # locally identify the appropriate set of master servers.
- # For now, we disable the code below.
- master_is_valid = False
-
- if master_is_valid:
- ret = self.xfrin_start(zone_name, rrclass, db_file,
- master_addr, True)
- else:
- errmsg = 'Failed to validate the master address ('
- errmsg += args['master'] + '), ignoring notify'
- ret = [1, errmsg]
- answer = create_answer(ret[0], ret[1])
+
else:
answer = create_answer(1, 'unknown command: ' + command)
-
except XfrinException as err:
+ log_error('error happened for command: %s, %s' % (command, str(err)) )
answer = create_answer(1, str(err))
-
return answer
- def _parse_cmd_params(self, args):
+ def _parse_zone_name_and_class(self, args):
zone_name = args.get('zone_name')
if not zone_name:
raise XfrinException('zone name should be provided')
- rrclass = args.get('rrclass')
+ rrclass = args.get('zone_class')
if not rrclass:
- # The default RR class is IN. We should fix this so that
- # the class is always passed in the command arg (where we specify
- # the default)
rrclass = RRClass.IN()
else:
try:
rrclass = RRClass(rrclass)
except InvalidRRClass as e:
raise XfrinException('invalid RRClass: ' + rrclass)
-
- master = args.get('master')
- if not master:
- raise XfrinException('master address should be provided')
-
- port_str = args.get('port')
- if not port_str:
- port_str = DEFAULT_MASTER_PORT
- master_addrinfo = check_addr_port(master, port_str)
-
- db_file = args.get('db_file')
- if not db_file:
- #TODO, the db file path should be got in auth server's configuration
- # if we need access to this configuration more often, we
- # should add it on start, and not remove it here
- # (or, if we have writable ds, we might not need this in
- # the first place)
- self._cc.add_remote_config(AUTH_SPECFILE_LOCATION)
- db_file, is_default = self._cc.get_remote_config_value("Auth", "database_file")
- if is_default and "B10_FROM_BUILD" in os.environ:
- # this too should be unnecessary, but currently the
- # 'from build' override isn't stored in the config
- # (and we don't have writable datasources yet)
- db_file = os.environ["B10_FROM_BUILD"] + os.sep + "bind10_zones.sqlite3"
- self._cc.remove_remote_config(AUTH_SPECFILE_LOCATION)
-
- return (zone_name, rrclass, master_addrinfo, db_file)
+
+ return zone_name, rrclass
+
+ def _parse_master_and_port(self, args):
+ port = args.get('port') or self._master_port
+ master = args.get('master') or self._master_addr
+ return check_addr_port(master, port)
+
+ def _get_db_file(self):
+ #TODO, the db file path should be got in auth server's configuration
+ # if we need access to this configuration more often, we
+ # should add it on start, and not remove it here
+ # (or, if we have writable ds, we might not need this in
+ # the first place)
+ self._module_cc.add_remote_config(AUTH_SPECFILE_LOCATION)
+ db_file, is_default = self._module_cc.get_remote_config_value("Auth", "database_file")
+ if is_default and "B10_FROM_BUILD" in os.environ:
+ # this too should be unnecessary, but currently the
+ # 'from build' override isn't stored in the config
+ # (and we don't have writable datasources yet)
+ db_file = os.environ["B10_FROM_BUILD"] + os.sep + "bind10_zones.sqlite3"
+ self._module_cc.remove_remote_config(AUTH_SPECFILE_LOCATION)
+ return db_file
+
+ def publish_xfrin_news(self, zone_name, zone_class, xfr_result):
+ '''Send command to xfrout/zone manager module.
+ If xfrin has finished successfully for one zone, tell the good
+ news(command: zone_new_data_ready) to zone manager and xfrout.
+ if xfrin failed, just tell the bad news to zone manager, so that
+ it can reset the refresh timer for that zone. '''
+ param = {'zone_name': zone_name, 'zone_class': zone_class.to_text()}
+ if xfr_result == XFRIN_OK:
+ msg = create_command(notify_out.ZONE_NEW_DATA_READY_CMD, param)
+ self._send_cc_session.group_sendmsg(msg, XFROUT_MODULE_NAME)
+ self._send_cc_session.group_sendmsg(msg, ZONE_MANAGER_MODULE_NAME)
+ else:
+ msg = create_command(ZONE_XFRIN_FAILED, param)
+ self._send_cc_session.group_sendmsg(msg, ZONE_MANAGER_MODULE_NAME)
def startup(self):
while not self._shutdown_event.is_set():
@@ -504,7 +534,8 @@
return (1, 'zone xfrin is in progress')
xfrin_thread = threading.Thread(target = process_xfrin,
- args = (self.recorder,
+ args = (self,
+ self.recorder,
zone_name, rrclass,
db_file,
self._shutdown_event,
Modified: trunk/src/bin/xfrin/xfrin.spec.pre.in
==============================================================================
--- trunk/src/bin/xfrin/xfrin.spec.pre.in (original)
+++ trunk/src/bin/xfrin/xfrin.spec.pre.in Mon Aug 16 09:05:52 2010
@@ -8,6 +8,17 @@
"item_type": "integer",
"item_optional": false,
"item_default": 10
+ },
+ {
+ "item_name": "master_addr",
+ "item_type": "string",
+ "item_optional": false,
+ "item_default": ""
+ },
+ { "item_name": "master_port",
+ "item_type": "integer",
+ "item_optional": false,
+ "item_default": 53
}
],
"commands": [
@@ -21,9 +32,15 @@
"item_default": ""
},
{
+ "item_name": "zone_class",
+ "item_type": "string",
+ "item_optional": true,
+ "item_default": "IN"
+ },
+ {
"item_name": "master",
"item_type": "string",
- "item_optional": false,
+ "item_optional": true,
"item_default": ""
},
{
Modified: trunk/src/bin/xfrout/xfrout.py.in
==============================================================================
--- trunk/src/bin/xfrout/xfrout.py.in (original)
+++ trunk/src/bin/xfrout/xfrout.py.in Mon Aug 16 09:05:52 2010
@@ -28,6 +28,7 @@
from isc.config.ccsession import *
from isc.log.log import *
from isc.cc import SessionError
+from isc.notify import notify_out
import socket
import select
import errno
@@ -303,7 +304,7 @@
self._log = log
self.update_config_data(config_data)
self._cc = cc
-
+
def finish_request(self, request, client_address):
'''Finish one request by instantiating RequestHandlerClass.'''
self.RequestHandlerClass(request, client_address, self, self._log)
@@ -415,16 +416,25 @@
self._config_data.get('log_severity'), self._config_data.get('log_versions'),
self._config_data.get('log_max_bytes'), True)
self._start_xfr_query_listener()
+ self._start_notifier()
def _start_xfr_query_listener(self):
'''Start a new thread to accept xfr query. '''
-
self._unix_socket_server = UnixSockServer(self._listen_sock_file, XfroutSession,
self._shutdown_event, self._config_data,
self._cc, self._log);
listener = threading.Thread(target = listen_on_xfr_query, args = (self._unix_socket_server,))
listener.start()
-
+
+ def _start_notifier(self):
+ datasrc = self._unix_socket_server.get_db_file()
+ self._notifier = notify_out.NotifyOut(datasrc, self._log)
+ td = threading.Thread(target = notify_out.dispatcher, args = (self._notifier,))
+ td.daemon = True
+ td.start()
+
+ def send_notify(self, zone_name, zone_class):
+ self._notifier.send_notify(zone_name, zone_class)
def config_handler(self, new_config):
'''Update config data. TODO. Do error check'''
@@ -466,11 +476,22 @@
self._log.log_message("info", "Received shutdown command.")
self.shutdown()
answer = create_answer(0)
+
+ elif cmd == notify_out.ZONE_NEW_DATA_READY_CMD:
+ zone_name = args.get('zone_name')
+ zone_class = args.get('zone_class')
+ if zone_name and zone_class:
+ self._log.log_message("info", "Receive notify command for zone:'%s/%s'" \
+ % (zone_name, zone_class))
+ self.send_notify(zone_name, zone_class)
+ answer = create_answer(0)
+ else:
+ answer = create_answer(1, "Bad command parameter:" + str(args))
+
else:
answer = create_answer(1, "Unknown command:" + str(cmd))
return answer
-
def run(self):
'''Get and process all commands sent from cfgmgr or other modules. '''
Modified: trunk/src/lib/python/isc/Makefile.am
==============================================================================
--- trunk/src/lib/python/isc/Makefile.am (original)
+++ trunk/src/lib/python/isc/Makefile.am Mon Aug 16 09:05:52 2010
@@ -1,4 +1,4 @@
-SUBDIRS = datasrc cc config log # Util
+SUBDIRS = datasrc cc config log notify # Util
python_PYTHON = __init__.py
Modified: trunk/src/lib/python/isc/datasrc/sqlite3_ds.py
==============================================================================
--- trunk/src/lib/python/isc/datasrc/sqlite3_ds.py (original)
+++ trunk/src/lib/python/isc/datasrc/sqlite3_ds.py Mon Aug 16 09:05:52 2010
@@ -17,6 +17,13 @@
import sqlite3, re, random
import isc
+
+
+#define the index of different part of one record
+RR_TYPE_INDEX = 5
+RR_NAME_INDEX = 2
+RR_TTL_INDEX = 4
+RR_RDATA_INDEX = 7
#########################################################################
# define exceptions
@@ -120,6 +127,39 @@
return datas
+
+#########################################################################
+# get_zone_rrset
+# returns the rrset of the zone with the given zone name, rrset name
+# and given rd type.
+# If the zone doesn't exist or rd type doesn't exist, return an empty list.
+#########################################################################
+def get_zone_rrset(zonename, rr_name, rdtype, dbfile):
+ conn, cur = open(dbfile)
+ id = get_zoneid(zonename, cur)
+ cur.execute("SELECT * FROM records WHERE name = ? and zone_id = ? and rdtype = ?",
+ [rr_name, id, rdtype])
+ datas = cur.fetchall()
+ cur.close()
+ conn.close()
+ return datas
+
+
+#########################################################################
+# get_zones_info:
+# returns all the zones' information.
+#########################################################################
+def get_zones_info(db_file):
+ conn, cur = open(db_file)
+ cur.execute("SELECT name, rdclass FROM zones")
+ info = cur.fetchone()
+ while info:
+ yield info
+ info = cur.fetchone()
+
+ cur.close()
+ conn.close()
+
#########################################################################
# get_zoneid:
# returns the zone_id for a given zone name, or an empty
@@ -132,7 +172,7 @@
return row[0]
else:
return ''
-
+
#########################################################################
# reverse_name:
# reverse the labels of a DNS name. (for example,
Modified: trunk/src/lib/python/isc/notify/tests/notify_out_test.py
==============================================================================
--- trunk/src/lib/python/isc/notify/tests/notify_out_test.py (original)
+++ trunk/src/lib/python/isc/notify/tests/notify_out_test.py Mon Aug 16 09:05:52 2010
@@ -20,7 +20,7 @@
import time
import socket
from isc.datasrc import sqlite3_ds
-import notify_out
+from isc.notify import notify_out
class TestZoneNotifyInfo(unittest.TestCase):
def setUp(self):
More information about the bind10-changes
mailing list