From: Francis Dupont Date: Mon, 22 Oct 2018 12:48:52 +0000 (+0200) Subject: [65-libyang-shared-network-translator] Added shared network translator code and tests... X-Git-Tag: 153-netconf-test-hang_base~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4c4c0f7ca14e13d32d77f257ce3ace5b0e6493db;p=thirdparty%2Fkea.git [65-libyang-shared-network-translator] Added shared network translator code and tests from kea-yang --- diff --git a/src/lib/yang/Makefile.am b/src/lib/yang/Makefile.am index 5a7545bccf..74aae0da0c 100644 --- a/src/lib/yang/Makefile.am +++ b/src/lib/yang/Makefile.am @@ -25,6 +25,8 @@ libkea_yang_la_SOURCES += translator_pool.cc translator_pool.h libkea_yang_la_SOURCES += translator_pd_pool.cc translator_pd_pool.h libkea_yang_la_SOURCES += translator_host.cc translator_host.h libkea_yang_la_SOURCES += translator_subnet.cc translator_subnet.h +libkea_yang_la_SOURCES += translator_shared_network.cc +libkea_yang_la_SOURCES += translator_shared_network.h libkea_yang_la_SOURCES += yang_models.h libkea_yang_la_LIBADD = $(top_builddir)/src/lib/asiolink/libkea-asiolink.la @@ -56,6 +58,7 @@ libkea_yang_include_HEADERS = \ translator_option_def.h \ translator_pool.h \ translator_pd_pool.h \ + translator_shared_network.h \ translator_subnet.h \ yang_models.h diff --git a/src/lib/yang/tests/Makefile.am b/src/lib/yang/tests/Makefile.am index ac62f820fd..a6764116e2 100644 --- a/src/lib/yang/tests/Makefile.am +++ b/src/lib/yang/tests/Makefile.am @@ -34,6 +34,7 @@ run_unittests_SOURCES += translator_pool_unittests.cc run_unittests_SOURCES += translator_pd_pool_unittests.cc run_unittests_SOURCES += translator_host_unittests.cc run_unittests_SOURCES += translator_subnet_unittests.cc +run_unittests_SOURCES += translator_shared_network_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/tests/translator_shared_network_unittests.cc b/src/lib/yang/tests/translator_shared_network_unittests.cc new file mode 100644 index 0000000000..3165926736 --- /dev/null +++ b/src/lib/yang/tests/translator_shared_network_unittests.cc @@ -0,0 +1,163 @@ +// 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 shared_networks[] = "shared networks"; + +/// @brief Test fixture class for @ref TranslatorSharedNetworks. +class TranslatorSharedNetworksTest : + public GenericTranslatorTest { +public: + + /// Constructor. + TranslatorSharedNetworksTest() { } + + /// Destructor (does nothing). + virtual ~TranslatorSharedNetworksTest() { } +}; + +// This test verifies that an empty shared network list can be properly +// translated from YANG to JSON. +TEST_F(TranslatorSharedNetworksTest, getEmpty) { + useModel(KEA_DHCP4_SERVER); + + // Get the shared network list and check if it is empty. + const string& xpath = "/kea-dhcp4-server:config/shared-networks"; + ConstElementPtr networks; + EXPECT_NO_THROW(networks = t_obj_->getSharedNetworks(xpath)); + ASSERT_TRUE(networks); + ASSERT_EQ(Element::list, networks->getType()); + EXPECT_EQ(0, networks->size()); +} + +// This test verifies that one shared network can be properly +// translated from YANG to JSON. +TEST_F(TranslatorSharedNetworksTest, get) { + useModel(KEA_DHCP6_SERVER); + + // Create the subnet 2001:db8::/48 #111 in shared network foo. + const string& xpath = "/kea-dhcp6-server:config/shared-networks"; + const string& xnetwork = xpath + "/shared-network[name='foo']"; + const string& xsubnet = xnetwork + "/subnet6/subnet6[id='111']/subnet"; + S_Val v_subnet(new Val("2001:db8::/48", SR_STRING_T)); + EXPECT_NO_THROW(sess_->set_item(xsubnet.c_str(), v_subnet)); + + // Get the shared network. + ConstElementPtr network; + EXPECT_NO_THROW(network = t_obj_->getSharedNetwork(xnetwork)); + ASSERT_TRUE(network); + ElementPtr subnet = Element::createMap(); + subnet->set("id", Element::create(111)); + subnet->set("subnet", Element::create(string("2001:db8::/48"))); + ElementPtr subnets = Element::createList(); + subnets->add(subnet); + ElementPtr expected = Element::createMap(); + expected->set("name", Element::create(string("foo"))); + expected->set("subnet6", subnets); + EXPECT_TRUE(expected->equals(*network)); + + // Get the shared network list and check if the shared network is in it. + ConstElementPtr networks; + EXPECT_NO_THROW(networks = t_obj_->getSharedNetworks(xpath)); + ASSERT_TRUE(networks); + ASSERT_EQ(Element::list, networks->getType()); + ASSERT_EQ(1, networks->size()); + EXPECT_TRUE(network->equals(*networks->get(0))); +} + +// This test verifies that an empty shared network list can be properly +// translated from JSON to YANG. +TEST_F(TranslatorSharedNetworksTest, setEmpty) { + useModel(KEA_DHCP4_SERVER); + + // Set empty list. + const string& xpath = "/kea-dhcp4-server:config/shared-networks"; + ConstElementPtr networks = Element::createList(); + EXPECT_NO_THROW(t_obj_->setSharedNetworks(xpath, networks)); + + // Get it back. + networks.reset(); + EXPECT_NO_THROW(networks = t_obj_->getSharedNetworks(xpath)); + ASSERT_TRUE(networks); + ASSERT_EQ(Element::list, networks->getType()); + EXPECT_EQ(0, networks->size()); + + // Check that the tree representation is empty. + S_Tree tree; + EXPECT_NO_THROW(tree = sess_->get_subtree("/kea-dhcp4-server:config")); + EXPECT_FALSE(tree); +} + +// This test verifies that one shared network can be properly +// translated from JSON to YANG. +TEST_F(TranslatorSharedNetworksTest, set) { + useModel(KEA_DHCP6_SERVER); + + // Set one shared network. + const string& xpath = "/kea-dhcp6-server:config/shared-networks"; + ElementPtr networks = Element::createList(); + ElementPtr share = Element::createMap(); + ElementPtr subnets = Element::createList(); + ElementPtr subnet = Element::createMap(); + subnet->set("subnet", Element::create(string("2001:db8::/48"))); + subnet->set("id", Element::create(123)); + subnets->add(subnet); + share->set("name", Element::create(string("foo"))); + share->set("subnet6", subnets); + networks->add(share); + EXPECT_NO_THROW(t_obj_->setSharedNetworks(xpath, networks)); + + // Get it back. + networks.reset(); + EXPECT_NO_THROW(networks = t_obj_->getSharedNetworks(xpath)); + ASSERT_TRUE(networks); + ASSERT_EQ(Element::list, networks->getType()); + ASSERT_EQ(1, networks->size()); + EXPECT_TRUE(share->equals(*networks->get(0))); + + // Check the tree representation. + S_Tree tree; + EXPECT_NO_THROW(tree = sess_->get_subtree("/kea-dhcp6-server:config")); + ASSERT_TRUE(tree); + string expected = + "kea-dhcp6-server:config (container)\n" + " |\n" + " -- shared-networks (container)\n" + " |\n" + " -- shared-network (list instance)\n" + " |\n" + " -- name = foo\n" + " |\n" + " -- subnet6 (container)\n" + " |\n" + " -- subnet6 (list instance)\n" + " |\n" + " -- id = 123\n" + " |\n" + " -- subnet = 2001:db8::/48\n"; + EXPECT_EQ(expected, tree->to_string(100)); + + // Check it validates. + EXPECT_NO_THROW(sess_->validate()); +} + +}; // end of anonymous namespace diff --git a/src/lib/yang/translator_shared_network.cc b/src/lib/yang/translator_shared_network.cc new file mode 100644 index 0000000000..b74bbaabec --- /dev/null +++ b/src/lib/yang/translator_shared_network.cc @@ -0,0 +1,339 @@ +// 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 { + +TranslatorSharedNetwork::TranslatorSharedNetwork(S_Session session, + const string& model) + : TranslatorBasic(session), + TranslatorOptionData(session, model), + TranslatorOptionDataList(session, model), + TranslatorPool(session, model), + TranslatorPools(session, model), + TranslatorPdPool(session, model), + TranslatorPdPools(session, model), + TranslatorHost(session, model), + TranslatorHosts(session, model), + TranslatorSubnet(session, model), + TranslatorSubnets(session, model), + model_(model) { +} + +TranslatorSharedNetwork::~TranslatorSharedNetwork() { +} + +ElementPtr +TranslatorSharedNetwork::getSharedNetwork(const string& xpath) { + try { + if (model_ == KEA_DHCP4_SERVER) { + return (getSharedNetworkKea(xpath, "subnet4")); + } else if (model_ == KEA_DHCP6_SERVER) { + return (getSharedNetworkKea(xpath, "subnet6")); + } + } catch (const sysrepo_exception& ex) { + isc_throw(SysrepoError, + "sysrepo error getting shared network at '" << xpath + << "': " << ex.what()); + } + isc_throw(NotImplemented, + "getSharedNetwork not implemented for the model: " << model_); +} + +ElementPtr +TranslatorSharedNetwork::getSharedNetworkKea(const string& xpath, + const std::string& subsel) { + ElementPtr result = Element::createMap(); + result->set("name", getItem(xpath + "/name")); + ConstElementPtr subnets = getSubnets(xpath + "/" + subsel); + if (subnets && (subnets->size() > 0)) { + result->set(subsel, subnets); + } + if (subsel == "subnet6") { + ConstElementPtr preferred = getItem(xpath + "/preferred-lifetime"); + if (preferred) { + result->set("preferred-lifetime", preferred); + } + } + ConstElementPtr valid = getItem(xpath + "/valid-lifetime"); + if (valid) { + result->set("valid-lifetime", valid); + } + ConstElementPtr renew = getItem(xpath + "/renew-timer"); + if (renew) { + result->set("renew-timer", renew); + } + ConstElementPtr rebind = getItem(xpath + "/rebind-timer"); + if (rebind) { + result->set("rebind-timer", rebind); + } + ConstElementPtr options = getOptionDataList(xpath + "/option-data-list"); + if (options && (options->size() > 0)) { + result->set("option-data", options); + } + ConstElementPtr interface = getItem(xpath + "/interface"); + if (interface) { + result->set("interface", interface); + } + if (subsel == "subnet6") { + ConstElementPtr interface_id = getItem(xpath + "/interface-id"); + if (interface_id) { + result->set("interface-id", interface_id); + } + ConstElementPtr rapid_commit = getItem(xpath + "/rapid-commit"); + if (rapid_commit) { + result->set("rapid-commit", rapid_commit); + } + } + ConstElementPtr guard = getItem(xpath + "/client-class"); + if (guard) { + result->set("client-class", guard); + } + ConstElementPtr required = getItems(xpath + "/require-client-classes"); + if (required && (required->size() > 0)) { + result->set("require-client-classes", required); + } + ConstElementPtr mode = getItem(xpath + "/reservation-mode"); + if (mode) { + result->set("reservation-mode", mode); + } + ConstElementPtr relay = getItems(xpath + "/relay/ip-addresses"); + if (relay && (relay->size() > 0)) { + ElementPtr relay_map = Element::createMap(); + relay_map->set("ip-addresses", relay); + result->set("relay", relay_map); + } + if (subsel == "subnet4") { + ConstElementPtr match = getItem(xpath + "/match-client-id"); + if (match) { + result->set("match-client-id", match); + } + ConstElementPtr next = getItem(xpath + "/next-server"); + if (next) { + result->set("next-server", next); + } + ConstElementPtr hostname = getItem(xpath + "/server-hostname"); + if (hostname) { + result->set("server-hostname", hostname); + } + ConstElementPtr boot = getItem(xpath + "/boot-file-name"); + if (boot) { + result->set("boot-file-name", boot); + } + } + ConstElementPtr context = getItem(xpath + "/user-context"); + if (context) { + result->set("user-context", Element::fromJSON(context->stringValue())); + } + return (result); +} + +void +TranslatorSharedNetwork::setSharedNetwork(const string& xpath, + ConstElementPtr elem) { + try { + if (model_ == KEA_DHCP4_SERVER) { + setSharedNetworkKea(xpath, elem, "subnet4"); + } else if (model_ == KEA_DHCP6_SERVER) { + setSharedNetworkKea(xpath, elem, "subnet6"); + } else { + isc_throw(NotImplemented, + "setSharedNetwork not implemented for the model: " + << model_); + } + } catch (const sysrepo_exception& ex) { + isc_throw(SysrepoError, + "sysrepo error setting shared network '" << elem->str() + << "' at '" << xpath << "': " << ex.what()); + } +} + +void +TranslatorSharedNetwork::setSharedNetworkKea(const string& xpath, + ConstElementPtr elem, + const std::string& subsel) { + // Skip name which is the key. + ConstElementPtr subnets = elem->get(subsel); + if (subnets && (subnets->size() > 0)) { + setSubnets(xpath + "/" + subsel, subnets); + } + if (subsel == "subnet6") { + ConstElementPtr preferred = elem->get("preferred-lifetime"); + if (preferred) { + setItem(xpath + "/preferred-lifetime", preferred, SR_UINT32_T); + } + } + ConstElementPtr valid = elem->get("valid-lifetime"); + if (valid) { + setItem(xpath + "/valid-lifetime", valid, SR_UINT32_T); + } + ConstElementPtr renew = elem->get("renew-timer"); + if (renew) { + setItem(xpath + "/renew-timer", renew, SR_UINT32_T); + } + ConstElementPtr rebind = elem->get("rebind-timer"); + if (rebind) { + setItem(xpath + "/rebind-timer", rebind, SR_UINT32_T); + } + ConstElementPtr options = elem->get("option-data"); + if (options && (options->size() > 0)) { + setOptionDataList(xpath + "/option-data-list", options); + } + ConstElementPtr interface = elem->get("interface"); + if (interface) { + setItem(xpath + "/interface", interface, SR_STRING_T); + } + if (subsel == "subnet6") { + ConstElementPtr interface_id = elem->get("interface-id"); + if (interface_id) { + setItem(xpath + "/interface-id", interface_id, SR_STRING_T); + } + ConstElementPtr rapid_commit = elem->get("rapid-commit"); + if (rapid_commit) { + setItem(xpath + "/rapid-commit", rapid_commit, SR_BOOL_T); + } + } + ConstElementPtr guard = elem->get("client-class"); + if (guard) { + setItem(xpath + "/client-class", guard, SR_STRING_T); + } + ConstElementPtr required = elem->get("require-client-classes"); + if (required && (required->size() > 0)) { + for (ConstElementPtr rclass : required->listValue()) { + setItem(xpath + "/require-client-classes", rclass, SR_STRING_T); + } + } + ConstElementPtr mode = elem->get("reservation-mode"); + if (mode) { + setItem(xpath + "/reservation-mode", mode, SR_ENUM_T); + } + ConstElementPtr relay = elem->get("relay"); + if (relay) { + ConstElementPtr address = relay->get("ip-address"); + ConstElementPtr addresses = relay->get("ip-addresses"); + if (address) { + setItem(xpath + "/relay/ip-addresses", address, SR_STRING_T); + } else if (addresses && (addresses->size() > 0)) { + for (ConstElementPtr addr : addresses->listValue()) { + setItem(xpath + "/relay/ip-addresses", addr, SR_STRING_T); + } + } + } + if (subsel == "subnet4") { + ConstElementPtr match = elem->get("match-client-id"); + if (match) { + setItem(xpath + "/match-client-id", match, SR_BOOL_T); + } + ConstElementPtr next = elem->get("next-server"); + if (next) { + setItem(xpath + "/next-server", next, SR_STRING_T); + } + ConstElementPtr hostname = elem->get("server-hostname"); + if (hostname) { + setItem(xpath + "/server-hostname", hostname, SR_STRING_T); + } + ConstElementPtr boot = elem->get("boot-file-name"); + if (boot) { + setItem(xpath + "/boot-file-name", boot, SR_STRING_T); + } + } + ConstElementPtr context = Adaptor::getContext(elem); + if (context) { + ConstElementPtr repr = Element::create(context->str()); + setItem(xpath + "/user-context", repr, SR_STRING_T); + } +} + +TranslatorSharedNetworks::TranslatorSharedNetworks(S_Session session, + const string& model) + : TranslatorBasic(session), + TranslatorOptionData(session, model), + TranslatorOptionDataList(session, model), + TranslatorPool(session, model), + TranslatorPools(session, model), + TranslatorPdPool(session, model), + TranslatorPdPools(session, model), + TranslatorHost(session, model), + TranslatorHosts(session, model), + TranslatorSubnet(session, model), + TranslatorSubnets(session, model), + TranslatorSharedNetwork(session, model), + model_(model) { +} + +TranslatorSharedNetworks::~TranslatorSharedNetworks() { +} + +ElementPtr +TranslatorSharedNetworks::getSharedNetworks(const string& xpath) { + try { + ElementPtr result = Element::createList(); + S_Iter_Value iter = getIter(xpath + "/*"); + if (!iter) { + // Can't happen. + isc_throw(Unexpected, "getSharedNetworks: can't get iterator: " + << xpath); + } + for (;;) { + const string& network = getNext(iter); + if (network.empty()) { + break; + } + result->add(getSharedNetwork(network)); + } + return (result); + } catch (const sysrepo_exception& ex) { + isc_throw(SysrepoError, + "sysrepo error getting shared networks at '" << xpath + << "': " << ex.what()); + } +} + +void +TranslatorSharedNetworks::setSharedNetworks(const string& xpath, + ConstElementPtr elem) { + try { + if ((model_ == KEA_DHCP4_SERVER) || + (model_ == KEA_DHCP6_SERVER)) { + setSharedNetworksKea(xpath, elem); + } else { + isc_throw(NotImplemented, + "setSharedNetworks not implemented for the model: " + << model_); + } + } catch (const sysrepo_exception& ex) { + isc_throw(SysrepoError, + "sysrepo error setting shared networks '" << elem->str() + << "' at '" << xpath << "': " << ex.what()); + } +} + +void +TranslatorSharedNetworks::setSharedNetworksKea(const string& xpath, + ConstElementPtr elem) { + for (size_t i = 0; i < elem->size(); ++i) { + ConstElementPtr network = elem->get(i); + if (!network->contains("name")) { + isc_throw(BadValue, "setSharedNetworksKea requires name: " + << network->str()); + } + string name = network->get("name")->stringValue(); + ostringstream key; + key<< xpath << "/shared-network[name='" << name << "']"; + setSharedNetwork(key.str(), network); + } +} + +}; // end of namespace isc::yang +}; // end of namespace isc diff --git a/src/lib/yang/translator_shared_network.h b/src/lib/yang/translator_shared_network.h new file mode 100644 index 0000000000..e39c0dff14 --- /dev/null +++ b/src/lib/yang/translator_shared_network.h @@ -0,0 +1,221 @@ +// 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_SHARED_NETWORK_H +#define ISC_TRANSLATOR_SHARED_NETWORK_H 1 + +#include +#include +#include + +namespace isc { +namespace yang { + +/// Shared network translation between YANG and JSON +/// +/// JSON syntax for kea-dhcp4 is: +/// @code +/// { +/// "name": , +/// "subnet4": , +/// "valid-lifetime": , +/// "renew-timer": , +/// "rebind-timer": , +/// "option-data": [ ], +/// "interface": "", +/// "client-class": "", +/// "require-client-classes": [ ], +/// "reservation-mode": , +/// "relay": , +/// "match-client-id": , +/// "next-server": "", +/// "server-hostname": "", +/// "boot-file-name": "", +/// "user-context": { }, +/// "comment": "" +/// } +/// @endcode +/// +/// JSON syntax for kea-dhcp6 is: +/// @code +/// { +/// "name": , +/// "subnet6": , +/// "preferred-lifetime": , +/// "valid-lifetime": , +/// "renew-timer": , +/// "rebind-timer": , +/// "option-data": [ ], +/// "interface": "", +/// "interface-id": "", +/// "rapid-commit": , +/// "client-class": "", +/// "require-client-classes": [ ], +/// "reservation-mode": , +/// "relay": , +/// "user-context": { }, +/// "comment": "" +/// } +/// @endcode +/// +/// YANG syntax for kea-dhcp[46] is with name as the list key: +/// @code +/// +--rw name string +/// +--rw valid-lifetime? uint32 +/// +--rw renew-timer? uint32 +/// +--rw rebind-timer? uint32 +/// +--rw option-data-list option-data* +/// +--rw interface? string +/// +--rw client-class? string +/// +--rw require-client-classes* string +/// +--rw reservation-mode? enumeration +/// +--rw relay ip-addresses* +/// +--rw user-context? string +/// (DHCPv4 only) +/// +--rw subnet4 subnet4* +/// +--rw match-client-id? boolean +/// +--rw next-server? inet:ipv4-address +/// +--rw server-hostname? string +/// +--rw boot-file-name? string +/// (DHCPv6 only) +/// +--rw subnet6 subnet6* +/// +--rw preferred-lifetime? uint32 +/// +--rw interface-id? string +/// +--rw rapid-commit? boolean +/// @endcode +/// +/// An example in JSON and YANG formats: +/// @code +/// [ +/// { +/// "name": "foo", +/// "subnet6": +/// [ +/// { +/// "subnet": "2001:db8::/48", +/// "id": 123 +/// } +/// ] +/// } +/// ] +/// @endcode +/// @code +/// /kea-dhcp6-server:config (container) +/// /kea-dhcp6-server:config/shared-networks (container) +/// /kea-dhcp6-server:config/shared-networks/ +/// shared-network[name='foo'] (list instance) +/// /kea-dhcp6-server:config/shared-networks/shared-network[name='foo']/ +/// name = foo +/// /kea-dhcp6-server:config/shared-networks/shared-network[name='foo']/ +/// subnet6 (container) +/// /kea-dhcp6-server:config/shared-networks/shared-network[name='foo']/ +/// subnet6/subnet6[id='123'] (list instance) +/// /kea-dhcp6-server:config/shared-networks/shared-network[name='foo']/ +/// subnet6/subnet6[id='123']/id = 123 +/// /kea-dhcp6-server:config/shared-networks/shared-network[name='foo']/ +/// subnet6/subnet6[id='123']/subnet = 2001:db8::/48 +/// @endcode + +/// @brief A translator class for converting a shared network between +/// YANG and JSON. +/// +/// Currently supports on kea-dhcp[46]-server. Does not exist in +/// ietf-dhcpv6-server. +class TranslatorSharedNetwork : virtual public TranslatorSubnets { +public: + + /// @brief Constructor. + /// + /// @param session Sysrepo session. + /// @param model Model name. + TranslatorSharedNetwork(S_Session session, const std::string& model); + + /// @brief Destructor. + virtual ~TranslatorSharedNetwork(); + + /// @brief Get and translate a shared network from YANG to JSON. + /// + /// @param xpath The xpath of the shared network. + /// @return JSON representation of the shared network. + /// @throw SysrepoError when sysrepo raises an error. + isc::data::ElementPtr getSharedNetwork(const std::string& xpath); + + /// @brief Translate and set shared network from JSON to YANG. + /// + /// @param xpath The xpath of the shared network. + /// @param elem The JSON element. + void setSharedNetwork(const std::string& xpath, + isc::data::ConstElementPtr elem); + +protected: + /// @brief getSharedNetwork for kea-dhcp[46]. + /// + /// @param xpath The xpath of the shared network. + /// @param subsel The subnet list name. + /// @return JSON representation of the shared network. + isc::data::ElementPtr getSharedNetworkKea(const std::string& xpath, + const std::string& subsel); + + /// @brief setSharedNetwork for kea-dhcp[46]. + /// + /// @param xpath The xpath of the shared network. + /// @param elem The JSON element. + /// @param subsel The subnet list name. + void setSharedNetworkKea(const std::string& xpath, + isc::data::ConstElementPtr elem, + const std::string& subsel); + + /// @brief The model. + std::string model_; +}; + +/// @brief A translator class for converting a shared network list between +/// YANG and JSON. +/// +/// Currently supports on kea-dhcp[46]-server. Does not exist in +/// ietf-dhcpv6-server. +class TranslatorSharedNetworks : virtual public TranslatorSharedNetwork { +public: + + /// @brief Constructor. + /// + /// @param session Sysrepo session. + /// @param model Model name. + TranslatorSharedNetworks(S_Session session, const std::string& model); + + /// @brief Destructor. + virtual ~TranslatorSharedNetworks(); + + /// @brief Get and translate shared networks from YANG to JSON. + /// + /// @param xpath The xpath of the shared network list. + /// @throw SysrepoError when sysrepo raises an error. + isc::data::ElementPtr getSharedNetworks(const std::string& xpath); + + /// @brief Translate and set shared networks from JSON to YANG. + /// + /// @param xpath The xpath of the shared network list. + /// @param elem The JSON element. + void setSharedNetworks(const std::string& xpath, + isc::data::ConstElementPtr elem); + +protected: + /// @brief setSharedNetworks for kea-dhcp[46]. + /// + /// @param xpath The xpath of the shared network list. + /// @param elem The JSON element. + /// @throw BadValue on a shared network without name. + void setSharedNetworksKea(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_SHARED_NETWORK_H