"name": "config-reload",
"brief": "The config-reload command instructs Kea to load again the configuration file that was used previously.",
"description": "See <xref linkend=\"command-config-reload\"/>",
- "support": [ "kea-dhcp4", "kea-dhcp6" ],
+ "support": [ "kea-dhcp4", "kea-dhcp6", "kea-dhcp-ddns", "kea-ctrl-agent" ],
"avail": "1.2.0",
"cmd-syntax": "{
\"command\": \"config-reload\"
<!--
- - Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2018-2019 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
.</para>
<para xml:id="commands-kea-ctrl-agent">Commands supported by kea-ctrl-agent daemon: <command><link linkend="ref-build-report">build-report</link></command>
, <command><link linkend="ref-config-get">config-get</link></command>
+, <command><link linkend="ref-config-reload">config-reload</link></command>
, <command><link linkend="ref-config-set">config-set</link></command>
, <command><link linkend="ref-config-test">config-test</link></command>
, <command><link linkend="ref-config-write">config-write</link></command>
.</para>
<para xml:id="commands-kea-dhcp-ddns">Commands supported by kea-dhcp-ddns daemon: <command><link linkend="ref-build-report">build-report</link></command>
, <command><link linkend="ref-config-get">config-get</link></command>
+, <command><link linkend="ref-config-reload">config-reload</link></command>
, <command><link linkend="ref-config-set">config-set</link></command>
, <command><link linkend="ref-config-test">config-test</link></command>
, <command><link linkend="ref-config-write">config-write</link></command>
<title>config-reload reference</title>
<para xml:id="ref-config-reload"><command>config-reload</command> - The config-reload command instructs Kea to load again the configuration file that was used previously.</para>
-<para>Supported by: <command><link linkend="commands-kea-dhcp4">kea-dhcp4</link></command>, <command><link linkend="commands-kea-dhcp6">kea-dhcp6</link></command></para>
+<para>Supported by: <command><link linkend="commands-kea-dhcp4">kea-dhcp4</link></command>, <command><link linkend="commands-kea-dhcp6">kea-dhcp6</link></command>, <command><link linkend="commands-kea-dhcp-ddns">kea-dhcp-ddns</link></command>, <command><link linkend="commands-kea-ctrl-agent">kea-ctrl-agent</link></command></para>
<para>Availability: 1.2.0 (built-in)</para>
<!--
- - Copyright (C) 2015-2018 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2015-2019 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
<listitem>
<simpara>config-get</simpara>
</listitem>
+ <listitem>
+ <simpara>config-reload</simpara>
+ </listitem>
<listitem>
<simpara>config-set</simpara>
</listitem>
<listitem>
<simpara>config-get</simpara>
</listitem>
+ <listitem>
+ <simpara>config-reload</simpara>
+ </listitem>
<listitem>
<simpara>config-set</simpara>
</listitem>
<!--
- - Copyright (C) 2014-2018 Internet Systems Consortium, Inc. ("ISC")
+ - Copyright (C) 2014-2019 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
<itemizedlist>
<listitem>build-report</listitem>
<listitem>config-get</listitem>
+ <listitem>config-reload</listitem>
<listitem>config-set</listitem>
<listitem>config-test</listitem>
<listitem>config-write</listitem>
-// Copyright (C) 2016-2018 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2016-2019 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
CtrlAgentCommandMgr::instance().registerCommand(CONFIG_GET_COMMAND,
boost::bind(&DControllerBase::configGetHandler, this, _1, _2));
+ CtrlAgentCommandMgr::instance().registerCommand(CONFIG_RELOAD_COMMAND,
+ boost::bind(&DControllerBase::configReloadHandler, this, _1, _2));
+
CtrlAgentCommandMgr::instance().registerCommand(CONFIG_SET_COMMAND,
boost::bind(&DControllerBase::configSetHandler, this, _1, _2));
CtrlAgentController::deregisterCommands() {
CtrlAgentCommandMgr::instance().deregisterCommand(BUILD_REPORT_COMMAND);
CtrlAgentCommandMgr::instance().deregisterCommand(CONFIG_GET_COMMAND);
+ CtrlAgentCommandMgr::instance().deregisterCommand(CONFIG_RELOAD_COMMAND);
CtrlAgentCommandMgr::instance().deregisterCommand(CONFIG_SET_COMMAND);
CtrlAgentCommandMgr::instance().deregisterCommand(CONFIG_TEST_COMMAND);
CtrlAgentCommandMgr::instance().deregisterCommand(CONFIG_WRITE_COMMAND);
-// Copyright (C) 2016-2018 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2016-2019 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
// Tests that the SIGTERM triggers a normal shutdown.
TEST_F(CtrlAgentControllerTest, sigtermShutdown) {
- // Setup to raise SIGHUP in 1 ms.
+ // Setup to raise SIGTERM in 1 ms.
TimedSignal sighup(*getIOService(), SIGTERM, 1);
// Write valid_agent_config and then run launch() for a maximum of 1 s.
// Check that the following command are really available.
checkCommandRegistered("build-report");
checkCommandRegistered("config-get");
+ checkCommandRegistered("config-reload");
checkCommandRegistered("config-set");
checkCommandRegistered("config-test");
checkCommandRegistered("config-write");
ctrl->deregisterCommands();
}
+// Tests if config-reload attempts to reload a file and reports that the
+// file is missing.
+TEST_F(CtrlAgentControllerTest, configReloadMissingFile) {
+ ASSERT_NO_THROW(initProcess());
+ EXPECT_TRUE(checkProcess());
+
+ // The framework available makes it very difficult to test the actual
+ // code as CtrlAgentController is not initialized the same way it is
+ // in production code. In particular, the way CtrlAgentController
+ // is initialized in tests does not call registerCommands().
+ // This is a crude workaround for this problem. Proper solution should
+ // be developed sooner rather than later.
+ const DControllerBasePtr& base = getController();
+ const CtrlAgentControllerPtr& ctrl
+ = boost::dynamic_pointer_cast<CtrlAgentController>(base);
+ ASSERT_TRUE(ctrl);
+ // Now clean up after ourselves.
+ ctrl->registerCommands();
+
+ // This is normally set to whatever value is passed to -c when the server is
+ // started, but we're not starting it that way, so need to set it by hand.
+ getController()->setConfigFile("does-not-exist.json");
+
+ // Build and execute the command.
+ string cmd_txt = "{ \"command\": \"config-reload\" }";
+ ConstElementPtr cmd = Element::fromJSON(cmd_txt);
+ ConstElementPtr params;
+ ConstElementPtr answer;
+ answer = CtrlAgentCommandMgr::instance().handleCommand("config-reload",
+ params, cmd);
+
+ // Verify the reload was rejected.
+ string expected = "[ { \"result\": 1, \"text\": "
+ "\"Configuration parsing failed: "
+ "Unable to open file does-not-exist.json\" } ]";
+ EXPECT_EQ(expected, answer->str());
+
+ // Now clean up after ourselves.
+ ctrl->deregisterCommands();
+}
+
+// Tests if config-reload attempts to reload a file and reports that the
+// file is not a valid JSON.
+TEST_F(CtrlAgentControllerTest, configReloadBrokenFile) {
+ ASSERT_NO_THROW(initProcess());
+ EXPECT_TRUE(checkProcess());
+
+ // The framework available makes it very difficult to test the actual
+ // code as CtrlAgentController is not initialized the same way it is
+ // in production code. In particular, the way CtrlAgentController
+ // is initialized in tests does not call registerCommands().
+ // This is a crude workaround for this problem. Proper solution should
+ // be developed sooner rather than later.
+ const DControllerBasePtr& base = getController();
+ const CtrlAgentControllerPtr& ctrl
+ = boost::dynamic_pointer_cast<CtrlAgentController>(base);
+ ASSERT_TRUE(ctrl);
+ // Now clean up after ourselves.
+ ctrl->registerCommands();
+
+ // This is normally set to whatever value is passed to -c when the server is
+ // started, but we're not starting it that way, so need to set it by hand.
+ getController()->setConfigFile("testbad.json");
+
+ // Although Kea is smart, its AI routines are not smart enough to handle
+ // this one... at least not yet.
+ ofstream f("testbad.json", ios::trunc);
+ f << "bla bla bla...";
+ f.close();
+
+ // Build and execute the command.
+ string cmd_txt = "{ \"command\": \"config-reload\" }";
+ ConstElementPtr cmd = Element::fromJSON(cmd_txt);
+ ConstElementPtr params;
+ ConstElementPtr answer;
+ answer = CtrlAgentCommandMgr::instance().handleCommand("config-reload",
+ params, cmd);
+
+ // Verify the reload was rejected.
+ string expected = "[ { \"result\": 1, \"text\": "
+ "\"Configuration parsing failed: "
+ "testbad.json:1.1: Invalid character: b\" } ]";
+ EXPECT_EQ(expected, answer->str());
+
+ // Remove the file.
+ ::remove("testbad.json");
+
+ // Now clean up after ourselves.
+ ctrl->deregisterCommands();
+}
+
+// Tests if config-reload attempts to reload a file and reports that the
+// file is missing.
+TEST_F(CtrlAgentControllerTest, configReloadFileValid) {
+ ASSERT_NO_THROW(initProcess());
+ EXPECT_TRUE(checkProcess());
+
+ // The framework available makes it very difficult to test the actual
+ // code as CtrlAgentController is not initialized the same way it is
+ // in production code. In particular, the way CtrlAgentController
+ // is initialized in tests does not call registerCommands().
+ // This is a crude workaround for this problem. Proper solution should
+ // be developed sooner rather than later.
+ const DControllerBasePtr& base = getController();
+ const CtrlAgentControllerPtr& ctrl
+ = boost::dynamic_pointer_cast<CtrlAgentController>(base);
+ ASSERT_TRUE(ctrl);
+ // Now clean up after ourselves.
+ ctrl->registerCommands();
+
+ // This is normally set to whatever value is passed to -c when the server is
+ // started, but we're not starting it that way, so need to set it by hand.
+ getController()->setConfigFile("testvalid.json");
+
+ // Ok, enough fooling around. Let's create a valid config.
+ ofstream f("testvalid.json", ios::trunc);
+ f << "{ \"Control-agent\": "
+ << string(valid_agent_config)
+ << " }" << endl;
+ f.close();
+
+ // Build and execute the command.
+ string cmd_txt = "{ \"command\": \"config-reload\" }";
+ ConstElementPtr cmd = Element::fromJSON(cmd_txt);
+ ConstElementPtr params;
+ ConstElementPtr answer;
+ answer = CtrlAgentCommandMgr::instance().handleCommand("config-reload",
+ params, cmd);
+
+
+ // Verify the reload was successful.
+ string expected = "[ { \"result\": 0, \"text\": "
+ "\"Configuration applied successfully.\" } ]";
+ EXPECT_EQ(expected, answer->str());
+
+ // Check that the config was indeed applied?
+
+ // Remove the file.
+ //::remove("testvalid.json");
+
+ // Now clean up after ourselves.
+ ctrl->deregisterCommands();
+}
+
}
-// Copyright (C) 2013-2018 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013-2019 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
CommandMgr::instance().registerCommand(CONFIG_GET_COMMAND,
boost::bind(&D2Controller::configGetHandler, this, _1, _2));
+ CommandMgr::instance().registerCommand(CONFIG_RELOAD_COMMAND,
+ boost::bind(&D2Controller::configReloadHandler, this, _1, _2));
+
CommandMgr::instance().registerCommand(CONFIG_SET_COMMAND,
boost::bind(&D2Controller::configSetHandler, this, _1, _2));
// Deregister any registered commands (please keep in alphabetic order)
CommandMgr::instance().deregisterCommand(BUILD_REPORT_COMMAND);
CommandMgr::instance().deregisterCommand(CONFIG_GET_COMMAND);
+ CommandMgr::instance().deregisterCommand(CONFIG_RELOAD_COMMAND);
CommandMgr::instance().deregisterCommand(CONFIG_SET_COMMAND);
CommandMgr::instance().deregisterCommand(CONFIG_TEST_COMMAND);
CommandMgr::instance().deregisterCommand(CONFIG_WRITE_COMMAND);
-// Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2018-2019 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
EXPECT_TRUE(command_list.find("\"list-commands\"") != string::npos);
EXPECT_TRUE(command_list.find("\"build-report\"") != string::npos);
EXPECT_TRUE(command_list.find("\"config-get\"") != string::npos);
+ EXPECT_TRUE(command_list.find("\"config-reload\"") != string::npos);
+ EXPECT_TRUE(command_list.find("\"config-set\"") != string::npos);
+ EXPECT_TRUE(command_list.find("\"config-test\"") != string::npos);
EXPECT_TRUE(command_list.find("\"config-write\"") != string::npos);
EXPECT_TRUE(command_list.find("\"shutdown\"") != string::npos);
EXPECT_TRUE(command_list.find("\"version-get\"") != string::npos);
// We expect the server to report at least the following commands:
checkListCommands(rsp, "build-report");
checkListCommands(rsp, "config-get");
+ checkListCommands(rsp, "config-reload");
+ checkListCommands(rsp, "config-set");
+ checkListCommands(rsp, "config-test");
checkListCommands(rsp, "config-write");
checkListCommands(rsp, "list-commands");
checkListCommands(rsp, "shutdown");
::remove("test2.json");
}
+// Tests if config-reload attempts to reload a file and reports that the
+// file is missing.
+TEST_F(CtrlChannelD2Test, configReloadMissingFile) {
+ EXPECT_NO_THROW(createUnixChannelServer());
+ string response;
+
+ // This is normally set to whatever value is passed to -c when the server is
+ // started, but we're not starting it that way, so need to set it by hand.
+ server_->setConfigFile("does-not-exist.json");
+
+ // Tell the server to reload its configuration. It should attempt to load
+ // does-not-exist.json (and fail, because the file is not there).
+ sendUnixCommand("{ \"command\": \"config-reload\" }", response);
+
+ // Verify the reload was rejected.
+ string expected = "{ \"result\": 1, \"text\": "
+ "\"Configuration parsing failed: "
+ "Unable to open file does-not-exist.json\" }";
+ EXPECT_EQ(expected, response);
+}
+
+// Tests if config-reload attempts to reload a file and reports that the
+// file is not a valid JSON.
+TEST_F(CtrlChannelD2Test, configReloadBrokenFile) {
+ EXPECT_NO_THROW(createUnixChannelServer());
+ string response;
+
+ // This is normally set to whatever value is passed to -c when the server is
+ // started, but we're not starting it that way, so need to set it by hand.
+ server_->setConfigFile("testbad.json");
+
+ // Although Kea is smart, its AI routines are not smart enough to handle
+ // this one... at least not yet.
+ ofstream f("testbad.json", ios::trunc);
+ f << "bla bla bla...";
+ f.close();
+
+ // Tell the server to reload its configuration. It should attempt to load
+ // testbad.json (and fail, because the file is not valid JSON).
+ // does-not-exist.json (and fail, because the file is not there).
+ sendUnixCommand("{ \"command\": \"config-reload\" }", response);
+
+ // Verify the reload was rejected.
+ string expected = "{ \"result\": 1, \"text\": "
+ "\"Configuration parsing failed: "
+ "testbad.json:1.1: Invalid character: b\" }";
+ EXPECT_EQ(expected, response);
+
+ // Remove the file.
+ ::remove("testbad.json");
+}
+
+// Tests if config-reload attempts to reload a file and reports that the
+// file is missing.
+TEST_F(CtrlChannelD2Test, configReloadFileValid) {
+ EXPECT_NO_THROW(createUnixChannelServer());
+ string response;
+
+ // This is normally set to whatever value is passed to -c when the server is
+ // started, but we're not starting it that way, so need to set it by hand.
+ server_->setConfigFile("testvalid.json");
+
+ // Ok, enough fooling around. Let's create a valid config.
+ ofstream f("testvalid.json", ios::trunc);
+ f << "{ \"DhcpDdns\": "
+ << "{"
+ << " \"ip-address\": \"192.168.77.1\" , "
+ << " \"port\": 777 , "
+ << "\"tsig-keys\": [], "
+ << "\"forward-ddns\" : {}, "
+ << "\"reverse-ddns\" : {} "
+ << "}"
+ << " }" << endl;
+ f.close();
+
+ // Tell the server to reload its configuration. It should attempt to load
+ // testvalid.json (and succeed).
+ sendUnixCommand("{ \"command\": \"config-reload\" }", response);
+
+ // Verify the reload was successful.
+ string expected = "{ \"result\": 0, \"text\": "
+ "\"Configuration applied successfully.\" }";
+ EXPECT_EQ(expected, response);
+
+ // Check that the config was indeed applied.
+ D2ProcessPtr proc = d2Controller()->getProcess();
+ ASSERT_TRUE(proc);
+ D2CfgMgrPtr d2_cfg_mgr = proc->getD2CfgMgr();
+ ASSERT_TRUE(d2_cfg_mgr);
+ D2ParamsPtr d2_params = d2_cfg_mgr->getD2Params();
+ ASSERT_TRUE(d2_params);
+
+ EXPECT_EQ("192.168.77.1", d2_params->getIpAddress().toText());
+ EXPECT_EQ(777, d2_params->getPort());
+ EXPECT_FALSE(d2_cfg_mgr->forwardUpdatesEnabled());
+ EXPECT_FALSE(d2_cfg_mgr->reverseUpdatesEnabled());
+
+ // Remove the file.
+ ::remove("testvalid.json");
+}
+
/// Verify that concurrent connections over the control channel can be
/// established. (@todo change when response will be sent in multiple chunks)
TEST_F(CtrlChannelD2Test, concurrentConnections) {
-// Copyright (C) 2013-2018 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013-2019 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
// Tests that the SIGINT triggers a normal shutdown.
TEST_F(D2ControllerTest, sigintShutdown) {
- // Setup to raise SIGHUP in 1 ms.
+ // Setup to raise SIGINT in 1 ms.
TimedSignal sighup(*getIOService(), SIGINT, 1);
// Write valid_d2_config and then run launch() for a maximum of 1000 ms.
// Tests that the SIGTERM triggers a normal shutdown.
TEST_F(D2ControllerTest, sigtermShutdown) {
- // Setup to raise SIGHUP in 1 ms.
+ // Setup to raise SIGTERM in 1 ms.
TimedSignal sighup(*getIOService(), SIGTERM, 1);
// Write valid_d2_config and then run launch() for a maximum of 1 s.
version_test "shell.version"
shell_command_test "shell.list-commands" "list-commands" \
- "[ { \"arguments\": [ \"build-report\", \"config-get\", \"config-set\", \"config-test\", \"config-write\", \"list-commands\", \"shutdown\", \"version-get\" ], \"result\": 0 } ]" ""
+ "[ { \"arguments\": [ \"build-report\", \"config-get\", \"config-reload\", \"config-set\", \"config-test\", \"config-write\", \"list-commands\", \"shutdown\", \"version-get\" ], \"result\": 0 } ]" ""
shell_command_test "shell.bogus" "give-me-a-beer" \
"[ { \"result\": 2, \"text\": \"'give-me-a-beer' command not supported. You did not include \\\"service\\\" parameter in the command, which indicates that Kea Control Agent should process this command rather than forward it to one or more Kea servers. If you aimed to send this command to one of the Kea servers you should include the \\\"service\\\" parameter in your request, e.g. \\\"service\\\": [ \\\"dhcp4\\\" ] to forward the command to the DHCPv4 server, or \\\"service\\\": [ \\\"dhcp4\\\", \\\"dhcp6\\\", \\\"d2\\\" ] to forward it to DHCPv4, DHCPv6 and D2 servers etc.\" } ]" ""
shell_command_test "shell.empty-config-test" "config-test" \
-// Copyright (C) 2013-2018 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013-2019 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
return (checkConfig(module_config));
}
+ConstElementPtr
+DControllerBase::configReloadHandler(const std::string&, ConstElementPtr) {
+ // Add reload in message?
+ return (configFromFile());
+}
+
ConstElementPtr
DControllerBase::configSetHandler(const std::string&, ConstElementPtr args) {
const int status_code = COMMAND_ERROR; // 1 indicates an error
-// Copyright (C) 2013-2018 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013-2019 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
configTestHandler(const std::string& command,
isc::data::ConstElementPtr args);
+ /// @brief handler for config-reload command
+ ///
+ /// This method handles the config-reload command, which reloads
+ /// the configuration file.
+ ///
+ /// @param command (ignored)
+ /// @param args (ignored)
+ /// @return status of the command
+ isc::data::ConstElementPtr
+ configReloadHandler(const std::string& command,
+ isc::data::ConstElementPtr args);
+
/// @brief handler for config-set command
///
/// This method handles the config-set command, which checks
-// Copyright (C) 2013-2018 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2013-2019 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
/// @brief String value for the config-test command.
static const std::string CONFIG_TEST_COMMAND("config-test");
+/// @brief String value for the config-reload command.
+static const std::string CONFIG_RELOAD_COMMAND("config-reload");
+
/// @brief String value for the config-set command.
static const std::string CONFIG_SET_COMMAND("config-set");