mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-09-02 15:05:16 +00:00
[master] Merged trac5152 (check D2 and CA config)
This commit is contained in:
1177
doc/guide/ddns.xml
1177
doc/guide/ddns.xml
File diff suppressed because it is too large
Load Diff
@@ -84,7 +84,8 @@ public:
|
|||||||
/// of an integer status value (0 means successful, non-zero means failure),
|
/// of an integer status value (0 means successful, non-zero means failure),
|
||||||
/// and a string explanation of the outcome.
|
/// and a string explanation of the outcome.
|
||||||
virtual isc::data::ConstElementPtr
|
virtual isc::data::ConstElementPtr
|
||||||
configure(isc::data::ConstElementPtr config_set, bool check_only);
|
configure(isc::data::ConstElementPtr config_set,
|
||||||
|
bool check_only = false);
|
||||||
|
|
||||||
/// @brief Processes the given command.
|
/// @brief Processes the given command.
|
||||||
///
|
///
|
||||||
|
@@ -52,7 +52,8 @@
|
|||||||
<arg><option>-V</option></arg>
|
<arg><option>-V</option></arg>
|
||||||
<arg><option>-W</option></arg>
|
<arg><option>-W</option></arg>
|
||||||
<arg><option>-d</option></arg>
|
<arg><option>-d</option></arg>
|
||||||
<arg><option>-s</option></arg>
|
<arg><option>-c<replaceable class="parameter">config-file</replaceable></option></arg>
|
||||||
|
<arg><option>-t<replaceable class="parameter">config-file</replaceable></option></arg>
|
||||||
</cmdsynopsis>
|
</cmdsynopsis>
|
||||||
</refsynopsisdiv>
|
</refsynopsisdiv>
|
||||||
|
|
||||||
@@ -115,6 +116,16 @@
|
|||||||
</para></listitem>
|
</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>-t</option></term>
|
||||||
|
<listitem><para>
|
||||||
|
Check the syntax of the configuration file and report the
|
||||||
|
first error if any. Note that not all parameters are
|
||||||
|
completely checked, in particular, service and client
|
||||||
|
sockets are not opened, and hook libraries are not loaded.
|
||||||
|
</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
@@ -25,9 +25,18 @@ int main(int argc, char* argv[]) {
|
|||||||
// 'false' value disables test mode.
|
// 'false' value disables test mode.
|
||||||
controller->launch(argc, argv, false);
|
controller->launch(argc, argv, false);
|
||||||
} catch (const VersionMessage& ex) {
|
} catch (const VersionMessage& ex) {
|
||||||
std::cout << ex.what() << std::endl;
|
std::string msg(ex.what());
|
||||||
|
if (!msg.empty()) {
|
||||||
|
std::cout << msg << std::endl;
|
||||||
|
}
|
||||||
|
} catch (const InvalidUsage& ex) {
|
||||||
|
std::string msg(ex.what());
|
||||||
|
if (!msg.empty()) {
|
||||||
|
std::cerr << msg << std::endl;
|
||||||
|
}
|
||||||
|
ret = EXIT_FAILURE;
|
||||||
} catch (const isc::Exception& ex) {
|
} catch (const isc::Exception& ex) {
|
||||||
std::cerr << "Service failed:" << ex.what() << std::endl;
|
std::cerr << "Service failed: " << ex.what() << std::endl;
|
||||||
ret = EXIT_FAILURE;
|
ret = EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
# Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
|
# Copyright (C) 2016-2017 Internet Systems Consortium, Inc. ("ISC")
|
||||||
#
|
#
|
||||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
# 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
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
@@ -34,12 +34,55 @@ CONFIG="{
|
|||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
|
|
||||||
|
# Invalid configuration (syntax error) to check that Kea can check syntax.
|
||||||
|
CONFIG_BAD_SYNTAX="{
|
||||||
|
\"Control-agent\":
|
||||||
|
{
|
||||||
|
\"http-port\": BOGUS
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
|
||||||
|
# Invalid configuration (out of range port) to check that Kea can check syntax.
|
||||||
|
CONFIG_BAD_VALUE="{
|
||||||
|
\"Control-agent\":
|
||||||
|
{
|
||||||
|
\"http-port\": 80000
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
|
||||||
bin="kea-ctrl-agent"
|
bin="kea-ctrl-agent"
|
||||||
bin_path=@abs_top_builddir@/src/bin/agent
|
bin_path=@abs_top_builddir@/src/bin/agent
|
||||||
|
|
||||||
# Import common test library.
|
# Import common test library.
|
||||||
. @abs_top_builddir@/src/lib/testutils/dhcp_test_lib.sh
|
. @abs_top_builddir@/src/lib/testutils/dhcp_test_lib.sh
|
||||||
|
|
||||||
|
# This test verifies that syntax checking works properly. This function
|
||||||
|
# requires 3 parameters:
|
||||||
|
# testname
|
||||||
|
# config - string with a content of the config (will be written to a file)
|
||||||
|
# exp_code - expected exit code returned by kea (0 - success, 1 - failure)
|
||||||
|
syntax_check_test() {
|
||||||
|
local TESTNAME="${1}"
|
||||||
|
local CONFIG="${2}"
|
||||||
|
local EXP_CODE="${3}"
|
||||||
|
|
||||||
|
# Log the start of the test and print test name.
|
||||||
|
test_start $TESTNAME
|
||||||
|
# Remove dangling Kea instances and remove log files.
|
||||||
|
cleanup
|
||||||
|
# Create correct configuration file.
|
||||||
|
create_config "${CONFIG}"
|
||||||
|
# Check it
|
||||||
|
printf "Running command %s.\n" "\"${bin_path}/${bin} -t ${CFG_FILE}\""
|
||||||
|
${bin_path}/${bin} -t ${CFG_FILE}
|
||||||
|
exit_code=$?
|
||||||
|
if [ ${exit_code} -ne $EXP_CODE ]; then
|
||||||
|
printf "ERROR: expected exit code ${EXP_CODE}, got ${exit_code}\n"
|
||||||
|
clean_exit 1
|
||||||
|
fi
|
||||||
|
test_finish 0
|
||||||
|
}
|
||||||
|
|
||||||
# This test verifies that Control Agent is shut down gracefully when it
|
# This test verifies that Control Agent is shut down gracefully when it
|
||||||
# receives a SIGINT or SIGTERM signal.
|
# receives a SIGINT or SIGTERM signal.
|
||||||
shutdown_test() {
|
shutdown_test() {
|
||||||
@@ -102,4 +145,6 @@ shutdown_test() {
|
|||||||
server_pid_file_test "${CONFIG}" DCTL_ALREADY_RUNNING
|
server_pid_file_test "${CONFIG}" DCTL_ALREADY_RUNNING
|
||||||
shutdown_test "ctrl-agent.sigterm_test" 15
|
shutdown_test "ctrl-agent.sigterm_test" 15
|
||||||
shutdown_test "ctrl-agent.sigint_test" 2
|
shutdown_test "ctrl-agent.sigint_test" 2
|
||||||
|
syntax_check_test "ctrl-agent.syntax_check_success" "${CONFIG}" 0
|
||||||
|
syntax_check_test "ctrl-agent.syntax_check_bad_syntax" "${CONFIG_BAD_SYNTAX}" 1
|
||||||
|
syntax_check_test "ctrl-agent.syntax_check_bad_values" "${CONFIG_BAD_VALUE}" 1
|
||||||
|
@@ -37,7 +37,7 @@ to shutdown and has met the required criteria to exit.
|
|||||||
This is a debug message issued when the DHCP-DDNS application command method
|
This is a debug message issued when the DHCP-DDNS application command method
|
||||||
has been invoked.
|
has been invoked.
|
||||||
|
|
||||||
% DHCP_DDNS_CONFIGURE configuration update received: %1
|
% DHCP_DDNS_CONFIGURE configuration %1 received: %2
|
||||||
This is a debug message issued when the DHCP-DDNS application configure method
|
This is a debug message issued when the DHCP-DDNS application configure method
|
||||||
has been invoked.
|
has been invoked.
|
||||||
|
|
||||||
|
@@ -192,17 +192,18 @@ D2Process::shutdown(isc::data::ConstElementPtr args) {
|
|||||||
|
|
||||||
isc::data::ConstElementPtr
|
isc::data::ConstElementPtr
|
||||||
D2Process::configure(isc::data::ConstElementPtr config_set, bool check_only) {
|
D2Process::configure(isc::data::ConstElementPtr config_set, bool check_only) {
|
||||||
LOG_DEBUG(d2_logger, DBGLVL_TRACE_BASIC,
|
LOG_DEBUG(d2_logger, DBGLVL_TRACE_BASIC, DHCP_DDNS_CONFIGURE)
|
||||||
DHCP_DDNS_CONFIGURE).arg(config_set->str());
|
.arg(check_only ? "check" : "update")
|
||||||
|
.arg(config_set->str());
|
||||||
|
|
||||||
/// @todo: Implement this eventually.
|
isc::data::ConstElementPtr answer;
|
||||||
|
answer = getCfgMgr()->parseConfig(config_set, check_only);;
|
||||||
if (check_only) {
|
if (check_only) {
|
||||||
return (isc::config::createAnswer(0, "Configuration check is not supported by D2."));
|
return (answer);
|
||||||
}
|
}
|
||||||
|
|
||||||
int rcode = 0;
|
int rcode = 0;
|
||||||
isc::data::ConstElementPtr comment;
|
isc::data::ConstElementPtr comment;
|
||||||
isc::data::ConstElementPtr answer = getCfgMgr()->parseConfig(config_set);;
|
|
||||||
comment = isc::config::parseAnswer(rcode, answer);
|
comment = isc::config::parseAnswer(rcode, answer);
|
||||||
|
|
||||||
if (rcode) {
|
if (rcode) {
|
||||||
|
@@ -158,7 +158,8 @@ public:
|
|||||||
/// of an integer status value (0 means successful, non-zero means failure),
|
/// of an integer status value (0 means successful, non-zero means failure),
|
||||||
/// and a string explanation of the outcome.
|
/// and a string explanation of the outcome.
|
||||||
virtual isc::data::ConstElementPtr
|
virtual isc::data::ConstElementPtr
|
||||||
configure(isc::data::ConstElementPtr config_set, bool check_only);
|
configure(isc::data::ConstElementPtr config_set,
|
||||||
|
bool check_only = false);
|
||||||
|
|
||||||
/// @brief Processes the given command.
|
/// @brief Processes the given command.
|
||||||
///
|
///
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
|
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
|
||||||
[<!ENTITY mdash "—">]>
|
[<!ENTITY mdash "—">]>
|
||||||
<!--
|
<!--
|
||||||
- Copyright (C) 2013-2016 Internet Systems Consortium, Inc. ("ISC")
|
- Copyright (C) 2013-2017 Internet Systems Consortium, Inc. ("ISC")
|
||||||
-
|
-
|
||||||
- This Source Code Form is subject to the terms of the Mozilla Public
|
- 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
|
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
@@ -52,8 +52,8 @@
|
|||||||
<arg><option>-V</option></arg>
|
<arg><option>-V</option></arg>
|
||||||
<arg><option>-W</option></arg>
|
<arg><option>-W</option></arg>
|
||||||
<arg><option>-d</option></arg>
|
<arg><option>-d</option></arg>
|
||||||
<!-- not yet <arg><option>-t</option></arg> -->
|
<arg><option>-c<replaceable class="parameter">config-file</replaceable></option></arg>
|
||||||
<arg><option>-c</option></arg>
|
<arg><option>-t<replaceable class="parameter">config-file</replaceable></option></arg>
|
||||||
</cmdsynopsis>
|
</cmdsynopsis>
|
||||||
</refsynopsisdiv>
|
</refsynopsisdiv>
|
||||||
|
|
||||||
@@ -105,16 +105,6 @@
|
|||||||
</para></listitem>
|
</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<!-- not yet
|
|
||||||
<varlistentry>
|
|
||||||
<term><option>-t</option></term>
|
|
||||||
<listitem><para>
|
|
||||||
Check the syntax of the configuration file and report the first
|
|
||||||
error if any.
|
|
||||||
</para></listitem>
|
|
||||||
</varlistentry>
|
|
||||||
-->
|
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>-c</option></term>
|
<term><option>-c</option></term>
|
||||||
<listitem><para>
|
<listitem><para>
|
||||||
@@ -123,6 +113,16 @@
|
|||||||
</para></listitem>
|
</para></listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>-t</option></term>
|
||||||
|
<listitem><para>
|
||||||
|
Check the syntax of the configuration file and report the
|
||||||
|
first error if any. Note that not all parameters are
|
||||||
|
completely checked, in particular, service socket is
|
||||||
|
not opened.
|
||||||
|
</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (C) 2013-2016 Internet Systems Consortium, Inc. ("ISC")
|
// Copyright (C) 2013-2017 Internet Systems Consortium, Inc. ("ISC")
|
||||||
//
|
//
|
||||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
// 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
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
@@ -34,9 +34,18 @@ int main(int argc, char* argv[]) {
|
|||||||
// 'false' value disables test mode.
|
// 'false' value disables test mode.
|
||||||
controller->launch(argc, argv, false);
|
controller->launch(argc, argv, false);
|
||||||
} catch (const VersionMessage& ex) {
|
} catch (const VersionMessage& ex) {
|
||||||
std::cout << ex.what() << std::endl;
|
std::string msg(ex.what());
|
||||||
|
if (!msg.empty()) {
|
||||||
|
std::cout << msg << std::endl;
|
||||||
|
}
|
||||||
|
} catch (const InvalidUsage& ex) {
|
||||||
|
std::string msg(ex.what());
|
||||||
|
if (!msg.empty()) {
|
||||||
|
std::cerr << msg << std::endl;
|
||||||
|
}
|
||||||
|
ret = EXIT_FAILURE;
|
||||||
} catch (const isc::Exception& ex) {
|
} catch (const isc::Exception& ex) {
|
||||||
std::cerr << "Service failed:" << ex.what() << std::endl;
|
std::cerr << "Service failed: " << ex.what() << std::endl;
|
||||||
ret = EXIT_FAILURE;
|
ret = EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -168,7 +168,8 @@ public:
|
|||||||
|
|
||||||
// The JSON parsed ok and we've added the defaults, pass the config
|
// The JSON parsed ok and we've added the defaults, pass the config
|
||||||
// into the Element parser and check for the expected outcome.
|
// into the Element parser and check for the expected outcome.
|
||||||
data::ConstElementPtr answer = cfg_mgr_->parseConfig(config_set_);
|
data::ConstElementPtr answer;
|
||||||
|
answer = cfg_mgr_->parseConfig(config_set_, false);
|
||||||
|
|
||||||
// Extract the result and error text from the answer.
|
// Extract the result and error text from the answer.
|
||||||
int rcode = 0;
|
int rcode = 0;
|
||||||
@@ -601,7 +602,7 @@ TEST_F(D2CfgMgrTest, fullConfig) {
|
|||||||
|
|
||||||
// Verify that parsing the exact same configuration a second time
|
// Verify that parsing the exact same configuration a second time
|
||||||
// does not cause a duplicate value errors.
|
// does not cause a duplicate value errors.
|
||||||
answer_ = cfg_mgr_->parseConfig(config_set_);
|
answer_ = cfg_mgr_->parseConfig(config_set_, false);
|
||||||
ASSERT_TRUE(checkAnswer(0));
|
ASSERT_TRUE(checkAnswer(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -181,12 +181,22 @@ TEST_F(D2ControllerTest, configUpdateTests) {
|
|||||||
isc::config::parseAnswer(rcode, answer);
|
isc::config::parseAnswer(rcode, answer);
|
||||||
EXPECT_EQ(0, rcode);
|
EXPECT_EQ(0, rcode);
|
||||||
|
|
||||||
|
// Verify that given a valid config we get a successful check result.
|
||||||
|
answer = checkConfig(config_set);
|
||||||
|
isc::config::parseAnswer(rcode, answer);
|
||||||
|
EXPECT_EQ(0, rcode);
|
||||||
|
|
||||||
// Use an invalid configuration to verify parsing error return.
|
// Use an invalid configuration to verify parsing error return.
|
||||||
std::string config = "{ \"bogus\": 1000 } ";
|
std::string config = "{ \"bogus\": 1000 } ";
|
||||||
config_set = isc::data::Element::fromJSON(config);
|
config_set = isc::data::Element::fromJSON(config);
|
||||||
answer = updateConfig(config_set);
|
answer = updateConfig(config_set);
|
||||||
isc::config::parseAnswer(rcode, answer);
|
isc::config::parseAnswer(rcode, answer);
|
||||||
EXPECT_EQ(1, rcode);
|
EXPECT_EQ(1, rcode);
|
||||||
|
|
||||||
|
// Use an invalid configuration to verify checking error return.
|
||||||
|
answer = checkConfig(config_set);
|
||||||
|
isc::config::parseAnswer(rcode, answer);
|
||||||
|
EXPECT_EQ(1, rcode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Command execution tests.
|
/// @brief Command execution tests.
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
# Copyright (C) 2014-2016 Internet Systems Consortium, Inc. ("ISC")
|
# Copyright (C) 2014-2017 Internet Systems Consortium, Inc. ("ISC")
|
||||||
#
|
#
|
||||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
# 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
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
@@ -36,7 +36,59 @@ CONFIG="{
|
|||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
|
|
||||||
# Invalid configuration (invalid port) to check that D2
|
# Invalid configuration (syntax error) to check that Kea can check syntax.
|
||||||
|
CONFIG_BAD_SYNTAX="{
|
||||||
|
\"DhcpDdns\":
|
||||||
|
{
|
||||||
|
\"ip-address\": \"127.0.0.1\",
|
||||||
|
\"port\": BOGUS,
|
||||||
|
\"tsig-keys\": [],
|
||||||
|
\"forward-ddns\" : {},
|
||||||
|
\"reverse-ddns\" : {}
|
||||||
|
},
|
||||||
|
\"Logging\":
|
||||||
|
{
|
||||||
|
\"loggers\": [
|
||||||
|
{
|
||||||
|
\"name\": \"kea-dhcp-ddns\",
|
||||||
|
\"output_options\": [
|
||||||
|
{
|
||||||
|
\"output\": \"$LOG_FILE\"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\"severity\": \"INFO\"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
|
||||||
|
# Invalid configuration (out of range port) to check that Kea can check syntax.
|
||||||
|
CONFIG_BAD_VALUE="{
|
||||||
|
\"DhcpDdns\":
|
||||||
|
{
|
||||||
|
\"ip-address\": \"127.0.0.1\",
|
||||||
|
\"port\": 80000,
|
||||||
|
\"tsig-keys\": [],
|
||||||
|
\"forward-ddns\" : {},
|
||||||
|
\"reverse-ddns\" : {}
|
||||||
|
},
|
||||||
|
\"Logging\":
|
||||||
|
{
|
||||||
|
\"loggers\": [
|
||||||
|
{
|
||||||
|
\"name\": \"kea-dhcp-ddns\",
|
||||||
|
\"output_options\": [
|
||||||
|
{
|
||||||
|
\"output\": \"$LOG_FILE\"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\"severity\": \"INFO\"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
|
||||||
|
# Invalid value configuration (invalid port) to check that D2
|
||||||
# gracefully handles reconfiguration errors.
|
# gracefully handles reconfiguration errors.
|
||||||
CONFIG_INVALID="{
|
CONFIG_INVALID="{
|
||||||
\"DhcpDdns\":
|
\"DhcpDdns\":
|
||||||
@@ -70,6 +122,33 @@ bin_path=@abs_top_builddir@/src/bin/d2
|
|||||||
# Import common test library.
|
# Import common test library.
|
||||||
. @abs_top_builddir@/src/lib/testutils/dhcp_test_lib.sh
|
. @abs_top_builddir@/src/lib/testutils/dhcp_test_lib.sh
|
||||||
|
|
||||||
|
# This test verifies that syntax checking works properly. This function
|
||||||
|
# requires 3 parameters:
|
||||||
|
# testname
|
||||||
|
# config - string with a content of the config (will be written to a file)
|
||||||
|
# exp_code - expected exit code returned by kea (0 - success, 1 - failure)
|
||||||
|
syntax_check_test() {
|
||||||
|
local TESTNAME="${1}"
|
||||||
|
local CONFIG="${2}"
|
||||||
|
local EXP_CODE="${3}"
|
||||||
|
|
||||||
|
# Log the start of the test and print test name.
|
||||||
|
test_start $TESTNAME
|
||||||
|
# Remove dangling Kea instances and remove log files.
|
||||||
|
cleanup
|
||||||
|
# Create correct configuration file.
|
||||||
|
create_config "${CONFIG}"
|
||||||
|
# Check it
|
||||||
|
printf "Running command %s.\n" "\"${bin_path}/${bin} -t ${CFG_FILE}\""
|
||||||
|
${bin_path}/${bin} -t ${CFG_FILE}
|
||||||
|
exit_code=$?
|
||||||
|
if [ ${exit_code} -ne $EXP_CODE ]; then
|
||||||
|
printf "ERROR: expected exit code ${EXP_CODE}, got ${exit_code}\n"
|
||||||
|
clean_exit 1
|
||||||
|
fi
|
||||||
|
test_finish 0
|
||||||
|
}
|
||||||
|
|
||||||
# This test verifies that D2 can be reconfigured with a SIGHUP signal.
|
# This test verifies that D2 can be reconfigured with a SIGHUP signal.
|
||||||
dynamic_reconfiguration_test() {
|
dynamic_reconfiguration_test() {
|
||||||
# Log the start of the test and print test name.
|
# Log the start of the test and print test name.
|
||||||
@@ -233,3 +312,6 @@ shutdown_test "dhcp-ddns.sigterm_test" 15
|
|||||||
shutdown_test "dhcp-ddns.sigint_test" 2
|
shutdown_test "dhcp-ddns.sigint_test" 2
|
||||||
version_test "dhcp-ddns.version"
|
version_test "dhcp-ddns.version"
|
||||||
logger_vars_test "dhcp-ddns.variables"
|
logger_vars_test "dhcp-ddns.variables"
|
||||||
|
syntax_check_test "dhcp-ddns.syntax_check_success" "${CONFIG}" 0
|
||||||
|
syntax_check_test "dhcp-ddns.syntax_check_bad_syntax" "${CONFIG_BAD_SYNTAX}" 1
|
||||||
|
syntax_check_test "dhcp-ddns.syntax_check_bad_values" "${CONFIG_BAD_VALUE}" 1
|
||||||
|
@@ -152,7 +152,7 @@ public:
|
|||||||
// try DHCPDDNS configure
|
// try DHCPDDNS configure
|
||||||
ConstElementPtr status;
|
ConstElementPtr status;
|
||||||
try {
|
try {
|
||||||
status = srv_->parseConfig(d2);
|
status = srv_->parseConfig(d2, false);
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
ADD_FAILURE() << "configure for " << operation
|
ADD_FAILURE() << "configure for " << operation
|
||||||
<< " failed with " << ex.what()
|
<< " failed with " << ex.what()
|
||||||
|
@@ -122,7 +122,8 @@ DCfgMgrBase::setContext(DCfgContextBasePtr& context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
isc::data::ConstElementPtr
|
isc::data::ConstElementPtr
|
||||||
DCfgMgrBase::parseConfig(isc::data::ConstElementPtr config_set) {
|
DCfgMgrBase::parseConfig(isc::data::ConstElementPtr config_set,
|
||||||
|
bool check_only) {
|
||||||
LOG_DEBUG(dctl_logger, DBGLVL_COMMAND,
|
LOG_DEBUG(dctl_logger, DBGLVL_COMMAND,
|
||||||
DCTL_CONFIG_START).arg(config_set->str());
|
DCTL_CONFIG_START).arg(config_set->str());
|
||||||
|
|
||||||
@@ -245,9 +246,15 @@ DCfgMgrBase::parseConfig(isc::data::ConstElementPtr config_set) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Everything was fine. Configuration set processed successfully.
|
// Everything was fine. Configuration set processed successfully.
|
||||||
LOG_INFO(dctl_logger, DCTL_CONFIG_COMPLETE).arg(getConfigSummary(0));
|
if (!check_only) {
|
||||||
answer = isc::config::createAnswer(0, "Configuration committed.");
|
LOG_INFO(dctl_logger, DCTL_CONFIG_COMPLETE).arg(getConfigSummary(0));
|
||||||
|
answer = isc::config::createAnswer(0, "Configuration committed.");
|
||||||
|
} else {
|
||||||
|
answer = isc::config::createAnswer(0, "Configuration seems sane.");
|
||||||
|
LOG_INFO(dctl_logger, DCTL_CONFIG_CHECK_COMPLETE)
|
||||||
|
.arg(getConfigSummary(0))
|
||||||
|
.arg(config::answerToText(answer));
|
||||||
|
}
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
LOG_ERROR(dctl_logger, DCTL_PARSER_FAIL).arg(ex.what());
|
LOG_ERROR(dctl_logger, DCTL_PARSER_FAIL).arg(ex.what());
|
||||||
answer = isc::config::createAnswer(1, ex.what());
|
answer = isc::config::createAnswer(1, ex.what());
|
||||||
@@ -257,6 +264,12 @@ DCfgMgrBase::parseConfig(isc::data::ConstElementPtr config_set) {
|
|||||||
return (answer);
|
return (answer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (check_only) {
|
||||||
|
// If this is a configuration check only, then don't actually apply
|
||||||
|
// the configuration and reverse to the previous one.
|
||||||
|
context_ = original_context;
|
||||||
|
}
|
||||||
|
|
||||||
return (answer);
|
return (answer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -246,7 +246,7 @@ typedef std::vector<std::string> ElementIdList;
|
|||||||
/// update context with parsed results
|
/// update context with parsed results
|
||||||
/// break on error
|
/// break on error
|
||||||
///
|
///
|
||||||
/// if an error occurred
|
/// if an error occurred or this is only a check
|
||||||
/// restore configuration context from backup
|
/// restore configuration context from backup
|
||||||
/// @endcode
|
/// @endcode
|
||||||
///
|
///
|
||||||
@@ -281,7 +281,7 @@ typedef std::vector<std::string> ElementIdList;
|
|||||||
/// 1. implementation calls simpleParseConfig from its configure method.
|
/// 1. implementation calls simpleParseConfig from its configure method.
|
||||||
/// 2. simpleParseConfig makes a configuration context
|
/// 2. simpleParseConfig makes a configuration context
|
||||||
/// 3. parse method from the derived class is called
|
/// 3. parse method from the derived class is called
|
||||||
/// 4. if the configuration was unsuccessful of this is only a check, the
|
/// 4. if the configuration was unsuccessful or this is only a check, the
|
||||||
/// old context is reinstantiated. If not, the configuration is kept.
|
/// old context is reinstantiated. If not, the configuration is kept.
|
||||||
///
|
///
|
||||||
/// See @ref isc::agent::CtrlAgentCfgMgr and @ref isc::agent::CtrlAgentProcess
|
/// See @ref isc::agent::CtrlAgentCfgMgr and @ref isc::agent::CtrlAgentProcess
|
||||||
@@ -303,12 +303,14 @@ public:
|
|||||||
/// the parsing as described in the class brief.
|
/// the parsing as described in the class brief.
|
||||||
///
|
///
|
||||||
/// @param config_set is a set of configuration elements to be parsed.
|
/// @param config_set is a set of configuration elements to be parsed.
|
||||||
|
/// @param check_only true if the config is to be checked only, but not applied
|
||||||
///
|
///
|
||||||
/// @return an Element that contains the results of configuration composed
|
/// @return an Element that contains the results of configuration composed
|
||||||
/// of an integer status value (0 means successful, non-zero means failure),
|
/// of an integer status value (0 means successful, non-zero means failure),
|
||||||
/// and a string explanation of the outcome.
|
/// and a string explanation of the outcome.
|
||||||
isc::data::ConstElementPtr parseConfig(isc::data::ConstElementPtr
|
isc::data::ConstElementPtr
|
||||||
config_set);
|
parseConfig(isc::data::ConstElementPtr config_set,
|
||||||
|
bool check_only = false);
|
||||||
|
|
||||||
|
|
||||||
/// @brief Acts as the receiver of new configurations.
|
/// @brief Acts as the receiver of new configurations.
|
||||||
|
@@ -37,7 +37,7 @@ DControllerBasePtr DControllerBase::controller_;
|
|||||||
// Note that the constructor instantiates the controller's primary IOService.
|
// Note that the constructor instantiates the controller's primary IOService.
|
||||||
DControllerBase::DControllerBase(const char* app_name, const char* bin_name)
|
DControllerBase::DControllerBase(const char* app_name, const char* bin_name)
|
||||||
: app_name_(app_name), bin_name_(bin_name),
|
: app_name_(app_name), bin_name_(bin_name),
|
||||||
verbose_(false), spec_file_name_(""),
|
verbose_(false), check_only_(false), spec_file_name_(""),
|
||||||
io_service_(new isc::asiolink::IOService()),
|
io_service_(new isc::asiolink::IOService()),
|
||||||
io_signal_queue_() {
|
io_signal_queue_() {
|
||||||
}
|
}
|
||||||
@@ -68,11 +68,17 @@ DControllerBase::launch(int argc, char* argv[], const bool test_mode) {
|
|||||||
parseArgs(argc, argv);
|
parseArgs(argc, argv);
|
||||||
} catch (const InvalidUsage& ex) {
|
} catch (const InvalidUsage& ex) {
|
||||||
usage(ex.what());
|
usage(ex.what());
|
||||||
throw; // rethrow it
|
// rethrow it with an empty message
|
||||||
|
isc_throw(InvalidUsage, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
setProcName(bin_name_);
|
setProcName(bin_name_);
|
||||||
|
|
||||||
|
if (isCheckOnly()) {
|
||||||
|
checkConfigOnly();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// It is important that we set a default logger name because this name
|
// It is important that we set a default logger name because this name
|
||||||
// will be used when the user doesn't provide the logging configuration
|
// will be used when the user doesn't provide the logging configuration
|
||||||
// in the Kea configuration file.
|
// in the Kea configuration file.
|
||||||
@@ -146,16 +152,71 @@ DControllerBase::launch(int argc, char* argv[], const bool test_mode) {
|
|||||||
.arg(app_name_).arg(getpid()).arg(VERSION);
|
.arg(app_name_).arg(getpid()).arg(VERSION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DControllerBase::checkConfigOnly() {
|
||||||
|
try {
|
||||||
|
// We need to initialize logging, in case any error
|
||||||
|
// messages are to be printed.
|
||||||
|
// This is just a test, so we don't care about lockfile.
|
||||||
|
setenv("KEA_LOCKFILE_DIR", "none", 0);
|
||||||
|
isc::dhcp::CfgMgr::instance().setDefaultLoggerName(bin_name_);
|
||||||
|
isc::dhcp::CfgMgr::instance().setVerbose(verbose_);
|
||||||
|
Daemon::loggerInit(bin_name_.c_str(), verbose_);
|
||||||
|
|
||||||
|
// Check the syntax first.
|
||||||
|
std::string config_file = getConfigFile();
|
||||||
|
if (config_file.empty()) {
|
||||||
|
// Basic sanity check: file name must not be empty.
|
||||||
|
isc_throw(InvalidUsage, "JSON configuration file not specified");
|
||||||
|
}
|
||||||
|
isc::data::ConstElementPtr whole_config = parseFile(config_file);
|
||||||
|
if (!whole_config) {
|
||||||
|
// No fallback to fromJSONFile
|
||||||
|
isc_throw(InvalidUsage, "No configuration found");
|
||||||
|
}
|
||||||
|
if (verbose_) {
|
||||||
|
std::cerr << "Syntax check OK" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the logic next.
|
||||||
|
isc::data::ConstElementPtr module_config;
|
||||||
|
module_config = whole_config->get(getAppName());
|
||||||
|
if (!module_config) {
|
||||||
|
isc_throw(InvalidUsage, "Config file " << config_file <<
|
||||||
|
" does not include '" << getAppName() << "' entry");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get an application process object.
|
||||||
|
initProcess();
|
||||||
|
|
||||||
|
isc::data::ConstElementPtr answer;
|
||||||
|
answer = checkConfig(module_config);
|
||||||
|
int rcode = 0;
|
||||||
|
answer = isc::config::parseAnswer(rcode, answer);
|
||||||
|
if (rcode != 0) {
|
||||||
|
isc_throw(InvalidUsage, "Error encountered: "
|
||||||
|
<< answer->stringValue());
|
||||||
|
}
|
||||||
|
} catch (const VersionMessage&) {
|
||||||
|
throw;
|
||||||
|
} catch (const InvalidUsage&) {
|
||||||
|
throw;
|
||||||
|
} catch (const std::exception& ex) {
|
||||||
|
isc_throw(InvalidUsage, "Syntax check failed with: " << ex.what());
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
DControllerBase::parseArgs(int argc, char* argv[])
|
DControllerBase::parseArgs(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
// Iterate over the given command line options. If its a stock option
|
// Iterate over the given command line options. If its a stock option
|
||||||
// ("s" or "v") handle it here. If its a valid custom option, then
|
// ("c" or "d") handle it here. If its a valid custom option, then
|
||||||
// invoke customOption.
|
// invoke customOption.
|
||||||
int ch;
|
int ch;
|
||||||
opterr = 0;
|
opterr = 0;
|
||||||
optind = 1;
|
optind = 1;
|
||||||
std::string opts("dvVWc:" + getCustomOpts());
|
std::string opts("dvVWc:t:" + getCustomOpts());
|
||||||
while ((ch = getopt(argc, argv, opts.c_str())) != -1) {
|
while ((ch = getopt(argc, argv, opts.c_str())) != -1) {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 'd':
|
case 'd':
|
||||||
@@ -182,12 +243,17 @@ DControllerBase::parseArgs(int argc, char* argv[])
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'c':
|
case 'c':
|
||||||
|
case 't':
|
||||||
// config file name
|
// config file name
|
||||||
if (optarg == NULL) {
|
if (optarg == NULL) {
|
||||||
isc_throw(InvalidUsage, "configuration file name missing");
|
isc_throw(InvalidUsage, "configuration file name missing");
|
||||||
}
|
}
|
||||||
|
|
||||||
setConfigFile(optarg);
|
setConfigFile(optarg);
|
||||||
|
|
||||||
|
if (ch == 't') {
|
||||||
|
check_only_ = true;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '?': {
|
case '?': {
|
||||||
@@ -333,6 +399,12 @@ DControllerBase::updateConfig(isc::data::ConstElementPtr new_config) {
|
|||||||
return (process_->configure(new_config, false));
|
return (process_->configure(new_config, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Instance method for checking new config
|
||||||
|
isc::data::ConstElementPtr
|
||||||
|
DControllerBase::checkConfig(isc::data::ConstElementPtr new_config) {
|
||||||
|
return (process_->configure(new_config, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Instance method for executing commands
|
// Instance method for executing commands
|
||||||
isc::data::ConstElementPtr
|
isc::data::ConstElementPtr
|
||||||
@@ -468,7 +540,9 @@ DControllerBase::usage(const std::string & text)
|
|||||||
<< std::endl
|
<< std::endl
|
||||||
<< " -d: optional, verbose output " << std::endl
|
<< " -d: optional, verbose output " << std::endl
|
||||||
<< " -c <config file name> : mandatory,"
|
<< " -c <config file name> : mandatory,"
|
||||||
<< " specifies name of configuration file " << std::endl;
|
<< " specify name of configuration file" << std::endl
|
||||||
|
<< " -t <config file name> : check the"
|
||||||
|
<< " configuration file and exit" << std::endl;
|
||||||
|
|
||||||
// add any derivation specific usage
|
// add any derivation specific usage
|
||||||
std::cerr << getUsageText() << std::endl;
|
std::cerr << getUsageText() << std::endl;
|
||||||
|
@@ -24,6 +24,7 @@ namespace isc {
|
|||||||
namespace process {
|
namespace process {
|
||||||
|
|
||||||
/// @brief Exception thrown when the command line is invalid.
|
/// @brief Exception thrown when the command line is invalid.
|
||||||
|
/// Can be used to transmit negative messages too.
|
||||||
class InvalidUsage : public isc::Exception {
|
class InvalidUsage : public isc::Exception {
|
||||||
public:
|
public:
|
||||||
InvalidUsage(const char* file, size_t line, const char* what) :
|
InvalidUsage(const char* file, size_t line, const char* what) :
|
||||||
@@ -34,7 +35,7 @@ public:
|
|||||||
/// Since command line argument parsing is done as part of
|
/// Since command line argument parsing is done as part of
|
||||||
/// DControllerBase::launch(), it uses this exception to propagate
|
/// DControllerBase::launch(), it uses this exception to propagate
|
||||||
/// version information up to main(), when command line argument
|
/// version information up to main(), when command line argument
|
||||||
/// -v or -V is given.
|
/// -v, -V or -W is given. Can be used to transmit positive messages too.
|
||||||
class VersionMessage : public isc::Exception {
|
class VersionMessage : public isc::Exception {
|
||||||
public:
|
public:
|
||||||
VersionMessage(const char* file, size_t line, const char* what) :
|
VersionMessage(const char* file, size_t line, const char* what) :
|
||||||
@@ -128,7 +129,7 @@ public:
|
|||||||
/// arguments.
|
/// arguments.
|
||||||
///
|
///
|
||||||
/// This function can be run in "test mode". It prevents initialization
|
/// This function can be run in "test mode". It prevents initialization
|
||||||
/// of D2 module logger. This is used in unit tests which initialize logger
|
/// of module logger. This is used in unit tests which initialize logger
|
||||||
/// in their main function. Such a logger uses environmental variables to
|
/// in their main function. Such a logger uses environmental variables to
|
||||||
/// control severity, verbosity etc.
|
/// control severity, verbosity etc.
|
||||||
///
|
///
|
||||||
@@ -161,6 +162,21 @@ public:
|
|||||||
virtual isc::data::ConstElementPtr updateConfig(isc::data::ConstElementPtr
|
virtual isc::data::ConstElementPtr updateConfig(isc::data::ConstElementPtr
|
||||||
new_config);
|
new_config);
|
||||||
|
|
||||||
|
/// @brief Instance method invoked by the configuration event handler and
|
||||||
|
/// which processes the actual configuration check. Provides behavioral
|
||||||
|
/// path for both integrated and stand-alone modes. The current
|
||||||
|
/// implementation will merge the configuration update into the existing
|
||||||
|
/// configuration and then invoke the application process' configure method
|
||||||
|
/// with a final rollback.
|
||||||
|
///
|
||||||
|
/// @param new_config is the new configuration
|
||||||
|
///
|
||||||
|
/// @return returns an Element that contains the results of configuration
|
||||||
|
/// update composed of an integer status value (0 means successful,
|
||||||
|
/// non-zero means failure), and a string explanation of the outcome.
|
||||||
|
virtual isc::data::ConstElementPtr checkConfig(isc::data::ConstElementPtr
|
||||||
|
new_config);
|
||||||
|
|
||||||
/// @brief Reconfigures the process from a configuration file
|
/// @brief Reconfigures the process from a configuration file
|
||||||
///
|
///
|
||||||
/// By default the file is assumed to be a JSON text file whose contents
|
/// By default the file is assumed to be a JSON text file whose contents
|
||||||
@@ -191,7 +207,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// It then extracts the set of configuration elements for the
|
/// It then extracts the set of configuration elements for the
|
||||||
/// module-name that matches the controller's app_name_ and passes that
|
/// module-name that matches the controller's app_name_ and passes that
|
||||||
/// set into @c updateConfig().
|
/// set into @c updateConfig() (or @c checkConfig()).
|
||||||
///
|
///
|
||||||
/// The file may contain an arbitrary number of other modules.
|
/// The file may contain an arbitrary number of other modules.
|
||||||
///
|
///
|
||||||
@@ -223,10 +239,10 @@ public:
|
|||||||
/// @return an Element that contains the results of command composed
|
/// @return an Element that contains the results of command composed
|
||||||
/// of an integer status value and a string explanation of the outcome.
|
/// of an integer status value and a string explanation of the outcome.
|
||||||
/// The status value is one of the following:
|
/// The status value is one of the following:
|
||||||
/// D2::COMMAND_SUCCESS - Command executed successfully
|
/// COMMAND_SUCCESS - Command executed successfully
|
||||||
/// D2::COMMAND_ERROR - Command is valid but suffered an operational
|
/// COMMAND_ERROR - Command is valid but suffered an operational
|
||||||
/// failure.
|
/// failure.
|
||||||
/// D2::COMMAND_INVALID - Command is not recognized as valid be either
|
/// COMMAND_INVALID - Command is not recognized as valid be either
|
||||||
/// the controller or the application process.
|
/// the controller or the application process.
|
||||||
virtual isc::data::ConstElementPtr executeCommand(const std::string&
|
virtual isc::data::ConstElementPtr executeCommand(const std::string&
|
||||||
command,
|
command,
|
||||||
@@ -283,10 +299,10 @@ protected:
|
|||||||
/// @return an Element that contains the results of command composed
|
/// @return an Element that contains the results of command composed
|
||||||
/// of an integer status value and a string explanation of the outcome.
|
/// of an integer status value and a string explanation of the outcome.
|
||||||
/// The status value is one of the following:
|
/// The status value is one of the following:
|
||||||
/// D2::COMMAND_SUCCESS - Command executed successfully
|
/// COMMAND_SUCCESS - Command executed successfully
|
||||||
/// D2::COMMAND_ERROR - Command is valid but suffered an operational
|
/// COMMAND_ERROR - Command is valid but suffered an operational
|
||||||
/// failure.
|
/// failure.
|
||||||
/// D2::COMMAND_INVALID - Command is not recognized as a valid custom
|
/// COMMAND_INVALID - Command is not recognized as a valid custom
|
||||||
/// controller command.
|
/// controller command.
|
||||||
virtual isc::data::ConstElementPtr customControllerCommand(
|
virtual isc::data::ConstElementPtr customControllerCommand(
|
||||||
const std::string& command, isc::data::ConstElementPtr args);
|
const std::string& command, isc::data::ConstElementPtr args);
|
||||||
@@ -302,7 +318,7 @@ protected:
|
|||||||
|
|
||||||
/// @brief Virtual method which returns a string containing the option
|
/// @brief Virtual method which returns a string containing the option
|
||||||
/// letters for any custom command line options supported by the derivation.
|
/// letters for any custom command line options supported by the derivation.
|
||||||
/// These are added to the stock options of "c" and "v" during command
|
/// These are added to the stock options of "c", "d", ..., during command
|
||||||
/// line interpretation.
|
/// line interpretation.
|
||||||
///
|
///
|
||||||
/// @return returns a string containing the custom option letters.
|
/// @return returns a string containing the custom option letters.
|
||||||
@@ -310,6 +326,13 @@ protected:
|
|||||||
return ("");
|
return ("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @brief Check the configuration
|
||||||
|
///
|
||||||
|
/// Called by @c launch() when @c check_only_ mode is enabled
|
||||||
|
/// @throw VersionMessage when successful but a message should be displayed
|
||||||
|
/// @throw InvalidUsage when an error was detected
|
||||||
|
void checkConfigOnly();
|
||||||
|
|
||||||
/// @brief Application-level signal processing method.
|
/// @brief Application-level signal processing method.
|
||||||
///
|
///
|
||||||
/// This method is the last step in processing a OS signal occurrence. It
|
/// This method is the last step in processing a OS signal occurrence. It
|
||||||
@@ -342,6 +365,22 @@ protected:
|
|||||||
verbose_ = value;
|
verbose_ = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @brief Supplies whether or not check only mode is enabled.
|
||||||
|
///
|
||||||
|
/// @return returns true if check only is enabled.
|
||||||
|
bool isCheckOnly() const {
|
||||||
|
return (check_only_);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Method for enabling or disabling check only mode.
|
||||||
|
///
|
||||||
|
/// @todo this method and @c setVerbose are currently not used.
|
||||||
|
///
|
||||||
|
/// @param value is the new value to assign the flag.
|
||||||
|
void setCheckOnly(bool value) {
|
||||||
|
check_only_ = value;
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief Getter for fetching the controller's IOService
|
/// @brief Getter for fetching the controller's IOService
|
||||||
///
|
///
|
||||||
/// @return returns a pointer reference to the IOService.
|
/// @return returns a pointer reference to the IOService.
|
||||||
@@ -385,14 +424,15 @@ protected:
|
|||||||
/// list of options with those returned by getCustomOpts(), and uses
|
/// list of options with those returned by getCustomOpts(), and uses
|
||||||
/// cstdlib's getopt to loop through the command line.
|
/// cstdlib's getopt to loop through the command line.
|
||||||
/// It handles stock options directly, and passes any custom options into
|
/// It handles stock options directly, and passes any custom options into
|
||||||
/// the customOption method. Currently there are only two stock options
|
/// the customOption method. Currently there are only some stock options
|
||||||
/// -c for specifying the configuration file, and -v for verbose logging.
|
/// -c/t for specifying the configuration file, -d for verbose logging,
|
||||||
|
/// and -v/V/W for version reports.
|
||||||
///
|
///
|
||||||
/// @param argc is the number of command line arguments supplied
|
/// @param argc is the number of command line arguments supplied
|
||||||
/// @param argv is the array of string (char *) command line arguments
|
/// @param argv is the array of string (char *) command line arguments
|
||||||
///
|
///
|
||||||
/// @throw InvalidUsage when there are usage errors.
|
/// @throw InvalidUsage when there are usage errors.
|
||||||
/// @throw VersionMessage if the -v or -V arguments is given.
|
/// @throw VersionMessage if the -v, -V or -W arguments is given.
|
||||||
void parseArgs(int argc, char* argv[]);
|
void parseArgs(int argc, char* argv[]);
|
||||||
|
|
||||||
|
|
||||||
@@ -536,6 +576,10 @@ private:
|
|||||||
/// @brief Indicates if the verbose logging mode is enabled.
|
/// @brief Indicates if the verbose logging mode is enabled.
|
||||||
bool verbose_;
|
bool verbose_;
|
||||||
|
|
||||||
|
/// @brief Indicates if the check only mode for the configuration
|
||||||
|
/// is enabled (usually specified by the command line -t argument).
|
||||||
|
bool check_only_;
|
||||||
|
|
||||||
/// @brief The absolute file name of the JSON spec file.
|
/// @brief The absolute file name of the JSON spec file.
|
||||||
std::string spec_file_name_;
|
std::string spec_file_name_;
|
||||||
|
|
||||||
|
@@ -102,7 +102,7 @@ public:
|
|||||||
///
|
///
|
||||||
/// @throw DProcessBaseError if an operational error is encountered.
|
/// @throw DProcessBaseError if an operational error is encountered.
|
||||||
virtual isc::data::ConstElementPtr
|
virtual isc::data::ConstElementPtr
|
||||||
shutdown(isc::data::ConstElementPtr args) = 0;
|
shutdown(isc::data::ConstElementPtr args) = 0;
|
||||||
|
|
||||||
/// @brief Processes the given configuration.
|
/// @brief Processes the given configuration.
|
||||||
///
|
///
|
||||||
@@ -118,7 +118,8 @@ public:
|
|||||||
/// of an integer status value (0 means successful, non-zero means failure),
|
/// of an integer status value (0 means successful, non-zero means failure),
|
||||||
/// and a string explanation of the outcome.
|
/// and a string explanation of the outcome.
|
||||||
virtual isc::data::ConstElementPtr
|
virtual isc::data::ConstElementPtr
|
||||||
configure(isc::data::ConstElementPtr config_set, bool check_only) = 0;
|
configure(isc::data::ConstElementPtr config_set,
|
||||||
|
bool check_only = false) = 0;
|
||||||
|
|
||||||
/// @brief Processes the given command.
|
/// @brief Processes the given command.
|
||||||
///
|
///
|
||||||
|
@@ -115,13 +115,22 @@ TEST_F(DStubCfgMgrTest, basicParseTest) {
|
|||||||
ASSERT_TRUE(fromJSON(config));
|
ASSERT_TRUE(fromJSON(config));
|
||||||
|
|
||||||
// Verify that we can parse a simple configuration.
|
// Verify that we can parse a simple configuration.
|
||||||
answer_ = cfg_mgr_->parseConfig(config_set_);
|
answer_ = cfg_mgr_->parseConfig(config_set_, false);
|
||||||
|
EXPECT_TRUE(checkAnswer(0));
|
||||||
|
|
||||||
|
// Verify that we can check a simple configuration.
|
||||||
|
answer_ = cfg_mgr_->parseConfig(config_set_, true);
|
||||||
EXPECT_TRUE(checkAnswer(0));
|
EXPECT_TRUE(checkAnswer(0));
|
||||||
|
|
||||||
// Verify that an unknown element error is caught and returns a failed
|
// Verify that an unknown element error is caught and returns a failed
|
||||||
// parse result.
|
// parse result.
|
||||||
SimFailure::set(SimFailure::ftElementUnknown);
|
SimFailure::set(SimFailure::ftElementUnknown);
|
||||||
answer_ = cfg_mgr_->parseConfig(config_set_);
|
answer_ = cfg_mgr_->parseConfig(config_set_, false);
|
||||||
|
EXPECT_TRUE(checkAnswer(1));
|
||||||
|
|
||||||
|
// Verify that an error is caught too when the config is checked for.
|
||||||
|
SimFailure::set(SimFailure::ftElementUnknown);
|
||||||
|
answer_ = cfg_mgr_->parseConfig(config_set_, true);
|
||||||
EXPECT_TRUE(checkAnswer(1));
|
EXPECT_TRUE(checkAnswer(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,7 +190,7 @@ TEST_F(DStubCfgMgrTest, parseOrderTest) {
|
|||||||
EXPECT_EQ(0, cfg_mgr_->getParseOrder().size());
|
EXPECT_EQ(0, cfg_mgr_->getParseOrder().size());
|
||||||
|
|
||||||
// Parse the configuration, verify it parses without error.
|
// Parse the configuration, verify it parses without error.
|
||||||
answer_ = cfg_mgr_->parseConfig(config_set_);
|
answer_ = cfg_mgr_->parseConfig(config_set_, false);
|
||||||
EXPECT_TRUE(checkAnswer(0));
|
EXPECT_TRUE(checkAnswer(0));
|
||||||
|
|
||||||
// Verify that the parsed order matches what we expected.
|
// Verify that the parsed order matches what we expected.
|
||||||
@@ -197,7 +206,7 @@ TEST_F(DStubCfgMgrTest, parseOrderTest) {
|
|||||||
EXPECT_EQ(1, cfg_mgr_->getParseOrder().size());
|
EXPECT_EQ(1, cfg_mgr_->getParseOrder().size());
|
||||||
|
|
||||||
// Verify the configuration fails.
|
// Verify the configuration fails.
|
||||||
answer_ = cfg_mgr_->parseConfig(config_set_);
|
answer_ = cfg_mgr_->parseConfig(config_set_, false);
|
||||||
EXPECT_TRUE(checkAnswer(1));
|
EXPECT_TRUE(checkAnswer(1));
|
||||||
|
|
||||||
// Verify that the configuration parses correctly, when the parse order
|
// Verify that the configuration parses correctly, when the parse order
|
||||||
@@ -212,7 +221,7 @@ TEST_F(DStubCfgMgrTest, parseOrderTest) {
|
|||||||
cfg_mgr_->parsed_order_.clear();
|
cfg_mgr_->parsed_order_.clear();
|
||||||
|
|
||||||
// Verify the configuration parses without error.
|
// Verify the configuration parses without error.
|
||||||
answer_ = cfg_mgr_->parseConfig(config_set_);
|
answer_ = cfg_mgr_->parseConfig(config_set_, false);
|
||||||
EXPECT_TRUE(checkAnswer(0));
|
EXPECT_TRUE(checkAnswer(0));
|
||||||
|
|
||||||
// Build expected order
|
// Build expected order
|
||||||
@@ -238,7 +247,7 @@ TEST_F(DStubCfgMgrTest, parseOrderTest) {
|
|||||||
EXPECT_EQ(4, cfg_mgr_->getParseOrder().size());
|
EXPECT_EQ(4, cfg_mgr_->getParseOrder().size());
|
||||||
|
|
||||||
// Verify the configuration fails.
|
// Verify the configuration fails.
|
||||||
answer_ = cfg_mgr_->parseConfig(config_set_);
|
answer_ = cfg_mgr_->parseConfig(config_set_, false);
|
||||||
EXPECT_TRUE(checkAnswer(1));
|
EXPECT_TRUE(checkAnswer(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,7 +271,7 @@ TEST_F(DStubCfgMgrTest, simpleTypesTest) {
|
|||||||
ASSERT_TRUE(fromJSON(config));
|
ASSERT_TRUE(fromJSON(config));
|
||||||
|
|
||||||
// Verify that the configuration parses without error.
|
// Verify that the configuration parses without error.
|
||||||
answer_ = cfg_mgr_->parseConfig(config_set_);
|
answer_ = cfg_mgr_->parseConfig(config_set_, false);
|
||||||
ASSERT_TRUE(checkAnswer(0));
|
ASSERT_TRUE(checkAnswer(0));
|
||||||
DStubContextPtr context = getStubContext();
|
DStubContextPtr context = getStubContext();
|
||||||
ASSERT_TRUE(context);
|
ASSERT_TRUE(context);
|
||||||
@@ -301,7 +310,7 @@ TEST_F(DStubCfgMgrTest, simpleTypesTest) {
|
|||||||
ASSERT_TRUE(fromJSON(config2));
|
ASSERT_TRUE(fromJSON(config2));
|
||||||
|
|
||||||
// Verify that the configuration parses without error.
|
// Verify that the configuration parses without error.
|
||||||
answer_ = cfg_mgr_->parseConfig(config_set_);
|
answer_ = cfg_mgr_->parseConfig(config_set_, false);
|
||||||
EXPECT_TRUE(checkAnswer(0));
|
EXPECT_TRUE(checkAnswer(0));
|
||||||
context = getStubContext();
|
context = getStubContext();
|
||||||
ASSERT_TRUE(context);
|
ASSERT_TRUE(context);
|
||||||
@@ -352,7 +361,7 @@ TEST_F(DStubCfgMgrTest, rollBackTest) {
|
|||||||
ASSERT_TRUE(fromJSON(config));
|
ASSERT_TRUE(fromJSON(config));
|
||||||
|
|
||||||
// Verify that the configuration parses without error.
|
// Verify that the configuration parses without error.
|
||||||
answer_ = cfg_mgr_->parseConfig(config_set_);
|
answer_ = cfg_mgr_->parseConfig(config_set_, false);
|
||||||
EXPECT_TRUE(checkAnswer(0));
|
EXPECT_TRUE(checkAnswer(0));
|
||||||
DStubContextPtr context = getStubContext();
|
DStubContextPtr context = getStubContext();
|
||||||
ASSERT_TRUE(context);
|
ASSERT_TRUE(context);
|
||||||
@@ -389,7 +398,7 @@ TEST_F(DStubCfgMgrTest, rollBackTest) {
|
|||||||
|
|
||||||
// Force a failure on the last element
|
// Force a failure on the last element
|
||||||
SimFailure::set(SimFailure::ftElementUnknown);
|
SimFailure::set(SimFailure::ftElementUnknown);
|
||||||
answer_ = cfg_mgr_->parseConfig(config_set_);
|
answer_ = cfg_mgr_->parseConfig(config_set_, false);
|
||||||
EXPECT_TRUE(checkAnswer(1));
|
EXPECT_TRUE(checkAnswer(1));
|
||||||
context = getStubContext();
|
context = getStubContext();
|
||||||
ASSERT_TRUE(context);
|
ASSERT_TRUE(context);
|
||||||
@@ -414,6 +423,76 @@ TEST_F(DStubCfgMgrTest, rollBackTest) {
|
|||||||
EXPECT_TRUE(object);
|
EXPECT_TRUE(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @brief Tests that the configuration context is preserved during
|
||||||
|
/// check only parsing.
|
||||||
|
TEST_F(DStubCfgMgrTest, checkOnly) {
|
||||||
|
// Create a configuration with all of the parameters.
|
||||||
|
string config = "{ \"bool_test\": true , "
|
||||||
|
" \"uint32_test\": 77 , "
|
||||||
|
" \"string_test\": \"hmmm chewy\" , "
|
||||||
|
" \"map_test\" : {} , "
|
||||||
|
" \"list_test\": [] }";
|
||||||
|
ASSERT_TRUE(fromJSON(config));
|
||||||
|
|
||||||
|
// Verify that the configuration parses without error.
|
||||||
|
answer_ = cfg_mgr_->parseConfig(config_set_, false);
|
||||||
|
EXPECT_TRUE(checkAnswer(0));
|
||||||
|
DStubContextPtr context = getStubContext();
|
||||||
|
ASSERT_TRUE(context);
|
||||||
|
|
||||||
|
// Verify that all of parameters have the expected values.
|
||||||
|
bool actual_bool = false;
|
||||||
|
EXPECT_NO_THROW(context->getParam("bool_test", actual_bool));
|
||||||
|
EXPECT_EQ(true, actual_bool);
|
||||||
|
|
||||||
|
uint32_t actual_uint32 = 0;
|
||||||
|
EXPECT_NO_THROW(context->getParam("uint32_test", actual_uint32));
|
||||||
|
EXPECT_EQ(77, actual_uint32);
|
||||||
|
|
||||||
|
std::string actual_string = "";
|
||||||
|
EXPECT_NO_THROW(context->getParam("string_test", actual_string));
|
||||||
|
EXPECT_EQ("hmmm chewy", actual_string);
|
||||||
|
|
||||||
|
isc::data::ConstElementPtr object;
|
||||||
|
EXPECT_NO_THROW(context->getObjectParam("map_test", object));
|
||||||
|
EXPECT_TRUE(object);
|
||||||
|
|
||||||
|
EXPECT_NO_THROW(context->getObjectParam("list_test", object));
|
||||||
|
EXPECT_TRUE(object);
|
||||||
|
|
||||||
|
// Create a configuration which "updates" all of the parameter values.
|
||||||
|
string config2 = "{ \"bool_test\": false , "
|
||||||
|
" \"uint32_test\": 88 , "
|
||||||
|
" \"string_test\": \"ewww yuk!\" , "
|
||||||
|
" \"map_test2\" : {} , "
|
||||||
|
" \"list_test2\": [] }";
|
||||||
|
ASSERT_TRUE(fromJSON(config2));
|
||||||
|
|
||||||
|
answer_ = cfg_mgr_->parseConfig(config_set_, true);
|
||||||
|
EXPECT_TRUE(checkAnswer(0));
|
||||||
|
context = getStubContext();
|
||||||
|
ASSERT_TRUE(context);
|
||||||
|
|
||||||
|
// Verify that all of parameters have the original values.
|
||||||
|
actual_bool = false;
|
||||||
|
EXPECT_NO_THROW(context->getParam("bool_test", actual_bool));
|
||||||
|
EXPECT_EQ(true, actual_bool);
|
||||||
|
|
||||||
|
actual_uint32 = 0;
|
||||||
|
EXPECT_NO_THROW(context->getParam("uint32_test", actual_uint32));
|
||||||
|
EXPECT_EQ(77, actual_uint32);
|
||||||
|
|
||||||
|
actual_string = "";
|
||||||
|
EXPECT_NO_THROW(context->getParam("string_test", actual_string));
|
||||||
|
EXPECT_EQ("hmmm chewy", actual_string);
|
||||||
|
|
||||||
|
EXPECT_NO_THROW(context->getObjectParam("map_test", object));
|
||||||
|
EXPECT_TRUE(object);
|
||||||
|
|
||||||
|
EXPECT_NO_THROW(context->getObjectParam("list_test", object));
|
||||||
|
EXPECT_TRUE(object);
|
||||||
|
}
|
||||||
|
|
||||||
// Tests that configuration element position is returned by getParam variants.
|
// Tests that configuration element position is returned by getParam variants.
|
||||||
TEST_F(DStubCfgMgrTest, paramPosition) {
|
TEST_F(DStubCfgMgrTest, paramPosition) {
|
||||||
// Create a configuration with one of each scalar types. We end them
|
// Create a configuration with one of each scalar types. We end them
|
||||||
@@ -424,7 +503,7 @@ TEST_F(DStubCfgMgrTest, paramPosition) {
|
|||||||
ASSERT_TRUE(fromJSON(config));
|
ASSERT_TRUE(fromJSON(config));
|
||||||
|
|
||||||
// Verify that the configuration parses without error.
|
// Verify that the configuration parses without error.
|
||||||
answer_ = cfg_mgr_->parseConfig(config_set_);
|
answer_ = cfg_mgr_->parseConfig(config_set_, false);
|
||||||
ASSERT_TRUE(checkAnswer(0));
|
ASSERT_TRUE(checkAnswer(0));
|
||||||
DStubContextPtr context = getStubContext();
|
DStubContextPtr context = getStubContext();
|
||||||
ASSERT_TRUE(context);
|
ASSERT_TRUE(context);
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (C) 2013-2016 Internet Systems Consortium, Inc. ("ISC")
|
// Copyright (C) 2013-2017 Internet Systems Consortium, Inc. ("ISC")
|
||||||
//
|
//
|
||||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
// 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
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
@@ -272,11 +272,22 @@ TEST_F(DStubControllerTest, configUpdateTests) {
|
|||||||
isc::config::parseAnswer(rcode, answer);
|
isc::config::parseAnswer(rcode, answer);
|
||||||
EXPECT_EQ(0, rcode);
|
EXPECT_EQ(0, rcode);
|
||||||
|
|
||||||
|
// Verify that a valid config gets a successful check result.
|
||||||
|
answer = checkConfig(config_set);
|
||||||
|
isc::config::parseAnswer(rcode, answer);
|
||||||
|
EXPECT_EQ(0, rcode);
|
||||||
|
|
||||||
// Verify that an error in process configure method is handled.
|
// Verify that an error in process configure method is handled.
|
||||||
SimFailure::set(SimFailure::ftProcessConfigure);
|
SimFailure::set(SimFailure::ftProcessConfigure);
|
||||||
answer = updateConfig(config_set);
|
answer = updateConfig(config_set);
|
||||||
isc::config::parseAnswer(rcode, answer);
|
isc::config::parseAnswer(rcode, answer);
|
||||||
EXPECT_EQ(1, rcode);
|
EXPECT_EQ(1, rcode);
|
||||||
|
|
||||||
|
// Verify that an error is handled too when the config is checked for.
|
||||||
|
SimFailure::set(SimFailure::ftProcessConfigure);
|
||||||
|
answer = checkConfig(config_set);
|
||||||
|
isc::config::parseAnswer(rcode, answer);
|
||||||
|
EXPECT_EQ(1, rcode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Command execution tests.
|
/// @brief Command execution tests.
|
||||||
|
@@ -68,18 +68,13 @@ DStubProcess::shutdown(isc::data::ConstElementPtr /* args */) {
|
|||||||
|
|
||||||
isc::data::ConstElementPtr
|
isc::data::ConstElementPtr
|
||||||
DStubProcess::configure(isc::data::ConstElementPtr config_set, bool check_only) {
|
DStubProcess::configure(isc::data::ConstElementPtr config_set, bool check_only) {
|
||||||
if (check_only) {
|
|
||||||
return (isc::config::createAnswer(1,
|
|
||||||
"Configuration checking is not supported."));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SimFailure::shouldFailOn(SimFailure::ftProcessConfigure)) {
|
if (SimFailure::shouldFailOn(SimFailure::ftProcessConfigure)) {
|
||||||
// Simulates a process configure failure.
|
// Simulates a process configure failure.
|
||||||
return (isc::config::createAnswer(1,
|
return (isc::config::createAnswer(1,
|
||||||
"Simulated process configuration error."));
|
"Simulated process configuration error."));
|
||||||
}
|
}
|
||||||
|
|
||||||
return (getCfgMgr()->parseConfig(config_set));
|
return (getCfgMgr()->parseConfig(config_set, check_only));
|
||||||
}
|
}
|
||||||
|
|
||||||
isc::data::ConstElementPtr
|
isc::data::ConstElementPtr
|
||||||
|
@@ -492,6 +492,13 @@ public:
|
|||||||
return (getController()->updateConfig(new_config));
|
return (getController()->updateConfig(new_config));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @Wrapper to invoke the Controller's checkConfig method. Please
|
||||||
|
/// refer to DControllerBase::checkConfig for details.
|
||||||
|
isc::data::ConstElementPtr checkConfig(isc::data::ConstElementPtr
|
||||||
|
new_config) {
|
||||||
|
return (getController()->checkConfig(new_config));
|
||||||
|
}
|
||||||
|
|
||||||
/// @Wrapper to invoke the Controller's executeCommand method. Please
|
/// @Wrapper to invoke the Controller's executeCommand method. Please
|
||||||
/// refer to DControllerBase::executeCommand for details.
|
/// refer to DControllerBase::executeCommand for details.
|
||||||
isc::data::ConstElementPtr executeCommand(const std::string& command,
|
isc::data::ConstElementPtr executeCommand(const std::string& command,
|
||||||
|
Reference in New Issue
Block a user