From: Francis Dupont Date: Thu, 13 Sep 2018 13:39:11 +0000 (+0200) Subject: [65-libyang-option-def] Filled files, waiting for adaptor merge X-Git-Tag: 65-libyang-class_base^2^2~6^2~8 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=7678be512efcd55aa6ab67a34e7cb82f554cb947;p=thirdparty%2Fkea.git [65-libyang-option-def] Filled files, waiting for adaptor merge --- diff --git a/src/lib/yang/Makefile.am b/src/lib/yang/Makefile.am index 01b3a633af..01e4eb69b2 100644 --- a/src/lib/yang/Makefile.am +++ b/src/lib/yang/Makefile.am @@ -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_option_def.cc +libkea_yang_la_SOURCES += translator_option_def.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 diff --git a/src/lib/yang/tests/Makefile.am b/src/lib/yang/tests/Makefile.am index f54de89164..bae9a7a33f 100644 --- a/src/lib/yang/tests/Makefile.am +++ b/src/lib/yang/tests/Makefile.am @@ -18,6 +18,7 @@ TESTS = if HAVE_GTEST TESTS += run_unittests run_unittests_SOURCES = translator_unittests.cc +run_unittests_SOURCES += translator_option_def_unittests.cc run_unittests_SOURCES += run_unittests.cc run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS) diff --git a/src/lib/yang/translator_option_def.cc b/src/lib/yang/translator_option_def.cc new file mode 100644 index 0000000000..ca7d80a530 --- /dev/null +++ b/src/lib/yang/translator_option_def.cc @@ -0,0 +1,204 @@ +// 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 +#include +#include + +using namespace std; +using namespace isc::data; + +namespace isc { +namespace yang { + +TranslatorOptionDef::TranslatorOptionDef(S_Session session, + const string& model) + : TranslatorBasic(session), model_(model) { +} + +TranslatorOptionDef::~TranslatorOptionDef() { +} + +ElementPtr +TranslatorOptionDef::getOptionDef(const string& xpath) { + try { + if ((model_ == "kea-dhcp4") || (model_ == "kea-dhcp6")) { + return (getOptionDefKea(xpath)); + } + } catch (const sysrepo_exception& ex) { + isc_throw(SysrepoError, + "sysrepo error getting option definition at '" << xpath + << "': " << ex.what()); + } + isc_throw(NotImplemented, + "getOptionDef not implemented for the model: " << model_); +} + +ElementPtr +TranslatorOptionDef::getOptionDefKea(const string& xpath) { + ConstElementPtr code = getItem(xpath + "/code"); + ConstElementPtr name = getItem(xpath + "/name"); + ConstElementPtr type = getItem(xpath + "/type"); + ConstElementPtr space = getItem(xpath + "/space"); + if (!code || !name || !type || !space) { + return (ElementPtr()); + } + ElementPtr result = Element::createMap(); + result->set("code", code); + result->set("name", name); + result->set("type", type); + result->set("space", getItem(xpath + "/space")); + ConstElementPtr record = getItem(xpath + "/record-types"); + if (record) { + result->set("record-types", record); + } + ConstElementPtr array = getItem(xpath + "/array"); + if (array) { + result->set("array", array); + } + ConstElementPtr encapsulate = getItem(xpath + "/encapsulate"); + if (encapsulate) { + result->set("encapsulate", encapsulate); + } + ConstElementPtr context = getItem(xpath + "/user-context"); + if (context) { + result->set("user-context", Element::fromJSON(context->stringValue())); + } + return (result); +} + +void +TranslatorOptionDef::setOptionDef(const string& xpath, ConstElementPtr elem) { + try { + if ((model_ == "kea-dhcp4") || (model_ == "kea-dhcp6")) { + setOptionDefKea(xpath, elem); + } else { + isc_throw(NotImplemented, + "setOptionDef not implemented for the model: " + << model_); + } + } catch (const sysrepo_exception& ex) { + isc_throw(SysrepoError, + "sysrepo error setting option definition '" << elem->str() + << "' at '" << xpath << "': " << ex.what()); + } +} + +void +TranslatorOptionDef::setOptionDefKea(const string& xpath, + ConstElementPtr elem) { + ConstElementPtr name = elem->get("name"); + if (!name) { + isc_throw(BadValue, "option definition with name: " << elem->str()); + } + setItem(xpath + "/name", name, SR_STRING_T); + ConstElementPtr type = elem->get("type"); + if (!type) { + isc_throw(BadValue, "option definition with type: " << elem->str()); + } + setItem(xpath + "/type", type, SR_STRING_T); + ConstElementPtr record = elem->get("record-types"); + if (record) { + setItem(xpath + "/record-types", record, SR_STRING_T); + } + ConstElementPtr array = elem->get("array"); + if (array) { + setItem(xpath + "/array", array, SR_BOOL_T); + } + ConstElementPtr encapsulate = elem->get("encapsulate"); + if (encapsulate) { + setItem(xpath + "/encapsulate", encapsulate, SR_STRING_T); + } + ConstElementPtr context = Adaptor::getContext(elem); + if (context) { + setItem(xpath + "/user-context", Element::create(context->str()), + SR_STRING_T); + } +} + +TranslatorOptionDefList::TranslatorOptionDefList(S_Session session, + const string& model) + : TranslatorBasic(session), TranslatorOptionDef(session, model), + model_(model) { +} + +TranslatorOptionDefList::~TranslatorOptionDefList() { +} + +ConstElementPtr +TranslatorOptionDefList::getOptionDefList(const string& xpath) { + try { + if ((model_ == "kea-dhcp4") || (model_ == "kea-dhcp6")) { + return (getOptionDefListKea(xpath)); + } + } catch (const sysrepo_exception& ex) { + isc_throw(SysrepoError, + "sysrepo error getting option definition list at '" << xpath + << "': " << ex.what()); + } + isc_throw(NotImplemented, + "getOptionDefList not implemented for the model: " << model_); +} + +ConstElementPtr +TranslatorOptionDefList::getOptionDefListKea(const string& xpath) { + ElementPtr result = Element::createList(); + S_Iter_Value iter = getIter(xpath + "/*"); + if (!iter) { + return (ConstElementPtr()); + } + for (;;) { + const string& def = getNext(iter); + if (def.empty()) { + break; + } + result->add(getOptionDef(def)); + } + return (result); +} + +void +TranslatorOptionDefList::setOptionDefList(const string& xpath, + ConstElementPtr elem) { + try { + if ((model_ == "kea-dhcp4") || (model_ == "kea-dhcp6")) { + setOptionDefListKea(xpath, elem); + } else { + isc_throw(NotImplemented, + "setOptionDefList not implemented for the model: " + << model_); + } + } catch (const sysrepo_exception& ex) { + isc_throw(SysrepoError, + "sysrepo error setting option definition list '" + << elem->str() << "' at '" << xpath << "': " << ex.what()); + } +} + +void +TranslatorOptionDefList::setOptionDefListKea(const string& xpath, + ConstElementPtr elem) { + for (size_t i = 0; i < elem->size(); ++i) { + ConstElementPtr def = elem->get(i); + if (!def->contains("code")) { + isc_throw(BadValue, + "option definition without code: " << def->str()); + } + unsigned code = static_cast(def->get("code")->intValue()); + if (!def->contains("space")) { + isc_throw(BadValue, + "option definition without space: " << def->str()); + } + string space = def->get("space")->stringValue(); + ostringstream keys; + keys << xpath << "/option-def[code='" << code + << "'][space='" << space << "']"; + setOptionDef(keys.str(), def); + } +} + +}; // end of namespace isc::yang +}; // end of namespace isc diff --git a/src/lib/yang/translator_option_def.h b/src/lib/yang/translator_option_def.h new file mode 100644 index 0000000000..3b012372c0 --- /dev/null +++ b/src/lib/yang/translator_option_def.h @@ -0,0 +1,138 @@ +// 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_OPTION_DEF_H +#define ISC_TRANSLATOR_OPTION_DEF_H 1 + +#include +#include + +namespace isc { +namespace yang { + +// @brief Between Yang and JSON translator class for the option definition. +class TranslatorOptionDef : virtual public TranslatorBasic { +public: + + /// @brief Constructor. + /// + /// @param session Sysrepo session. + /// @param model Model name. + TranslatorOptionDef(S_Session session, const std::string& model); + + /// @brief Destructor. + virtual ~TranslatorOptionDef(); + + /// @brief Get and translate an option definition from Yang to JSON. + /// + /// JSON syntax for Kea DHCP with command channel is: + /// @code + /// { + /// "code": , + /// "name": , + /// "space": , + /// "type": , + /// "array": , + /// "encapsulate": , + /// "record-types": , + /// "user-context": { }, + /// "comment": "" + /// } + /// @endcode + /// + /// @param xpath The xpath of the option definition. + /// @return JSON representation of the option definition. + /// @throw SysrepoError when sysrepo raises an error. + isc::data::ElementPtr getOptionDef(const std::string& xpath); + + /// @brief Translate and set option definition from JSON to Yang. + /// + /// @param xpath The xpath of the option definition.. + /// @param elem The JSON element. + void setOptionDef(const std::string& xpath, + isc::data::ConstElementPtr elem); + +protected: + /// @brief getOptionDef JSON for kea-dhcp[46]. + /// + /// @param xpath The xpath of the option definition. + /// @return JSON representation of the option definition. + /// @throw SysrepoError when sysrepo raises an error. + isc::data::ElementPtr getOptionDefKea(const std::string& xpath); + + /// @brief setOptionDef for kea-dhcp[46]. + /// + /// Yang syntax for kea-dhcp[46] with code and space as keys is: + /// @code + /// +--rw name string + /// +--rw code uint8 / uint16 + /// +--rw type string + /// +--rw record-types? string + /// +--rw space string + /// +--rw encapsulate? string + /// +--rw array? boolean + /// +--rw user-context? string + /// @endcode + /// + /// @param xpath The xpath of the option definition. + /// @param elem The JSON element. + void setOptionDefKea(const std::string& xpath, + isc::data::ConstElementPtr elem); + + /// @brief The model. + std::string model_; +}; + +// @brief Between Yang and JSON translator class for option definition list. +class TranslatorOptionDefList : virtual public TranslatorOptionDef { +public: + + /// @brief Constructor. + /// + /// @param session Sysrepo session. + /// @param model Model name. + TranslatorOptionDefList(S_Session session, const std::string& model); + + /// @brief Destructor. + virtual ~TranslatorOptionDefList(); + + /// @brief Get and translate option definition list from Yang to JSON. + /// + /// @param xpath The xpath of the option definition list. + /// @throw SysrepoError when sysrepo raises an error. + isc::data::ConstElementPtr getOptionDefList(const std::string& xpath); + + /// @brief Translate and set option definition list from JSON to Yang. + /// + /// @param xpath The xpath of the option definition list. + /// @param elem The JSON element. + void setOptionDefList(const std::string& xpath, + isc::data::ConstElementPtr elem); + +protected: + /// @brief getOptionDefList for kea-dhcp[46]. + /// + /// @param xpath The xpath of the option definition list. + /// @throw SysrepoError when sysrepo raises an error. + isc::data::ConstElementPtr getOptionDefListKea(const std::string& xpath); + + /// @brief setOptionDefList for kea-dhcp[46]. + /// + /// Yang syntax is a option-def list keyed by code and space. + /// + /// @param xpath The xpath of the option definition list. + /// @param elem The JSON element. + void setOptionDefListKea(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_OPTION_DEF_H