From: Francis Dupont Date: Sat, 6 Oct 2018 10:33:20 +0000 (+0200) Subject: [65-libyang-logger_rebased] Updated after pool merge X-Git-Tag: 153-netconf-configs_base^2~1^2^2^2 X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=480fa67c0cf1c26ac6c8bf817e71f110b2936d46;p=thirdparty%2Fkea.git [65-libyang-logger_rebased] Updated after pool merge --- 480fa67c0cf1c26ac6c8bf817e71f110b2936d46 diff --cc src/lib/yang/Makefile.am index bc7d227481,b36ca9641f..8bb0f5e835 --- a/src/lib/yang/Makefile.am +++ b/src/lib/yang/Makefile.am @@@ -31,9 -30,9 +32,11 @@@ libkea_yang_include_HEADERS = adaptor.h \ sysrepo_error.h \ translator.h \ + translator_logger.h \ translator_option_data.h \ - translator_option_def.h + translator_option_def.h \ - translator_pool.h ++ translator_pool.h \ ++ yang_models.h EXTRA_DIST = yang.dox # Distribute yang models. diff --cc src/lib/yang/tests/Makefile.am index 58018a599b,6d29445b36..f919ff9d43 --- a/src/lib/yang/tests/Makefile.am +++ b/src/lib/yang/tests/Makefile.am @@@ -20,9 -20,10 +20,10 @@@ TESTS += run_unittest run_unittests_SOURCES = adaptor_unittests.cc run_unittests_SOURCES += sysrepo_setup.h run_unittests_SOURCES += translator_unittests.cc + run_unittests_SOURCES += translator_logger_unittests.cc run_unittests_SOURCES += translator_option_data_unittests.cc run_unittests_SOURCES += translator_option_def_unittests.cc -run_unittests_SOURCES = translator_unittests.cc +run_unittests_SOURCES += translator_pool_unittests.cc run_unittests_SOURCES += run_unittests.cc run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS) diff --cc src/lib/yang/tests/translator_logger_unittests.cc index 0000000000,361d8395e2..3c24db0ea5 mode 000000,100644..100644 --- a/src/lib/yang/tests/translator_logger_unittests.cc +++ b/src/lib/yang/tests/translator_logger_unittests.cc @@@ -1,0 -1,178 +1,179 @@@ + // 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 + #include + + #include + + using namespace std; + using namespace isc; + using namespace isc::data; + using namespace isc::yang; + using namespace isc::yang::test; + + namespace { + + /// @brief Translator name. + extern char const logger_list[] = "logger list"; + + /// @brief Test fixture class for @ref TranslatorLoggers. + class TranslatorLoggersTest : + public GenericTranslatorTest { + public: + + /// Constructor. + TranslatorLoggersTest() { } + + /// Destructor (does nothing). + virtual ~TranslatorLoggersTest() { } + }; + + // This test verifies that an empty logger list can be properly + // translated from YANG to JSON. + TEST_F(TranslatorLoggersTest, getEmpty) { - useModel("kea-dhcp4-server"); ++ useModel(KEA_DHCP4_SERVER); + + // Get empty. + const string& xpath = "/kea-dhcp4-server:logging/loggers"; + ConstElementPtr loggers; + EXPECT_NO_THROW(loggers = t_obj_->getLoggers(xpath)); + ASSERT_TRUE(loggers); + EXPECT_EQ(0, loggers->size()); + } + + // This test verifies that one logger can be properly + // translated from YANG to JSON. + TEST_F(TranslatorLoggersTest, get) { - useModel("kea-dhcp6-server"); ++ useModel(KEA_DHCP6_SERVER); + + // Set a value. + const string& xpath = "/kea-dhcp6-server:logging/loggers"; + const string& xlogger = xpath + "/logger[name='foo']"; + const string& xseverity = xlogger + "/severity"; + const string& xoption = xlogger + "/output-options/option[output='/bar']"; + const string& xmaxver = xoption + "/maxver"; + S_Val s_severity(new Val("WARN", SR_ENUM_T)); + EXPECT_NO_THROW(sess_->set_item(xseverity.c_str(), s_severity)); + uint32_t max_ver = 10; + S_Val s_maxver(new Val(max_ver, SR_UINT32_T)); + EXPECT_NO_THROW(sess_->set_item(xmaxver.c_str(), s_maxver)); + + // Get empty. + ConstElementPtr loggers; + EXPECT_NO_THROW(loggers = t_obj_->getLoggers(xpath)); + ASSERT_TRUE(loggers); + ASSERT_EQ(1, loggers->size()); + ConstElementPtr logger = loggers->get(0); + ASSERT_TRUE(logger); + EXPECT_EQ(3, logger->size()); + ConstElementPtr name = logger->get("name"); + ASSERT_TRUE(name); + ASSERT_EQ(Element::string, name->getType()); + EXPECT_EQ("foo", name->stringValue()); + ConstElementPtr severity = logger->get("severity"); + ASSERT_TRUE(severity); + ASSERT_EQ(Element::string, severity->getType()); + EXPECT_EQ("WARN", severity->stringValue()); + ConstElementPtr options = logger->get("output_options"); + ASSERT_TRUE(options); + ASSERT_EQ(1, options->size()); + ConstElementPtr option = options->get(0); + ASSERT_TRUE(option); + EXPECT_EQ(2, option->size()); + ConstElementPtr output = option->get("output"); + ASSERT_TRUE(output); + ASSERT_EQ(Element::string, output->getType()); + EXPECT_EQ("/bar", output->stringValue()); + ConstElementPtr maxver = option->get("maxver"); + ASSERT_TRUE(maxver); + ASSERT_EQ(Element::integer, maxver->getType()); + EXPECT_EQ(max_ver, maxver->intValue()); + } + + // This test verifies that one logger can be properly + // translated from JSON to YANG. + TEST_F(TranslatorLoggersTest, set) { - useModel("kea-dhcp4-server"); ++ useModel(KEA_DHCP4_SERVER); + + // Set a value. + const string& xpath = "/kea-dhcp4-server:logging/loggers"; + ElementPtr option = Element::createMap(); + option->set("output", Element::create(string("/bar"))); + option->set("maxver", Element::create(10)); + ElementPtr options = Element::createList(); + options->add(option); + ElementPtr logger = Element::createMap(); + logger->set("name", Element::create(string("foo"))); + logger->set("severity", Element::create(string("WARN"))); + logger->set("output_options", options); + ElementPtr loggers = Element::createList(); + loggers->add(logger); + ASSERT_NO_THROW(t_obj_->setLoggers(xpath, loggers)); + + // Get it back. + ConstElementPtr gots; + EXPECT_NO_THROW(gots = t_obj_->getLoggers(xpath)); + ASSERT_TRUE(gots); + ASSERT_EQ(1, gots->size()); + ConstElementPtr got = gots->get(0); + ASSERT_TRUE(got); + EXPECT_EQ(3, got->size()); + ConstElementPtr name = got->get("name"); + ASSERT_TRUE(name); + ASSERT_EQ(Element::string, name->getType()); + EXPECT_EQ("foo", name->stringValue()); + ConstElementPtr severity = logger->get("severity"); + ASSERT_TRUE(severity); + ASSERT_EQ(Element::string, severity->getType()); + EXPECT_EQ("WARN", severity->stringValue()); + ConstElementPtr got_os = logger->get("output_options"); + ASSERT_TRUE(got_os); + ASSERT_EQ(1, got_os->size()); + ConstElementPtr got_o = got_os->get(0); + ASSERT_TRUE(got_o); + EXPECT_EQ(2, got_o->size()); + ConstElementPtr output = got_o->get("output"); + ASSERT_TRUE(output); + ASSERT_EQ(Element::string, output->getType()); + EXPECT_EQ("/bar", output->stringValue()); + ConstElementPtr maxver = got_o->get("maxver"); + ASSERT_TRUE(maxver); + ASSERT_EQ(Element::integer, maxver->getType()); + EXPECT_EQ(10, maxver->intValue()); + + // Check the tree representation. + S_Tree tree; + EXPECT_NO_THROW(tree = sess_->get_subtree("/kea-dhcp4-server:logging")); + ASSERT_TRUE(tree); + string expected = + "kea-dhcp4-server:logging (container)\n" + " |\n" + " -- loggers (container)\n" + " |\n" + " -- logger (list instance)\n" + " |\n" + " -- name = foo\n" + " |\n" + " -- output-options (container)\n" + " | |\n" + " | -- option (list instance)\n" + " | |\n" + " | -- output = /bar\n" + " | |\n" + " | -- maxver = 10\n" + " |\n" + " -- severity = WARN\n"; + EXPECT_EQ(expected, tree->to_string(100)); + + // Check it validates. + EXPECT_NO_THROW(sess_->validate()); + } + + }; // end of anonymous namespace diff --cc src/lib/yang/translator_logger.cc index 0000000000,2b46a47e61..e43de36de8 mode 000000,100644..100644 --- a/src/lib/yang/translator_logger.cc +++ b/src/lib/yang/translator_logger.cc @@@ -1,0 -1,274 +1,275 @@@ + // 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 + #include + + using namespace std; + using namespace isc::data; + + namespace isc { + namespace yang { + + TranslatorLogger::TranslatorLogger(S_Session session, const string& model) + : TranslatorBasic(session), model_(model) { + } + + TranslatorLogger::~TranslatorLogger() { + } + + ElementPtr + TranslatorLogger::getLogger(const string& xpath) { + try { - if ((model_ == "kea-dhcp4-server") || - (model_ == "kea-dhcp6-server") || - (model_ == "kea-dhcp-ddns") || - (model_ == "kea-ctrl-agent")) { ++ if ((model_ == KEA_DHCP4_SERVER) || ++ (model_ == KEA_DHCP6_SERVER) || ++ (model_ == KEA_DHCP_DDNS) || ++ (model_ == KEA_CTRL_AGENT)) { + return (getLoggerKea(xpath)); + } + } catch (const sysrepo_exception& ex) { + isc_throw(SysrepoError, + "sysrepo error getting logger at '" << xpath + << "': " << ex.what()); + } + isc_throw(NotImplemented, + "getLogger not implemented for the model: " << model_); + } + + ElementPtr + TranslatorLogger::getLoggerKea(const string& xpath) { + ConstElementPtr name = getItem(xpath + "/name"); + if (!name) { + // Can't happen as name is the key. + isc_throw(Unexpected, "getLoggerKea requires name: " << xpath); + } + ElementPtr result = Element::createMap(); + result->set("name", name); + ConstElementPtr options = getOutputOptions(xpath + "/output-options"); + if (options && (options->size() > 0)) { + result->set("output_options", options); + } + ConstElementPtr severity = getItem(xpath + "/severity"); + if (severity) { + result->set("severity", severity); + } + ConstElementPtr debuglevel = getItem(xpath + "/debuglevel"); + if (debuglevel) { + result->set("debuglevel", debuglevel); + } + ConstElementPtr context = getItem(xpath + "/user-context"); + if (context) { + result->set("user-context", Element::fromJSON(context->stringValue())); + } + return (result); + } + + ElementPtr + TranslatorLogger::getOutputOption(const string& xpath) { + ConstElementPtr output = getItem(xpath + "/output"); + if (!output) { + // Can't happen as output is the key. + isc_throw(Unexpected, "getOutputOption requires (!output): " << xpath); + } + ElementPtr result = Element::createMap(); + result->set("output", output); + ConstElementPtr maxver = getItem(xpath + "/maxver"); + if (maxver) { + result->set("maxver", maxver); + } + ConstElementPtr maxsize = getItem(xpath + "/maxsize"); + if (maxsize) { + result->set("maxsize", maxsize); + } + ConstElementPtr flush = getItem(xpath + "/flush"); + if (flush) { + result->set("flush", flush); + } + return (result); + } + + ElementPtr + TranslatorLogger::getOutputOptions(const string& xpath) { + S_Iter_Value iter = getIter(xpath + "/*"); + if (!iter) { + // Can't happen. + isc_throw(Unexpected, "getOutputOptions: can't get iterator: " + << xpath); + } + ElementPtr result = Element::createList(); + for (;;) { + const string& option = getNext(iter); + if (option.empty()) { + break; + } + result->add(getOutputOption(option)); + } + return (result); + } + + void + TranslatorLogger::setLogger(const string& xpath, ConstElementPtr elem) { + try { - if ((model_ == "kea-dhcp4-server") || - (model_ == "kea-dhcp6-server") || - (model_ == "kea-dhcp-ddns") || - (model_ == "kea-ctrl-agent")) { ++ if ((model_ == KEA_DHCP4_SERVER) || ++ (model_ == KEA_DHCP6_SERVER) || ++ (model_ == KEA_DHCP_DDNS) || ++ (model_ == KEA_CTRL_AGENT)) { + setLoggerKea(xpath, elem); + } else { + isc_throw(NotImplemented, + "setLogger not implemented for the model: " << model_); + } + } catch (const sysrepo_exception& ex) { + isc_throw(SysrepoError, + "sysrepo error setting logger '" << elem->str() + << "' at '" << xpath << "': " << ex.what()); + } + } + + void + TranslatorLogger::setLoggerKea(const string& xpath, ConstElementPtr elem) { + // Skip name as it is the key. + ConstElementPtr options = elem->get("output_options"); + if (options && (options->size() > 0)) { + setOutputOptions(xpath + "/output-options", options); + } + ConstElementPtr debuglevel = elem->get("debuglevel"); + if (debuglevel) { + setItem(xpath + "/debuglevel", debuglevel, SR_UINT8_T); + } + ConstElementPtr severity = elem->get("severity"); + if (severity) { + setItem(xpath + "/severity", severity, SR_ENUM_T); + } + ConstElementPtr context = Adaptor::getContext(elem); + if (context) { + setItem(xpath + "/user-context", Element::create(context->str()), + SR_STRING_T); + } + } + + void + TranslatorLogger::setOutputOption(const string& xpath, ConstElementPtr elem) { + bool created = false; + // Skip output as it is the key. + ConstElementPtr maxver = elem->get("maxver"); + if (maxver) { + setItem(xpath + "/maxver", maxver, SR_UINT32_T); + created = true; + } + ConstElementPtr maxsize = elem->get("maxsize"); + if (maxsize) { + setItem(xpath + "/maxsize", maxsize, SR_UINT32_T); + created = true; + } + ConstElementPtr flush = elem->get("flush"); + if (flush) { + setItem(xpath + "/flush", flush, SR_BOOL_T); + created = true; + } + // There is no mandatory fields outside the key so force creation. + if (!created) { + ConstElementPtr list = Element::createList(); + setItem(xpath, list, SR_LIST_T); + } + } + + void + TranslatorLogger::setOutputOptions(const string& xpath, ConstElementPtr elem) { + for (size_t i = 0; i < elem->size(); ++i) { + ConstElementPtr option = elem->get(i); + if (!option->contains("output")) { + isc_throw(BadValue, "output-options without output: " + << option->str()); + } + string output = option->get("output")->stringValue(); + ostringstream key; + key << xpath << "/option[output='" << output << "']"; + setOutputOption(key.str(), option); + } + } + + TranslatorLoggers::TranslatorLoggers(S_Session session, const string& model) + : TranslatorBasic(session), + TranslatorLogger(session, model), + model_(model) { + } + + TranslatorLoggers::~TranslatorLoggers() { + } + + ConstElementPtr + TranslatorLoggers::getLoggers(const string& xpath) { + try { - if ((model_ == "kea-dhcp4-server") || - (model_ == "kea-dhcp6-server") || - (model_ == "kea-dhcp-ddns") || - (model_ == "kea-ctrl-agent")) { ++ if ((model_ == KEA_DHCP4_SERVER) || ++ (model_ == KEA_DHCP6_SERVER) || ++ (model_ == KEA_DHCP_DDNS) || ++ (model_ == KEA_CTRL_AGENT)) { + return (getLoggersKea(xpath)); + } + } catch (const sysrepo_exception& ex) { + isc_throw(SysrepoError, + "sysrepo error getting loggeres at '" << xpath + << "': " << ex.what()); + } + isc_throw(NotImplemented, + "getLoggers not implemented for the model: " << model_); + } + + ElementPtr + TranslatorLoggers::getLoggersKea(const string& xpath) { + S_Iter_Value iter = getIter(xpath + "/*"); + if (!iter) { + // Can't happen. + isc_throw(Unexpected, "getLoggersKea: can't get iterator: " << xpath); + } + ElementPtr result = Element::createList(); + for (;;) { + const string& logger = getNext(iter); + if (logger.empty()) { + break; + } + result->add(getLogger(logger)); + } + return (result); + } + + void + TranslatorLoggers::setLoggers(const string& xpath, ConstElementPtr elem) { + try { - if ((model_ == "kea-dhcp4-server") || - (model_ == "kea-dhcp6-server") || - (model_ == "kea-dhcp-ddns") || - (model_ == "kea-ctrl-agent")) { ++ if ((model_ == KEA_DHCP4_SERVER) || ++ (model_ == KEA_DHCP6_SERVER) || ++ (model_ == KEA_DHCP_DDNS) || ++ (model_ == KEA_CTRL_AGENT)) { + setLoggersKea(xpath, elem); + } else { + isc_throw(NotImplemented, + "setLoggers not implemented for the model: " << model_); + } + } catch (const sysrepo_exception& ex) { + isc_throw(SysrepoError, + "sysrepo error setting loggeres '" << elem->str() + << "' at '" << xpath << "': " << ex.what()); + } + } + + void + TranslatorLoggers::setLoggersKea(const string& xpath, ConstElementPtr elem) { + for (size_t i = 0; i < elem->size(); ++i) { + ConstElementPtr logger = elem->get(i); + if (!logger->contains("name")) { + isc_throw(BadValue, "logger without name: " << logger->str()); + } + string name = logger->get("name")->stringValue(); + ostringstream key; + key << xpath << "/logger[name='" << name << "']"; + setLogger(key.str(), logger); + } + } + + }; // end of namespace isc::yang + }; // end of namespace isc