Commit 12d62d54 authored by Ocean Wang's avatar Ocean Wang
Browse files

Merge branch 'master' into trac1112

parents ee468e8f c38112d8
282. [func] ocean
libdns++: Implement the NAPTR rrtype according to RFC2915,
RFC2168 and RFC3403.
(Trac #1130, git 01d8d0f13289ecdf9996d6d5d26ac0d43e30549c)
285. [bug] jelte
sqlite3 data source: fixed a race condition on initial startup,
when the database has not been initialized yet, and multiple
processes are trying to do so, resulting in one of them failing.
(Trac #326, git 5de6f9658f745e05361242042afd518b444d7466)
284. [bug] jerry
b10-zonemgr: zonemgr will not terminate on empty zones, it will
log a warning and try to do zone transfer for them.
(Trac #1153, git 0a39659638fc68f60b95b102968d7d0ad75443ea)
283. [bug] zhanglikun
Make stats and boss processes wait for answer messages from each
other in block mode to avoid orphan answer messages, add an internal
command "getstats" to boss process for getting statistics data from
boss.
(Trac #519, git 67d8e93028e014f644868fede3570abb28e5fb43)
282. [func] ocean
libdns++: Implement the NAPTR rrtype according to RFC2915,
RFC2168 and RFC3403.
(Trac #1130, git 01d8d0f13289ecdf9996d6d5d26ac0d43e30549c)
bind10-devel-20110819 released on August 19, 2011
......
......@@ -12,6 +12,12 @@ AC_PROG_CXX
# Libtool configuration
#
# libtool cannot handle spaces in paths, so exit early if there is one
if [ test `echo $PWD | grep -c ' '` != "0" ]; then
AC_MSG_ERROR([BIND 10 cannot be built in a directory that contains spaces, because of libtool limitations. Please change the directory name, or use a symbolic link that does not contain spaces.])
fi
# On FreeBSD (and probably some others), clang++ does not meet an autoconf
# assumption in identifying libtool configuration regarding shared library:
# the configure script will execute "$CC -shared $CFLAGS/$CXXFLAGS -v" and
......@@ -856,6 +862,7 @@ AC_CONFIG_FILES([Makefile
src/lib/exceptions/tests/Makefile
src/lib/datasrc/Makefile
src/lib/datasrc/tests/Makefile
src/lib/datasrc/tests/testdata/Makefile
src/lib/xfr/Makefile
src/lib/log/Makefile
src/lib/log/compiler/Makefile
......
......@@ -568,8 +568,8 @@ WARN_LOGFILE =
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
INPUT = ../src/lib/cc ../src/lib/config \
../src/lib/cryptolink ../src/lib/dns ../src/lib/datasrc \
INPUT = ../src/lib/exceptions ../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/log/compiler ../src/lib/asiolink/ ../src/lib/nsas \
../src/lib/testutils ../src/lib/cache ../src/lib/server_common/ \
......
......@@ -67,20 +67,21 @@ Query::findAddrs(ZoneFinder& zone, const Name& qname,
// Find A rrset
if (qname_ != qname || qtype_ != RRType::A()) {
ZoneFinder::FindResult a_result = zone.find(qname, RRType::A(), NULL,
options);
options | dnssec_opt_);
if (a_result.code == ZoneFinder::SUCCESS) {
response_.addRRset(Message::SECTION_ADDITIONAL,
boost::const_pointer_cast<RRset>(a_result.rrset));
boost::const_pointer_cast<RRset>(a_result.rrset), dnssec_);
}
}
// Find AAAA rrset
if (qname_ != qname || qtype_ != RRType::AAAA()) {
ZoneFinder::FindResult aaaa_result =
zone.find(qname, RRType::AAAA(), NULL, options);
zone.find(qname, RRType::AAAA(), NULL, options | dnssec_opt_);
if (aaaa_result.code == ZoneFinder::SUCCESS) {
response_.addRRset(Message::SECTION_ADDITIONAL,
boost::const_pointer_cast<RRset>(aaaa_result.rrset));
boost::const_pointer_cast<RRset>(aaaa_result.rrset),
dnssec_);
}
}
}
......@@ -88,7 +89,7 @@ Query::findAddrs(ZoneFinder& zone, const Name& qname,
void
Query::putSOA(ZoneFinder& zone) const {
ZoneFinder::FindResult soa_result(zone.find(zone.getOrigin(),
RRType::SOA()));
RRType::SOA(), NULL, dnssec_opt_));
if (soa_result.code != ZoneFinder::SUCCESS) {
isc_throw(NoSOA, "There's no SOA record in zone " <<
zone.getOrigin().toText());
......@@ -99,7 +100,7 @@ Query::putSOA(ZoneFinder& zone) const {
* to insist.
*/
response_.addRRset(Message::SECTION_AUTHORITY,
boost::const_pointer_cast<RRset>(soa_result.rrset));
boost::const_pointer_cast<RRset>(soa_result.rrset), dnssec_);
}
}
......@@ -107,14 +108,15 @@ void
Query::getAuthAdditional(ZoneFinder& zone) const {
// Fill in authority and addtional sections.
ZoneFinder::FindResult ns_result = zone.find(zone.getOrigin(),
RRType::NS());
RRType::NS(), NULL,
dnssec_opt_);
// zone origin name should have NS records
if (ns_result.code != ZoneFinder::SUCCESS) {
isc_throw(NoApexNS, "There's no apex NS records in zone " <<
zone.getOrigin().toText());
} else {
response_.addRRset(Message::SECTION_AUTHORITY,
boost::const_pointer_cast<RRset>(ns_result.rrset));
boost::const_pointer_cast<RRset>(ns_result.rrset), dnssec_);
// Handle additional for authority section
getAdditional(zone, *ns_result.rrset);
}
......@@ -147,12 +149,14 @@ Query::process() const {
keep_doing = false;
std::auto_ptr<RRsetList> target(qtype_is_any ? new RRsetList : NULL);
const ZoneFinder::FindResult db_result(
result.zone_finder->find(qname_, qtype_, target.get()));
result.zone_finder->find(qname_, qtype_, target.get(),
dnssec_opt_));
switch (db_result.code) {
case ZoneFinder::DNAME: {
// First, put the dname into the answer
response_.addRRset(Message::SECTION_ANSWER,
boost::const_pointer_cast<RRset>(db_result.rrset));
boost::const_pointer_cast<RRset>(db_result.rrset),
dnssec_);
/*
* Empty DNAME should never get in, as it is impossible to
* create one in master file.
......@@ -188,7 +192,7 @@ Query::process() const {
qname_.getLabelCount() -
db_result.rrset->getName().getLabelCount()).
concatenate(dname.getDname())));
response_.addRRset(Message::SECTION_ANSWER, cname);
response_.addRRset(Message::SECTION_ANSWER, cname, dnssec_);
break;
}
case ZoneFinder::CNAME:
......@@ -202,20 +206,23 @@ Query::process() const {
* So, just put it there.
*/
response_.addRRset(Message::SECTION_ANSWER,
boost::const_pointer_cast<RRset>(db_result.rrset));
boost::const_pointer_cast<RRset>(db_result.rrset),
dnssec_);
break;
case ZoneFinder::SUCCESS:
if (qtype_is_any) {
// If quety type is ANY, insert all RRs under the domain
// into answer section.
BOOST_FOREACH(RRsetPtr rrset, *target) {
response_.addRRset(Message::SECTION_ANSWER, rrset);
response_.addRRset(Message::SECTION_ANSWER, rrset,
dnssec_);
// Handle additional for answer section
getAdditional(*result.zone_finder, *rrset.get());
}
} else {
response_.addRRset(Message::SECTION_ANSWER,
boost::const_pointer_cast<RRset>(db_result.rrset));
boost::const_pointer_cast<RRset>(db_result.rrset),
dnssec_);
// Handle additional for answer section
getAdditional(*result.zone_finder, *db_result.rrset);
}
......@@ -233,7 +240,8 @@ Query::process() const {
case ZoneFinder::DELEGATION:
response_.setHeaderFlag(Message::HEADERFLAG_AA, false);
response_.addRRset(Message::SECTION_AUTHORITY,
boost::const_pointer_cast<RRset>(db_result.rrset));
boost::const_pointer_cast<RRset>(db_result.rrset),
dnssec_);
getAdditional(*result.zone_finder, *db_result.rrset);
break;
case ZoneFinder::NXDOMAIN:
......
......@@ -139,11 +139,15 @@ public:
/// \param qname The query name
/// \param qtype The RR type of the query
/// \param response The response message to store the answer to the query.
/// \param dnssec If the answer should include signatures and NSEC/NSEC3 if
/// possible.
Query(const isc::datasrc::DataSourceClient& datasrc_client,
const isc::dns::Name& qname, const isc::dns::RRType& qtype,
isc::dns::Message& response) :
isc::dns::Message& response, bool dnssec = false) :
datasrc_client_(datasrc_client), qname_(qname), qtype_(qtype),
response_(response)
response_(response), dnssec_(dnssec),
dnssec_opt_(dnssec ? isc::datasrc::ZoneFinder::FIND_DNSSEC :
isc::datasrc::ZoneFinder::FIND_DEFAULT)
{}
/// Process the query.
......@@ -211,6 +215,8 @@ private:
const isc::dns::Name& qname_;
const isc::dns::RRType& qtype_;
isc::dns::Message& response_;
const bool dnssec_;
const isc::datasrc::ZoneFinder::FindOptions dnssec_opt_;
};
}
......
......@@ -111,7 +111,8 @@ public:
dname_name_("dname.example.com"),
has_SOA_(true),
has_apex_NS_(true),
rrclass_(RRClass::IN())
rrclass_(RRClass::IN()),
include_rrsig_anyway_(false)
{
stringstream zone_stream;
zone_stream << soa_txt << zone_ns_txt << ns_addrs_txt <<
......@@ -137,11 +138,14 @@ public:
// the apex NS.
void setApexNSFlag(bool on) { has_apex_NS_ = on; }
// Turn this on if you want it to return RRSIGs regardless of FIND_GLUE_OK
void setIncludeRRSIGAnyway(bool on) { include_rrsig_anyway_ = on; }
private:
typedef map<RRType, ConstRRsetPtr> RRsetStore;
typedef map<Name, RRsetStore> Domains;
Domains domains_;
void loadRRset(ConstRRsetPtr rrset) {
void loadRRset(RRsetPtr rrset) {
domains_[rrset->getName()][rrset->getType()] = rrset;
if (rrset->getName() == delegation_name_ &&
rrset->getType() == RRType::NS()) {
......@@ -149,6 +153,26 @@ private:
} else if (rrset->getName() == dname_name_ &&
rrset->getType() == RRType::DNAME()) {
dname_rrset_ = rrset;
// Add some signatures
} else if (rrset->getName() == Name("example.com.") &&
rrset->getType() == RRType::NS()) {
rrset->addRRsig(RdataPtr(new generic::RRSIG("NS 5 3 3600 "
"20000101000000 "
"20000201000000 "
"12345 example.com. "
"FAKEFAKEFAKE")));
} else if (rrset->getType() == RRType::A()) {
rrset->addRRsig(RdataPtr(new generic::RRSIG("A 5 3 3600 "
"20000101000000 "
"20000201000000 "
"12345 example.com. "
"FAKEFAKEFAKE")));
} else if (rrset->getType() == RRType::AAAA()) {
rrset->addRRsig(RdataPtr(new generic::RRSIG("AAAA 5 3 3600 "
"20000101000000 "
"20000201000000 "
"12345 example.com. "
"FAKEFAKEFAKE")));
}
}
......@@ -161,6 +185,7 @@ private:
ConstRRsetPtr delegation_rrset_;
ConstRRsetPtr dname_rrset_;
const RRClass rrclass_;
bool include_rrsig_anyway_;
};
ZoneFinder::FindResult
......@@ -195,7 +220,26 @@ MockZoneFinder::find(const Name& name, const RRType& type,
RRsetStore::const_iterator found_rrset =
found_domain->second.find(type);
if (found_rrset != found_domain->second.end()) {
return (FindResult(SUCCESS, found_rrset->second));
ConstRRsetPtr rrset;
// Strip whatever signature there is in case DNSSEC is not required
// Just to make sure the Query asks for it when it is needed
if (options & ZoneFinder::FIND_DNSSEC ||
include_rrsig_anyway_ ||
!found_rrset->second->getRRsig()) {
rrset = found_rrset->second;
} else {
RRsetPtr noconst(new RRset(found_rrset->second->getName(),
found_rrset->second->getClass(),
found_rrset->second->getType(),
found_rrset->second->getTTL()));
for (RdataIteratorPtr
i(found_rrset->second->getRdataIterator());
!i->isLast(); i->next()) {
noconst->addRdata(i->getCurrent());
}
rrset = noconst;
}
return (FindResult(SUCCESS, rrset));
}
// If not found but we have a target, fill it with all RRsets here
......@@ -304,6 +348,58 @@ TEST_F(QueryTest, exactMatch) {
www_a_txt, zone_ns_txt, ns_addrs_txt);
}
TEST_F(QueryTest, exactMatchIgnoreSIG) {
// Check that we do not include the RRSIG when not requested even when
// we receive it from the data source.
mock_finder->setIncludeRRSIGAnyway(true);
Query query(memory_client, qname, qtype, response);
EXPECT_NO_THROW(query.process());
// find match rrset
responseCheck(response, Rcode::NOERROR(), AA_FLAG, 1, 3, 3,
www_a_txt, zone_ns_txt, ns_addrs_txt);
}
TEST_F(QueryTest, dnssecPositive) {
// Just like exactMatch, but the signatures should be included as well
Query query(memory_client, qname, qtype, response, true);
EXPECT_NO_THROW(query.process());
// find match rrset
// We can't let responseCheck to check the additional section as well,
// it gets confused by the two RRs for glue.delegation.../RRSIG due
// to it's design and fixing it would be hard. Therefore we simply
// check manually this one time.
responseCheck(response, Rcode::NOERROR(), AA_FLAG, 2, 4, 6,
(www_a_txt + std::string("www.example.com. 3600 IN RRSIG "
"A 5 3 3600 20000101000000 "
"20000201000000 12345 example.com. "
"FAKEFAKEFAKE\n")).c_str(),
(zone_ns_txt + std::string("example.com. 3600 IN RRSIG NS 5 "
"3 3600 20000101000000 "
"20000201000000 12345 "
"example.com. FAKEFAKEFAKE\n")).
c_str(), NULL);
RRsetIterator iterator(response.beginSection(Message::SECTION_ADDITIONAL));
const char* additional[] = {
"glue.delegation.example.com. 3600 IN A 192.0.2.153\n",
"glue.delegation.example.com. 3600 IN RRSIG A 5 3 3600 20000101000000 "
"20000201000000 12345 example.com. FAKEFAKEFAKE\n",
"glue.delegation.example.com. 3600 IN AAAA 2001:db8::53\n",
"glue.delegation.example.com. 3600 IN RRSIG AAAA 5 3 3600 "
"20000101000000 20000201000000 12345 example.com. FAKEFAKEFAKE\n",
"noglue.example.com. 3600 IN A 192.0.2.53\n",
"noglue.example.com. 3600 IN RRSIG A 5 3 3600 20000101000000 "
"20000201000000 12345 example.com. FAKEFAKEFAKE\n",
NULL
};
for (const char** rr(additional); *rr != NULL; ++ rr) {
ASSERT_FALSE(iterator ==
response.endSection(Message::SECTION_ADDITIONAL));
EXPECT_EQ(*rr, (*iterator)->toText());
iterator ++;
}
EXPECT_TRUE(iterator == response.endSection(Message::SECTION_ADDITIONAL));
}
TEST_F(QueryTest, exactAddrMatch) {
// find match rrset, omit additional data which has already been provided
// in the answer section from the additional.
......
......@@ -307,6 +307,11 @@ class BoB:
process_list.append([pid, self.processes[pid].name])
return process_list
def _get_stats_data(self):
return { "stats_data": {
'bind10.boot_time': time.strftime('%Y-%m-%dT%H:%M:%SZ', _BASETIME)
}}
def command_handler(self, command, args):
logger.debug(DBG_COMMANDS, BIND10_RECEIVED_COMMAND, command)
answer = isc.config.ccsession.create_answer(1, "command not implemented")
......@@ -316,14 +321,18 @@ class BoB:
if command == "shutdown":
self.runnable = False
answer = isc.config.ccsession.create_answer(0)
elif command == "getstats":
answer = isc.config.ccsession.create_answer(0, self._get_stats_data())
elif command == "sendstats":
# send statistics data to the stats daemon immediately
cmd = isc.config.ccsession.create_command(
'set', { "stats_data": {
'bind10.boot_time': time.strftime('%Y-%m-%dT%H:%M:%SZ', _BASETIME)
}})
'set', self._get_stats_data())
seq = self.cc_session.group_sendmsg(cmd, 'Stats')
self.cc_session.group_recvmsg(True, seq)
# Consume the answer, in case it becomes a orphan message.
try:
self.cc_session.group_recvmsg(False, seq)
except isc.cc.session.SessionTimeout:
pass
answer = isc.config.ccsession.create_answer(0)
elif command == "ping":
answer = isc.config.ccsession.create_answer(0, "pong")
......
......@@ -30,7 +30,7 @@ export PYTHONPATH
# required by loadable python modules.
SET_ENV_LIBRARY_PATH=@SET_ENV_LIBRARY_PATH@
if test $SET_ENV_LIBRARY_PATH = yes; then
@ENV_LIBRARY_PATH@=@abs_top_builddir@/src/lib/dns/.libs:@abs_top_builddir@/src/lib/cryptolink/.libs:@abs_top_builddir@/src/lib/cc/.libs:@abs_top_builddir@/src/lib/config/.libs:@abs_top_builddir@/src/lib/log/.libs:@abs_top_builddir@/src/lib/acl/.libs:@abs_top_builddir@/src/lib/util/.libs:@abs_top_builddir@/src/lib/util/io/.libs:@abs_top_builddir@/src/lib/exceptions/.libs:$@ENV_LIBRARY_PATH@
@ENV_LIBRARY_PATH@=@abs_top_builddir@/src/lib/dns/.libs:@abs_top_builddir@/src/lib/dns/python/.libs:@abs_top_builddir@/src/lib/cryptolink/.libs:@abs_top_builddir@/src/lib/cc/.libs:@abs_top_builddir@/src/lib/config/.libs:@abs_top_builddir@/src/lib/log/.libs:@abs_top_builddir@/src/lib/acl/.libs:@abs_top_builddir@/src/lib/util/.libs:@abs_top_builddir@/src/lib/util/io/.libs:@abs_top_builddir@/src/lib/exceptions/.libs:$@ENV_LIBRARY_PATH@
export @ENV_LIBRARY_PATH@
fi
......
......@@ -2,6 +2,7 @@ PYCOVERAGE_RUN = @PYCOVERAGE_RUN@
#PYTESTS = args_test.py bind10_test.py
# NOTE: this has a generated test found in the builddir
PYTESTS = bind10_test.py
noinst_SCRIPTS = $(PYTESTS)
# If necessary (rare cases), explicitly specify paths to dynamic libraries
# required by loadable python modules.
......@@ -19,6 +20,7 @@ if ENABLE_PYTHON_COVERAGE
endif
for pytest in $(PYTESTS) ; do \
echo Running test: $$pytest ; \
chmod +x $(abs_builddir)/$$pytest ; \
$(LIBRARY_PATH_PLACEHOLDER) \
env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_srcdir)/src/bin:$(abs_top_builddir)/src/bin/bind10:$(abs_top_builddir)/src/lib/util/io/.libs \
BIND10_MSGQ_SOCKET_FILE=$(abs_top_builddir)/msgq_socket \
......
......@@ -147,6 +147,12 @@ class TestBoB(unittest.TestCase):
self.assertEqual(bob.command_handler("shutdown", None),
isc.config.ccsession.create_answer(0))
self.assertFalse(bob.runnable)
# "getstats" command
self.assertEqual(bob.command_handler("getstats", None),
isc.config.ccsession.create_answer(0,
{ "stats_data": {
'bind10.boot_time': time.strftime('%Y-%m-%dT%H:%M:%SZ', _BASETIME)
}}))
# "sendstats" command
self.assertEqual(bob.command_handler("sendstats", None),
isc.config.ccsession.create_answer(0))
......
......@@ -7,7 +7,7 @@ EXTRA_DIST = $(PYTESTS)
# required by loadable python modules.
LIBRARY_PATH_PLACEHOLDER =
if SET_ENV_LIBRARY_PATH
LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/cc/.libs:$(abs_top_builddir)/src/lib/config/.libs:$(abs_top_builddir)/src/lib/log/.libs:$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/cryptolink/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs
LIBRARY_PATH_PLACEHOLDER += $(ENV_LIBRARY_PATH)=$(abs_top_builddir)/src/lib/cc/.libs:$(abs_top_builddir)/src/lib/config/.libs:$(abs_top_builddir)/src/lib/log/.libs:$(abs_top_builddir)/src/lib/dns/.libs:$(abs_top_builddir)/src/lib/dns/python/.libs:$(abs_top_builddir)/src/lib/cryptolink/.libs:$(abs_top_builddir)/src/lib/util/.libs:$(abs_top_builddir)/src/lib/exceptions/.libs
endif
# test using command-line arguments, so use check-local target instead of TESTS
......
PYCOVERAGE_RUN = @PYCOVERAGE_RUN@
PYTESTS = b10-cfgmgr_test.py
EXTRA_DIST = $(PYTESTS) testdata/plugins/testplugin.py
noinst_SCRIPTS = $(PYTESTS)
EXTRA_DIST = testdata/plugins/testplugin.py
# If necessary (rare cases), explicitly specify paths to dynamic libraries
# required by loadable python modules.
......@@ -19,6 +20,7 @@ if ENABLE_PYTHON_COVERAGE
endif
for pytest in $(PYTESTS) ; do \
echo Running test: $$pytest ; \
chmod +x $(abs_builddir)/$$pytest ; \
env TESTDATA_PATH=$(abs_srcdir)/testdata \
$(LIBRARY_PATH_PLACEHOLDER) \
env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/bin/cfgmgr:$(abs_top_builddir)/src/lib/python/isc/config \
......
......@@ -36,7 +36,7 @@ with other modules like
\fBb10\-auth\fR
and so on\&. It waits for coming data from other modules, then other modules send data to stats module periodically\&. Other modules send stats data to stats module independently from implementation of stats module, so the frequency of sending data may not be constant\&. Stats module collects data and aggregates it\&.
\fBb10\-stats\fR
invokes "sendstats" command for
invokes an internal command for
\fBbind10\fR
after its initial starting because it\'s sure to collect statistics data from
\fBbind10\fR\&.
......
......@@ -64,7 +64,7 @@
send stats data to stats module independently from
implementation of stats module, so the frequency of sending data
may not be constant. Stats module collects data and aggregates
it. <command>b10-stats</command> invokes "sendstats" command
it. <command>b10-stats</command> invokes an internal command
for <command>bind10</command> after its initial starting because it's
sure to collect statistics data from <command>bind10</command>.
<!-- TODO: reword that last sentence? -->
......
......@@ -213,6 +213,14 @@ class CCSessionListener(Listener):
except AttributeError as ae:
logger.error(STATS_UNKNOWN_COMMAND_IN_SPEC, cmd["command_name"])
def _update_stats_data(self, args):
# 'args' must be dictionary type
if isinstance(args, dict) and isinstance(args.get('stats_data'), dict):
self.stats_data.update(args['stats_data'])
# overwrite "stats.LastUpdateTime"
self.stats_data['stats.last_update_time'] = get_datetime()
def start(self):
"""
start the cc chanel
......@@ -225,9 +233,16 @@ class CCSessionListener(Listener):
self.cc_session.start()
# request Bob to send statistics data
logger.debug(DBG_STATS_MESSAGING, STATS_SEND_REQUEST_BOSS)
cmd = isc.config.ccsession.create_command("sendstats", None)
cmd = isc.config.ccsession.create_command("getstats", None)
seq = self.session.group_sendmsg(cmd, 'Boss')
self.session.group_recvmsg(True, seq)
try:
answer, env = self.session.group_recvmsg(False, seq)
if answer:
rcode, arg = isc.config.ccsession.parse_answer(answer)
if rcode == 0:
self._update_stats_data(arg)
except isc.cc.session.SessionTimeout:
pass
def stop(self):
"""
......@@ -276,12 +291,7 @@ class CCSessionListener(Listener):
"""
handle set command
"""
# 'args' must be dictionary type
self.stats_data.update(args['stats_data'])
# overwrite "stats.LastUpdateTime"
self.stats_data['stats.last_update_time'] = get_datetime()
self._update_stats_data(args)
return create_answer(0)
def command_remove(self, args, stats_item_name=''):
......
......@@ -59,6 +59,7 @@ class TestStats(unittest.TestCase):
# check starting
self.assertFalse(self.subject.running)
self.subject.start()
self.assertEqual(len(self.session.old_message_queue), 1)
self.assertTrue(self.subject.running)
self.assertEqual(len(self.session.message_queue), 0)
self.assertEqual(self.module_name, 'Stats')
......@@ -509,7 +510,7 @@ class TestStats(unittest.TestCase):
def test_for_boss(self):
last_queue = self.session.old_message_queue.pop()
self.assertEqual(
last_queue.msg, {'command': ['sendstats']})
last_queue.msg, {'command': ['getstats']})
self.assertEqual(
last_queue.env['group'], 'Boss')
......
......@@ -115,8 +115,16 @@ class Session:
def group_recvmsg(self, nonblock=True, seq=0):
que = self.dequeue()
if que.msg != None:
cmd = que.msg.get("command")
if cmd and cmd[0] == 'getstats':
# Create answer for command 'getstats'
retdata = { "stats_data": {
'bind10.boot_time' : "1970-01-01T00:00:00Z"
}}
return {'result': [0, retdata]}, que.env
return que.msg, que.env
def group_reply(self, routing, msg):
return self.enqueue(msg=msg, env={
"type": "send",
......
......@@ -20,6 +20,7 @@ if ENABLE_PYTHON_COVERAGE
endif
for pytest in $(PYTESTS) ; do \
echo Running test: $$pytest ; \
chmod +x $(abs_builddir)/$$pytest ; \
$(LIBRARY_PATH_PLACEHOLDER) \
env PYTHONPATH=$(abs_top_srcdir)/src/lib/python:$(abs_top_builddir)/src/lib/python:$(abs_top_builddir)/src/lib/dns/python/.libs \
$(PYCOVERAGE_RUN) $(abs_builddir)/$$pytest || exit ; \
......
......@@ -2,12 +2,12 @@
.\" Title: b10-xfrin
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
.\" Date: May 19, 2011
.\" Date: September 8, 2011
.\" Manual: BIND10
.\" Source: BIND10
.\" Language: English
.\"
.TH "B10\-XFRIN" "8" "May 19, 2011" "BIND10" "BIND10"
.TH "B10\-XFRIN" "8" "September 8, 2011" "BIND10" "BIND10"
.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
......@@ -61,7 +61,7 @@ receives its configurations from
.PP
The configurable settings are:
.PP
\fItransfers\-in\fR
\fItransfers_in\fR
defines the maximum number of inbound zone transfers that can run concurrently\&. The default is 10\&.
.PP
......
......@@ -20,7 +20,7 @@
<refentry>
<refentryinfo>
<date>May 19, 2011</date>
<date>September 8, 2011</date>
</refentryinfo>
<refmeta>
......@@ -92,7 +92,7 @@ in separate zonemgr process.
The configurable settings are:
</para>
<para><varname>transfers-in</varname>
<para><varname>transfers_in</varname>
defines the maximum number of inbound zone transfers
that can run concurrently. The default is 10.
</para>
......