BIND 10 master, updated. ef10033b844f147caa9e91c5dae8a33db0241630 [master] Merge branch 'trac1978-2'
BIND 10 source code commits
bind10-changes at lists.isc.org
Mon Jun 11 21:05:56 UTC 2012
The branch, master has been updated
via ef10033b844f147caa9e91c5dae8a33db0241630 (commit)
via 18cd6a77d6a673679aaec4717267a06bcce2995a (commit)
via 81239a632d1190e9b836287a41d62df05bf535c8 (commit)
via 0dbe89e24e6757013e58ab3e0e7c5f5b7afb23f2 (commit)
via d8655b3c7a7f98c3f8974fa4c8856f2a6ac056d7 (commit)
from 6aa01f0ed3541cbb35510c76a584c6dd50f7401f (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 ef10033b844f147caa9e91c5dae8a33db0241630
Merge: 6aa01f0 18cd6a7
Author: JINMEI Tatuya <jinmei at isc.org>
Date: Mon Jun 11 14:02:24 2012 -0700
[master] Merge branch 'trac1978-2'
-----------------------------------------------------------------------
Summary of changes:
src/bin/ddns/ddns.py.in | 24 +++--
src/bin/ddns/tests/ddns_test.py | 65 ++++++++++++--
src/bin/xfrin/xfrin.py.in | 52 ++---------
src/bin/xfrin/xfrin_messages.mes | 6 --
src/lib/python/isc/server_common/Makefile.am | 2 +-
src/lib/python/isc/server_common/auth_command.py | 94 ++++++++++++++++++++
.../isc/server_common/server_common_messages.mes | 6 ++
7 files changed, 186 insertions(+), 63 deletions(-)
create mode 100644 src/lib/python/isc/server_common/auth_command.py
-----------------------------------------------------------------------
diff --git a/src/bin/ddns/ddns.py.in b/src/bin/ddns/ddns.py.in
index 9c432f4..6d44623 100755
--- a/src/bin/ddns/ddns.py.in
+++ b/src/bin/ddns/ddns.py.in
@@ -31,6 +31,7 @@ import isc.util.cio.socketsession
from isc.notify.notify_out import ZONE_NEW_DATA_READY_CMD
import isc.server_common.tsig_keyring
from isc.datasrc import DataSourceClient
+from isc.server_common.auth_command import auth_loadzone_command
import select
import errno
@@ -82,6 +83,7 @@ isc.util.process.rename()
# Cooperating modules
XFROUT_MODULE_NAME = 'Xfrout'
+AUTH_MODULE_NAME = 'Auth'
class DDNSConfigError(Exception):
'''An exception indicating an error in updating ddns configuration.
@@ -380,7 +382,8 @@ class DDNSServer:
ret = self.__send_response(sock, self.__response_renderer.get_data(),
remote_addr)
if result == isc.ddns.session.UPDATE_SUCCESS:
- self.__notify_update(zname, zclass)
+ self.__notify_auth(zname, zclass)
+ self.__notify_xfrout(zname, zclass)
return ret
def __send_response(self, sock, data, dest):
@@ -409,8 +412,20 @@ class DDNSServer:
return True
- def __notify_update(self, zname, zclass):
- '''Notify other modules of the update.
+ def __notify_auth(self, zname, zclass):
+ '''Notify auth of the update, if necessary.'''
+ msg = auth_loadzone_command(self._cc, zname, zclass)
+ if msg is not None:
+ self.__notify_update(AUTH_MODULE_NAME, msg, zname, zclass)
+
+ def __notify_xfrout(self, zname, zclass):
+ '''Notify xfrout of the update.'''
+ param = {'zone_name': zname.to_text(), 'zone_class': zclass.to_text()}
+ msg = create_command(ZONE_NEW_DATA_READY_CMD, param)
+ self.__notify_update(XFROUT_MODULE_NAME, msg, zname, zclass)
+
+ def __notify_update(self, modname, msg, zname, zclass):
+ '''Notify other module of the update.
Note that we use blocking communication here. While the internal
communication bus is generally expected to be pretty responsive and
@@ -428,9 +443,6 @@ class DDNSServer:
of the cc session.
'''
- param = {'zone_name': zname.to_text(), 'zone_class': zclass.to_text()}
- msg = create_command(ZONE_NEW_DATA_READY_CMD, param)
- modname = XFROUT_MODULE_NAME
try:
seq = self._cc._session.group_sendmsg(msg, modname)
answer, _ = self._cc._session.group_recvmsg(False, seq)
diff --git a/src/bin/ddns/tests/ddns_test.py b/src/bin/ddns/tests/ddns_test.py
index 992e587..823c429 100755
--- a/src/bin/ddns/tests/ddns_test.py
+++ b/src/bin/ddns/tests/ddns_test.py
@@ -161,6 +161,8 @@ class MyCCSession(isc.config.ConfigData):
self._stopped = False
# Used as the return value of get_remote_config_value. Customizable.
self.auth_db_file = READ_ZONE_DB_FILE
+ # Used as the return value of get_remote_config_value. Customizable.
+ self.auth_datasources = None
# faked cc channel, providing group_send/recvmsg itself. The following
# attributes are for inspection/customization in tests.
self._session = self
@@ -190,6 +192,11 @@ class MyCCSession(isc.config.ConfigData):
def get_remote_config_value(self, module_name, item):
if module_name == "Auth" and item == "database_file":
return self.auth_db_file, False
+ if module_name == "Auth" and item == "datasources":
+ if self.auth_datasources is None:
+ return [], True # default
+ else:
+ return self.auth_datasources, False
def group_sendmsg(self, msg, group):
# remember the passed parameter, and return dummy sequence
@@ -745,20 +752,42 @@ class TestDDNSSession(unittest.TestCase):
num_rrsets = len(self.__req_message.get_section(SECTION_PREREQUISITE))
self.assertEqual(2, num_rrsets)
- def check_session_msg(self, result, expect_recv=1):
+ def check_session_msg(self, result, expect_recv=1, notify_auth=False):
'''Check post update communication with other modules.'''
# iff the update succeeds, b10-ddns should tell interested other
- # modules the information about the update zone in the form of
+ # modules the information about the update zone. Possible modules
+ # are xfrout and auth: for xfrout, the message format should be:
# {'command': ['notify', {'zone_name': <updated_zone_name>,
# 'zone_class', <updated_zone_class>}]}
+ # for auth, it should be:
+ # {'command': ['loadzone', {'origin': <updated_zone_name>,
+ # 'class', <updated_zone_class>,
+ # 'datasrc', <datasrc type, should be
+ # "memory" in practice>}]}
# and expect an answer by calling group_recvmsg().
#
# expect_recv indicates the expected number of calls to
- # group_recvmsg(), which is normally 1, but can be 0 if send fails.
+ # group_recvmsg(), which is normally 1, but can be 0 if send fails;
+ # if the message is to be sent
if result == UPDATE_SUCCESS:
- self.assertEqual(1, len(self.__cc_session._sent_msg))
+ expected_sentmsg = 2 if notify_auth else 1
+ self.assertEqual(expected_sentmsg,
+ len(self.__cc_session._sent_msg))
self.assertEqual(expect_recv, self.__cc_session._recvmsg_called)
- sent_msg, sent_group = self.__cc_session._sent_msg[0]
+ msg_cnt = 0
+ if notify_auth:
+ sent_msg, sent_group = self.__cc_session._sent_msg[msg_cnt]
+ sent_cmd = sent_msg['command']
+ self.assertEqual('Auth', sent_group)
+ self.assertEqual('loadzone', sent_cmd[0])
+ self.assertEqual(3, len(sent_cmd[1]))
+ self.assertEqual(TEST_ZONE_NAME.to_text(),
+ sent_cmd[1]['origin'])
+ self.assertEqual(TEST_RRCLASS.to_text(),
+ sent_cmd[1]['class'])
+ self.assertEqual('memory', sent_cmd[1]['datasrc'])
+ msg_cnt += 1
+ sent_msg, sent_group = self.__cc_session._sent_msg[msg_cnt]
sent_cmd = sent_msg['command']
self.assertEqual('Xfrout', sent_group)
self.assertEqual('notify', sent_cmd[0])
@@ -815,8 +844,32 @@ class TestDDNSSession(unittest.TestCase):
self.__cc_session._sendmsg_exception = RuntimeError('unexpected')
self.assertRaises(RuntimeError, self.check_session)
+ def test_session_msg_for_auth(self):
+ '''Test post update communication with other modules including Auth.'''
+ # Let the CC session return in-memory config with sqlite3 backend.
+ # (The default case was covered by other tests.)
+ self.__cc_session.auth_datasources = \
+ [{'type': 'memory', 'class': 'IN', 'zones': [
+ {'origin': TEST_ZONE_NAME_STR, 'filetype': 'sqlite3'}]}]
+ self.check_session()
+ self.check_session_msg(UPDATE_SUCCESS, expect_recv=2, notify_auth=True)
+
+ # Let sendmsg() raise an exception. The first exception shouldn't
+ # stop sending the second message. There's just no recv calls.
+ self.__cc_session.clear_msg()
+ self.__cc_session._sendmsg_exception = SessionError('send error')
+ self.check_session()
+ self.check_session_msg(UPDATE_SUCCESS, expect_recv=0, notify_auth=True)
+
+ # Likewise, in the case recvmsg() raises (and there should be recv
+ # calls in this case)
+ self.__cc_session.clear_msg()
+ self.__cc_session._recvmsg_exception = SessionError('recv error')
+ self.check_session()
+ self.check_session_msg(UPDATE_SUCCESS, expect_recv=2, notify_auth=True)
+
def test_session_with_config(self):
- '''Check a session with more relistic config setups
+ '''Check a session with more realistic config setups.
We don't have to explore various cases in detail in this test.
We're just checking if the expected configured objects are passed
diff --git a/src/bin/xfrin/xfrin.py.in b/src/bin/xfrin/xfrin.py.in
index 114bac4..74e0faf 100755
--- a/src/bin/xfrin/xfrin.py.in
+++ b/src/bin/xfrin/xfrin.py.in
@@ -33,6 +33,7 @@ import isc.util.process
from isc.datasrc import DataSourceClient, ZoneFinder
import isc.net.parse
from isc.xfrin.diff import Diff
+from isc.server_common.auth_command import auth_loadzone_command
from isc.log_messages.xfrin_messages import *
isc.log.init("b10-xfrin")
@@ -1248,50 +1249,13 @@ class ZoneInfo:
(str(self.master_addr), self.master_port))
def _do_auth_loadzone(server, zone_name, zone_class):
- # On a successful zone transfer, if the zone is served by
- # b10-auth in the in-memory data source using sqlite3 as a
- # backend, send the "loadzone" command for the zone to auth.
- datasources, is_default =\
- server._module_cc.get_remote_config_value(AUTH_MODULE_NAME, "datasources")
- if is_default:
- return
- for d in datasources:
- if "type" not in d:
- continue
- try:
- if "class" in d:
- dclass = RRClass(d["class"])
- else:
- dclass = RRClass("IN")
- except InvalidRRClass as err:
- logger.info(XFRIN_AUTH_CONFIG_RRCLASS_ERROR, str(err))
- continue
-
- if d["type"].lower() == "memory" and dclass == zone_class:
- for zone in d["zones"]:
- if "filetype" not in zone:
- continue
- if "origin" not in zone:
- continue
- if "filetype" not in zone:
- continue
- try:
- name = Name(zone["origin"])
- except (EmptyLabel, TooLongLabel, BadLabelType, BadEscape, TooLongName, IncompleteName):
- logger.info(XFRIN_AUTH_CONFIG_NAME_PARSER_ERROR, str(err))
- continue
-
- if zone["filetype"].lower() == "sqlite3" and name == zone_name:
- param = {"origin": zone_name.to_text(),
- "class": zone_class.to_text(),
- "datasrc": d["type"]}
-
- logger.debug(DBG_XFRIN_TRACE, XFRIN_AUTH_LOADZONE,
- param["origin"], param["class"], param["datasrc"])
-
- msg = create_command("loadzone", param)
- seq = server._send_cc_session.group_sendmsg(msg, AUTH_MODULE_NAME)
- answer, env = server._send_cc_session.group_recvmsg(False, seq)
+ msg = auth_loadzone_command(server._module_cc, zone_name, zone_class)
+ if msg is not None:
+ param = msg['command'][1]
+ logger.debug(DBG_XFRIN_TRACE, XFRIN_AUTH_LOADZONE, param["origin"],
+ param["class"], param["datasrc"])
+ seq = server._send_cc_session.group_sendmsg(msg, AUTH_MODULE_NAME)
+ answer, env = server._send_cc_session.group_recvmsg(False, seq)
class Xfrin:
def __init__(self):
diff --git a/src/bin/xfrin/xfrin_messages.mes b/src/bin/xfrin/xfrin_messages.mes
index 6b51661..ffea249 100644
--- a/src/bin/xfrin/xfrin_messages.mes
+++ b/src/bin/xfrin/xfrin_messages.mes
@@ -15,12 +15,6 @@
# No namespace declaration - these constants go in the global namespace
# of the xfrin messages python module.
-% XFRIN_AUTH_CONFIG_NAME_PARSER_ERROR Invalid name when parsing Auth configuration: %1
-There was an invalid name when parsing Auth configuration.
-
-% XFRIN_AUTH_CONFIG_RRCLASS_ERROR Invalid RRClass when parsing Auth configuration: %1
-There was an invalid RR class when parsing Auth configuration.
-
% XFRIN_AUTH_LOADZONE sending Auth loadzone for origin=%1, class=%2, datasrc=%3
There was a successful zone transfer, and the zone is served by b10-auth
in the in-memory data source using sqlite3 as a backend. We send the
diff --git a/src/lib/python/isc/server_common/Makefile.am b/src/lib/python/isc/server_common/Makefile.am
index a9eca2e..8d2be7e 100644
--- a/src/lib/python/isc/server_common/Makefile.am
+++ b/src/lib/python/isc/server_common/Makefile.am
@@ -1,6 +1,6 @@
SUBDIRS = tests
-python_PYTHON = __init__.py tsig_keyring.py
+python_PYTHON = __init__.py tsig_keyring.py auth_command.py
pythondir = $(pyexecdir)/isc/server_common
diff --git a/src/lib/python/isc/server_common/auth_command.py b/src/lib/python/isc/server_common/auth_command.py
new file mode 100644
index 0000000..60fc1cc
--- /dev/null
+++ b/src/lib/python/isc/server_common/auth_command.py
@@ -0,0 +1,94 @@
+# Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SYSTEMS CONSORTIUM
+# DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+# INTERNET SYSTEMS CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+# FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+# NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+# WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+'''This module is a utility to create some intermodule command(s) for Auth.'''
+
+from isc.dns import *
+import isc.log
+from isc.config.ccsession import create_command
+from isc.log_messages.server_common_messages import *
+
+# Import tsig_keyring just to share the logger. Once #2003 is merged, this
+# should be replaced with the package level logger:
+# from isc.server_common.logger import logger
+from isc.server_common.tsig_keyring import logger
+
+AUTH_MODULE_NAME = 'Auth'
+
+def auth_loadzone_command(module_cc, zone_name, zone_class):
+ '''Create a 'loadzone' command with a given zone for Auth server.
+
+ This function checks the Auth module configuration to see if it
+ servers a given zone via an in-memory data source on top of SQLite3
+ data source, and, if so, generate an inter-module command for Auth
+ to force it to reload the zone.
+
+ Parameters:
+ module_cc (CCSession): a CC session that can get access to auth module
+ configuration as a remote configuration
+ zone_name (isc.dns.Name): the zone name to be possibly reloaded
+ zone_class (isc.dns.RRClass): the RR class of the zone to be possibly
+ reloaded.
+
+ Return: a CC command message for the reload if the zone is found;
+ otherwise None.
+
+ '''
+ # Note: this function was originally a dedicated subroutine of xfrin,
+ # but was moved here so it can be shared by some other modules
+ # (specifically, by ddns). It's expected that we'll soon fundamentally
+ # revisit the whole data source related configuration, at which point
+ # this function should be substantially modified if not completely
+ # deprecated (which is a more likely scenario). For this reason, the
+ # corresponding tests were still kept in xfrin.
+
+ datasources, is_default =\
+ module_cc.get_remote_config_value(AUTH_MODULE_NAME, "datasources")
+ if is_default:
+ return None
+ for d in datasources:
+ if "type" not in d:
+ continue
+ try:
+ if "class" in d:
+ dclass = RRClass(d["class"])
+ else:
+ dclass = RRClass("IN")
+ except InvalidRRClass as err:
+ logger.info(PYSERVER_COMMON_AUTH_CONFIG_RRCLASS_ERROR, err)
+ continue
+
+ if d["type"].lower() == "memory" and dclass == zone_class:
+ for zone in d["zones"]:
+ if "filetype" not in zone:
+ continue
+ if "origin" not in zone:
+ continue
+ if "filetype" not in zone:
+ continue
+ try:
+ name = Name(zone["origin"])
+ except (EmptyLabel, TooLongLabel, BadLabelType, BadEscape,
+ TooLongName, IncompleteName):
+ logger.info(PYSERVER_COMMON_AUTH_CONFIG_NAME_PARSER_ERROR,
+ err)
+ continue
+
+ if zone["filetype"].lower() == "sqlite3" and name == zone_name:
+ param = {"origin": zone_name.to_text(),
+ "class": zone_class.to_text(),
+ "datasrc": d["type"]}
+ return create_command("loadzone", param)
+ return None
diff --git a/src/lib/python/isc/server_common/server_common_messages.mes b/src/lib/python/isc/server_common/server_common_messages.mes
index b32205c..81b314e 100644
--- a/src/lib/python/isc/server_common/server_common_messages.mes
+++ b/src/lib/python/isc/server_common/server_common_messages.mes
@@ -21,6 +21,12 @@
# have that at this moment. So when adding a message, make sure that
# the name is not already used in src/lib/config/config_messages.mes
+% PYSERVER_COMMON_AUTH_CONFIG_NAME_PARSER_ERROR Invalid name when parsing Auth configuration: %1
+There was an invalid name when parsing Auth configuration.
+
+% PYSERVER_COMMON_AUTH_CONFIG_RRCLASS_ERROR Invalid RRClass when parsing Auth configuration: %1
+There was an invalid RR class when parsing Auth configuration.
+
% PYSERVER_COMMON_TSIG_KEYRING_DEINIT Deinitializing global TSIG keyring
A debug message noting that the global TSIG keyring is being removed from
memory. Most programs don't do that, they just exit, which is OK.
More information about the bind10-changes
mailing list