BIND10 shmemfix, updated. e34a4199a18deb3dc51d27efb4561a30fd1d533a [shmemfix] removed now-unused imports.
BIND 10 source code commits
bind10-changes at lists.isc.org
Thu Apr 17 16:09:36 UTC 2014
The branch, shmemfix has been updated
via e34a4199a18deb3dc51d27efb4561a30fd1d533a (commit)
via ce6e96bb7776c84c8d546c50ae51023a585cace7 (commit)
via b944f266662db1591f71b8fe7e550fba3108a5d9 (commit)
from e0b3dd07237f4f04b8cdfb45a1611d20740f111e (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 e34a4199a18deb3dc51d27efb4561a30fd1d533a
Author: JINMEI Tatuya <jinmei at isc.org>
Date: Wed Apr 16 23:30:21 2014 -0700
[shmemfix] removed now-unused imports.
commit ce6e96bb7776c84c8d546c50ae51023a585cace7
Author: JINMEI Tatuya <jinmei at isc.org>
Date: Wed Apr 16 23:27:57 2014 -0700
[shmemfix] use notification to notify auth
commit b944f266662db1591f71b8fe7e550fba3108a5d9
Author: JINMEI Tatuya <jinmei at isc.org>
Date: Wed Apr 16 23:24:01 2014 -0700
[shmemfix] handle zone_updated notification in b10-auth.
also, in this case quitely ignore non-writable in-memory cache.
-----------------------------------------------------------------------
Summary of changes:
src/bin/auth/auth_messages.mes | 13 ++
src/bin/auth/auth_srv.cc | 18 +++
src/bin/auth/auth_srv.h | 8 +
src/bin/auth/datasrc_clients_mgr.h | 154 +++++++++++++-------
src/bin/auth/main.cc | 4 +
.../auth/tests/datasrc_clients_builder_unittest.cc | 93 +++++++++---
src/bin/auth/tests/datasrc_clients_mgr_unittest.cc | 63 ++++++--
src/bin/ddns/ddns.py.in | 9 --
src/bin/ddns/tests/ddns_test.py | 21 +--
9 files changed, 272 insertions(+), 111 deletions(-)
-----------------------------------------------------------------------
diff --git a/src/bin/auth/auth_messages.mes b/src/bin/auth/auth_messages.mes
index 5009de8..fe3d77a 100644
--- a/src/bin/auth/auth_messages.mes
+++ b/src/bin/auth/auth_messages.mes
@@ -304,6 +304,10 @@ process the message further, and returns a response with the Rcode being
NOTAUTH. Note: RFC 1996 does not specify the server behavior in this case;
responding with Rcode of NOTAUTH follows BIND 9's behavior.
+% AUTH_RECEIVED_ZONE_UPDATED received zone_updated notification
+A debug message. b10-auth received a notification for a zone update from
+other module.
+
% AUTH_RESPONSE_FAILURE exception while building response to query: %1
This is a debug message, generated by the authoritative server when an
attempt to create a response to a received DNS packet has failed. The
@@ -432,3 +436,12 @@ worth filing a bug report). In any case, the authoritative server
simply drops the NOTIFY message; if it's a temporary failure or
delayed startup, subsequently resent messages will eventually reach
Zonemgr.
+
+% AUTH_ZONE_UPDATE_FAIL failed to perform zone_updated notification: %1
+b10-auth received a notification for a zone update from other module,
+but failed to perform it. This generally means a bug of the sender module.
+
+% AUTH_ZONE_UPDATE_UNKNOWN unknown notification: %1
+b10-auth received a notification that is supposed to be of zone update,
+but the notification name was known. This generally means a bug of the sender
+module.
diff --git a/src/bin/auth/auth_srv.cc b/src/bin/auth/auth_srv.cc
index 9b85c43..f3afa0b 100644
--- a/src/bin/auth/auth_srv.cc
+++ b/src/bin/auth/auth_srv.cc
@@ -941,6 +941,24 @@ hasMappedSegment(auth::DataSrcClientsMgr& mgr) {
}
void
+AuthSrv::zoneUpdated(const std::string& event_name,
+ const ConstElementPtr& params)
+{
+ if (event_name == "zone_updated") {
+ LOG_DEBUG(auth_logger, DBG_AUTH_OPS, AUTH_RECEIVED_ZONE_UPDATED);
+ try {
+ impl_->datasrc_clients_mgr_.updateZone(params);
+ } catch (const isc::Exception& ex) {
+ // notify handler seems to assume exception free, so we catch
+ // almost everything and log it.
+ LOG_ERROR(auth_logger, AUTH_ZONE_UPDATE_FAIL).arg(ex.what());
+ }
+ } else {
+ LOG_ERROR(auth_logger, AUTH_ZONE_UPDATE_UNKNOWN).arg(event_name);
+ }
+}
+
+void
AuthSrv::listsReconfigured() {
const bool has_remote = hasMappedSegment(impl_->datasrc_clients_mgr_);
if (has_remote && !impl_->readers_group_subscribed_) {
diff --git a/src/bin/auth/auth_srv.h b/src/bin/auth/auth_srv.h
index 02d8798..77b5baf 100644
--- a/src/bin/auth/auth_srv.h
+++ b/src/bin/auth/auth_srv.h
@@ -280,6 +280,14 @@ public:
/// memory manager for segments, if some are remotely mapped.
void listsReconfigured();
+ /// \brief Notification callback for zone updates.
+ ///
+ /// \param event_name Should be "zone_updated"
+ /// \param params parameters for the zone_updated notification, consisting
+ /// of origin, (RR) class, and data source name.
+ void zoneUpdated(const std::string& event_name,
+ const isc::data::ConstElementPtr& params);
+
private:
void reconfigureDone(isc::data::ConstElementPtr request);
void foreignCommand(const std::string& command, const std::string&,
diff --git a/src/bin/auth/datasrc_clients_mgr.h b/src/bin/auth/datasrc_clients_mgr.h
index c6eed31..23fc2bb 100644
--- a/src/bin/auth/datasrc_clients_mgr.h
+++ b/src/bin/auth/datasrc_clients_mgr.h
@@ -81,6 +81,13 @@ enum CommandID {
LOADZONE, ///< Load a new version of zone into a memory,
/// the argument to the command is a map containing 'class'
/// and 'origin' elements, both should have been validated.
+ UPDATEZONE, ///< Similar to LOADZONE, but is intended to be used for
+ /// internal notification from other modules. It takes
+ /// specific data source name where the updated zone is
+ /// expected to belong. It also silently ignores the command
+ /// if the underlying memory segment is not writable
+ /// (implicitly assuming it's shared-memory based and is
+ /// updated by another module).
SEGMENT_INFO_UPDATE, ///< The memory manager sent an update about segments.
SHUTDOWN, ///< Shutdown the builder; no argument
NUM_COMMANDS
@@ -357,47 +364,13 @@ public:
const datasrc_clientmgr_internal::FinishedCallback& callback =
datasrc_clientmgr_internal::FinishedCallback())
{
- if (!args) {
- isc_throw(CommandError, "loadZone argument empty");
- }
- if (args->getType() != isc::data::Element::map) {
- isc_throw(CommandError, "loadZone argument not a map");
- }
- if (!args->contains("origin")) {
- isc_throw(CommandError,
- "loadZone argument has no 'origin' value");
- }
- // Also check if it really is a valid name
- try {
- dns::Name(args->get("origin")->stringValue());
- } catch (const isc::Exception& exc) {
- isc_throw(CommandError, "bad origin: " << exc.what());
- }
-
- if (args->get("origin")->getType() != data::Element::string) {
- isc_throw(CommandError,
- "loadZone argument 'origin' value not a string");
- }
- if (args->contains("class")) {
- if (args->get("class")->getType() != data::Element::string) {
- isc_throw(CommandError,
- "loadZone argument 'class' value not a string");
- }
- // Also check if it is a valid class
- try {
- dns::RRClass(args->get("class")->stringValue());
- } catch (const isc::Exception& exc) {
- isc_throw(CommandError, "bad class: " << exc.what());
- }
- }
-
- // Note: we could do some more advanced checks here,
- // e.g. check if the zone is known at all in the configuration.
- // For now these are skipped, but one obvious way to
- // implement it would be to factor out the code from
- // the start of doLoadZone(), and call it here too
+ updateZoneInternal(datasrc_clientmgr_internal::LOADZONE, args,
+ callback);
+ }
- sendCommand(datasrc_clientmgr_internal::LOADZONE, args, callback);
+ void updateZone(const data::ConstElementPtr& args) {
+ updateZoneInternal(datasrc_clientmgr_internal::UPDATEZONE, args,
+ datasrc_clientmgr_internal::FinishedCallback());
}
void segmentInfoUpdate(const data::ConstElementPtr& args,
@@ -425,7 +398,6 @@ public:
}
}
-
sendCommand(datasrc_clientmgr_internal::SEGMENT_INFO_UPDATE, args,
callback);
}
@@ -437,6 +409,72 @@ private:
// state of the class.
void cleanup() {}
+ // Common handler for LOADZONE and UPDATEZONE.
+ void updateZoneInternal(datasrc_clientmgr_internal::CommandID command,
+ const data::ConstElementPtr& args,
+ const datasrc_clientmgr_internal::FinishedCallback&
+ callback)
+ {
+ const std::string& command_str =
+ (command == datasrc_clientmgr_internal::LOADZONE) ?
+ "loadZone" : "updateZone";
+
+ if (!args) {
+ isc_throw(CommandError, command_str + " argument empty");
+ }
+
+ if (args->getType() != isc::data::Element::map) {
+ isc_throw(CommandError, command_str + " argument not a map");
+ }
+ if (!args->contains("origin")) {
+ isc_throw(CommandError,
+ command_str + " argument has no 'origin' value");
+ }
+ // Also check if it really is a valid name
+ try {
+ dns::Name(args->get("origin")->stringValue());
+ } catch (const isc::Exception& exc) {
+ isc_throw(CommandError, "bad origin: " << exc.what());
+ }
+
+ if (args->get("origin")->getType() != data::Element::string) {
+ isc_throw(CommandError,
+ "loadZone argument 'origin' value not a string");
+ }
+ if (args->contains("class")) {
+ if (args->get("class")->getType() != data::Element::string) {
+ isc_throw(CommandError,
+ "loadZone argument 'class' value not a string");
+ }
+ // Also check if it is a valid class
+ try {
+ dns::RRClass(args->get("class")->stringValue());
+ } catch (const isc::Exception& exc) {
+ isc_throw(CommandError, "bad class: " << exc.what());
+ }
+ }
+ // If "datasource" is provided as a parameter, it must be a string.
+ // For UPDATEZONE, datasource must be specified.
+ if (args->contains("datasource")) {
+ if (args->get("datasource")->getType() !=
+ isc::data::Element::string)
+ {
+ isc_throw(CommandError,
+ "invalid type for datasource (must be string)");
+ }
+ } else if (command == datasrc_clientmgr_internal::UPDATEZONE) {
+ isc_throw(CommandError, "missing datasource for UPDATEZONE");
+ }
+
+ // Note: we could do some more advanced checks here,
+ // e.g. check if the zone is known at all in the configuration.
+ // For now these are skipped, but one obvious way to
+ // implement it would be to factor out the code from
+ // the start of doUpdateZone(), and call it here too
+
+ sendCommand(command, args, callback);
+ }
+
// same as cleanup(), for reconfigure().
void reconfigureHook() {}
@@ -664,10 +702,13 @@ private:
}
}
- void doLoadZone(const isc::data::ConstElementPtr& arg);
+ void doUpdateZone(datasrc_clientmgr_internal::CommandID command,
+ const isc::data::ConstElementPtr& arg);
boost::shared_ptr<datasrc::memory::ZoneWriter> getZoneWriter(
+ datasrc_clientmgr_internal::CommandID command,
datasrc::ConfigurableClientList& client_list,
- const dns::RRClass& rrclass, const dns::Name& origin);
+ const std::string& datasrc_name, const dns::RRClass& rrclass,
+ const dns::Name& origin);
// The following are shared with the manager
std::list<Command>* command_queue_;
@@ -763,7 +804,8 @@ DataSrcClientsBuilderBase<MutexType, CondVarType>::handleCommand(
}
const boost::array<const char*, NUM_COMMANDS> command_desc = {
- {"NOOP", "RECONFIGURE", "LOADZONE", "SEGMENT_INFO_UPDATE", "SHUTDOWN"}
+ {"NOOP", "RECONFIGURE", "LOADZONE", "UPDATEZONE", "SEGMENT_INFO_UPDATE",
+ "SHUTDOWN"}
};
LOG_DEBUG(auth_logger, DBGLVL_TRACE_BASIC,
AUTH_DATASRC_CLIENTS_BUILDER_COMMAND).arg(command_desc.at(cid));
@@ -772,7 +814,8 @@ DataSrcClientsBuilderBase<MutexType, CondVarType>::handleCommand(
doReconfigure(command.params);
break;
case LOADZONE:
- doLoadZone(command.params);
+ case UPDATEZONE: // need test
+ doUpdateZone(command.id, command.params);
break;
case SEGMENT_INFO_UPDATE:
doSegmentUpdate(command.params);
@@ -790,7 +833,8 @@ DataSrcClientsBuilderBase<MutexType, CondVarType>::handleCommand(
template <typename MutexType, typename CondVarType>
void
-DataSrcClientsBuilderBase<MutexType, CondVarType>::doLoadZone(
+DataSrcClientsBuilderBase<MutexType, CondVarType>::doUpdateZone(
+ datasrc_clientmgr_internal::CommandID command,
const isc::data::ConstElementPtr& arg)
{
// We assume some basic level validation as this method can only be
@@ -818,13 +862,17 @@ DataSrcClientsBuilderBase<MutexType, CondVarType>::doLoadZone(
"/" << rrclass << ": not configured for the class");
}
+ const isc::data::ConstElementPtr datasrc_name_elem = arg->get("datasource");
+ const std::string& datasrc_name = datasrc_name_elem ?
+ datasrc_name_elem->stringValue() : "";
+
boost::shared_ptr<datasrc::ConfigurableClientList> client_list =
found->second;
assert(client_list);
try {
boost::shared_ptr<datasrc::memory::ZoneWriter> zwriter =
- getZoneWriter(*client_list, rrclass, origin);
+ getZoneWriter(command, *client_list, datasrc_name, rrclass, origin);
if (!zwriter) {
return;
}
@@ -853,13 +901,15 @@ DataSrcClientsBuilderBase<MutexType, CondVarType>::doLoadZone(
}
}
-// A dedicated subroutine of doLoadZone(). Separated just for keeping the
+// A dedicated subroutine of doUpdateZone(). Separated just for keeping the
// main method concise.
template <typename MutexType, typename CondVarType>
boost::shared_ptr<datasrc::memory::ZoneWriter>
DataSrcClientsBuilderBase<MutexType, CondVarType>::getZoneWriter(
+ datasrc_clientmgr_internal::CommandID command,
datasrc::ConfigurableClientList& client_list,
- const dns::RRClass& rrclass, const dns::Name& origin)
+ const std::string& datasrc_name, const dns::RRClass& rrclass,
+ const dns::Name& origin)
{
// getCachedZoneWriter() could get access to an underlying data source
// that can cause a race condition with the main thread using that data
@@ -867,7 +917,8 @@ DataSrcClientsBuilderBase<MutexType, CondVarType>::getZoneWriter(
datasrc::ConfigurableClientList::ZoneWriterPair writerpair;
{
typename MutexType::Locker locker(*map_mutex_);
- writerpair = client_list.getCachedZoneWriter(origin, false);
+ writerpair = client_list.getCachedZoneWriter(origin, false,
+ datasrc_name);
}
switch (writerpair.first) {
@@ -884,6 +935,9 @@ DataSrcClientsBuilderBase<MutexType, CondVarType>::getZoneWriter(
.arg(origin).arg(rrclass);
break; // return NULL below
case datasrc::ConfigurableClientList::CACHE_NOT_WRITABLE:
+ if (command == UPDATEZONE) {
+ break;
+ }
// This is an internal error. Auth server should skip reloading zones
// on non writable caches.
isc_throw(InternalCommandError, "failed to load zone " << origin
diff --git a/src/bin/auth/main.cc b/src/bin/auth/main.cc
index d6b1119..66adba5 100644
--- a/src/bin/auth/main.cc
+++ b/src/bin/auth/main.cc
@@ -226,6 +226,10 @@ main(int argc, char* argv[]) {
isc::server_common::initKeyring(*config_session);
auth_server->setTSIGKeyRing(&isc::server_common::keyring);
+ config_session->subscribeNotification(
+ "ZoneUpdateListener",
+ boost::bind(&AuthSrv::zoneUpdated, auth_server, _1, _2));
+
// Start the data source configuration. We pass first_time and
// config_session for the hack described in datasrcConfigHandler.
bool first_time = true;
diff --git a/src/bin/auth/tests/datasrc_clients_builder_unittest.cc b/src/bin/auth/tests/datasrc_clients_builder_unittest.cc
index 0c085e1..554b2cc 100644
--- a/src/bin/auth/tests/datasrc_clients_builder_unittest.cc
+++ b/src/bin/auth/tests/datasrc_clients_builder_unittest.cc
@@ -76,6 +76,7 @@ protected:
}
void configureZones(); // used for loadzone related tests
+ void checkLoadOrUpdateZone(CommandID cmdid);
ClientListMapPtr clients_map; // configured clients
std::list<Command> command_queue; // test command queue
@@ -387,14 +388,9 @@ TEST_F(DataSrcClientsBuilderTest, loadZone) {
newZoneChecks(clients_map, rrclass);
}
-TEST_F(DataSrcClientsBuilderTest,
-#ifdef USE_STATIC_LINK
- DISABLED_loadZoneSQLite3
-#else
- loadZoneSQLite3
-#endif
- )
-{
+// Shared test for both LOADZONE and UPDATEZONE
+void
+DataSrcClientsBuilderTest::checkLoadOrUpdateZone(CommandID cmdid) {
// Prepare the database first
const std::string test_db = TEST_DATA_BUILDDIR "/auth_test.sqlite3.copied";
std::stringstream ss("example.org. 3600 IN SOA . . 0 0 0 0 0\n"
@@ -416,7 +412,7 @@ TEST_F(DataSrcClientsBuilderTest,
find(Name("example.org")).finder_->
find(Name("www.example.org"), RRType::A())->code);
- // Add the record to the underlying sqlite database, by loading
+ // Add the record to the underlying sqlite database, by loading/updating
// it as a separate datasource, and updating it
ConstElementPtr sql_cfg = Element::fromJSON("{ \"type\": \"sqlite3\","
"\"database_file\": \""
@@ -433,12 +429,12 @@ TEST_F(DataSrcClientsBuilderTest,
find(Name("example.org")).finder_->
find(Name("www.example.org"), RRType::A())->code);
- // Now send the command to reload it
- const Command loadzone_cmd(LOADZONE, Element::fromJSON(
- "{\"class\": \"IN\","
- " \"origin\": \"example.org\"}"),
- FinishedCallback());
- EXPECT_TRUE(builder.handleCommand(loadzone_cmd));
+ // Now send the command to reload/update it
+ const Command cmd(cmdid, Element::fromJSON(
+ "{\"class\": \"IN\","
+ " \"origin\": \"example.org\"}"),
+ FinishedCallback());
+ EXPECT_TRUE(builder.handleCommand(cmd));
// And now it should be present too.
EXPECT_EQ(ZoneFinder::SUCCESS,
clients_map->find(rrclass)->second->
@@ -446,7 +442,7 @@ TEST_F(DataSrcClientsBuilderTest,
find(Name("www.example.org"), RRType::A())->code);
// An error case: the zone has no configuration. (note .com here)
- const Command nozone_cmd(LOADZONE, Element::fromJSON(
+ const Command nozone_cmd(cmdid, Element::fromJSON(
"{\"class\": \"IN\","
" \"origin\": \"example.com\"}"),
FinishedCallback());
@@ -457,8 +453,8 @@ TEST_F(DataSrcClientsBuilderTest,
find(Name("example.org")).finder_->
find(Name("example.org"), RRType::SOA())->code);
- // attempt of reloading a zone but in-memory cache is disabled. In this
- // case the command is simply ignored.
+ // attempt of reloading/updating a zone but in-memory cache is disabled.
+ // In this case the command is simply ignored.
const size_t orig_lock_count = map_mutex.lock_count;
const size_t orig_unlock_count = map_mutex.unlock_count;
const ConstElementPtr config2(Element::fromJSON("{"
@@ -470,11 +466,11 @@ TEST_F(DataSrcClientsBuilderTest,
"}]}"));
clients_map = configureDataSource(config2);
builder.handleCommand(
- Command(LOADZONE, Element::fromJSON(
+ Command(cmdid, Element::fromJSON(
"{\"class\": \"IN\","
" \"origin\": \"example.org\"}"),
FinishedCallback()));
- // Only one mutex was needed because there was no actual reload.
+ // Only one mutex was needed because there was no actual reload/update.
EXPECT_EQ(orig_lock_count + 1, map_mutex.lock_count);
EXPECT_EQ(orig_unlock_count + 1, map_mutex.unlock_count);
@@ -489,7 +485,7 @@ TEST_F(DataSrcClientsBuilderTest,
clients_map = configureDataSource(config_nozone);
EXPECT_THROW(
builder.handleCommand(
- Command(LOADZONE, Element::fromJSON(
+ Command(cmdid, Element::fromJSON(
"{\"class\": \"IN\","
" \"origin\": \"nosuchzone.example\"}"),
FinishedCallback())),
@@ -510,13 +506,35 @@ TEST_F(DataSrcClientsBuilderTest,
"}]"), false); // false = disable cache
(*clients_map)[rrclass] = nocache_list;
EXPECT_THROW(builder.handleCommand(
- Command(LOADZONE, Element::fromJSON(
+ Command(cmdid, Element::fromJSON(
"{\"class\": \"IN\","
" \"origin\": \"example.org\"}"),
FinishedCallback())),
TestDataSrcClientsBuilder::InternalCommandError);
}
+TEST_F(DataSrcClientsBuilderTest,
+#ifdef USE_STATIC_LINK
+ DISABLED_loadZoneSQLite3
+#else
+ loadZoneSQLite3
+#endif
+ )
+{
+ checkLoadOrUpdateZone(LOADZONE);
+}
+
+TEST_F(DataSrcClientsBuilderTest,
+#ifdef USE_STATIC_LINK
+ DISABLED_updateZoneSQLite3
+#else
+ updateZoneSQLite3
+#endif
+ )
+{
+ checkLoadOrUpdateZone(UPDATEZONE);
+}
+
TEST_F(DataSrcClientsBuilderTest, loadBrokenZone) {
configureZones();
@@ -654,6 +672,37 @@ TEST_F(DataSrcClientsBuilderTest,
TestDataSrcClientsBuilder::InternalCommandError);
}
+// Similar to the previous case, but for UPDATEZLONE command. In this case,
+// non-writable cache isn't considered an error, and just ignored.
+TEST_F(DataSrcClientsBuilderTest,
+#ifdef USE_SHARED_MEMORY
+ updateInNonWritableCache
+#else
+ DISABLED_updateInNonWritableCache
+#endif
+ )
+{
+ const ConstElementPtr config = Element::fromJSON(
+ "{"
+ "\"IN\": [{"
+ " \"type\": \"MasterFiles\","
+ " \"params\": {"
+ " \"test1.example\": \"" +
+ std::string(TEST_DATA_BUILDDIR "/test1.zone.copied") + "\"},"
+ " \"cache-enable\": true,"
+ " \"cache-type\": \"mapped\""
+ "}]}");
+ clients_map = configureDataSource(config);
+
+ EXPECT_TRUE(builder.handleCommand(
+ Command(UPDATEZONE,
+ Element::fromJSON(
+ "{\"origin\": \"test1.example\","
+ " \"class\": \"IN\","
+ " \"datasource\": \"MasterFiles\"}"),
+ FinishedCallback())));
+}
+
// Test the SEGMENT_INFO_UPDATE command. This test is little bit
// indirect. It doesn't seem possible to fake the client list inside
// easily. So we create a real image to load and load it. Then we check
diff --git a/src/bin/auth/tests/datasrc_clients_mgr_unittest.cc b/src/bin/auth/tests/datasrc_clients_mgr_unittest.cc
index 565deb5..6abf062 100644
--- a/src/bin/auth/tests/datasrc_clients_mgr_unittest.cc
+++ b/src/bin/auth/tests/datasrc_clients_mgr_unittest.cc
@@ -26,6 +26,7 @@
#include <gtest/gtest.h>
#include <boost/function.hpp>
+#include <boost/bind.hpp>
using namespace isc::dns;
using namespace isc::data;
@@ -199,53 +200,89 @@ TEST(DataSrcClientsMgrTest, holder) {
EXPECT_THROW(TestDataSrcClientsMgr::Holder holder2(mgr), isc::Unexpected);
}
-TEST(DataSrcClientsMgrTest, reload) {
- TestDataSrcClientsMgr mgr;
+namespace {
+/* wrapper for hiding the optional argument for loadZone(). */
+void loadZoneWrapper(TestDataSrcClientsMgr* mgr, const ConstElementPtr& args) {
+ mgr->loadZone(args);
+}
+
+void checkLoadOrUpdateZone(boost::function<void(const ConstElementPtr& args)>
+ handler)
+{
EXPECT_TRUE(FakeDataSrcClientsBuilder::started);
EXPECT_TRUE(FakeDataSrcClientsBuilder::command_queue->empty());
+ // mutable, as it's overridden later in the test.
isc::data::ElementPtr args =
isc::data::Element::fromJSON("{ \"class\": \"IN\","
- " \"origin\": \"example.com\" }");
- mgr.loadZone(args);
+ " \"origin\": \"example.com\", "
+ " \"datasource\": \"testsrc\"}");
+ handler(args);
EXPECT_EQ(1, FakeDataSrcClientsBuilder::command_queue->size());
- mgr.loadZone(args);
+ handler(args);
EXPECT_EQ(2, FakeDataSrcClientsBuilder::command_queue->size());
// Should fail with non-string 'class' value
args->set("class", Element::create(1));
- EXPECT_THROW(mgr.loadZone(args), CommandError);
+ EXPECT_THROW(handler(args), CommandError);
EXPECT_EQ(2, FakeDataSrcClientsBuilder::command_queue->size());
// And with badclass
args->set("class", Element::create("BADCLASS"));
- EXPECT_THROW(mgr.loadZone(args), CommandError);
+ EXPECT_THROW(handler(args), CommandError);
EXPECT_EQ(2, FakeDataSrcClientsBuilder::command_queue->size());
// Should succeed without 'class'
args->remove("class");
- mgr.loadZone(args);
+ handler(args);
EXPECT_EQ(3, FakeDataSrcClientsBuilder::command_queue->size());
// but fail without origin, without sending new commands
args->remove("origin");
- EXPECT_THROW(mgr.loadZone(args), CommandError);
+ EXPECT_THROW(handler(args), CommandError);
EXPECT_EQ(3, FakeDataSrcClientsBuilder::command_queue->size());
// And for 'origin' that is not a string
args->set("origin", Element::create(1));
- EXPECT_THROW(mgr.loadZone(args), CommandError);
+ EXPECT_THROW(handler(args), CommandError);
EXPECT_EQ(3, FakeDataSrcClientsBuilder::command_queue->size());
// And origin that is not a correct name
args->set("origin", Element::create(".."));
- EXPECT_THROW(mgr.loadZone(args), CommandError);
+ EXPECT_THROW(handler(args), CommandError);
EXPECT_EQ(3, FakeDataSrcClientsBuilder::command_queue->size());
// same for empty data and data that is not a map
- EXPECT_THROW(mgr.loadZone(isc::data::ConstElementPtr()), CommandError);
- EXPECT_THROW(mgr.loadZone(isc::data::Element::createList()), CommandError);
+ EXPECT_THROW(handler(isc::data::ConstElementPtr()), CommandError);
+ EXPECT_THROW(handler(isc::data::Element::createList()), CommandError);
EXPECT_EQ(3, FakeDataSrcClientsBuilder::command_queue->size());
+
+ // "datasource" is provided but not a string
+ EXPECT_THROW(handler(isc::data::Element::fromJSON(
+ "{ \"origin\": \".\", \"datasource\": 42 }")),
+ CommandError);
+}
+}
+
+TEST(DataSrcClientsMgrTest, reload) {
+ TestDataSrcClientsMgr mgr;
+
+ checkLoadOrUpdateZone(boost::bind(loadZoneWrapper, &mgr, _1));
+
+ // For LOADZONE, datasource can be omitted.
+ const size_t orig_qlen = FakeDataSrcClientsBuilder::command_queue->size();
+ mgr.loadZone(isc::data::Element::fromJSON("{ \"origin\": \".\"}"));
+ EXPECT_EQ(orig_qlen + 1, FakeDataSrcClientsBuilder::command_queue->size());
+}
+
+TEST(DataSrcClientsMgrTest, updateZone) {
+ TestDataSrcClientsMgr mgr;
+
+ checkLoadOrUpdateZone(boost::bind(&TestDataSrcClientsMgr::updateZone, &mgr,
+ _1));
+ // UPDATEZONE requires datasource be specified.
+ EXPECT_THROW(mgr.updateZone(isc::data::Element::fromJSON(
+ "{ \"origin\": \".\"}")), CommandError);
}
TEST(DataSrcClientsMgrTest, segmentUpdate) {
diff --git a/src/bin/ddns/ddns.py.in b/src/bin/ddns/ddns.py.in
index a09f011..d22c0c7 100755
--- a/src/bin/ddns/ddns.py.in
+++ b/src/bin/ddns/ddns.py.in
@@ -35,8 +35,6 @@ from isc.server_common.dns_tcp import DNSTCPContext
from isc.server_common.datasrc_clients_mgr \
import DataSrcClientsMgr, ConfigError
from isc.datasrc import DataSourceClient
-from isc.server_common.auth_command import AUTH_LOADZONE_COMMAND, \
- auth_loadzone_params
import select
import time
import errno
@@ -460,7 +458,6 @@ class DDNSServer:
{ 'datasource': datasrc_name,
'origin': str(zname),
'class': str(zclass) })
- self.__notify_auth(zname, zclass)
self.__notify_xfrout(zname, zclass)
return ret
@@ -522,12 +519,6 @@ class DDNSServer:
except RPCError as e:
logger.error(DDNS_STOP_FORWARDER_ERROR, e)
- def __notify_auth(self, zname, zclass):
- '''Notify auth of the update, if necessary.'''
- self.__notify_update(AUTH_MODULE_NAME, AUTH_LOADZONE_COMMAND,
- auth_loadzone_params(zname, zclass), zname,
- zclass)
-
def __notify_xfrout(self, zname, zclass):
'''Notify xfrout of the update.'''
param = {'zone_name': zname.to_text(), 'zone_class': zclass.to_text()}
diff --git a/src/bin/ddns/tests/ddns_test.py b/src/bin/ddns/tests/ddns_test.py
index e4a1a90..4bb106b 100755
--- a/src/bin/ddns/tests/ddns_test.py
+++ b/src/bin/ddns/tests/ddns_test.py
@@ -1101,7 +1101,7 @@ 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=2):
+ def check_session_msg(self, result, expect_recv=1):
'''Check post update communication with other modules.'''
# iff the update succeeds, b10-ddns should tell interested other
# modules the information about the update zone. Eventually this should
@@ -1110,20 +1110,17 @@ class TestDDNSSession(unittest.TestCase):
# {'zone_updated': {'datasource': <data_source_name>,
# 'origin': <updated_zone_name>,
# 'class': <updated_zone_class>}}
- # Until it's completed, we'll also notify specific modules, which are
- # xfrout and auth: for xfrout, the message format should be:
+ # Until it's completed, we'll also notify specific modules, which is
+ # xfrout: 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>}]}
# and expect an answer by calling group_recvmsg().
#
# expect_recv indicates the expected number of calls to
# group_recvmsg(), which is normally 2, but can be 0 if send fails;
# if the message is to be sent
if result == UPDATE_SUCCESS:
- expected_sentmsg = 3
+ expected_sentmsg = 2
self.assertEqual(expected_sentmsg,
len(self.__cc_session._sent_msg))
self.assertEqual(expect_recv, self.__cc_session._recvmsg_called)
@@ -1139,16 +1136,6 @@ class TestDDNSSession(unittest.TestCase):
msg_cnt += 1
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(2, 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'])
- 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])
self.assertEqual(2, len(sent_cmd[1]))
More information about the bind10-changes
mailing list