BIND 10 master, updated. 2357e7abc8bac23f60d79ca8abe81854b5550eea Merge branch 'trac764'
BIND 10 source code commits
bind10-changes at lists.isc.org
Mon Jul 11 17:00:17 UTC 2011
The branch, master has been updated
via 2357e7abc8bac23f60d79ca8abe81854b5550eea (commit)
via 0dd272381befd9b464365cc7df0bb2d761d0d2e0 (commit)
via 65bc0fbf12199bee2d16b914a544a69345c37cae (commit)
via 9ff2f7bc88be85c09d37209bd0feeb96ca256892 (commit)
via a837df2e0c4858543c0bd2e420f726b89994a7e2 (commit)
via 0cd32b208c9a92e5e773b7874a3f75ee58abd6c0 (commit)
via 551a2d7f6ed5744170265ea5bc7b99690b58a6f5 (commit)
via 0529433796c0024e9345edd3c458e22e1aec9043 (commit)
via e2127bd275b2263f06d7ba039123411c9b7cf07d (commit)
via 35d4ca9a46fd8372cce752577944b2fdc458a0f5 (commit)
via 4082b7fdb7a1b23518e2dcbb5077f52a79bffa8c (commit)
via 18ba901c91b5bd1e910c7ccc8ae1ebbb1e00fa36 (commit)
via 2f088998525f389391efb86ac4e917174449df85 (commit)
via 87fe9bf486e8671d74ed7e6683309a77add03f51 (commit)
from 046f1b9556d3b8197c03225843ff96d0d79ae762 (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 2357e7abc8bac23f60d79ca8abe81854b5550eea
Merge: 046f1b9556d3b8197c03225843ff96d0d79ae762 0dd272381befd9b464365cc7df0bb2d761d0d2e0
Author: Jelte Jansen <jelte at isc.org>
Date: Mon Jul 11 18:54:50 2011 +0200
Merge branch 'trac764'
-----------------------------------------------------------------------
Summary of changes:
doc/Doxyfile | 4 +-
src/bin/bindctl/bindcmd.py | 5 +-
src/lib/log/compiler/message.cc | 92 ++++++++++++++------
src/lib/python/isc/config/Makefile.am | 16 +++-
src/lib/python/isc/config/ccsession.py | 14 ++--
src/lib/python/isc/config/config_messages.mes | 33 +++++++
src/lib/python/isc/config/tests/ccsession_test.py | 2 +
src/lib/python/isc/notify/Makefile.am | 11 +++
src/lib/python/isc/notify/notify_out.py | 71 ++++++++-------
src/lib/python/isc/notify/notify_out_messages.mes | 83 ++++++++++++++++++
src/lib/python/isc/notify/tests/notify_out_test.py | 25 ++++--
src/lib/util/filename.cc | 18 ++++
src/lib/util/filename.h | 7 ++
src/lib/util/tests/filename_unittest.cc | 37 ++++++++
14 files changed, 336 insertions(+), 82 deletions(-)
create mode 100644 src/lib/python/isc/config/config_messages.mes
create mode 100644 src/lib/python/isc/notify/notify_out_messages.mes
-----------------------------------------------------------------------
diff --git a/doc/Doxyfile b/doc/Doxyfile
index b8a4656..ceb806f 100644
--- a/doc/Doxyfile
+++ b/doc/Doxyfile
@@ -570,8 +570,8 @@ WARN_LOGFILE =
INPUT = ../src/lib/cc ../src/lib/config \
../src/lib/cryptolink ../src/lib/dns ../src/lib/datasrc \
- ../src/bin/auth ../src/bin/resolver ../src/lib/bench \
- ../src/lib/log ../src/lib/asiolink/ ../src/lib/nsas \
+ ../src/bin/auth ../src/bin/resolver ../src/lib/bench ../src/lib/log \
+ ../src/lib/log/compiler ../src/lib/asiolink/ ../src/lib/nsas \
../src/lib/testutils ../src/lib/cache ../src/lib/server_common/ \
../src/bin/sockcreator/ ../src/lib/util/ \
../src/lib/resolve ../src/lib/acl
diff --git a/src/bin/bindctl/bindcmd.py b/src/bin/bindctl/bindcmd.py
index 8973aa5..0bfcda5 100644
--- a/src/bin/bindctl/bindcmd.py
+++ b/src/bin/bindctl/bindcmd.py
@@ -674,7 +674,10 @@ class BindCmdInterpreter(Cmd):
elif cmd.command == "revert":
self.config_data.clear_local_changes()
elif cmd.command == "commit":
- self.config_data.commit()
+ try:
+ self.config_data.commit()
+ except isc.config.ModuleCCSessionError as mcse:
+ print(str(mcse))
elif cmd.command == "diff":
print(self.config_data.get_local_changes());
elif cmd.command == "go":
diff --git a/src/lib/log/compiler/message.cc b/src/lib/log/compiler/message.cc
index 68335dc..f74020a 100644
--- a/src/lib/log/compiler/message.cc
+++ b/src/lib/log/compiler/message.cc
@@ -43,6 +43,7 @@ using namespace isc::util;
static const char* VERSION = "1.0-0";
+/// \file log/compiler/message.cc
/// \brief Message Compiler
///
/// \b Overview<BR>
@@ -55,13 +56,16 @@ static const char* VERSION = "1.0-0";
/// \b Invocation<BR>
/// The program is invoked with the command:
///
-/// <tt>message [-v | -h | \<message-file\>]</tt>
+/// <tt>message [-v | -h | -p | -d <dir> | <message-file>]</tt>
///
-/// It reads the message file and writes out two files of the same name in the
-/// default directory but with extensions of .h and .cc.
+/// It reads the message file and writes out two files of the same
+/// name in the current working directory (unless -d is used) but
+/// with extensions of .h and .cc, or .py if -p is used.
///
-/// \-v causes it to print the version number and exit. \-h prints a help
-/// message (and exits).
+/// -v causes it to print the version number and exit. -h prints a help
+/// message (and exits). -p sets the output to python. -d <dir> will make
+/// it write the output file(s) to dir instead of current working
+/// directory
/// \brief Print Version
@@ -80,11 +84,12 @@ version() {
void
usage() {
cout <<
- "Usage: message [-h] [-v] [-p] <message-file>\n" <<
+ "Usage: message [-h] [-v] [-p] [-d dir] <message-file>\n" <<
"\n" <<
"-h Print this message and exit\n" <<
"-v Print the program version and exit\n" <<
"-p Output python source instead of C++ ones\n" <<
+ "-d <dir> Place output files in given directory\n" <<
"\n" <<
"<message-file> is the name of the input message file.\n";
}
@@ -106,7 +111,7 @@ currentTime() {
// Convert to string and strip out the trailing newline
string current_time = buffer;
- return isc::util::str::trim(current_time);
+ return (isc::util::str::trim(current_time));
}
@@ -127,7 +132,7 @@ sentinel(Filename& file) {
string ext = file.extension();
string sentinel_text = "__" + name + "_" + ext.substr(1);
isc::util::str::uppercase(sentinel_text);
- return sentinel_text;
+ return (sentinel_text);
}
@@ -154,7 +159,7 @@ quoteString(const string& instring) {
outstring += instring[i];
}
- return outstring;
+ return (outstring);
}
@@ -177,7 +182,7 @@ sortedIdentifiers(MessageDictionary& dictionary) {
}
sort(ident.begin(), ident.end());
- return ident;
+ return (ident);
}
@@ -207,7 +212,7 @@ splitNamespace(string ns) {
// ... and return the vector of namespace components split on the single
// colon.
- return isc::util::str::tokens(ns, ":");
+ return (isc::util::str::tokens(ns, ":"));
}
@@ -249,14 +254,22 @@ writeClosingNamespace(ostream& output, const vector<string>& ns) {
/// \param file Name of the message file. The source code is written to a file
/// file of the same name but with a .py suffix.
/// \param dictionary The dictionary holding the message definitions.
+/// \param output_directory if not null NULL, output files are written
+/// to the given directory. If NULL, they are written to the current
+/// working directory.
///
/// \note We don't use the namespace as in C++. We don't need it, because
/// python file/module works as implicit namespace as well.
void
-writePythonFile(const string& file, MessageDictionary& dictionary) {
+writePythonFile(const string& file, MessageDictionary& dictionary,
+ const char* output_directory)
+{
Filename message_file(file);
Filename python_file(Filename(message_file.name()).useAsDefault(".py"));
+ if (output_directory != NULL) {
+ python_file.setDirectory(output_directory);
+ }
// Open the file for writing
ofstream pyfile(python_file.fullName().c_str());
@@ -291,13 +304,19 @@ writePythonFile(const string& file, MessageDictionary& dictionary) {
/// \param ns Namespace in which the definitions are to be placed. An empty
/// string indicates no namespace.
/// \param dictionary Dictionary holding the message definitions.
+/// \param output_directory if not null NULL, output files are written
+/// to the given directory. If NULL, they are written to the current
+/// working directory.
void
writeHeaderFile(const string& file, const vector<string>& ns_components,
- MessageDictionary& dictionary)
+ MessageDictionary& dictionary, const char* output_directory)
{
Filename message_file(file);
Filename header_file(Filename(message_file.name()).useAsDefault(".h"));
+ if (output_directory != NULL) {
+ header_file.setDirectory(output_directory);
+ }
// Text to use as the sentinels.
string sentinel_text = sentinel(header_file);
@@ -382,13 +401,25 @@ replaceNonAlphaNum(char c) {
/// optimisation is done at link-time, not compiler-time. In this it _may_
/// decide to remove the initializer object because of a lack of references
/// to it. But until BIND-10 is ported to Windows, we won't know.
-
+///
+/// \param file Name of the message file. The header file is written to a
+/// file of the same name but with a .h suffix.
+/// \param ns Namespace in which the definitions are to be placed. An empty
+/// string indicates no namespace.
+/// \param dictionary Dictionary holding the message definitions.
+/// \param output_directory if not null NULL, output files are written
+/// to the given directory. If NULL, they are written to the current
+/// working directory.
void
writeProgramFile(const string& file, const vector<string>& ns_components,
- MessageDictionary& dictionary)
+ MessageDictionary& dictionary,
+ const char* output_directory)
{
Filename message_file(file);
Filename program_file(Filename(message_file.name()).useAsDefault(".cc"));
+ if (output_directory) {
+ program_file.setDirectory(output_directory);
+ }
// Open the output file for writing
ofstream ccfile(program_file.fullName().c_str());
@@ -496,30 +527,35 @@ warnDuplicates(MessageReader& reader) {
int
main(int argc, char* argv[]) {
- const char* soptions = "hvp"; // Short options
+ const char* soptions = "hvpd:"; // Short options
optind = 1; // Ensure we start a new scan
int opt; // Value of the option
bool doPython = false;
+ const char *output_directory = NULL;
while ((opt = getopt(argc, argv, soptions)) != -1) {
switch (opt) {
+ case 'd':
+ output_directory = optarg;
+ break;
+
case 'p':
doPython = true;
break;
case 'h':
usage();
- return 0;
+ return (0);
case 'v':
version();
- return 0;
+ return (0);
default:
// A message will have already been output about the error.
- return 1;
+ return (1);
}
}
@@ -527,11 +563,11 @@ main(int argc, char* argv[]) {
if (optind < (argc - 1)) {
cout << "Error: excess arguments in command line\n";
usage();
- return 1;
+ return (1);
} else if (optind >= argc) {
cout << "Error: missing message file\n";
usage();
- return 1;
+ return (1);
}
string message_file = argv[optind];
@@ -552,7 +588,7 @@ main(int argc, char* argv[]) {
}
// Write the whole python file
- writePythonFile(message_file, dictionary);
+ writePythonFile(message_file, dictionary, output_directory);
} else {
// Get the namespace into which the message definitions will be put and
// split it into components.
@@ -560,16 +596,18 @@ main(int argc, char* argv[]) {
splitNamespace(reader.getNamespace());
// Write the header file.
- writeHeaderFile(message_file, ns_components, dictionary);
+ writeHeaderFile(message_file, ns_components, dictionary,
+ output_directory);
// Write the file that defines the message symbols and text
- writeProgramFile(message_file, ns_components, dictionary);
+ writeProgramFile(message_file, ns_components, dictionary,
+ output_directory);
}
// Finally, warn of any duplicates encountered.
warnDuplicates(reader);
}
- catch (MessageException& e) {
+ catch (const MessageException& e) {
// Create an error message from the ID and the text
MessageDictionary& global = MessageDictionary::globalDictionary();
string text = e.id();
@@ -583,9 +621,9 @@ main(int argc, char* argv[]) {
cerr << text << "\n";
- return 1;
+ return (1);
}
- return 0;
+ return (0);
}
diff --git a/src/lib/python/isc/config/Makefile.am b/src/lib/python/isc/config/Makefile.am
index 1efb6fc..312ad33 100644
--- a/src/lib/python/isc/config/Makefile.am
+++ b/src/lib/python/isc/config/Makefile.am
@@ -1,19 +1,27 @@
SUBDIRS = . tests
python_PYTHON = __init__.py ccsession.py cfgmgr.py config_data.py module_spec.py
-pyexec_DATA = cfgmgr_messages.py
+pyexec_DATA = cfgmgr_messages.py $(top_builddir)/src/lib/python/config_messages.py
pythondir = $(pyexecdir)/isc/config
# Define rule to build logging source files from message file
cfgmgr_messages.py: cfgmgr_messages.mes
- $(top_builddir)/src/lib/log/compiler/message -p $(top_srcdir)/src/lib/python/isc/config/cfgmgr_messages.mes
+ $(top_builddir)/src/lib/log/compiler/message \
+ -p $(top_srcdir)/src/lib/python/isc/config/cfgmgr_messages.mes
-CLEANFILES = cfgmgr_messages.py cfgmgr_messages.pyc
+$(top_builddir)/src/lib/python/config_messages.py: config_messages.mes
+ $(top_builddir)/src/lib/log/compiler/message \
+ -p -d $(top_builddir)/src/lib/python \
+ $(top_srcdir)/src/lib/python/isc/config/config_messages.mes
+
+CLEANFILES = cfgmgr_messages.py cfgmgr_messages.pyc
+CLEANFILES += $(top_builddir)/src/lib/python/config_messages.py
+CLEANFILES += $(top_builddir)/src/lib/python/config_messages.pyc
CLEANDIRS = __pycache__
-EXTRA_DIST = cfgmgr_messages.mes
+EXTRA_DIST = cfgmgr_messages.mes config_messages.mes
clean-local:
rm -rf $(CLEANDIRS)
diff --git a/src/lib/python/isc/config/ccsession.py b/src/lib/python/isc/config/ccsession.py
index bff4f58..8bf7d33 100644
--- a/src/lib/python/isc/config/ccsession.py
+++ b/src/lib/python/isc/config/ccsession.py
@@ -43,6 +43,9 @@ from isc.util.file import path_search
import bind10_config
from isc.log import log_config_update
import json
+from config_messages import *
+
+logger = isc.log.Logger("config")
class ModuleCCSessionError(Exception): pass
@@ -127,10 +130,7 @@ def default_logconfig_handler(new_config, config_data):
isc.log.log_config_update(json.dumps(new_config),
json.dumps(config_data.get_module_spec().get_full_spec()))
else:
- # no logging here yet, TODO: log these errors
- print("Error in logging configuration, ignoring config update: ")
- for err in errors:
- print(err)
+ logger.error(CONFIG_LOG_CONFIG_ERRORS, errors)
class ModuleCCSession(ConfigData):
"""This class maintains a connection to the command channel, as
@@ -385,8 +385,7 @@ class ModuleCCSession(ConfigData):
"Wrong data in configuration: " +
" ".join(errors))
else:
- # log error
- print("[" + self._module_name + "] Error requesting configuration: " + value)
+ logger.error(CONFIG_GET_FAILED, value)
else:
raise ModuleCCSessionError("No answer from configuration manager")
except isc.cc.SessionTimeout:
@@ -498,7 +497,6 @@ class UIModuleCCSession(MultiConfigData):
self.request_current_config()
self.clear_local_changes()
elif "error" in answer:
- print("Error: " + answer["error"])
- print("Configuration not committed")
+ raise ModuleCCSessionError("Error: " + str(answer["error"]) + "\n" + "Configuration not committed")
else:
raise ModuleCCSessionError("Unknown format of answer in commit(): " + str(answer))
diff --git a/src/lib/python/isc/config/config_messages.mes b/src/lib/python/isc/config/config_messages.mes
new file mode 100644
index 0000000..c52efb4
--- /dev/null
+++ b/src/lib/python/isc/config/config_messages.mes
@@ -0,0 +1,33 @@
+# Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+#
+# Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS. IN NO EVENT SHALL ISC 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.
+
+# No namespace declaration - these constants go in the global namespace
+# of the config_messages python module.
+
+# since these messages are for the python config library, care must
+# be taken that names do not conflict with the messages from the c++
+# config library. A checker script should verify that, but we do not
+# 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
+
+% CONFIG_LOG_CONFIG_ERRORS error(s) in logging configuration: %1
+There was a logging configuration update, but the internal validator
+for logging configuration found that it contained errors. The errors
+are shown, and the update is ignored.
+
+% CONFIG_GET_FAILED error getting configuration from cfgmgr: %1
+The configuration manager returned an error response when the module
+requested its configuration. The full error message answer from the
+configuration manager is appended to the log error.
+
diff --git a/src/lib/python/isc/config/tests/ccsession_test.py b/src/lib/python/isc/config/tests/ccsession_test.py
index 830cbd7..5d09c96 100644
--- a/src/lib/python/isc/config/tests/ccsession_test.py
+++ b/src/lib/python/isc/config/tests/ccsession_test.py
@@ -23,6 +23,7 @@ from isc.config.ccsession import *
from isc.config.config_data import BIND10_CONFIG_DATA_VERSION
from unittest_fakesession import FakeModuleCCSession, WouldBlockForever
import bind10_config
+import isc.log
class TestHelperFunctions(unittest.TestCase):
def test_parse_answer(self):
@@ -739,5 +740,6 @@ class TestUIModuleCCSession(unittest.TestCase):
uccs.commit()
if __name__ == '__main__':
+ isc.log.init("bind10")
unittest.main()
diff --git a/src/lib/python/isc/notify/Makefile.am b/src/lib/python/isc/notify/Makefile.am
index 4081a17..a23a1ff 100644
--- a/src/lib/python/isc/notify/Makefile.am
+++ b/src/lib/python/isc/notify/Makefile.am
@@ -1,9 +1,20 @@
SUBDIRS = . tests
python_PYTHON = __init__.py notify_out.py
+pyexec_DATA = $(top_builddir)/src/lib/python/notify_out_messages.py
pythondir = $(pyexecdir)/isc/notify
+$(top_builddir)/src/lib/python/notify_out_messages.py: notify_out_messages.mes
+ $(top_builddir)/src/lib/log/compiler/message \
+ -p -d $(top_builddir)/src/lib/python \
+ $(top_srcdir)/src/lib/python/isc/notify/notify_out_messages.mes
+
+EXTRA_DIST = notify_out_messages.mes
+
+CLEANFILES = $(top_builddir)/src/lib/python/notify_out_messages.pyc
+CLEANFILES += $(top_builddir)/src/lib/python/notify_out_messages.py
+
CLEANDIRS = __pycache__
clean-local:
diff --git a/src/lib/python/isc/notify/notify_out.py b/src/lib/python/isc/notify/notify_out.py
index 4b25463..f1e02ca 100644
--- a/src/lib/python/isc/notify/notify_out.py
+++ b/src/lib/python/isc/notify/notify_out.py
@@ -23,11 +23,15 @@ import errno
from isc.datasrc import sqlite3_ds
from isc.net import addr
import isc
-try:
- from pydnspp import *
-except ImportError as e:
- # C++ loadable module may not be installed;
- sys.stderr.write('[b10-xfrout] failed to import DNS or XFR module: %s\n' % str(e))
+from notify_out_messages import *
+
+logger = isc.log.Logger("notify_out")
+
+# there used to be a printed message if this import failed, but if
+# we can't import we should not start anyway, and logging an error
+# is a bad idea since the logging system is most likely not
+# initialized yet. see trac ticket #1103
+from pydnspp import *
ZONE_NEW_DATA_READY_CMD = 'zone_new_data_ready'
_MAX_NOTIFY_NUM = 30
@@ -46,9 +50,6 @@ _BAD_QR = 4
_BAD_REPLY_PACKET = 5
SOCK_DATA = b's'
-def addr_to_str(addr):
- return '%s#%s' % (addr[0], addr[1])
-
class ZoneNotifyInfo:
'''This class keeps track of notify-out information for one zone.'''
@@ -105,11 +106,10 @@ class NotifyOut:
notify message to its slaves). notify service can be started by
calling dispatcher(), and it can be stoped by calling shutdown()
in another thread. '''
- def __init__(self, datasrc_file, log=None, verbose=True):
+ def __init__(self, datasrc_file, verbose=True):
self._notify_infos = {} # key is (zone_name, zone_class)
self._waiting_zones = []
self._notifying_zones = []
- self._log = log
self._serving = False
self._read_sock, self._write_sock = socket.socketpair()
self._read_sock.setblocking(False)
@@ -362,18 +362,19 @@ class NotifyOut:
tgt = zone_notify_info.get_current_notify_target()
if event_type == _EVENT_READ:
reply = self._get_notify_reply(zone_notify_info.get_socket(), tgt)
- if reply:
- if self._handle_notify_reply(zone_notify_info, reply):
+ if reply is not None:
+ if self._handle_notify_reply(zone_notify_info, reply, tgt):
self._notify_next_target(zone_notify_info)
elif event_type == _EVENT_TIMEOUT and zone_notify_info.notify_try_num > 0:
- self._log_msg('info', 'notify retry to %s' % addr_to_str(tgt))
+ logger.info(NOTIFY_OUT_TIMEOUT, tgt[0], tgt[1])
tgt = zone_notify_info.get_current_notify_target()
if tgt:
zone_notify_info.notify_try_num += 1
if zone_notify_info.notify_try_num > _MAX_NOTIFY_TRY_NUM:
- self._log_msg('info', 'notify to %s: retried exceeded' % addr_to_str(tgt))
+ logger.warn(NOTIFY_OUT_RETRY_EXCEEDED, tgt[0], tgt[1],
+ _MAX_NOTIFY_TRY_NUM)
self._notify_next_target(zone_notify_info)
else:
# set exponential backoff according rfc1996 section 3.6
@@ -412,10 +413,15 @@ class NotifyOut:
try:
sock = zone_notify_info.create_socket(addrinfo[0])
sock.sendto(render.get_data(), 0, addrinfo)
- self._log_msg('info', 'sending notify to %s' % addr_to_str(addrinfo))
+ logger.info(NOTIFY_OUT_SENDING_NOTIFY, addrinfo[0],
+ addrinfo[1])
except (socket.error, addr.InvalidAddress) as err:
- self._log_msg('error', 'send notify to %s failed: %s' %
- (addr_to_str(addrinfo), str(err)))
+ logger.error(NOTIFY_OUT_SOCKET_ERROR, addrinfo[0],
+ addrinfo[1], err)
+ return False
+ except addr.InvalidAddress as iae:
+ logger.error(NOTIFY_OUT_INVALID_ADDRESS, addrinfo[0],
+ addrinfo[1], iae)
return False
return True
@@ -446,34 +452,38 @@ class NotifyOut:
msg.add_rrset(Message.SECTION_ANSWER, rrset_soa)
return msg, qid
- def _handle_notify_reply(self, zone_notify_info, msg_data):
+ def _handle_notify_reply(self, zone_notify_info, msg_data, from_addr):
'''Parse the notify reply message.
- TODO, the error message should be refined properly.
rcode will not checked here, If we get the response
from the slave, it means the slaves has got the notify.'''
msg = Message(Message.PARSE)
try:
- errstr = 'notify reply error: '
msg.from_wire(msg_data)
if not msg.get_header_flag(Message.HEADERFLAG_QR):
- self._log_msg('error', errstr + 'bad flags')
+ logger.warn(NOTIFY_OUT_REPLY_QR_NOT_SET, from_addr[0],
+ from_addr[1])
return _BAD_QR
if msg.get_qid() != zone_notify_info.notify_msg_id:
- self._log_msg('error', errstr + 'bad query ID')
+ logger.warn(NOTIFY_OUT_REPLY_BAD_QID, from_addr[0],
+ from_addr[1], msg.get_qid(),
+ zone_notify_info.notify_msg_id)
return _BAD_QUERY_ID
question = msg.get_question()[0]
if question.get_name() != Name(zone_notify_info.zone_name):
- self._log_msg('error', errstr + 'bad query name')
+ logger.warn(NOTIFY_OUT_REPLY_BAD_QUERY_NAME, from_addr[0],
+ from_addr[1], question.get_name().to_text(),
+ Name(zone_notify_info.zone_name).to_text())
return _BAD_QUERY_NAME
if msg.get_opcode() != Opcode.NOTIFY():
- self._log_msg('error', errstr + 'bad opcode')
+ logger.warn(NOTIFY_OUT_REPLY_BAD_OPCODE, from_addr[0],
+ from_addr[1], msg.get_opcode().to_text())
return _BAD_OPCODE
except Exception as err:
# We don't care what exception, just report it?
- self._log_msg('error', errstr + str(err))
+ logger.error(NOTIFY_OUT_REPLY_UNCAUGHT_EXCEPTION, err)
return _BAD_REPLY_PACKET
return _REPLY_OK
@@ -481,14 +491,9 @@ class NotifyOut:
def _get_notify_reply(self, sock, tgt_addr):
try:
msg, addr = sock.recvfrom(512)
- except socket.error:
- self._log_msg('error', "notify to %s failed: can't read notify reply" % addr_to_str(tgt_addr))
+ except socket.error as err:
+ logger.error(NOTIFY_OUT_SOCKET_RECV_ERROR, tgt_addr[0],
+ tgt_addr[1], err)
return None
return msg
-
-
- def _log_msg(self, level, msg):
- if self._log:
- self._log.log_message(level, msg)
-
diff --git a/src/lib/python/isc/notify/notify_out_messages.mes b/src/lib/python/isc/notify/notify_out_messages.mes
new file mode 100644
index 0000000..f9de744
--- /dev/null
+++ b/src/lib/python/isc/notify/notify_out_messages.mes
@@ -0,0 +1,83 @@
+# Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
+#
+# Permission to use, copy, modify, and/or 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 ISC DISCLAIMS ALL WARRANTIES WITH
+# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+# AND FITNESS. IN NO EVENT SHALL ISC 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.
+
+# No namespace declaration - these constants go in the global namespace
+# of the notify_out_messages python module.
+
+% NOTIFY_OUT_INVALID_ADDRESS invalid address %1#%2: %3
+The notify_out library tried to send a notify message to the given
+address, but it appears to be an invalid address. The configuration
+for secondary nameservers might contain a typographic error, or a
+different BIND 10 module has forgotten to validate its data before
+sending this module a notify command. As such, this should normally
+not happen, and points to an oversight in a different module.
+
+% NOTIFY_OUT_REPLY_BAD_OPCODE bad opcode in notify reply from %1#%2: %3
+The notify_out library sent a notify message to the nameserver at
+the given address, but the response did not have the opcode set to
+NOTIFY. The opcode in the response is printed. Since there was a
+response, no more notifies will be sent to this server for this
+notification event.
+
+% NOTIFY_OUT_REPLY_BAD_QID bad QID in notify reply from %1#%2: got %3, should be %4
+The notify_out library sent a notify message to the nameserver at
+the given address, but the query id in the response does not match
+the one we sent. Since there was a response, no more notifies will
+be sent to this server for this notification event.
+
+% NOTIFY_OUT_REPLY_BAD_QUERY_NAME bad query name in notify reply from %1#%2: got %3, should be %4
+The notify_out library sent a notify message to the nameserver at
+the given address, but the query name in the response does not match
+the one we sent. Since there was a response, no more notifies will
+be sent to this server for this notification event.
+
+% NOTIFY_OUT_REPLY_QR_NOT_SET QR flags set to 0 in reply to notify from %1#%2
+The notify_out library sent a notify message to the namesever at the
+given address, but the reply did not have the QR bit set to one.
+Since there was a response, no more notifies will be sent to this
+server for this notification event.
+
+% NOTIFY_OUT_RETRY_EXCEEDED notify to %1#%2: number of retries (%3) exceeded
+The maximum number of retries for the notify target has been exceeded.
+Either the address of the secondary nameserver is wrong, or it is not
+responding.
+
+% NOTIFY_OUT_SENDING_NOTIFY sending notify to %1#%2
+A notify message is sent to the secondary nameserver at the given
+address.
+
+% NOTIFY_OUT_SOCKET_ERROR socket error sending notify to %1#%2: %3
+There was a network error while trying to send a notify message to
+the given address. The address might be unreachable. The socket
+error is printed and should provide more information.
+
+% NOTIFY_OUT_SOCKET_RECV_ERROR socket error reading notify reply from %1#%2: %3
+There was a network error while trying to read a notify reply
+message from the given address. The socket error is printed and should
+provide more information.
+
+% NOTIFY_OUT_TIMEOUT retry notify to %1#%2
+The notify message to the given address (noted as address#port) has
+timed out, and the message will be resent until the max retry limit
+is reached.
+
+% NOTIFY_OUT_REPLY_UNCAUGHT_EXCEPTION uncaught exception: %1
+There was an uncaught exception in the handling of a notify reply
+message, either in the message parser, or while trying to extract data
+from the parsed message. The error is printed, and notify_out will
+treat the response as a bad message, but this does point to a
+programming error, since all exceptions should have been caught
+explicitely. Please file a bug report. Since there was a response,
+no more notifies will be sent to this server for this notification
+event.
diff --git a/src/lib/python/isc/notify/tests/notify_out_test.py b/src/lib/python/isc/notify/tests/notify_out_test.py
index 0eb77a3..83f6d1a 100644
--- a/src/lib/python/isc/notify/tests/notify_out_test.py
+++ b/src/lib/python/isc/notify/tests/notify_out_test.py
@@ -21,6 +21,7 @@ import time
import socket
from isc.datasrc import sqlite3_ds
from isc.notify import notify_out, SOCK_DATA
+import isc.log
# our fake socket, where we can read and insert messages
class MockSocket():
@@ -79,7 +80,6 @@ class TestZoneNotifyInfo(unittest.TestCase):
self.info.prepare_notify_out()
self.assertEqual(self.info.get_current_notify_target(), ('127.0.0.1', 53))
- self.assertEqual('127.0.0.1#53', notify_out.addr_to_str(('127.0.0.1', 53)))
self.info.set_next_notify_target()
self.assertEqual(self.info.get_current_notify_target(), ('1.1.1.1', 5353))
self.info.set_next_notify_target()
@@ -223,29 +223,30 @@ class TestNotifyOut(unittest.TestCase):
self.assertEqual(0, len(self._notify._waiting_zones))
def test_handle_notify_reply(self):
- self.assertEqual(notify_out._BAD_REPLY_PACKET, self._notify._handle_notify_reply(None, b'badmsg'))
+ fake_address = ('192.0.2.1', 53)
+ self.assertEqual(notify_out._BAD_REPLY_PACKET, self._notify._handle_notify_reply(None, b'badmsg', fake_address))
example_com_info = self._notify._notify_infos[('example.com.', 'IN')]
example_com_info.notify_msg_id = 0X2f18
# test with right notify reply message
data = b'\x2f\x18\xa0\x00\x00\x01\x00\x00\x00\x00\x00\x00\x07example\03com\x00\x00\x06\x00\x01'
- self.assertEqual(notify_out._REPLY_OK, self._notify._handle_notify_reply(example_com_info, data))
+ self.assertEqual(notify_out._REPLY_OK, self._notify._handle_notify_reply(example_com_info, data, fake_address))
# test with unright query id
data = b'\x2e\x18\xa0\x00\x00\x01\x00\x00\x00\x00\x00\x00\x07example\03com\x00\x00\x06\x00\x01'
- self.assertEqual(notify_out._BAD_QUERY_ID, self._notify._handle_notify_reply(example_com_info, data))
+ self.assertEqual(notify_out._BAD_QUERY_ID, self._notify._handle_notify_reply(example_com_info, data, fake_address))
# test with unright query name
data = b'\x2f\x18\xa0\x00\x00\x01\x00\x00\x00\x00\x00\x00\x07example\03net\x00\x00\x06\x00\x01'
- self.assertEqual(notify_out._BAD_QUERY_NAME, self._notify._handle_notify_reply(example_com_info, data))
+ self.assertEqual(notify_out._BAD_QUERY_NAME, self._notify._handle_notify_reply(example_com_info, data, fake_address))
# test with unright opcode
data = b'\x2f\x18\x80\x00\x00\x01\x00\x00\x00\x00\x00\x00\x07example\03com\x00\x00\x06\x00\x01'
- self.assertEqual(notify_out._BAD_OPCODE, self._notify._handle_notify_reply(example_com_info, data))
+ self.assertEqual(notify_out._BAD_OPCODE, self._notify._handle_notify_reply(example_com_info, data, fake_address))
# test with unright qr
data = b'\x2f\x18\x10\x10\x00\x01\x00\x00\x00\x00\x00\x00\x07example\03com\x00\x00\x06\x00\x01'
- self.assertEqual(notify_out._BAD_QR, self._notify._handle_notify_reply(example_com_info, data))
+ self.assertEqual(notify_out._BAD_QR, self._notify._handle_notify_reply(example_com_info, data, fake_address))
def test_send_notify_message_udp_ipv4(self):
example_com_info = self._notify._notify_infos[('example.net.', 'IN')]
@@ -300,6 +301,15 @@ class TestNotifyOut(unittest.TestCase):
self._notify._zone_notify_handler(example_net_info, notify_out._EVENT_NONE)
self.assertNotEqual(cur_tgt, example_net_info._notify_current)
+ cur_tgt = example_net_info._notify_current
+ example_net_info.create_socket('127.0.0.1')
+ # dns message, will result in bad_qid, but what we are testing
+ # here is whether handle_notify_reply is called correctly
+ example_net_info._sock.remote_end().send(b'\x2f\x18\xa0\x00\x00\x01\x00\x00\x00\x00\x00\x00\x07example\03com\x00\x00\x06\x00\x01')
+ self._notify._zone_notify_handler(example_net_info, notify_out._EVENT_READ)
+ self.assertNotEqual(cur_tgt, example_net_info._notify_current)
+
+
def _example_net_data_reader(self):
zone_data = [
('example.net.', '1000', 'IN', 'SOA', 'a.dns.example.net. mail.example.net. 1 1 1 1 1'),
@@ -406,6 +416,7 @@ class TestNotifyOut(unittest.TestCase):
self.assertFalse(thread.is_alive())
if __name__== "__main__":
+ isc.log.init("bind10")
unittest.main()
diff --git a/src/lib/util/filename.cc b/src/lib/util/filename.cc
index 1f2e5db..d7da9c8 100644
--- a/src/lib/util/filename.cc
+++ b/src/lib/util/filename.cc
@@ -132,6 +132,24 @@ Filename::useAsDefault(const string& name) const {
return (retstring);
}
+void
+Filename::setDirectory(const std::string& new_directory) {
+ std::string directory(new_directory);
+
+ if (directory.length() > 0) {
+ // append '/' if necessary
+ size_t sep = directory.rfind('/');
+ if (sep == std::string::npos || sep < directory.size() - 1) {
+ directory += "/";
+ }
+ }
+ // and regenerate the full name
+ std::string full_name = directory + name_ + extension_;
+
+ directory_.swap(directory);
+ full_name_.swap(full_name);
+}
+
} // namespace log
} // namespace isc
diff --git a/src/lib/util/filename.h b/src/lib/util/filename.h
index 984ecb0..c9874ce 100644
--- a/src/lib/util/filename.h
+++ b/src/lib/util/filename.h
@@ -86,6 +86,13 @@ public:
return (directory_);
}
+ /// \brief Set directory for the file
+ ///
+ /// \param new_directory The directory to set. If this is an empty
+ /// string, the directory this filename object currently
+ /// has will be removed.
+ void setDirectory(const std::string& new_directory);
+
/// \return Name of Given File Name
std::string name() const {
return (name_);
diff --git a/src/lib/util/tests/filename_unittest.cc b/src/lib/util/tests/filename_unittest.cc
index 33e6456..be29ff1 100644
--- a/src/lib/util/tests/filename_unittest.cc
+++ b/src/lib/util/tests/filename_unittest.cc
@@ -177,3 +177,40 @@ TEST_F(FilenameTest, UseAsDefault) {
EXPECT_EQ("/s/t/u", fname.useAsDefault("/s/t/u"));
EXPECT_EQ("/a/b/c", fname.useAsDefault(""));
}
+
+TEST_F(FilenameTest, setDirectory) {
+ Filename fname("a.b");
+ EXPECT_EQ("", fname.directory());
+ EXPECT_EQ("a.b", fname.fullName());
+ EXPECT_EQ("a.b", fname.expandWithDefault(""));
+
+ fname.setDirectory("/just/some/dir/");
+ EXPECT_EQ("/just/some/dir/", fname.directory());
+ EXPECT_EQ("/just/some/dir/a.b", fname.fullName());
+ EXPECT_EQ("/just/some/dir/a.b", fname.expandWithDefault(""));
+
+ fname.setDirectory("/just/some/dir");
+ EXPECT_EQ("/just/some/dir/", fname.directory());
+ EXPECT_EQ("/just/some/dir/a.b", fname.fullName());
+ EXPECT_EQ("/just/some/dir/a.b", fname.expandWithDefault(""));
+
+ fname.setDirectory("/");
+ EXPECT_EQ("/", fname.directory());
+ EXPECT_EQ("/a.b", fname.fullName());
+ EXPECT_EQ("/a.b", fname.expandWithDefault(""));
+
+ fname.setDirectory("");
+ EXPECT_EQ("", fname.directory());
+ EXPECT_EQ("a.b", fname.fullName());
+ EXPECT_EQ("a.b", fname.expandWithDefault(""));
+
+ fname = Filename("/first/a.b");
+ EXPECT_EQ("/first/", fname.directory());
+ EXPECT_EQ("/first/a.b", fname.fullName());
+ EXPECT_EQ("/first/a.b", fname.expandWithDefault(""));
+
+ fname.setDirectory("/just/some/dir");
+ EXPECT_EQ("/just/some/dir/", fname.directory());
+ EXPECT_EQ("/just/some/dir/a.b", fname.fullName());
+ EXPECT_EQ("/just/some/dir/a.b", fname.expandWithDefault(""));
+}
More information about the bind10-changes
mailing list