Commit 784ae3c5 authored by Jelte Jansen's avatar Jelte Jansen
Browse files

make auth_srv use the Auth/database_file setting

if not set, the hardcoded default is used
Added removeDataSrc(ConstDataSrcPtr) to remove a running one (auth_srv has a copy of the currently running sqlite datasrcptr to keep track of this)
added test for addDataSrc and removeDataSrc (for which is also added an dataSrcCount() function)
removed zone_list from auth.spec to avoid confusion
updated ccsession to give a better error when there is something wrong (like a bad .spec file)


git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@1203 e5f2f494-b856-4b98-b285-d166d9295462
parent f5355855
......@@ -4,19 +4,7 @@
"config_data": [
{ "item_name": "database_file",
"item_type": "string",
"item_optional": False,
"item_default": "b10-auth.db"
},
{ "item_name": "zone_list",
"item_type": "list",
"item_optional": False,
"item_default": [],
"list_item_spec":
{ "item_name": "zone_name",
"item_type": "string",
"item_optional": True,
"item_default": ""
}
"item_optional": True
}
],
"commands": [
......
......@@ -32,6 +32,8 @@
#include <dns/rrttl.h>
#include <dns/message.h>
#include <config/ccsession.h>
#include <cc/data.h>
#include <exceptions/exceptions.h>
#include <auth/query.h>
#include <auth/data_source.h>
......@@ -65,18 +67,17 @@ public:
};
AuthSrvImpl::AuthSrvImpl() {
// add static data source
data_sources.addDataSrc(ConstDataSrcPtr(new StaticDataSrc));
// add SQL data source
Sqlite3DataSrc* sd = new Sqlite3DataSrc;
sd->init();
data_sources.addDataSrc(ConstDataSrcPtr(sd));
}
AuthSrv::AuthSrv()
{
impl_ = new AuthSrvImpl;
// set empty (sqlite) data source, once ccsession is up
// the datasource will be set by the configuration setting
// (or the default one if none is set)
cur_datasrc_ = ConstDataSrcPtr();
// add static data source
impl_->data_sources.addDataSrc(ConstDataSrcPtr(new StaticDataSrc));
}
AuthSrv::~AuthSrv()
......@@ -133,24 +134,52 @@ AuthSrv::processMessage(const int fd)
}
}
void
AuthSrv::setDbFile(const std::string& db_file)
ElementPtr
AuthSrv::setDbFile(const isc::data::ElementPtr config)
{
cout << "Change data source file, call our data source's function to now read " << db_file << endl;
impl_->_db_file = db_file;
if (config) {
impl_->_db_file = config->get("database_file")->stringValue();
cout << "[AuthSrv] Data source database file: " << impl_->_db_file << endl;
}
try {
// create SQL data source
// config may be empty here; in that case it will load the default
// database file
Sqlite3DataSrc* sd = new Sqlite3DataSrc;
sd->init(config);
if (cur_datasrc_) {
impl_->data_sources.removeDataSrc(cur_datasrc_);
}
ConstDataSrcPtr csd = ConstDataSrcPtr(sd);
impl_->data_sources.addDataSrc(csd);
cur_datasrc_ = csd;
return isc::config::createAnswer(0);
} catch (isc::Exception error) {
cout << "[AuthSrv] error: " << error.what() << endl;
return isc::config::createAnswer(1, error.what());
}
}
ElementPtr
AuthSrv::updateConfig(isc::data::ElementPtr new_config)
{
ElementPtr answer = isc::config::createAnswer(0);
if (new_config) {
// the ModuleCCSession has already checked if we have
// the correct ElementPtr type as specified in our .spec file
if (new_config->contains("database_file")) {
// We only get this if the value has actually changed.
setDbFile(new_config->get("database_file")->stringValue());
answer = setDbFile(new_config);
}
}
// if we have no sqlite3 data source, use the default
if (!cur_datasrc_) {
setDbFile(ElementPtr());
}
return isc::config::createAnswer(0);
return answer;
}
......@@ -20,6 +20,7 @@
#include <string>
#include <cc/data.h>
#include <auth/data_source.h>
class AuthSrvImpl;
......@@ -39,10 +40,14 @@ public:
//@}
void processMessage(int fd);
void serve(std::string zone_name);
void setDbFile(const std::string& db_file);
isc::data::ElementPtr setDbFile(const isc::data::ElementPtr config);
isc::data::ElementPtr updateConfig(isc::data::ElementPtr config);
private:
AuthSrvImpl* impl_;
/// We keep a pointer to the currently running sqlite datasource
/// so that we can specifically remove that one should the database
/// file change
isc::auth::ConstDataSrcPtr cur_datasrc_;
};
#endif // __AUTH_SRV_H
......
......@@ -67,15 +67,13 @@ usage() {
ElementPtr
my_config_handler(ElementPtr new_config)
{
auth_server->updateConfig(new_config);
return createAnswer(0);
return auth_server->updateConfig(new_config);
}
ElementPtr
my_command_handler(const string& command, const ElementPtr args) {
ElementPtr answer = createAnswer(0);
cout << "[XX] Handle command: " << endl << command << endl;
if (command == "print_message")
{
cout << args << endl;
......
......@@ -23,6 +23,7 @@ run_unittests_LDADD = $(GTEST_LDADD)
run_unittests_LDADD += $(SQLITE_LIBS)
run_unittests_LDADD += .libs/libauth.a
run_unittests_LDADD += $(top_builddir)/src/lib/dns/.libs/libdns.a
run_unittests_LDADD += $(top_builddir)/src/lib/cc/libcc.a
run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/.libs/libexceptions.a
endif
......
......@@ -781,6 +781,19 @@ MetaDataSrc::addDataSrc(ConstDataSrcPtr data_src)
data_sources.push_back(data_src);
}
void
MetaDataSrc::removeDataSrc(ConstDataSrcPtr data_src)
{
std::vector<ConstDataSrcPtr>::iterator it, itr;
for (it = data_sources.begin(); it != data_sources.end(); it++) {
if (*it == data_src) {
itr = it;
}
}
data_sources.erase(itr);
}
void
MetaDataSrc::findClosestEnclosure(NameMatch& match, const RRClass& qclass) const
{
......
......@@ -25,6 +25,7 @@
#include <dns/name.h>
#include <dns/rrclass.h>
#include <cc/data.h>
namespace isc {
......@@ -102,6 +103,7 @@ public:
// Optional 'low-level' methods. These will have stub implementations
// in the general DataSrc class but MAY be overwritten by subclasses
virtual Result init() = 0;
virtual Result init(const isc::data::ElementPtr config) = 0;
virtual Result close() = 0;
// Mandatory 'low-level' methods: These will NOT be implemented by
......@@ -181,6 +183,7 @@ public:
void setClass(const isc::dns::RRClass& c) { rrclass = c; }
Result init() { return NOT_IMPLEMENTED; }
Result init(const isc::data::ElementPtr config) { return NOT_IMPLEMENTED; }
Result close() { return NOT_IMPLEMENTED; }
virtual Result findRRset(const Query& q,
......@@ -245,6 +248,9 @@ public:
//@}
void addDataSrc(ConstDataSrcPtr data_src);
void removeDataSrc(ConstDataSrcPtr data_src);
size_t dataSrcCount() { return data_sources.size(); };
void findClosestEnclosure(NameMatch& match,
const isc::dns::RRClass& qclass) const;
......
......@@ -487,18 +487,15 @@ Sqlite3DataSrc::~Sqlite3DataSrc() {
}
DataSrc::Result
Sqlite3DataSrc::init(const string& dbfile) {
open(dbfile);
cerr << "Schema version: " << getVersion() << endl;
Sqlite3DataSrc::init(const isc::data::ElementPtr config) {
if (config and config->contains("database_file")) {
open(config->get("database_file")->stringValue());
} else {
open(DEFAULT_DB_FILE);
}
return (SUCCESS);
}
DataSrc::Result
Sqlite3DataSrc::init() {
return (init(DEFAULT_DB_FILE));
}
void
Sqlite3DataSrc::findClosestEnclosure(NameMatch& match,
const RRClass& qclass) const {
......
......@@ -102,8 +102,8 @@ public:
std::string& hash,
isc::dns::RRsetList& target) const;
Result init();
Result init(const std::string& dbfile);
Result init() { return init(isc::data::ElementPtr()); };
Result init(const isc::data::ElementPtr config);
Result close();
private:
......
......@@ -29,6 +29,7 @@
#include <dns/rrtype.h>
#include <dns/rdataclass.h>
#include <dns/rrsetlist.h>
#include <cc/data.h>
#include "query.h"
#include "data_source.h"
......@@ -38,15 +39,19 @@ using namespace std;
using namespace isc::dns;
using namespace isc::dns::rdata;
using namespace isc::auth;
using namespace isc::data;
namespace {
static const char* SQLITE_DBFILE_EXAMPLE = "testdata/test.sqlite3";
static const char* SQLITE_DBFILE_EXAMPLE2 = "testdata/test2.sqlite3";
static ElementPtr SQLITE_DBFILE_EXAMPLE = Element::createFromString(
"{ \"database_file\": \"testdata/test.sqlite3\"}");
static ElementPtr SQLITE_DBFILE_EXAMPLE2 = Element::createFromString(
"{ \"database_file\": \"testdata/test2.sqlite3\"}");
// The following file must be non existent and mutt be "creatable";
// the sqlite3 library will try to create a new DB file if it doesn't exist,
// so to test a failure case the create operation should also fail.
// The "nodir", a non existent directory, is inserted for this purpose.
static const char* SQLITE_DBFILE_NOTEXIST = "testdata/nodir/notexist";
static ElementPtr SQLITE_DBFILE_NOTEXIST = Element::createFromString(
"{ \"database_file\": \"testdata/nodir/notexist\"}");
static const string sigdata_common(" 20100322084538 20100220084538 "
"33495 example.com. FAKEFAKEFAKEFAKE");
......@@ -350,6 +355,7 @@ TEST_F(Sqlite3DataSourceTest, reOpen) {
// Replace the data with a totally different zone. This should succeed,
// and shouldn't match any names in the previously managed domains.
EXPECT_EQ(DataSrc::SUCCESS, data_source.close());
EXPECT_EQ(DataSrc::SUCCESS, data_source.init(SQLITE_DBFILE_EXAMPLE2));
NameMatch name_match(www_name);
......
......@@ -88,6 +88,7 @@ public:
isc::dns::RRsetList& target) const;
Result init();
Result init(const isc::data::ElementPtr config) { return init(); };
Result close();
private:
StaticDataSrcImpl* impl_;
......
......@@ -27,6 +27,7 @@
#include <dns/rrtype.h>
#include <dns/rdataclass.h>
#include <dns/rrsetlist.h>
#include <cc/data.h>
#include "query.h"
#include "data_source.h"
......
......@@ -489,5 +489,15 @@ TEST_F(DataSrcTest, Nsec3Hash) {
EXPECT_EQ("FHA27EURONFH5640SFJQ8MJAKMCVB7UJ", nsec3.getHash(Name("test2")));
EXPECT_EQ("A4M93LR7A60IDDQMO6TCVUPCC60CU38A", nsec3.getHash(Name("test3")));
}
TEST_F(DataSrcTest, AddRemoveDataSrc) {
MetaDataSrc ds;
ConstDataSrcPtr tsp = ConstDataSrcPtr(new TestDataSrc);
EXPECT_EQ(0, ds.dataSrcCount());
ds.addDataSrc(tsp);
EXPECT_EQ(1, ds.dataSrcCount());
ds.removeDataSrc(tsp);
EXPECT_EQ(0, ds.dataSrcCount());
}
}
......@@ -95,6 +95,12 @@ RRsetPtr loop1_cname;
RRsetPtr loop2_cname;
}
DataSrc::Result
TestDataSrc::init(const isc::data::ElementPtr config)
{
return init();
}
DataSrc::Result
TestDataSrc::init() {
if (initialized) {
......
......@@ -92,6 +92,7 @@ public:
isc::dns::RRsetList& target) const;
Result init();
Result init(const isc::data::ElementPtr config);
Result close() { return (SUCCESS); }
private:
......
......@@ -189,16 +189,24 @@ ModuleCCSession::ModuleCCSession(std::string spec_file_name,
ElementPtr spec_msg = createCommand("module_spec", module_specification_.getFullSpec());
session_.group_sendmsg(spec_msg, "ConfigManager");
session_.group_recvmsg(env, answer, false);
int rcode;
ElementPtr err = parseAnswer(rcode, answer);
if (rcode != 0) {
std::cerr << "[" << module_name_ << "] Error in specification: " << answer << std::endl;
}
config_ = Element::createFromString("{}");
// get any stored configuration from the manager
if (config_handler_) {
ElementPtr cmd = Element::createFromString("{ \"command\": [\"get_config\", {\"module_name\":\"" + module_name_ + "\"} ] }");
session_.group_sendmsg(cmd, "ConfigManager");
session_.group_recvmsg(env, answer, false);
int rcode;
ElementPtr new_config = parseAnswer(rcode, answer);
handleConfigUpdate(new_config);
if (rcode == 0) {
handleConfigUpdate(new_config);
} else {
std::cerr << "[" << module_name_ << "] Error getting config: " << new_config << std::endl;
}
}
}
......
......@@ -113,9 +113,9 @@ def _encode_item(item):
def _encode_bool(item):
"""Encode a boolean value into a bytearray of one byte (0=false)"""
if item:
return b'\x01'
return b'1'
else:
return b'\x00'
return b'0'
def _encode_array(item):
"""Encode an array, where each value is encoded recursively"""
......@@ -203,7 +203,7 @@ def _decode_item(data):
return (value, data)
def _decode_bool(data):
return data == b'0x01'
return data == b'1' or data == b'0x01'
def _decode_int(data):
return int(str(data, 'utf-8'))
......
......@@ -287,7 +287,6 @@ class ConfigManager:
self.config.data = old_data
answer = isc.config.ccsession.create_answer(1, " ".join(err_list))
else:
print(cmd)
answer = isc.config.ccsession.create_answer(1, "Wrong number of arguments")
if not answer:
answer = isc.config.ccsession.create_answer(1, "No answer message from " + cmd[0])
......@@ -317,6 +316,7 @@ class ConfigManager:
"""Handle a command from the cc channel to the configuration manager"""
answer = {}
cmd, arg = isc.config.ccsession.parse_command(msg)
print("[b10-cfgmgr] got message: " + str(msg))
if cmd:
if cmd == isc.config.ccsession.COMMAND_GET_COMMANDS_SPEC:
answer = isc.config.ccsession.create_answer(0, self.get_commands_spec())
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment