From: Francis Dupont Date: Tue, 26 Jun 2018 14:35:13 +0000 (+0200) Subject: [3543] Checkpoint: specific unit tests to write X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3ccbbb915178429be64935c8126cd9e4ca7d7213;p=thirdparty%2Fkea.git [3543] Checkpoint: specific unit tests to write --- diff --git a/doc/examples/ddns/comments.json b/doc/examples/ddns/comments.json index 44a28b8364..f97005b098 100644 --- a/doc/examples/ddns/comments.json +++ b/doc/examples/ddns/comments.json @@ -12,6 +12,13 @@ "port": 53001, "dns-server-timeout" : 1000, + "control-socket": + { + "comment": "Control channel", + "socket-type": "unix", + "socket-name": "/tmp/d2-ctrl-socket" + }, + "forward-ddns": { "ddns-domains": diff --git a/doc/examples/ddns/sample1.json b/doc/examples/ddns/sample1.json index a413dc6e1b..890fc08adf 100644 --- a/doc/examples/ddns/sample1.json +++ b/doc/examples/ddns/sample1.json @@ -29,6 +29,15 @@ "user-context": { "version": 1 }, +// +// ----------------- Control Socket ----------------- +// + + "control-socket": + { + "socket-type": "unix", + "socket-name": "/tmp/d2-ctrl-socket" + }, // // ----------------- Forward DDNS ------------------ diff --git a/doc/examples/ddns/template.json b/doc/examples/ddns/template.json index c11f5b38e4..a3024bf364 100644 --- a/doc/examples/ddns/template.json +++ b/doc/examples/ddns/template.json @@ -20,6 +20,16 @@ // "ncr-protocol" : "UDP" // "ncr-format" : "JSON" +// +// ----------------- Control Socket ----------------- +// + +// "control-socket": +// { +// "socket-type": "unix", +// "socket-name": "/tmp/d2-ctrl-socket" +// }, + // // ----------------- Forward DDNS ------------------ // diff --git a/doc/guide/ctrl-channel.xml b/doc/guide/ctrl-channel.xml index 0fdf8e8340..213d80db97 100644 --- a/doc/guide/ctrl-channel.xml +++ b/doc/guide/ctrl-channel.xml @@ -19,14 +19,14 @@ the server may refuse to start, which will further extend the downtime period until the issue is resolved. - To avoid such problems, both the DHCPv4 and DHCPv6 servers + To avoid such problems, the DHCPv4, DHCPv6 and D2 servers include support for a mechanism that allows on-line reconfiguration without requiring server shutdown. Both servers can be instructed to open control sockets, which is a communication channel. The server is able to receive commands on that channel, act on them and report back status. - The DHCPv4 and DHCPv6 servers receive commands over the + The DHCPv4, DHCPv6 and D2 servers receive commands over the unix domain sockets. The details how to configure these sockets, see and . While it is possible control the servers directly using unix domain sockets it requires that @@ -613,6 +613,36 @@ $ curl -X POST -H "Content-Type: application/json" -d '{ "command": "config-get" +
+ Commands Supported by D2 Server + The D2 server supports only a subset of DHCPv4 / DHCPv6 server + commands: + + + build-report + + + config-get + + + config-test + + + config-write + + + list-commands + + + shutdown + + + version-get + + + +
+
Commands Supported by Control Agent The following commands listed in diff --git a/doc/guide/ddns.xml b/doc/guide/ddns.xml index 2bde0a43b5..fd2e5bc721 100644 --- a/doc/guide/ddns.xml +++ b/doc/guide/ddns.xml @@ -238,6 +238,11 @@ strings path/kea-dhcp-ddns | sed -n 's/;;;; //p' Global Server Parameters - values which control connectivity and global server behavior + + + Control Socket - defines the Control Socket type and name. + + TSIG Key Info - defines the TSIG keys used for secure traffic with DNS servers @@ -320,6 +325,57 @@ corresponding values in the DHCP servers' "dhcp-ddns" configuration section.
+
+ Management API for the D2 Server + + The management API allows the issuing of specific management + commands, such as configuration retrieval or shutdown. + For more details, see . + Currently the only supported communication channel type is UNIX + stream socket. By default there are no sockets open. To instruct + Kea to open a socket, the following entry in the configuration + file can be used: + +"DhcpDdns": { + "control-socket": { + "socket-type": "unix", + "socket-name": "/path/to/the/unix/socket" + }, + ... +} + + + + + The length of the path specified by + the socket-name parameter is restricted by + the maximum length for the unix socket name on your operating + system, i.e. the size of the sun_path field + in the sockaddr_un structure, decreased by 1. + This value varies on different operating systems between + 91 and 107 characters. Typical values are 107 on Linux and 103 + on FreeBSD. + + + + Communication over control channel is conducted using JSON + structures. See the Control Channel section in the Kea + Developer's Guide for more details. + + + The D2 server supports the following operational commands: + + build-report + config-get + config-test + config-write + list-commands + shutdown + version-get + + +
+
TSIG Key List diff --git a/src/bin/d2/d2_controller.h b/src/bin/d2/d2_controller.h index e34bfd5d2a..1673533929 100644 --- a/src/bin/d2/d2_controller.h +++ b/src/bin/d2/d2_controller.h @@ -12,6 +12,10 @@ namespace isc { namespace d2 { +class D2Controller; +/// @brief Pointer to a process controller. +typedef boost::shared_ptr D2ControllerPtr; + /// @brief Process Controller for D2 Process /// This class is the DHCP-DDNS specific derivation of DControllerBase. It /// creates and manages an instance of the DHCP-DDNS application process, diff --git a/src/bin/d2/d2_lexer.cc b/src/bin/d2/d2_lexer.cc index 2878cf69c7..10da0eb1a9 100644 --- a/src/bin/d2/d2_lexer.cc +++ b/src/bin/d2/d2_lexer.cc @@ -1782,6 +1782,7 @@ YY_RULE_SETUP case isc::d2::D2ParserContext::DNS_SERVERS: case isc::d2::D2ParserContext::TSIG_KEY: case isc::d2::D2ParserContext::TSIG_KEYS: + case isc::d2::D2ParserContext::CONTROL_SOCKET: case isc::d2::D2ParserContext::LOGGERS: return isc::d2::D2Parser::make_USER_CONTEXT(driver.loc_); default: @@ -1801,6 +1802,7 @@ YY_RULE_SETUP case isc::d2::D2ParserContext::DNS_SERVERS: case isc::d2::D2ParserContext::TSIG_KEY: case isc::d2::D2ParserContext::TSIG_KEYS: + case isc::d2::D2ParserContext::CONTROL_SOCKET: case isc::d2::D2ParserContext::LOGGERS: return isc::d2::D2Parser::make_COMMENT(driver.loc_); default: diff --git a/src/bin/d2/d2_lexer.ll b/src/bin/d2/d2_lexer.ll index ce5262d3db..df44c7e7fe 100644 --- a/src/bin/d2/d2_lexer.ll +++ b/src/bin/d2/d2_lexer.ll @@ -269,6 +269,7 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence} case isc::d2::D2ParserContext::DNS_SERVERS: case isc::d2::D2ParserContext::TSIG_KEY: case isc::d2::D2ParserContext::TSIG_KEYS: + case isc::d2::D2ParserContext::CONTROL_SOCKET: case isc::d2::D2ParserContext::LOGGERS: return isc::d2::D2Parser::make_USER_CONTEXT(driver.loc_); default: @@ -285,6 +286,7 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence} case isc::d2::D2ParserContext::DNS_SERVERS: case isc::d2::D2ParserContext::TSIG_KEY: case isc::d2::D2ParserContext::TSIG_KEYS: + case isc::d2::D2ParserContext::CONTROL_SOCKET: case isc::d2::D2ParserContext::LOGGERS: return isc::d2::D2Parser::make_COMMENT(driver.loc_); default: diff --git a/src/bin/d2/d2_process.cc b/src/bin/d2/d2_process.cc index 215c146ba8..5848f7f85b 100644 --- a/src/bin/d2/d2_process.cc +++ b/src/bin/d2/d2_process.cc @@ -10,6 +10,7 @@ #include #include #include +#include #include using namespace isc::process; @@ -248,10 +249,17 @@ D2Process::configureCommandChannel() { if (!ctx) { return; } + D2ControllerPtr ctrl = + boost::dynamic_pointer_cast(D2Controller::instance()); + if (!ctrl) { + return; + } isc::data::ConstElementPtr sock_cfg = ctx->getControlSocketInfo(); - if (sock_cfg) { + if (sock_cfg && (sock_cfg->size() > 0)) { // Assume that CommandMgr works with D2 I/O. + isc::config::CommandMgr::instance().setIOService(getIoService()); isc::config::CommandMgr::instance().openCommandSocket(sock_cfg); + ctrl->registerCommands(); } } diff --git a/src/bin/d2/d2_simple_parser.cc b/src/bin/d2/d2_simple_parser.cc index ad5c68314e..6880fd524d 100644 --- a/src/bin/d2/d2_simple_parser.cc +++ b/src/bin/d2/d2_simple_parser.cc @@ -120,6 +120,13 @@ D2SimpleParser::setAllDefaults(isc::data::ElementPtr global) { // Set global defaults first. cnt = setDefaults(global, D2_GLOBAL_DEFAULTS); + // If the control socket is no present, set it to empty map. + if (!global->find("control-socket")) { + ConstElementPtr map(new MapElement()); + global->set("control-socket", map); + cnt++; + } + // If the key list is present, set its members' defaults if (global->find("tsig-keys")) { ConstElementPtr keys = global->get("tsig-keys"); diff --git a/src/bin/d2/tests/d2_cfg_mgr_unittests.cc b/src/bin/d2/tests/d2_cfg_mgr_unittests.cc index 2579b2ef46..5ce55843bf 100644 --- a/src/bin/d2/tests/d2_cfg_mgr_unittests.cc +++ b/src/bin/d2/tests/d2_cfg_mgr_unittests.cc @@ -271,6 +271,10 @@ TEST_F(D2CfgMgrTest, defaultValues) { ASSERT_NO_THROW(deflt = defaults->get("ip-address")); ASSERT_TRUE(deflt); EXPECT_EQ(deflt->stringValue(), d2_params_->getIpAddress().toText()); + ConstElementPtr ctrl_sock; + ASSERT_NO_THROW(ctrl_sock = defaults->get("control-socket")); + ASSERT_TRUE(ctrl_sock); + EXPECT_EQ(0, ctrl_sock->size()); // Check that omitting port gets you its default config = @@ -426,6 +430,8 @@ TEST_F(D2CfgMgrTest, invalidEntry) { " unexpected constant string, expecting JSON"); } +// Control socket tests in d2_process_unittests.cc + // DdnsDomainList and TSIGKey tests moved to d2_simple_parser_unittest.cc /// @brief Tests construction of D2CfgMgr @@ -462,9 +468,13 @@ TEST_F(D2CfgMgrTest, fullConfig) { std::string config = "{ " "\"ip-address\" : \"192.168.1.33\" , " "\"port\" : 88 , " - " \"dns-server-timeout\": 333 , " - " \"ncr-protocol\": \"UDP\" , " - " \"ncr-format\": \"JSON\", " + "\"dns-server-timeout\": 333 , " + "\"ncr-protocol\": \"UDP\" , " + "\"ncr-format\": \"JSON\", " + "\"control-socket\" : {" + " \"socket-type\" : \"unix\" ," + " \"socket-name\" : \"/tmp/d2-ctrl-channel\" " + "}," "\"tsig-keys\": [" "{" " \"name\": \"d2_key.example.com\" , " @@ -533,6 +543,16 @@ TEST_F(D2CfgMgrTest, fullConfig) { EXPECT_EQ(dhcp_ddns::NCR_UDP, d2_params->getNcrProtocol()); EXPECT_EQ(dhcp_ddns::FMT_JSON, d2_params->getNcrFormat()); + // Verify that the control socket can be retrieved. + ConstElementPtr ctrl_sock = context->getControlSocketInfo(); + ASSERT_TRUE(ctrl_sock); + ASSERT_EQ(Element::map, ctrl_sock->getType()); + EXPECT_EQ(2, ctrl_sock->size()); + ASSERT_TRUE(ctrl_sock->get("socket-type")); + EXPECT_EQ("\"unix\"", ctrl_sock->get("socket-type")->str()); + ASSERT_TRUE(ctrl_sock->get("socket-name")); + EXPECT_EQ("\"/tmp/d2-ctrl-channel\"", ctrl_sock->get("socket-name")->str()); + // Verify that the forward manager can be retrieved. DdnsDomainListMgrPtr mgr = context->getForwardMgr(); ASSERT_TRUE(mgr); @@ -941,6 +961,11 @@ TEST_F(D2CfgMgrTest, comments) { "\"comment\": \"D2 config\" , " "\"ip-address\" : \"192.168.1.33\" , " "\"port\" : 88 , " + "\"control-socket\": {" + " \"comment\": \"Control channel\" , " + " \"socket-type\": \"unix\" ," + " \"socket-name\": \"/tmp/d2-ctrl-channel\" " + "}," "\"tsig-keys\": [" "{" " \"user-context\": { " @@ -976,6 +1001,13 @@ TEST_F(D2CfgMgrTest, comments) { ASSERT_TRUE(ctx->get("comment")); EXPECT_EQ("\"D2 config\"", ctx->get("comment")->str()); + // Check control socket. + ConstElementPtr ctrl_sock = d2_context->getControlSocketInfo(); + ASSERT_TRUE(ctrl_sock); + ASSERT_TRUE(ctrl_sock->get("user-context")); + EXPECT_EQ("{ \"comment\": \"Control channel\" }", + ctrl_sock->get("user-context")->str()); + // Check TSIG keys. TSIGKeyInfoMapPtr keys = d2_context->getKeys(); ASSERT_TRUE(keys); diff --git a/src/bin/d2/tests/d2_simple_parser_unittest.cc b/src/bin/d2/tests/d2_simple_parser_unittest.cc index 686d7fae8c..6bb3ab968e 100644 --- a/src/bin/d2/tests/d2_simple_parser_unittest.cc +++ b/src/bin/d2/tests/d2_simple_parser_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2017-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 @@ -70,8 +70,22 @@ void checkStringValue(const ConstElementPtr& element, ASSERT_EQ(Element::string, element->getType()); // Verify it has the expected value - EXPECT_EQ(deflt.value_, element->stringValue()); - } + EXPECT_EQ(deflt.value_, element->stringValue()); +} + +/// @brief Checks if specified element is a map +/// +/// @param element defaulted element to check +/// @param deflt expected size +void checkMap(const ConstElementPtr& element, size_t deflt) { + ASSERT_TRUE(element); + + // Verify it's a map + ASSERT_EQ(Element::map, element->getType()); + + // verify the map size + EXPECT_EQ(deflt, element->size()); +} /// TSIGKeyInfo against the given set of values, and that the TSIGKey /// member points to a key. @@ -273,8 +287,8 @@ TEST_F(D2SimpleParserTest, globalD2Defaults) { EXPECT_NO_THROW(num = D2SimpleParser::setAllDefaults(empty)); - // We expect 5 parameters to be inserted. - EXPECT_EQ(num, 8); + // We expect 9 parameters to be inserted. + EXPECT_EQ(num, 9); // Let's go over all parameters we have defaults for. BOOST_FOREACH(SimpleDefault deflt, D2SimpleParser::D2_GLOBAL_DEFAULTS) { @@ -296,6 +310,9 @@ TEST_F(D2SimpleParserTest, globalD2Defaults) { } } } + + // Check control-socket + checkMap(empty->get("control-socket"), 0); } /// @brief Test fixture class for testing TSIGKeyInfo parsing. diff --git a/src/bin/d2/tests/parser_unittest.cc b/src/bin/d2/tests/parser_unittest.cc index 2bb62543f6..37c454bf4e 100644 --- a/src/bin/d2/tests/parser_unittest.cc +++ b/src/bin/d2/tests/parser_unittest.cc @@ -128,9 +128,9 @@ TEST(ParserTest, keywordDhcpDdns) { " \"ip-address\": \"192.168.77.1\", \n" " \"port\": 777 , \n " " \"ncr-protocol\": \"UDP\", \n" - "\"tsig-keys\": [], \n" - "\"forward-ddns\" : {}, \n" - "\"reverse-ddns\" : {} \n" + " \"tsig-keys\": [], \n" + " \"forward-ddns\" : {}, \n" + " \"reverse-ddns\" : {} \n" "} \n" "} \n"; testParser(txt, D2ParserContext::PARSER_DHCPDDNS); diff --git a/src/bin/d2/tests/testdata/get_config.json b/src/bin/d2/tests/testdata/get_config.json index b040c058ed..d0905d1e27 100644 --- a/src/bin/d2/tests/testdata/get_config.json +++ b/src/bin/d2/tests/testdata/get_config.json @@ -1,5 +1,9 @@ { "DhcpDdns": { + "control-socket": { + "socket-name": "/tmp/d2-ctrl-socket", + "socket-type": "unix" + }, "dns-server-timeout": 1000, "forward-ddns": { "ddns-domains": [