Commit 4c4c0f7c authored by Francis Dupont's avatar Francis Dupont Committed by Tomek Mrugalski

[65-libyang-shared-network-translator] Added shared network translator code and tests from kea-yang

parent 180a6382
......@@ -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
......
......@@ -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)
......
// 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 <config.h>
#include <yang/translator_shared_network.h>
#include <yang/yang_models.h>
#include <yang/tests/sysrepo_setup.h>
#include <gtest/gtest.h>
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<shared_networks, TranslatorSharedNetworks> {
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
This diff is collapsed.
// 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 <yang/translator.h>
#include <yang/translator_subnet.h>
#include <list>
namespace isc {
namespace yang {
/// Shared network translation between YANG and JSON
///
/// JSON syntax for kea-dhcp4 is:
/// @code
/// {
/// "name": <name>,
/// "subnet4": <subnet list>,
/// "valid-lifetime": <valid lifetime>,
/// "renew-timer": <renew timer>,
/// "rebind-timer": <rebind timer>,
/// "option-data": [ <list of option data> ],
/// "interface": "<interface>",
/// "client-class": "<guard class name>",
/// "require-client-classes": [ <list of required class names> ],
/// "reservation-mode": <host reservation mode>,
/// "relay": <relay ip address(es)>,
/// "match-client-id": <match client id flag>,
/// "next-server": "<next server>",
/// "server-hostname": "<server hostname>",
/// "boot-file-name": "<boot file name>",
/// "user-context": { <json map> },
/// "comment": "<comment>"
/// }
/// @endcode
///
/// JSON syntax for kea-dhcp6 is:
/// @code
/// {
/// "name": <name>,
/// "subnet6": <subnet list>,
/// "preferred-lifetime": <preferred lifetime>,
/// "valid-lifetime": <valid lifetime>,
/// "renew-timer": <renew timer>,
/// "rebind-timer": <rebind timer>,
/// "option-data": [ <list of option data> ],
/// "interface": "<interface>",
/// "interface-id": "<interface id>",
/// "rapid-commit": <rapid commit flag>,
/// "client-class": "<guard class name>",
/// "require-client-classes": [ <list of required class names> ],
/// "reservation-mode": <host reservation mode>,
/// "relay": <relay ip address(es)>,
/// "user-context": { <json map> },
/// "comment": "<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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment