summaryrefslogtreecommitdiffstats
path: root/src/lib/yang/translator.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/yang/translator.cc')
-rw-r--r--src/lib/yang/translator.cc318
1 files changed, 318 insertions, 0 deletions
diff --git a/src/lib/yang/translator.cc b/src/lib/yang/translator.cc
new file mode 100644
index 0000000..9e38cfa
--- /dev/null
+++ b/src/lib/yang/translator.cc
@@ -0,0 +1,318 @@
+// Copyright (C) 2018-2019,2021 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.h>
+#include <util/encode/base64.h>
+#include <cstring>
+
+using namespace std;
+using namespace isc::data;
+using namespace isc::util::encode;
+using namespace sysrepo;
+
+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, const string& model)
+ : session_(session), model_(model) {
+}
+
+TranslatorBasic::~TranslatorBasic() {
+}
+
+ElementPtr
+TranslatorBasic::value(sysrepo::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_DECIMAL64_T:
+ return (Element::create(s_val->data()->get_decimal64()));
+
+ 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 unsupported 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) {
+ if (std::string(ex.what()).find("Item not found") != string::npos) {
+ // The YANG configuration node was not there.
+ return nullptr;
+ }
+ 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(getValuesFromItems(xpath));
+ if (!s_vals) {
+ return (ElementPtr());
+ }
+ ElementPtr result(Element::createList());
+ try {
+ for (size_t i = 0; i < s_vals->val_cnt(); ++i) {
+ S_Val s_val = s_vals->val(i);
+ result->add(value(s_val));
+ }
+ } catch (const sysrepo_exception& ex) {
+ isc_throw(SysrepoError, "sysrepo error getting item at '"
+ << xpath << "': " << ex.what());
+ }
+ return (result);
+}
+
+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: "
+ << elem->str());
+ }
+ // 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: "
+ << elem->str());
+ }
+ 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: "
+ << elem->str());
+ }
+ 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: "
+ << elem->str());
+ }
+ s_val.reset(new Val(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: "
+ << elem->str());
+ }
+ s_val.reset(new Val(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: "
+ << elem->str());
+ }
+ s_val.reset(new Val(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: "
+ << elem->str());
+ }
+ s_val.reset(new Val(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: "
+ << elem->str());
+ }
+ s_val.reset(new Val(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: "
+ << elem->str());
+ }
+ s_val.reset(new Val(elem->intValue(), type));
+ break;
+
+ case SR_DECIMAL64_T:
+ if (elem->getType() != Element::real) {
+ isc_throw(BadValue, "value for a real called with not a real");
+ }
+ s_val.reset(new Val(elem->doubleValue()));
+ break;
+
+ case SR_BINARY_T:
+ if (elem->getType() != Element::string) {
+ isc_throw(BadValue,
+ "value for a base64 called with not a string: "
+ << elem->str());
+ }
+ s_val.reset(new Val(encode64(elem->stringValue()).c_str(), type));
+ break;
+
+ default:
+ isc_throw(NotImplemented,
+ "value called with unsupported type: " << type);
+ }
+
+ return (s_val);
+}
+
+void
+TranslatorBasic::setItem(const string& xpath, ConstElementPtr elem,
+ sr_type_t type) {
+ S_Val s_val = value(elem, type);
+ 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());
+ }
+ session_->apply_changes();
+}
+
+void
+TranslatorBasic::checkAndGetLeaf(ElementPtr& storage,
+ const std::string& xpath,
+ const std::string& name) {
+ ConstElementPtr x = getItem(xpath + "/" + name);
+ if (x) {
+ storage->set(name, x);
+ }
+}
+
+void TranslatorBasic::checkAndSetLeaf(ConstElementPtr const& from,
+ string const& xpath,
+ string const& name,
+ sr_type_t const type) {
+ ConstElementPtr const& x(from->get(name));
+ if (x) {
+ setItem(xpath + "/" + name, x, type);
+ }
+}
+
+void
+TranslatorBasic::delItem(const std::string& xpath) {
+ try {
+ session_->delete_item(xpath.c_str());
+ } catch (const sysrepo_exception& ex) {
+ if (std::string(ex.what()).find("Invalid argument") != string::npos) {
+ // The YANG configuration node was not there.
+ return;
+ }
+ isc_throw(SysrepoError,
+ "sysrepo error deleting item at '"
+ << xpath << "': " << ex.what());
+ }
+ session_->apply_changes();
+}
+
+S_Vals TranslatorBasic::getValuesFromItems(std::string const& xpath) {
+ try {
+ return session_->get_items(xpath.c_str());
+ } catch (sysrepo::sysrepo_exception const& exception) {
+ isc_throw(SysrepoError, "sysrepo error getting items: " << exception.what());
+ }
+}
+
+} // namespace yang
+} // namespace isc