]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[65-libyang-option-def] Filled files, waiting for adaptor merge
authorFrancis Dupont <fdupont@isc.org>
Thu, 13 Sep 2018 13:39:11 +0000 (15:39 +0200)
committerFrancis Dupont <fdupont@isc.org>
Fri, 14 Sep 2018 14:15:46 +0000 (16:15 +0200)
src/lib/yang/Makefile.am
src/lib/yang/tests/Makefile.am
src/lib/yang/translator_option_def.cc [new file with mode: 0644]
src/lib/yang/translator_option_def.h [new file with mode: 0644]

index 01b3a633afbfb8df9ff014a2abcdd6323c8c2823..01e4eb69b23ed4e50e7e87b3f77c4e83b42edcfe 100644 (file)
@@ -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
index f54de8916496de5858c5fadc2a26c0872e7490d0..bae9a7a33f04206b5987e51048a0f078ef240b55 100644 (file)
@@ -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 (file)
index 0000000..ca7d80a
--- /dev/null
@@ -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 <yang/translator_option_def.h>
+#include <yang/adaptor.h>
+#include <sstream>
+
+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<unsigned>(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 (file)
index 0000000..3b01237
--- /dev/null
@@ -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 <yang/translator.h>
+#include <list>
+
+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": <code>,
+    ///     "name": <name>,
+    ///     "space": <space>,
+    ///     "type": <type>,
+    ///     "array": <array flag>,
+    ///     "encapsulate": <encapsulated space>,
+    ///     "record-types": <record types>,
+    ///     "user-context": { <json map> },
+    ///     "comment": "<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