Commit 8051d349 authored by Francis Dupont's avatar Francis Dupont

[65-libyang-generic] Imported generic stuff

parent 61289a15
SUBDIRS = . tests
AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
AM_CPPFLAGS += $(BOOST_INCLUDES) $(SYSREPO_CPPFLAGS)
AM_CXXFLAGS = $(KEA_CXXFLAGS)
lib_LTLIBRARIES = libkea-yang.la
libkea_yang_la_SOURCES = sysrepo_error.h
libkea_yang_la_SOURCES += sysrepo_connection.cc sysrepo_connection.h
libkea_yang_la_SOURCES += translator.cc translator.h
libkea_yang_la_SOURCES += watcher.cc watcher.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
libkea_yang_la_LIBADD += $(top_builddir)/src/lib/log/libkea-log.la
libkea_yang_la_LIBADD += $(top_builddir)/src/lib/util/threads/libkea-threads.la
libkea_yang_la_LIBADD += $(top_builddir)/src/lib/util/libkea-util.la
libkea_yang_la_LIBADD += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la
libkea_yang_la_LIBADD += $(LOG4CPLUS_LIBS) $(BOOST_LIBS) $(SYSREPO_LIBS)
libkea_yang_la_LDFLAGS = -no-undefined -version-info 0:0:0
# Specify the headers for copying into the installation directory tree.
libkea_yang_includedir = $(pkgincludedir)/yang
libkea_yang_include_HEADERS = \
sysrepo_connection.h \
sysrepo_error.h \
translator.h \
watcher.h
EXTRA_DIST = yang.dox
CLEANFILES = *.gcno *.gcda
// 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/sysrepo_connection.h>
namespace isc {
namespace yang {
SysrepoConnection::SysrepoConnection() {
}
SysrepoConnection::~SysrepoConnection() {
if (session_) {
session_->discard_changes();
session_->unlock_datastore();
session_->session_stop();
// how to call disconnect?
}
}
void
SysrepoConnection::connect() {
// Get a connection.
S_Connection conn(new Connection("kea-netconf"));
// Get a session.
session_.reset(new Session(conn, SR_DS_CANDIDATE));
// Get a from yang object.
}
void
SysrepoConnection::commit() {
if (!session_) {
isc_throw(SysrepoConnectionError, "session not established");
}
session_->commit();
}
}
}
// 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 NETCONF_CONNECTION_H
#define NETCONF_CONNECTION_H
#include <exceptions/exceptions.h>
#include <sysrepo-cpp/Session.h>
namespace isc {
namespace yang {
class SysrepoConnectionError : public Exception {
public:
SysrepoConnectionError(const char* file, size_t line, const char* what) :
isc::Exception(file, line, what) {}
};
class SysrepoConnection {
public:
SysrepoConnection();
virtual ~SysrepoConnection();
void connect();
void commit();
private:
S_Session session_;
};
} // sysrepo
} // isc
#endif /* NETCONF_CONNECTION_H_ */
// 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_SYSREPO_ERROR_H
#define ISC_SYSREPO_ERROR_H 1
#include <exceptions/exceptions.h>
namespace isc {
namespace yang {
/// @brief Sysrepo error.
class SysrepoError : public isc::Exception {
public:
SysrepoError(const char* file, size_t line, const char* what) :
isc::Exception(file, line, what)
{}
};
}; // end of namespace isc::yang
}; // end of namespace isc
#endif // ISC_SYSREPO_ERROR_H
AM_CPPFLAGS = -I$(top_builddir)/src/lib -I$(top_srcdir)/src/lib
AM_CPPFLAGS += $(BOOST_INCLUDES) $(SYSREPO_CPPFLAGS)
AM_CPPFLAGS += -DCFG_EXAMPLES=\"$(abs_top_srcdir)/doc/examples\"
AM_CXXFLAGS = $(KEA_CXXFLAGS)
if USE_STATIC_LINK
AM_LDFLAGS = -static
endif
CLEANFILES = *.gcno *.gcda
TESTS_ENVIRONMENT = \
$(LIBTOOL) --mode=execute $(VALGRIND_COMMAND)
TESTS =
if HAVE_GTEST
TESTS += run_unittests
run_unittests_SOURCES = translator_unittests.cc
run_unittests_SOURCES += run_unittests.cc
run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES)
run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS)
run_unittests_LDADD = $(top_builddir)/src/lib/yang/testutils/libyangtest.la
run_unittests_LDADD += $(top_builddir)/src/lib/yang/libkea-yang.la
run_unittests_LDADD += $(top_builddir)/src/lib/testutils/libkea-testutils.la
run_unittests_LDADD += $(top_builddir)/src/lib/cc/libkea-cc.la
run_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libkea-asiolink.la
run_unittests_LDADD += $(top_builddir)/src/lib/log/libkea-log.la
run_unittests_LDADD += $(top_builddir)/src/lib/util/threads/libkea-threads.la
run_unittests_LDADD += $(top_builddir)/src/lib/util/unittests/libutil_unittests.la
run_unittests_LDADD += $(top_builddir)/src/lib/util/libkea-util.la
run_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la
run_unittests_LDADD += $(LOG4CPLUS_LIBS) $(BOOST_LIBS)
run_unittests_LDADD += $(SYSREPO_LIBS) $(GTEST_LDADD)
endif
noinst_PROGRAMS = $(TESTS)
// 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 <gtest/gtest.h>
#include <util/unittests/run_all.h>
#include <log/logger_support.h>
int
main(int argc, char* argv[]) {
::testing::InitGoogleTest(&argc, argv);
isc::log::initLogger();
return (isc::util::unittests::run_all());
}
This diff is collapsed.
// 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.h>
#include <util/encode/base64.h>
#include <cstring>
using namespace std;
using namespace isc::data;
using namespace isc::util::encode;
namespace {
string encode64(const string& input) {
vector<uint8_t> binary;
binary.resize(input.size());
memmove(&binary[0], input.c_str(), binary.size());
return (encodeBase64(binary));
}
string decode64(const string& input) {
vector<uint8_t> binary;
decodeBase64(input, binary);
string result;
result.resize(binary.size());
memmove(&result[0], &binary[0], result.size());
return (result);
}
} // end of anonymous namespace
namespace isc {
namespace yang {
TranslatorBasic::TranslatorBasic(S_Session session) : session_(session) {
}
TranslatorBasic::~TranslatorBasic() {
}
ElementPtr
TranslatorBasic::value(S_Val s_val) {
if (!s_val) {
isc_throw(BadValue, "value called with null");
}
switch (s_val->type()) {
case SR_CONTAINER_T:
case SR_CONTAINER_PRESENCE_T:
// Internal node.
return (ElementPtr());
case SR_LIST_T:
return (Element::createList());
case SR_STRING_T:
return (Element::create(string(s_val->data()->get_string())));
case SR_BOOL_T:
return (Element::create(s_val->data()->get_bool() ? true : false));
case SR_UINT8_T:
return (Element::create(static_cast<long long>(s_val->data()->get_uint8())));
case SR_UINT16_T:
return (Element::create(static_cast<long long>(s_val->data()->get_uint16())));
case SR_UINT32_T:
return (Element::create(static_cast<long long>(s_val->data()->get_uint32())));
case SR_INT8_T:
return (Element::create(static_cast<long long>(s_val->data()->get_int8())));
case SR_INT16_T:
return (Element::create(static_cast<long long>(s_val->data()->get_int16())));
case SR_INT32_T:
return (Element::create(static_cast<long long>(s_val->data()->get_int32())));
case SR_IDENTITYREF_T:
return (Element::create(string(s_val->data()->get_identityref())));
case SR_ENUM_T:
return (Element::create(string(s_val->data()->get_enum())));
case SR_BINARY_T:
return (Element::create(decode64(s_val->data()->get_binary())));
default:
isc_throw(NotImplemented,
"value called with unupported type: " << s_val->type());
}
}
ElementPtr
TranslatorBasic::getItem(const string& xpath) {
S_Val s_val;
try {
s_val = session_->get_item(xpath.c_str());
} catch (const sysrepo_exception& ex) {
isc_throw(SysrepoError,
"sysrepo error getting item at '" << xpath
<< "': " << ex.what());
}
if (!s_val) {
return (ElementPtr());
}
return (value(s_val));
}
ElementPtr
TranslatorBasic::getItems(const string& xpath) {
S_Vals s_vals;
try {
s_vals = session_->get_items(xpath.c_str());
if (!s_vals) {
return (ElementPtr());
}
ElementPtr result = Element::createList();
for (size_t i = 0; i < s_vals->val_cnt(); ++i) {
S_Val s_val = s_vals->val(i);
result->add(value(s_val));
}
return (result);
} catch (const sysrepo_exception& ex) {
isc_throw(SysrepoError,
"sysrepo error getting item at '" << xpath
<< "': " << ex.what());
}
}
S_Val
TranslatorBasic::value(ConstElementPtr elem, sr_type_t type) {
if (!elem) {
isc_throw(BadValue, "value called with null");
}
S_Val s_val;
switch (type) {
case SR_CONTAINER_T:
case SR_CONTAINER_PRESENCE_T:
isc_throw(NotImplemented, "value called for a container");
case SR_LIST_T:
if (elem->getType() != Element::list) {
isc_throw(BadValue, "value for a list called with not a list");
}
// Return null.
break;
case SR_STRING_T:
case SR_IDENTITYREF_T:
case SR_ENUM_T:
if (elem->getType() != Element::string) {
isc_throw(BadValue, "value for a string called with not a string");
}
s_val.reset(new Val(elem->stringValue().c_str(), type));
break;
case SR_BOOL_T:
if (elem->getType() != Element::boolean) {
isc_throw(BadValue, "value for a boolean called with not a boolean");
}
s_val.reset(new Val(elem->boolValue(), type));
break;
case SR_UINT8_T:
if (elem->getType() != Element::integer) {
isc_throw(BadValue, "value for an integer called with not an integer");
}
s_val.reset(new Val(static_cast<uint8_t>(elem->intValue()), type));
break;
case SR_UINT16_T:
if (elem->getType() != Element::integer) {
isc_throw(BadValue, "value for an integer called with not an integer");
}
s_val.reset(new Val(static_cast<uint16_t>(elem->intValue()), type));
break;
case SR_UINT32_T:
if (elem->getType() != Element::integer) {
isc_throw(BadValue, "value for an integer called with not an integer");
}
s_val.reset(new Val(static_cast<uint32_t>(elem->intValue()), type));
break;
case SR_INT8_T:
if (elem->getType() != Element::integer) {
isc_throw(BadValue, "value for an integer called with not an integer");
}
s_val.reset(new Val(static_cast<int8_t>(elem->intValue()), type));
break;
case SR_INT16_T:
if (elem->getType() != Element::integer) {
isc_throw(BadValue, "value for an integer called with not an integer");
}
s_val.reset(new Val(static_cast<int16_t>(elem->intValue()), type));
break;
case SR_INT32_T:
if (elem->getType() != Element::integer) {
isc_throw(BadValue, "value for an integer called with not an integer");
}
s_val.reset(new Val(static_cast<int32_t>(elem->intValue()), type));
break;
case SR_BINARY_T:
if (elem->getType() != Element::string) {
isc_throw(BadValue, "value for a base64 called with not a string");
}
s_val.reset(new Val(encode64(elem->stringValue()).c_str(), type));
break;
default:
isc_throw(NotImplemented,
"value called with unupported type: " << type);
}
return (s_val);
}
void
TranslatorBasic::setItem(const string& xpath, ConstElementPtr elem,
sr_type_t type) {
S_Val s_val = value(elem, type);
if (!s_val && (type != SR_LIST_T)) {
return;
}
try {
session_->set_item(xpath.c_str(), s_val);
} catch (const sysrepo_exception& ex) {
isc_throw(SysrepoError,
"sysrepo error setting item '" << elem->str()
<< "' at '" << xpath << "': " << ex.what());
}
}
void
TranslatorBasic::delItem(const std::string& xpath) {
try {
session_->delete_item(xpath.c_str());
} catch (const sysrepo_exception& ex) {
isc_throw(SysrepoError,
"sysrepo error deleting item at '"
<< xpath << "': " << ex.what());
}
}
S_Iter_Value
TranslatorBasic::getIter(const std::string& xpath) {
return (session_->get_items_iter(xpath.c_str()));
}
string
TranslatorBasic::getNext(S_Iter_Value iter) {
if (!iter) {
isc_throw(BadValue, "getNext called with null");
}
S_Val s_val;
try {
s_val = session_->get_item_next(iter);
} catch (const sysrepo_exception&) {
// Should not happen according to the doc but still happen?
return ("");
}
if (!s_val) {
return ("");
}
return (s_val->xpath());
}
}; // 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_H
#define ISC_TRANSLATOR_H 1
#include <cc/data.h>
#include <yang/sysrepo_error.h>
#include <sysrepo-cpp/Session.h>
namespace isc {
namespace yang {
/// @brief Between Yang and JSON translator class for basic values.
class TranslatorBasic {
public:
/// @brief Constructor.
///
/// @param session Sysrepo session.
TranslatorBasic(S_Session session);
/// @brief Destructor.
virtual ~TranslatorBasic();
/// @brief Translate basic value from Yang to JSON.
///
/// @note Please don't use this outside tests.
///
/// @param s_val The value.
/// @return The Element representing the sysrepo value.
/// @throw NotImplemented when the value type is not supported.
static isc::data::ElementPtr value(S_Val s_val);
/// @brief Get and translate basic value from Yang to JSON.
///
/// @note Should be const as it is read only...
///
/// @param xpath The xpath of the basic value.
/// @return The Element representing the item at xpath or null when not found.
/// @throw SysrepoError when sysrepo raises an error.
/// @throw NotImplemented when the value type is not supported.
isc::data::ElementPtr getItem(const std::string& xpath);
/// @brief Get and translate a list of basic values from Yang to JSON.
///
/// @param xpath The xpath of the list of basic values.
/// @return The ListElement representing the leaf-list at xpath or
/// null when not found.
isc::data::ElementPtr getItems(const std::string& xpath);
/// @brief Translate basic value from JSON to Yang.
///
/// @note Please don't use this outside tests.
///
/// @param elem The JSON element.
/// @param type The sysrepo type.
static S_Val value(isc::data::ConstElementPtr elem, sr_type_t type);
/// @brief Translate and set basic value from JSON to Yang.
///
/// @param xpath The xpath of the basic value.
/// @param elem The JSON element.
/// @param type The sysrepo type.
void setItem(const std::string& xpath, isc::data::ConstElementPtr elem,
sr_type_t type);
/// @brief Delete basic value from Yang.
///
/// @param xpath The xpath of the basic value.
void delItem(const std::string& xpath);
/// List iterator methods keeping the session private.
/// @brief Get iterator over a Yang list.
///
/// @param xpath The xpath of the list.
/// @return An S_Iter_Value pointer. Null is the list does not exist.
S_Iter_Value getIter(const std::string& xpath);
/// @brief Get xpath of the next Yang list item.
///
/// @param iter The iterator.
/// @return The xpath of the next element. Null when at the end of the list.
std::string getNext(S_Iter_Value iter);
protected:
/// @brief The sysrepo session.
S_Session session_;
};
}; // end of namespace isc::yang
}; // end of namespace isc
#endif // ISC_TRANSLATOR_H
// 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/watcher.h>
using namespace std;
using namespace isc::data;
namespace isc {
namespace yang {
Watcher::Watcher(SysrepoConnection &connection, const string &xpath)
: xpath_(xpath), netconf_data_(0), connection_(connection) {
};
Watcher::~Watcher() {
}
string
Watcher::getXPath() {
return (xpath_);
}
ElementPtr
Watcher::getJSON() {
return (json_);
}
} // namespace netconf
} // 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_WATCHER_H
#define ISC_WATCHER_H
#include <config.h>
#include <boost/shared_ptr.hpp>
#include <cc/data.h>
#include <yang/sysrepo_connection.h>
namespace isc {
namespace yang {
/// @brief This represents a base class for all watchers.
///
/// Isc_Watcher is an object that receives callback notification
/// from sysrepo (in YANG format) and converts it to appropriate
/// JSON that can be sent over control channel and understood by Kea.
class Watcher {
public:
// Constructor (requires xpath to install a callback)
Watcher(SysrepoConnection &connection, const std::string &xpath);