Commit f759c307 authored by Francis Dupont's avatar Francis Dupont

[65-libyang-database] Filled files, waiting for adaptor merge

parent ae3d891f
......@@ -7,6 +7,7 @@ AM_CXXFLAGS = $(KEA_CXXFLAGS)
lib_LTLIBRARIES = libkea-yang.la
libkea_yang_la_SOURCES = sysrepo_error.h
libkea_yang_la_SOURCES += translator.cc translator.h
libkea_yang_la_SOURCES += translator_database.cc translator_database.h
libkea_yang_la_LIBADD = $(top_builddir)/src/lib/asiolink/libkea-asiolink.la
libkea_yang_la_LIBADD += $(top_builddir)/src/lib/cc/libkea-cc.la
......
......@@ -18,6 +18,7 @@ TESTS =
if HAVE_GTEST
TESTS += run_unittests
run_unittests_SOURCES = translator_unittests.cc
run_unittests_SOURCES += translator_database_unittests.cc
run_unittests_SOURCES += run_unittests.cc
run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
......
// Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <config.h>
#include <yang/translator_database.h>
#include <boost/scoped_ptr.hpp>
#include <gtest/gtest.h>
using namespace std;
using namespace isc;
using namespace isc::data;
using namespace isc::yang;
namespace {
// Test get empty database using the ad hoc model.
TEST(TranslatorDatabaseTest, getEmpty) {
// Get a translator database object to play with.
S_Connection conn(new Connection("translator database access unittests"));
S_Session sess(new Session(conn, SR_DS_CANDIDATE));
boost::scoped_ptr<TranslatorDatabase> td_obj;
// Use the ad hoc model.
const string& model = "kea-dhcp4";
EXPECT_NO_THROW(td_obj.reset(new TranslatorDatabase(sess, model)));
// Get empty.
const string& xpath = "/kea-dhcp4:config/lease-database";
ConstElementPtr database;
EXPECT_NO_THROW(database = td_obj->getDatabase(xpath));
EXPECT_FALSE(database);
}
// Test get a database using the ad hoc model.
TEST(TranslatorDatabaseTest, get) {
// Get a translator database object to play with.
S_Connection conn(new Connection("translator database access unittests"));
S_Session sess(new Session(conn, SR_DS_CANDIDATE));
boost::scoped_ptr<TranslatorDatabase> td_obj;
// Use the ad hoc model.
const string& model = "kea-dhcp4";
EXPECT_NO_THROW(td_obj.reset(new TranslatorDatabase(sess, model)));
// Set a value.
const string& xpath = "/kea-dhcp4:config/lease-database";
const string& xtype = xpath + "/database-type";
const string& xinterval = xpath + "/lfc-interval";
S_Val s_type(new Val("memfile"));
EXPECT_NO_THROW(sess->set_item(xtype.c_str(), s_type));
uint32_t li = 3600;
S_Val s_interval(new Val(li, SR_UINT32_T));
EXPECT_NO_THROW(sess->set_item(xinterval.c_str(), s_interval));
// Get empty.
ConstElementPtr database;
EXPECT_NO_THROW(database = td_obj->getDatabase(xpath));
ASSERT_TRUE(database);
EXPECT_EQ(2, database->size());
ConstElementPtr type = database->get("type");
ASSERT_TRUE(type);
ASSERT_EQ(Element::string, type->getType());
EXPECT_EQ("memfile", type->stringValue());
ConstElementPtr interval = database->get("lfc-interval");
ASSERT_TRUE(interval);
ASSERT_EQ(Element::integer, interval->getType());
EXPECT_EQ(li, interval->intValue());
}
// Test set a database using the ad hoc model.
TEST(TranslatorDatabaseTest, set) {
// Get a translator database object to play with.
S_Connection conn(new Connection("translator database access unittests"));
S_Session sess(new Session(conn, SR_DS_CANDIDATE));
boost::scoped_ptr<TranslatorDatabase> td_obj;
// Use the ad hoc model.
const string& model = "kea-dhcp4";
EXPECT_NO_THROW(td_obj.reset(new TranslatorDatabase(sess, model)));
// Set a value.
const string& xpath = "/kea-dhcp4:config/lease-database";
ElementPtr database = Element::createMap();
database->set("type", Element::create(string("memfile")));
database->set("lfc-interval", Element::create(3600));
ASSERT_NO_THROW(td_obj->setDatabase(xpath, database));
// Get it back.
ConstElementPtr got;
EXPECT_NO_THROW(got = td_obj->getDatabase(xpath));
ASSERT_TRUE(got);
ASSERT_EQ(Element::map, got->getType());
EXPECT_EQ(2, got->size());
ConstElementPtr type = got->get("type");
ASSERT_TRUE(type);
ASSERT_EQ(Element::string, type->getType());
EXPECT_EQ("memfile", type->stringValue());
ConstElementPtr interval = database->get("lfc-interval");
ASSERT_TRUE(interval);
ASSERT_EQ(Element::integer, interval->getType());
EXPECT_EQ(3600, interval->intValue());
}
// Test set empty database using the ad hoc model.
TEST(TranslatorDatabaseTest, setEmpty) {
// Get a translator database object to play with.
S_Connection conn(new Connection("translator database access unittests"));
S_Session sess(new Session(conn, SR_DS_CANDIDATE));
boost::scoped_ptr<TranslatorDatabase> td_obj;
// Use the ad hoc model.
const string& model = "kea-dhcp4";
EXPECT_NO_THROW(td_obj.reset(new TranslatorDatabase(sess, model)));
// Set a value.
const string& xpath = "/kea-dhcp4:config/lease-database";
const string& xtype = xpath + "/database-type";
const string& xinterval = xpath + "/lfc-interval";
S_Val s_type(new Val("memfile"));
EXPECT_NO_THROW(sess->set_item(xtype.c_str(), s_type));
uint32_t li = 3600;
S_Val s_interval(new Val(li, SR_UINT32_T));
EXPECT_NO_THROW(sess->set_item(xinterval.c_str(), s_interval));
// Reset to empty.
ASSERT_NO_THROW(td_obj->setDatabase(xpath, ConstElementPtr()));
// Get it back.
ConstElementPtr database;
EXPECT_NO_THROW(database = td_obj->getDatabase(xpath));
EXPECT_FALSE(database);
}
// Test get empty databases.
TEST(TranslatorDatabasesTest, getEmpty) {
// Get a translator databases object to play with.
S_Connection conn(new Connection("translator database accesses unittests"));
S_Session sess(new Session(conn, SR_DS_CANDIDATE));
boost::scoped_ptr<TranslatorDatabases> tds_obj;
// Use the ad hoc model.
const string& model = "kea-dhcp6";
EXPECT_NO_THROW(tds_obj.reset(new TranslatorDatabases(sess, model)));
// Get empty.
const string& xpath = "/kea-dhcp6:config/hosts-databases";
ConstElementPtr databases;
EXPECT_NO_THROW(databases = tds_obj->getDatabases(xpath));
EXPECT_FALSE(databases);
}
// Test get databases.
TEST(TranslatorDatabasesTest, get) {
// Get a translator databases object to play with.
S_Connection conn(new Connection("translator database accesses unittests"));
S_Session sess(new Session(conn, SR_DS_CANDIDATE));
boost::scoped_ptr<TranslatorDatabases> tds_obj;
// Use the ad hoc model.
const string& model = "kea-dhcp4";
EXPECT_NO_THROW(tds_obj.reset(new TranslatorDatabases(sess, model)));
// Set a value.
const string& xpath = "/kea-dhcp4:config/hosts-databases";
const string& xdatabase =
xpath + "/hosts-database[database-type='mysql']";
const string& xname = xdatabase + "/name";
const string& xuser = xdatabase + "/user";
const string& xpassword = xdatabase + "/password";
const string& xhost = xdatabase + "/host";
const string& xport = xdatabase + "/port";
S_Val s_name(new Val("kea"));
EXPECT_NO_THROW(sess->set_item(xname.c_str(), s_name));
S_Val s_user(new Val("kea"));
EXPECT_NO_THROW(sess->set_item(xuser.c_str(), s_user));
S_Val s_password(new Val("kea"));
EXPECT_NO_THROW(sess->set_item(xpassword.c_str(), s_password));
S_Val s_host(new Val("localhost"));
EXPECT_NO_THROW(sess->set_item(xhost.c_str(), s_host));
uint16_t mport = 3306;
S_Val s_port(new Val(mport, SR_UINT16_T));
EXPECT_NO_THROW(sess->set_item(xport.c_str(), s_port));
// Get empty.
ConstElementPtr databases;
EXPECT_NO_THROW(databases = tds_obj->getDatabases(xpath));
ASSERT_TRUE(databases);
ASSERT_EQ(1, databases->size());
ConstElementPtr database = databases->get(0);
ASSERT_TRUE(database);
EXPECT_EQ(6, database->size());
ConstElementPtr type = database->get("type");
ASSERT_TRUE(type);
ASSERT_EQ(Element::string, type->getType());
EXPECT_EQ("mysql", type->stringValue());
ConstElementPtr name = database->get("name");
ASSERT_TRUE(name);
ASSERT_EQ(Element::string, name->getType());
EXPECT_EQ("kea", name->stringValue());
ConstElementPtr user = database->get("user");
ASSERT_TRUE(user);
ASSERT_EQ(Element::string, user->getType());
EXPECT_EQ("kea", user->stringValue());
ConstElementPtr password = database->get("password");
ASSERT_TRUE(password);
ASSERT_EQ(Element::string, password->getType());
EXPECT_EQ("kea", password->stringValue());
ConstElementPtr host = database->get("host");
ASSERT_TRUE(host);
ASSERT_EQ(Element::string, host->getType());
EXPECT_EQ("localhost", host->stringValue());
ConstElementPtr port = database->get("port");
ASSERT_TRUE(port);
ASSERT_EQ(Element::integer, port->getType());
EXPECT_EQ(mport, port->intValue());
}
// Test set databases.
TEST(TranslatorDatabasesTest, set) {
// Get a translator databases object to play with.
S_Connection conn(new Connection("translator database accesses unittests"));
S_Session sess(new Session(conn, SR_DS_CANDIDATE));
boost::scoped_ptr<TranslatorDatabases> tds_obj;
// Use the ad hoc model.
const string& model = "kea-dhcp6";
EXPECT_NO_THROW(tds_obj.reset(new TranslatorDatabases(sess, model)));
// Set a value.
const string& xpath = "/kea-dhcp6:config/hosts-databases";
ElementPtr database = Element::createMap();
database->set("type", Element::create(string("memfile")));
database->set("lfc-interval", Element::create(3600));
ElementPtr databases = Element::createList();
databases->add(database);
ASSERT_NO_THROW(tds_obj->setDatabases(xpath, databases));
// Get it back.
ConstElementPtr gots;
EXPECT_NO_THROW(gots = tds_obj->getDatabases(xpath));
ASSERT_TRUE(gots);
ASSERT_EQ(Element::list, gots->getType());
ASSERT_EQ(1, gots->size());
ConstElementPtr got = gots->get(0);
ASSERT_TRUE(got);
ASSERT_EQ(Element::map, got->getType());
EXPECT_EQ(2, got->size());
ConstElementPtr type = got->get("type");
ASSERT_TRUE(type);
ASSERT_EQ(Element::string, type->getType());
EXPECT_EQ("memfile", type->stringValue());
ConstElementPtr interval = database->get("lfc-interval");
ASSERT_TRUE(interval);
ASSERT_EQ(Element::integer, interval->getType());
EXPECT_EQ(3600, interval->intValue());
}
// Test set empty database.
TEST(TranslatorDatabasesTest, setEmpty) {
// Get a translator databases object to play with.
S_Connection conn(new Connection("translator database accesses unittests"));
S_Session sess(new Session(conn, SR_DS_CANDIDATE));
boost::scoped_ptr<TranslatorDatabases> tds_obj;
boost::scoped_ptr<TranslatorDatabase> td_obj;
// Use the ad hoc model.
const string& model = "kea-dhcp4";
EXPECT_NO_THROW(tds_obj.reset(new TranslatorDatabases(sess, model)));
EXPECT_NO_THROW(td_obj.reset(new TranslatorDatabase(sess, model)));
// Set a value.
const string& xpath = "/kea-dhcp4:config/hosts-databases";
const string& xdatabase =
xpath + "/hosts-database[database-type='mysql']";
const string& xname = xdatabase + "/name";
const string& xuser = xdatabase + "/user";
const string& xpassword = xdatabase + "/password";
const string& xhost = xdatabase + "/host";
const string& xport = xdatabase + "/port";
S_Val s_name(new Val("kea"));
EXPECT_NO_THROW(sess->set_item(xname.c_str(), s_name));
S_Val s_user(new Val("kea"));
EXPECT_NO_THROW(sess->set_item(xuser.c_str(), s_user));
S_Val s_password(new Val("kea"));
EXPECT_NO_THROW(sess->set_item(xpassword.c_str(), s_password));
S_Val s_host(new Val("localhost"));
EXPECT_NO_THROW(sess->set_item(xhost.c_str(), s_host));
uint16_t mport = 3306;
S_Val s_port(new Val(mport, SR_UINT16_T));
EXPECT_NO_THROW(sess->set_item(xport.c_str(), s_port));
// Reset to empty.
ASSERT_NO_THROW(td_obj->setDatabase(xdatabase, ConstElementPtr()));
// Get empty.
ConstElementPtr databases;
EXPECT_NO_THROW(databases = tds_obj->getDatabases(xpath));
EXPECT_FALSE(databases);
}
// Test set empty databases.
TEST(TranslatorDatabasesTest, setEmpties) {
// Get a translator databases object to play with.
S_Connection conn(new Connection("translator database accesses unittests"));
S_Session sess(new Session(conn, SR_DS_CANDIDATE));
boost::scoped_ptr<TranslatorDatabases> tds_obj;
// Use the ad hoc model.
const string& model = "kea-dhcp4";
EXPECT_NO_THROW(tds_obj.reset(new TranslatorDatabases(sess, model)));
// Set a value.
const string& xpath = "/kea-dhcp4:config/hosts-databases";
const string& xdatabase =
xpath + "/hosts-database[database-type='mysql']";
const string& xname = xdatabase + "/name";
const string& xuser = xdatabase + "/user";
const string& xpassword = xdatabase + "/password";
const string& xhost = xdatabase + "/host";
const string& xport = xdatabase + "/port";
S_Val s_name(new Val("kea"));
EXPECT_NO_THROW(sess->set_item(xname.c_str(), s_name));
S_Val s_user(new Val("kea"));
EXPECT_NO_THROW(sess->set_item(xuser.c_str(), s_user));
S_Val s_password(new Val("kea"));
EXPECT_NO_THROW(sess->set_item(xpassword.c_str(), s_password));
S_Val s_host(new Val("localhost"));
EXPECT_NO_THROW(sess->set_item(xhost.c_str(), s_host));
uint16_t mport = 3306;
S_Val s_port(new Val(mport, SR_UINT16_T));
EXPECT_NO_THROW(sess->set_item(xport.c_str(), s_port));
// Reset to empty.
ASSERT_NO_THROW(tds_obj->setDatabases(xdatabase, ConstElementPtr()));
// Get empty.
ConstElementPtr databases;
EXPECT_NO_THROW(databases = tds_obj->getDatabases(xpath));
EXPECT_FALSE(databases);
}
}; // end of anonymous namespace
// Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include <yang/translator_database.h>
#include <yang/adaptor.h>
#include <sstream>
using namespace std;
using namespace isc::data;
namespace isc {
namespace yang {
TranslatorDatabase::TranslatorDatabase(S_Session session, const string& model)
: TranslatorBasic(session), model_(model) {
}
TranslatorDatabase::~TranslatorDatabase() {
}
ElementPtr
TranslatorDatabase::getDatabase(const string& xpath) {
try {
if ((model_ == "kea-dhcp4") || (model_ == "kea-dhcp6")) {
return (getDatabaseKea(xpath));
}
} catch (const sysrepo_exception& ex) {
isc_throw(SysrepoError,
"sysrepo error getting database access at '" << xpath
<< "': " << ex.what());
}
isc_throw(NotImplemented,
"getDatabase not implemented for the model: " << model_);
}
ElementPtr
TranslatorDatabase::getDatabaseKea(const string& xpath) {
ConstElementPtr type = getItem(xpath + "/database-type");
if (!type) {
return (ElementPtr());
}
ElementPtr result = Element::createMap();
result->set("type", type);
ConstElementPtr user = getItem(xpath + "/user");
if (user) {
result->set("user", user);
}
ConstElementPtr password = getItem(xpath + "/password");
if (password) {
result->set("password", password);
}
ConstElementPtr host = getItem(xpath + "/host");
if (host) {
result->set("host", host);
}
ConstElementPtr name = getItem(xpath + "/name");
if (name) {
result->set("name", name);
}
ConstElementPtr persist = getItem(xpath + "/persist");
if (persist) {
result->set("persist", persist);
}
ConstElementPtr port = getItem(xpath + "/port");
if (port) {
result->set("port", port);
}
ConstElementPtr lfc_interval = getItem(xpath + "/lfc-interval");
if (lfc_interval) {
result->set("lfc-interval", lfc_interval);
}
ConstElementPtr readonly = getItem(xpath + "/readonly");
if (readonly) {
result->set("readonly", readonly);
}
ConstElementPtr connect_timeout = getItem(xpath + "/connect-timeout");
if (connect_timeout) {
result->set("connect-timeout", connect_timeout);
}
ConstElementPtr contact_points = getItem(xpath + "/contact-points");
if (contact_points) {
result->set("contact-points", contact_points);
}
ConstElementPtr keyspace = getItem(xpath + "/keyspace");
if (keyspace) {
result->set("keyspace", keyspace);
}
ConstElementPtr max_reconnect = getItem(xpath + "/max-reconnect-tries");
if (max_reconnect) {
result->set("max-reconnect-tries", max_reconnect);
}
ConstElementPtr reconnect_time = getItem(xpath + "/reconnect-wait-time");
if (reconnect_time) {
result->set("reconnect-wait-time", reconnect_time);
}
ConstElementPtr request_timeout = getItem(xpath + "/request-timeout");
if (request_timeout) {
result->set("request-timeout", request_timeout);
}
ConstElementPtr keepalive = getItem(xpath + "/tcp-keepalive");
if (keepalive) {
result->set("tcp-keepalive", keepalive);
}
ConstElementPtr nodelay = getItem(xpath + "/tcp-nodelay");
if (nodelay) {
result->set("tcp-nodelay", nodelay);
}
ConstElementPtr context = getItem(xpath + "/user-context");
if (context) {
result->set("user-context", Element::fromJSON(context->stringValue()));
}
return (result);
}
void
TranslatorDatabase::setDatabase(const string& xpath,
ConstElementPtr elem,
bool skip) {
try {
if ((model_ == "kea-dhcp4") || (model_ == "kea-dhcp6")) {
setDatabaseKea(xpath, elem, skip);
} else {
isc_throw(NotImplemented,
"setDatabase not implemented for the model: " << model_);
}
} catch (const sysrepo_exception& ex) {
isc_throw(SysrepoError,
"sysrepo error setting database access '" << elem->str()
<< "' at '" << xpath << "': " << ex.what());
}
}
void
TranslatorDatabase::setDatabaseKea(const string& xpath,
ConstElementPtr elem,
bool skip) {
if (!elem) {
delItem(xpath);
return;
}
if (!skip) {
ConstElementPtr type = elem->get("type");
if (!type) {
isc_throw(BadValue, "setDatabase missing database type");
}
setItem(xpath + "/database-type", type, SR_STRING_T);
}
ConstElementPtr user = elem->get("user");
if (user) {
setItem(xpath + "/user", user, SR_STRING_T);
}
ConstElementPtr password = elem->get("password");
if (password) {
setItem(xpath + "/password", password, SR_STRING_T);
}
ConstElementPtr host = elem->get("host");
if (host) {
setItem(xpath + "/host", host, SR_STRING_T);
}
ConstElementPtr name = elem->get("name");
if (name) {
setItem(xpath + "/name", name, SR_STRING_T);
}
ConstElementPtr persist = elem->get("persist");
if (persist) {
setItem(xpath + "/persist", persist, SR_BOOL_T);
}
ConstElementPtr port = elem->get("port");
if (port) {
setItem(xpath + "/port", port, SR_UINT16_T);
}
ConstElementPtr lfc_interval = elem->get("lfc-interval");
if (lfc_interval) {
setItem(xpath + "/lfc-interval", lfc_interval, SR_UINT32_T);
}
ConstElementPtr readonly = elem->get("readonly");
if (readonly) {
setItem(xpath + "/readonly", readonly, SR_BOOL_T);
}
ConstElementPtr connect_timeout = elem->get("connect-timeout");
if (connect_timeout) {
setItem(xpath + "/connect-timeout", connect_timeout, SR_UINT32_T);
}
ConstElementPtr contact_points = elem->get("contact-points");
if (contact_points) {
setItem(xpath + "/contact-points", contact_points, SR_STRING_T);
}
ConstElementPtr keyspace = elem->get("keyspace");
if (keyspace) {
setItem(xpath + "/keyspace", keyspace, SR_STRING_T);
}
ConstElementPtr max_reconnect = elem->get("max-reconnect-tries");
if (max_reconnect) {
setItem(xpath + "/max-reconnect-tries", max_reconnect, SR_UINT32_T);
}
ConstElementPtr reconnect_wait = elem->get("reconnect-wait-time");
if (reconnect_wait) {
setItem(xpath + "/reconnect-wait-time", reconnect_wait, SR_UINT32_T);
}
ConstElementPtr request_timeout = elem->get("request-timeout");
if (request_timeout) {
setItem(xpath + "/request-timeout", request_timeout, SR_UINT32_T);
}
ConstElementPtr keepalive = elem->get("tcp-keepalive");
if (keepalive) {
setItem(xpath + "/tcp-keepalive", keepalive, SR_UINT32_T);
}
ConstElementPtr nodelay = elem->get("tcp-nodelay");
if (nodelay) {
setItem(xpath + "/tcp-nodelay", nodelay, SR_BOOL_T);
}
ConstElementPtr context = Adaptor::getContext(elem);
if (context) {
setItem(xpath + "/user-context", Element::create(context->str()),
SR_STRING_T);
}
}
TranslatorDatabases::TranslatorDatabases(S_Session session,
const string& model)
: TranslatorBasic(session),
TranslatorDatabase(session, model),
model_(model) {
}
TranslatorDatabases::~TranslatorDatabases() {
}
ConstElementPtr
TranslatorDatabases::getDatabases(const string& xpath) {
try {
if ((model_ == "kea-dhcp4") || (model_ == "kea-dhcp6")) {
return (getDatabasesKea(xpath));
}
} catch (const sysrepo_exception& ex) {
isc_throw(SysrepoError,
"sysrepo error getting database accesses at '" << xpath
<< "': " << ex.what());
}
isc_throw(NotImplemented,
"getDatabases not implemented for the model: " << model_);
}
ElementPtr
TranslatorDatabases::getDatabasesKea(const string& xpath) {
S_Iter_Value iter = getIter(xpath + "/*");
if (!iter) {