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
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)
--- /dev/null
+// 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
--- /dev/null
+// 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) {
+ return (ElementPtr());
+ }
+ ElementPtr result = Element::createList();
+ for (;;) {
+ const string& database = getNext(iter);
+ if (database.empty()) {
+ break;
+ }
+ result->add(getDatabase(database));
+ }
+ if (result->size() > 0) {
+ return (result);
+ } else {
+ return (ElementPtr());
+ }
+}
+
+void
+TranslatorDatabases::setDatabases(const string& xpath, ConstElementPtr elem) {
+ try {
+ if ((model_ == "kea-dhcp4") || (model_ == "kea-dhcp6")) {
+ setDatabasesKea(xpath, elem);
+ } else {
+ isc_throw(NotImplemented,
+ "setDatabases not implemented for the model: "
+ << model_);
+ }
+ } catch (const sysrepo_exception& ex) {
+ isc_throw(SysrepoError,
+ "sysrepo error setting database accesses '" << elem->str()
+ << "' at '" << xpath << "': " << ex.what());
+ }
+}
+
+void
+TranslatorDatabases::setDatabasesKea(const string& xpath,
+ ConstElementPtr elem) {
+ if (!elem) {
+ delItem(xpath + "/hosts-database");
+ delItem(xpath);
+ return;
+ }
+ for (size_t i = 0; i < elem->size(); ++i) {
+ ConstElementPtr database = elem->get(i);
+ if (!database->contains("type")) {
+ isc_throw(BadValue, "database without type: " << database->str());
+ }
+ string type = database->get("type")->stringValue();
+ ostringstream key;
+ key << xpath << "/hosts-database[database-type='" << type << "']";
+ setDatabase(key.str(), database, true);
+ }
+}
+
+}; // end of namespace isc::yang
+}; // end of namespace isc
--- /dev/null
+// 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/.
+
+#ifndef ISC_TRANSLATOR_DATABASE_H
+#define ISC_TRANSLATOR_DATABASE_H 1
+
+#include <yang/translator.h>
+#include <list>
+
+namespace isc {
+namespace yang {
+
+// @brief Between Yang and JSON translator class for a database access.
+class TranslatorDatabase : virtual public TranslatorBasic {
+public:
+
+ /// @brief Constructor.
+ ///
+ /// @param session Sysrepo session.
+ /// @param model Model name.
+ TranslatorDatabase(S_Session session, const std::string& model);
+
+ /// @brief Destructor.
+ virtual ~TranslatorDatabase();
+
+ /// @brief Get and translate a database access from Yang to JSON.
+ ///
+ /// JSON syntax for all Kea servers with database access is:
+ /// @code
+ /// {
+ /// "type": <type>, // required
+ /// "user": <user>,
+ /// "password": <password>,
+ /// "host": <host>,
+ /// "name": <name>,
+ /// "persist": <persist flag>,
+ /// "port": <port>,
+ /// "lfc-interval": <lfc interval>,
+ /// "readonly": <readonly flag>,
+ /// "connect-timeout": <connect timeout>,
+ /// "contact-points": <contact points>,
+ /// "keyspace": <keyspace>,
+ /// "max-reconnect-tries": <maximum reconnect tries>,
+ /// "reconnect-wait-time": <reconnect wait time>,
+ /// "request-timeout": <request timeout>,
+ /// "tcp-keepalive": <TCP keepalive>,
+ /// "tcp-nodelay": <TCP nodelay flag>,
+ /// "user-context": { <json map> },
+ /// "comment": <comment>
+ /// }
+ /// @endcode
+ ///
+ /// @param xpath The xpath of the database.
+ /// @return JSON representation of the database.
+ /// @throw SysrepoError when sysrepo raises an error.
+ isc::data::ElementPtr getDatabase(const std::string& xpath);
+
+ /// @brief Translate and set database access from JSON to Yang.
+ ///
+ /// @param xpath The xpath of the database access.
+ /// @param elem The JSON element.
+ /// @param skip The skip type field flag.
+ void setDatabase(const std::string& xpath,
+ isc::data::ConstElementPtr elem,
+ bool skip = false);
+
+protected:
+ /// @brief getDatabase JSON for kea-dhcp[46].
+ ///
+ /// @param xpath The xpath of the database.
+ /// @return JSON representation of the database.
+ /// @throw SysrepoError when sysrepo raises an error.
+ isc::data::ElementPtr getDatabaseKea(const std::string& xpath);
+
+ /// @brief setDatabase for kea-dhcp[46].
+ ///
+ /// Yang syntax for kea-dhcp[46] is:
+ /// @code
+ /// +--rw database container
+ /// |
+ /// +--rw datanase=type? string
+ /// +--rw user? string
+ /// +--rw password? string
+ /// +--rw host? string
+ /// +--rw name? string
+ /// +--rw persist? boolean
+ /// +--rw port? uint16
+ /// +--rw lfc-interval? uint32
+ /// +--rw readonly? boolean
+ /// +--rw connect-timeout? uint32
+ /// +--rw contact-points? string
+ /// +--rw keyspace? string
+ /// +--rw max-reconnect-tries? uint32
+ /// +--rw reconnect-wait-time? uint32
+ /// +--rw request-timeout? uint32
+ /// +--rw tcp-keepalive? uint32
+ /// +--rw tcp-nodelay? boolean
+ /// +--rw user-context? string
+ /// @endcode
+ ///
+ /// @param xpath The xpath of the database access.
+ /// @param elem The JSON element.
+ /// @param skip The skip type field flag.
+ void setDatabaseKea(const std::string& xpath,
+ isc::data::ConstElementPtr elem,
+ bool skip);
+
+ /// @brief The model.
+ std::string model_;
+};
+
+// @brief Between Yang and JSON translator class for database accesses.
+class TranslatorDatabases : virtual public TranslatorDatabase {
+public:
+
+ /// @brief Constructor.
+ ///
+ /// @param session Sysrepo session.
+ /// @param model Model name.
+ TranslatorDatabases(S_Session session, const std::string& model);
+
+ /// @brief Destructor.
+ virtual ~TranslatorDatabases();
+
+ /// @brief Get and translate database accesses from Yang to JSON.
+ ///
+ /// @param xpath The xpath of databases.
+ /// @return JSON representation of databases.
+ /// @throw SysrepoError when sysrepo raises an error.
+ isc::data::ConstElementPtr getDatabases(const std::string& xpath);
+
+ /// @brief Translate and set database accesses from JSON to Yang.
+ ///
+ /// @param xpath The xpath of databases.
+ /// @param elem The JSON element.
+ void setDatabases(const std::string& xpath,
+ isc::data::ConstElementPtr elem);
+
+protected:
+ /// @brief getDatabases JSON for kea-dhcp[46].
+ ///
+ /// @param xpath The xpath of databases.
+ /// @return JSON representation of databases.
+ /// @throw SysrepoError when sysrepo raises an error.
+ isc::data::ElementPtr getDatabasesKea(const std::string& xpath);
+
+ /// @brief setDatabases for kea-dhcp[46].
+ ///
+ /// Key is the database-type.
+ ///
+ /// @param xpath The xpath of databases.
+ /// @param elem The JSON element.
+ void setDatabasesKea(const std::string& xpath,
+ isc::data::ConstElementPtr elem);
+
+ /// @brief The model.
+ std::string model_;
+};
+
+}; // end of namespace isc::yang
+}; // end of namespace isc
+
+#endif // ISC_TRANSLATOR_DATABASE_H