Commit d4530a00 authored by Francis Dupont's avatar Francis Dupont

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

parent ae3d891f
......@@ -7,6 +7,8 @@ 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_control_socket.cc
libkea_yang_la_SOURCES += translator_control_socket.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_control_socket_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_control_socket.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 control socket using the Kea ad hoc model.
TEST(TranslatorControlSocketTest, getEmpty) {
// Get a translator control socket object to play with.
S_Connection conn(new Connection("translator control socket unittests"));
S_Session sess(new Session(conn, SR_DS_CANDIDATE));
boost::scoped_ptr<TranslatorControlSocket> tcs_obj;
// Use the ad hoc model.
const string& model = "kea-dhcp4";
EXPECT_NO_THROW(tcs_obj.reset(new TranslatorControlSocket(sess, model)));
// Get empty.
const string& xpath = "/kea-dhcp4:config/control-socket";
ConstElementPtr sock;
EXPECT_NO_THROW(sock = tcs_obj->getControlSocket(xpath));
EXPECT_FALSE(sock);
}
// Test get not empty control socket using the Kea ad hoc model.
TEST(TranslatorControlSocketTest, get) {
// Get a translator control socket object to play with.
S_Connection conn(new Connection("translator control socket unittests"));
S_Session sess(new Session(conn, SR_DS_CANDIDATE));
boost::scoped_ptr<TranslatorControlSocket> tcs_obj;
// Use the ad hoc model.
const string& model = "kea-dhcp6";
EXPECT_NO_THROW(tcs_obj.reset(new TranslatorControlSocket(sess, model)));
// Set a value.
const string& xpath = "/kea-dhcp6:config/control-socket";
const string& xname = xpath + "/socket-name";
const string& xtype = xpath + "/socket-type";
const string& xcontext = xpath + "/user-context";
S_Val s_name(new Val("/tmp/kea.sock"));
EXPECT_NO_THROW(sess->set_item(xname.c_str(), s_name));
S_Val s_type(new Val("unix", SR_ENUM_T));
EXPECT_NO_THROW(sess->set_item(xtype.c_str(), s_type));
S_Val s_context(new Val("{ \"foo\": 1 }"));
EXPECT_NO_THROW(sess->set_item(xcontext.c_str(), s_context));
// Get it.
ConstElementPtr sock;
EXPECT_NO_THROW(sock = tcs_obj->getControlSocket(xpath));
ASSERT_TRUE(sock);
ASSERT_EQ(Element::map, sock->getType());
EXPECT_EQ(3, sock->size());
ConstElementPtr type = sock->get("socket-type");
ASSERT_TRUE(type);
ASSERT_EQ(Element::string, type->getType());
EXPECT_EQ("unix", type->stringValue());
ConstElementPtr name = sock->get("socket-name");
ASSERT_TRUE(name);
ASSERT_EQ(Element::string, name->getType());
EXPECT_EQ("/tmp/kea.sock", name->stringValue());
ConstElementPtr context = sock->get("user-context");
ASSERT_TRUE(context);
EXPECT_EQ("{ \"foo\": 1 }", context->str());
}
// Test set not empty control socket using the Kea ad hoc model.
TEST(TranslatorControlSocketTest, set) {
// Get a translator control socket object to play with.
S_Connection conn(new Connection("translator control socket unittests"));
S_Session sess(new Session(conn, SR_DS_CANDIDATE));
boost::scoped_ptr<TranslatorControlSocket> tcs_obj;
// Use the ad hoc model.
const string& model = "kea-control-agent";
EXPECT_NO_THROW(tcs_obj.reset(new TranslatorControlSocket(sess, model)));
// Set a value.
const string& xpath =
"/kea-control-agent:config/control-sockets/socket[server-type='dhcp4']/control-socket";
ElementPtr sock = Element::createMap();
sock->set("socket-name", Element::create(string("/tmp/kea.sock")));
sock->set("socket-type", Element::create(string("unix")));
sock->set("comment", Element::create(string("a comment")));
try {
tcs_obj->setControlSocket(xpath, sock);
} catch (const std::exception& ex) {
cerr << "setControlSocket fail with " << ex.what() << endl;
}
ASSERT_NO_THROW(tcs_obj->setControlSocket(xpath, sock));
// Get it back.
ConstElementPtr got;
EXPECT_NO_THROW(got = tcs_obj->getControlSocket(xpath));
ASSERT_TRUE(got);
ASSERT_EQ(Element::map, got->getType());
EXPECT_EQ(3, got->size());
ConstElementPtr name = got->get("socket-name");
ASSERT_TRUE(name);
ASSERT_EQ(Element::string, name->getType());
EXPECT_EQ("/tmp/kea.sock", name->stringValue());
ConstElementPtr type = got->get("socket-type");
ASSERT_TRUE(type);
ASSERT_EQ(Element::string, type->getType());
EXPECT_EQ("unix", type->stringValue());
ConstElementPtr context = got->get("user-context");
ASSERT_TRUE(context);
EXPECT_EQ("{ \"comment\": \"a comment\" }", context->str());
}
// Test set empty control socket using the Kea ad hoc model.
TEST(TranslatorControlSocketTest, setEmpty) {
// Get a translator control socket object to play with.
S_Connection conn(new Connection("translator control socket unittests"));
S_Session sess(new Session(conn, SR_DS_CANDIDATE));
boost::scoped_ptr<TranslatorControlSocket> tcs_obj;
// Use the ad hoc model.
const string& model = "kea-dhcp4";
EXPECT_NO_THROW(tcs_obj.reset(new TranslatorControlSocket(sess, model)));
// Set a value.
const string& xpath = "/kea-dhcp4:config/control-socket";
const string& xname = xpath + "/socket-name";
const string& xtype = xpath + "/socket-type";
const string& xcontext = xpath + "/user-context";
S_Val s_name(new Val("/tmp/kea.sock"));
EXPECT_NO_THROW(sess->set_item(xname.c_str(), s_name));
S_Val s_type(new Val("unix", SR_ENUM_T));
EXPECT_NO_THROW(sess->set_item(xtype.c_str(), s_type));
S_Val s_context(new Val("{ \"foo\": 1 }"));
EXPECT_NO_THROW(sess->set_item(xcontext.c_str(), s_context));
// Reset to empty.
ASSERT_NO_THROW(tcs_obj->setControlSocket(xpath, ConstElementPtr()));
// Get it back.
ConstElementPtr sock;
EXPECT_NO_THROW(sock = tcs_obj->getControlSocket(xpath));
EXPECT_FALSE(sock);
}
}; // 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_control_socket.h>
#include <yang/adaptor.h>
#include <sstream>
using namespace std;
using namespace isc::data;
namespace isc {
namespace yang {
TranslatorControlSocket::TranslatorControlSocket(S_Session session,
const string& model)
: TranslatorBasic(session), model_(model) {
}
TranslatorControlSocket::~TranslatorControlSocket() {
}
ConstElementPtr
TranslatorControlSocket::getControlSocket(const string& xpath) {
try {
if ((model_ == "kea-dhcp4") || (model_ == "kea-dhcp6") ||
(model_ == "kea-dhcpddns") || (model_ == "kea-control-agent")) {
return (getControlSocketKea(xpath));
}
} catch (const sysrepo_exception& ex) {
isc_throw(SysrepoError,
"sysrepo error getting control socket at '" << xpath
<< "': " << ex.what());
}
isc_throw(NotImplemented,
"getControlSocket not implemented for the model: " << model_);
}
ElementPtr
TranslatorControlSocket::getControlSocketKea(const string& xpath) {
ConstElementPtr name = getItem(xpath + "/socket-name");
ConstElementPtr type = getItem(xpath + "/socket-type");
if (name && type) {
ElementPtr result = Element::createMap();
result->set("socket-name", name);
result->set("socket-type", type);
ConstElementPtr context = getItem(xpath + "/user-context");
if (context) {
result->set("user-context",
Element::fromJSON(context->stringValue()));
}
return (result);
}
return (ElementPtr());
}
void
TranslatorControlSocket::setControlSocket(const string& xpath,
ConstElementPtr elem) {
try {
if ((model_ == "kea-dhcp4") || (model_ == "kea-dhcp6") ||
(model_ == "kea-dhcpddns") || (model_ == "kea-control-agent")) {
setControlSocketKea(xpath, elem);
} else {
isc_throw(NotImplemented,
"setControlSocket not implemented for the model: "
<< model_);
}
} catch (const sysrepo_exception& ex) {
isc_throw(SysrepoError,
"sysrepo error setting control socket '" << elem->str()
<< "' at '" << xpath << "': " << ex.what());
}
}
void
TranslatorControlSocket::setControlSocketKea(const string& xpath,
ConstElementPtr elem) {
if (!elem) {
delItem(xpath + "/socket-name");
delItem(xpath + "/socket-type");
delItem(xpath + "/user-context");
delItem(xpath);
return;
}
ConstElementPtr name = elem->get("socket-name");
if (!name) {
isc_throw(BadValue, "setControlSocket missing socket name");
}
ConstElementPtr type = elem->get("socket-type");
if (!type) {
isc_throw(BadValue, "setControlSocket missing socket type");
}
setItem(xpath + "/socket-name", name, SR_STRING_T);
setItem(xpath + "/socket-type", type, SR_ENUM_T);
ConstElementPtr context = Adaptor::getContext(elem);
if (context) {
setItem(xpath + "/user-context", Element::create(context->str()),
SR_STRING_T);
}
}
}; // end of namespace isc::yang
}; // end of namespace isc
// 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_CONTROL_SOCKET_H
#define ISC_TRANSLATOR_CONTROL_SOCKET_H 1
#include <yang/translator.h>
#include <list>
namespace isc {
namespace yang {
// @brief Between Yang and JSON translator class for the control socket.
class TranslatorControlSocket : virtual public TranslatorBasic {
public:
/// @brief Constructor.
///
/// @param session Sysrepo session.
/// @param model Model name.
TranslatorControlSocket(S_Session session, const std::string& model);
/// @brief Destructor.
virtual ~TranslatorControlSocket();
/// @brief Get and translate a control socket from Yang to JSON.
///
/// JSON syntax for all Kea servers with command channel is:
/// @code
/// "control-socket": {
/// "socket-type": "<socket type>",
/// "socket-name": "<socket name>",
/// "user-context": { <json map> },
/// "comment": "<comment>"
/// }
/// @endcode
///
/// @param xpath The xpath of the control socket.
/// @return JSON representation of the control socket.
/// @throw SysrepoError when sysrepo raises an error.
isc::data::ConstElementPtr getControlSocket(const std::string& xpath);
/// @brief Translate and set control socket from JSON to Yang.
///
/// @param xpath The xpath of the control socket.
/// @param elem The JSON element.
void setControlSocket(const std::string& xpath,
isc::data::ConstElementPtr elem);
protected:
/// @brief getControlSocket JSON for kea models.
///
/// @param xpath The xpath of the control socket.
/// @return JSON representation of the control socket.
/// @throw SysrepoError when sysrepo raises an error.
isc::data::ElementPtr getControlSocketKea(const std::string& xpath);
/// @brief setControlSocket for kea models.
///
/// Yang syntax is:
/// @code
/// +--rw control-socket container
/// |
/// +--rw socket-name string
/// +--rw socket-type enumeration
/// +--rw user-context? string
/// @endcode
///
/// @param xpath The xpath of the control socket.
/// @param elem The JSON element.
void setControlSocketKea(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_CONTROL_SOCKET_H
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