mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-31 05:55:28 +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),
|
||||
/// and a string explanation of the outcome.
|
||||
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.
|
||||
///
|
||||
|
@@ -52,7 +52,8 @@
|
||||
<arg><option>-V</option></arg>
|
||||
<arg><option>-W</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>
|
||||
</refsynopsisdiv>
|
||||
|
||||
@@ -115,6 +116,16 @@
|
||||
</para></listitem>
|
||||
</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>
|
||||
</refsect1>
|
||||
|
||||
|
@@ -25,9 +25,18 @@ int main(int argc, char* argv[]) {
|
||||
// 'false' value disables test mode.
|
||||
controller->launch(argc, argv, false);
|
||||
} 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) {
|
||||
std::cerr << "Service failed:" << ex.what() << std::endl;
|
||||
std::cerr << "Service failed: " << ex.what() << std::endl;
|
||||
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
|
||||
# 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_path=@abs_top_builddir@/src/bin/agent
|
||||
|
||||
# Import common test library.
|
||||
. @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
|
||||
# receives a SIGINT or SIGTERM signal.
|
||||
shutdown_test() {
|
||||
@@ -102,4 +145,6 @@ shutdown_test() {
|
||||
server_pid_file_test "${CONFIG}" DCTL_ALREADY_RUNNING
|
||||
shutdown_test "ctrl-agent.sigterm_test" 15
|
||||
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
|
||||
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
|
||||
has been invoked.
|
||||
|
||||
|
@@ -192,17 +192,18 @@ D2Process::shutdown(isc::data::ConstElementPtr args) {
|
||||
|
||||
isc::data::ConstElementPtr
|
||||
D2Process::configure(isc::data::ConstElementPtr config_set, bool check_only) {
|
||||
LOG_DEBUG(d2_logger, DBGLVL_TRACE_BASIC,
|
||||
DHCP_DDNS_CONFIGURE).arg(config_set->str());
|
||||
LOG_DEBUG(d2_logger, DBGLVL_TRACE_BASIC, DHCP_DDNS_CONFIGURE)
|
||||
.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) {
|
||||
return (isc::config::createAnswer(0, "Configuration check is not supported by D2."));
|
||||
return (answer);
|
||||
}
|
||||
|
||||
int rcode = 0;
|
||||
isc::data::ConstElementPtr comment;
|
||||
isc::data::ConstElementPtr answer = getCfgMgr()->parseConfig(config_set);;
|
||||
comment = isc::config::parseAnswer(rcode, answer);
|
||||
|
||||
if (rcode) {
|
||||
|
@@ -158,7 +158,8 @@ public:
|
||||
/// of an integer status value (0 means successful, non-zero means failure),
|
||||
/// and a string explanation of the outcome.
|
||||
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.
|
||||
///
|
||||
|
@@ -2,7 +2,7 @@
|
||||
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd"
|
||||
[<!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
|
||||
- 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>-W</option></arg>
|
||||
<arg><option>-d</option></arg>
|
||||
<!-- not yet <arg><option>-t</option></arg> -->
|
||||
<arg><option>-c</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>
|
||||
</refsynopsisdiv>
|
||||
|
||||
@@ -105,16 +105,6 @@
|
||||
</para></listitem>
|
||||
</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>
|
||||
<term><option>-c</option></term>
|
||||
<listitem><para>
|
||||
@@ -123,6 +113,16 @@
|
||||
</para></listitem>
|
||||
</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>
|
||||
</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
|
||||
// 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.
|
||||
controller->launch(argc, argv, false);
|
||||
} 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) {
|
||||
std::cerr << "Service failed:" << ex.what() << std::endl;
|
||||
std::cerr << "Service failed: " << ex.what() << std::endl;
|
||||
ret = EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
@@ -168,7 +168,8 @@ public:
|
||||
|
||||
// The JSON parsed ok and we've added the defaults, pass the config
|
||||
// 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.
|
||||
int rcode = 0;
|
||||
@@ -601,7 +602,7 @@ TEST_F(D2CfgMgrTest, fullConfig) {
|
||||
|
||||
// Verify that parsing the exact same configuration a second time
|
||||
// does not cause a duplicate value errors.
|
||||
answer_ = cfg_mgr_->parseConfig(config_set_);
|
||||
answer_ = cfg_mgr_->parseConfig(config_set_, false);
|
||||
ASSERT_TRUE(checkAnswer(0));
|
||||
}
|
||||
|
||||
|
@@ -181,12 +181,22 @@ TEST_F(D2ControllerTest, configUpdateTests) {
|
||||
isc::config::parseAnswer(rcode, answer);
|
||||
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.
|
||||
std::string config = "{ \"bogus\": 1000 } ";
|
||||
config_set = isc::data::Element::fromJSON(config);
|
||||
answer = updateConfig(config_set);
|
||||
isc::config::parseAnswer(rcode, answer);
|
||||
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.
|
||||
|
@@ -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
|
||||
# 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.
|
||||
CONFIG_INVALID="{
|
||||
\"DhcpDdns\":
|
||||
@@ -70,6 +122,33 @@ bin_path=@abs_top_builddir@/src/bin/d2
|
||||
# Import common test library.
|
||||
. @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.
|
||||
dynamic_reconfiguration_test() {
|
||||
# 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
|
||||
version_test "dhcp-ddns.version"
|
||||
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
|
||||
ConstElementPtr status;
|
||||
try {
|
||||
status = srv_->parseConfig(d2);
|
||||
status = srv_->parseConfig(d2, false);
|
||||
} catch (const std::exception& ex) {
|
||||
ADD_FAILURE() << "configure for " << operation
|
||||
<< " failed with " << ex.what()
|
||||
|
@@ -122,7 +122,8 @@ DCfgMgrBase::setContext(DCfgContextBasePtr& context) {
|
||||
}
|
||||
|
||||
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,
|
||||
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.
|
||||
LOG_INFO(dctl_logger, DCTL_CONFIG_COMPLETE).arg(getConfigSummary(0));
|
||||
answer = isc::config::createAnswer(0, "Configuration committed.");
|
||||
|
||||
if (!check_only) {
|
||||
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) {
|
||||
LOG_ERROR(dctl_logger, DCTL_PARSER_FAIL).arg(ex.what());
|
||||
answer = isc::config::createAnswer(1, ex.what());
|
||||
@@ -257,6 +264,12 @@ DCfgMgrBase::parseConfig(isc::data::ConstElementPtr config_set) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
@@ -246,7 +246,7 @@ typedef std::vector<std::string> ElementIdList;
|
||||
/// update context with parsed results
|
||||
/// break on error
|
||||
///
|
||||
/// if an error occurred
|
||||
/// if an error occurred or this is only a check
|
||||
/// restore configuration context from backup
|
||||
/// @endcode
|
||||
///
|
||||
@@ -281,7 +281,7 @@ typedef std::vector<std::string> ElementIdList;
|
||||
/// 1. implementation calls simpleParseConfig from its configure method.
|
||||
/// 2. simpleParseConfig makes a configuration context
|
||||
/// 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.
|
||||
///
|
||||
/// See @ref isc::agent::CtrlAgentCfgMgr and @ref isc::agent::CtrlAgentProcess
|
||||
@@ -303,12 +303,14 @@ public:
|
||||
/// the parsing as described in the class brief.
|
||||
///
|
||||
/// @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
|
||||
/// of an integer status value (0 means successful, non-zero means failure),
|
||||
/// and a string explanation of the outcome.
|
||||
isc::data::ConstElementPtr parseConfig(isc::data::ConstElementPtr
|
||||
config_set);
|
||||
isc::data::ConstElementPtr
|
||||
parseConfig(isc::data::ConstElementPtr config_set,
|
||||
bool check_only = false);
|
||||
|
||||
|
||||
/// @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.
|
||||
DControllerBase::DControllerBase(const char* app_name, const char* 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_signal_queue_() {
|
||||
}
|
||||
@@ -68,11 +68,17 @@ DControllerBase::launch(int argc, char* argv[], const bool test_mode) {
|
||||
parseArgs(argc, argv);
|
||||
} catch (const InvalidUsage& ex) {
|
||||
usage(ex.what());
|
||||
throw; // rethrow it
|
||||
// rethrow it with an empty message
|
||||
isc_throw(InvalidUsage, "");
|
||||
}
|
||||
|
||||
setProcName(bin_name_);
|
||||
|
||||
if (isCheckOnly()) {
|
||||
checkConfigOnly();
|
||||
return;
|
||||
}
|
||||
|
||||
// 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
|
||||
// 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);
|
||||
}
|
||||
|
||||
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
|
||||
DControllerBase::parseArgs(int argc, char* argv[])
|
||||
{
|
||||
// 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.
|
||||
int ch;
|
||||
opterr = 0;
|
||||
optind = 1;
|
||||
std::string opts("dvVWc:" + getCustomOpts());
|
||||
std::string opts("dvVWc:t:" + getCustomOpts());
|
||||
while ((ch = getopt(argc, argv, opts.c_str())) != -1) {
|
||||
switch (ch) {
|
||||
case 'd':
|
||||
@@ -182,12 +243,17 @@ DControllerBase::parseArgs(int argc, char* argv[])
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
case 't':
|
||||
// config file name
|
||||
if (optarg == NULL) {
|
||||
isc_throw(InvalidUsage, "configuration file name missing");
|
||||
}
|
||||
|
||||
setConfigFile(optarg);
|
||||
|
||||
if (ch == 't') {
|
||||
check_only_ = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case '?': {
|
||||
@@ -333,6 +399,12 @@ DControllerBase::updateConfig(isc::data::ConstElementPtr new_config) {
|
||||
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
|
||||
isc::data::ConstElementPtr
|
||||
@@ -468,7 +540,9 @@ DControllerBase::usage(const std::string & text)
|
||||
<< std::endl
|
||||
<< " -d: optional, verbose output " << std::endl
|
||||
<< " -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
|
||||
std::cerr << getUsageText() << std::endl;
|
||||
|
@@ -24,6 +24,7 @@ namespace isc {
|
||||
namespace process {
|
||||
|
||||
/// @brief Exception thrown when the command line is invalid.
|
||||
/// Can be used to transmit negative messages too.
|
||||
class InvalidUsage : public isc::Exception {
|
||||
public:
|
||||
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
|
||||
/// DControllerBase::launch(), it uses this exception to propagate
|
||||
/// 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 {
|
||||
public:
|
||||
VersionMessage(const char* file, size_t line, const char* what) :
|
||||
@@ -128,7 +129,7 @@ public:
|
||||
/// arguments.
|
||||
///
|
||||
/// 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
|
||||
/// control severity, verbosity etc.
|
||||
///
|
||||
@@ -161,6 +162,21 @@ public:
|
||||
virtual isc::data::ConstElementPtr updateConfig(isc::data::ConstElementPtr
|
||||
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
|
||||
///
|
||||
/// 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
|
||||
/// 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.
|
||||
///
|
||||
@@ -223,10 +239,10 @@ public:
|
||||
/// @return an Element that contains the results of command composed
|
||||
/// of an integer status value and a string explanation of the outcome.
|
||||
/// The status value is one of the following:
|
||||
/// D2::COMMAND_SUCCESS - Command executed successfully
|
||||
/// D2::COMMAND_ERROR - Command is valid but suffered an operational
|
||||
/// COMMAND_SUCCESS - Command executed successfully
|
||||
/// COMMAND_ERROR - Command is valid but suffered an operational
|
||||
/// 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.
|
||||
virtual isc::data::ConstElementPtr executeCommand(const std::string&
|
||||
command,
|
||||
@@ -283,10 +299,10 @@ protected:
|
||||
/// @return an Element that contains the results of command composed
|
||||
/// of an integer status value and a string explanation of the outcome.
|
||||
/// The status value is one of the following:
|
||||
/// D2::COMMAND_SUCCESS - Command executed successfully
|
||||
/// D2::COMMAND_ERROR - Command is valid but suffered an operational
|
||||
/// COMMAND_SUCCESS - Command executed successfully
|
||||
/// COMMAND_ERROR - Command is valid but suffered an operational
|
||||
/// failure.
|
||||
/// D2::COMMAND_INVALID - Command is not recognized as a valid custom
|
||||
/// COMMAND_INVALID - Command is not recognized as a valid custom
|
||||
/// controller command.
|
||||
virtual isc::data::ConstElementPtr customControllerCommand(
|
||||
const std::string& command, isc::data::ConstElementPtr args);
|
||||
@@ -302,7 +318,7 @@ protected:
|
||||
|
||||
/// @brief Virtual method which returns a string containing the option
|
||||
/// 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.
|
||||
///
|
||||
/// @return returns a string containing the custom option letters.
|
||||
@@ -310,6 +326,13 @@ protected:
|
||||
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.
|
||||
///
|
||||
/// This method is the last step in processing a OS signal occurrence. It
|
||||
@@ -342,6 +365,22 @@ protected:
|
||||
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
|
||||
///
|
||||
/// @return returns a pointer reference to the IOService.
|
||||
@@ -385,14 +424,15 @@ protected:
|
||||
/// list of options with those returned by getCustomOpts(), and uses
|
||||
/// cstdlib's getopt to loop through the command line.
|
||||
/// It handles stock options directly, and passes any custom options into
|
||||
/// the customOption method. Currently there are only two stock options
|
||||
/// -c for specifying the configuration file, and -v for verbose logging.
|
||||
/// the customOption method. Currently there are only some stock options
|
||||
/// -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 argv is the array of string (char *) command line arguments
|
||||
///
|
||||
/// @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[]);
|
||||
|
||||
|
||||
@@ -536,6 +576,10 @@ private:
|
||||
/// @brief Indicates if the verbose logging mode is enabled.
|
||||
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.
|
||||
std::string spec_file_name_;
|
||||
|
||||
|
@@ -102,7 +102,7 @@ public:
|
||||
///
|
||||
/// @throw DProcessBaseError if an operational error is encountered.
|
||||
virtual isc::data::ConstElementPtr
|
||||
shutdown(isc::data::ConstElementPtr args) = 0;
|
||||
shutdown(isc::data::ConstElementPtr args) = 0;
|
||||
|
||||
/// @brief Processes the given configuration.
|
||||
///
|
||||
@@ -118,7 +118,8 @@ public:
|
||||
/// of an integer status value (0 means successful, non-zero means failure),
|
||||
/// and a string explanation of the outcome.
|
||||
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.
|
||||
///
|
||||
|
@@ -115,13 +115,22 @@ TEST_F(DStubCfgMgrTest, basicParseTest) {
|
||||
ASSERT_TRUE(fromJSON(config));
|
||||
|
||||
// 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));
|
||||
|
||||
// Verify that an unknown element error is caught and returns a failed
|
||||
// parse result.
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -181,7 +190,7 @@ TEST_F(DStubCfgMgrTest, parseOrderTest) {
|
||||
EXPECT_EQ(0, cfg_mgr_->getParseOrder().size());
|
||||
|
||||
// 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));
|
||||
|
||||
// Verify that the parsed order matches what we expected.
|
||||
@@ -197,7 +206,7 @@ TEST_F(DStubCfgMgrTest, parseOrderTest) {
|
||||
EXPECT_EQ(1, cfg_mgr_->getParseOrder().size());
|
||||
|
||||
// Verify the configuration fails.
|
||||
answer_ = cfg_mgr_->parseConfig(config_set_);
|
||||
answer_ = cfg_mgr_->parseConfig(config_set_, false);
|
||||
EXPECT_TRUE(checkAnswer(1));
|
||||
|
||||
// Verify that the configuration parses correctly, when the parse order
|
||||
@@ -212,7 +221,7 @@ TEST_F(DStubCfgMgrTest, parseOrderTest) {
|
||||
cfg_mgr_->parsed_order_.clear();
|
||||
|
||||
// Verify the configuration parses without error.
|
||||
answer_ = cfg_mgr_->parseConfig(config_set_);
|
||||
answer_ = cfg_mgr_->parseConfig(config_set_, false);
|
||||
EXPECT_TRUE(checkAnswer(0));
|
||||
|
||||
// Build expected order
|
||||
@@ -238,7 +247,7 @@ TEST_F(DStubCfgMgrTest, parseOrderTest) {
|
||||
EXPECT_EQ(4, cfg_mgr_->getParseOrder().size());
|
||||
|
||||
// Verify the configuration fails.
|
||||
answer_ = cfg_mgr_->parseConfig(config_set_);
|
||||
answer_ = cfg_mgr_->parseConfig(config_set_, false);
|
||||
EXPECT_TRUE(checkAnswer(1));
|
||||
}
|
||||
|
||||
@@ -262,7 +271,7 @@ TEST_F(DStubCfgMgrTest, simpleTypesTest) {
|
||||
ASSERT_TRUE(fromJSON(config));
|
||||
|
||||
// Verify that the configuration parses without error.
|
||||
answer_ = cfg_mgr_->parseConfig(config_set_);
|
||||
answer_ = cfg_mgr_->parseConfig(config_set_, false);
|
||||
ASSERT_TRUE(checkAnswer(0));
|
||||
DStubContextPtr context = getStubContext();
|
||||
ASSERT_TRUE(context);
|
||||
@@ -301,7 +310,7 @@ TEST_F(DStubCfgMgrTest, simpleTypesTest) {
|
||||
ASSERT_TRUE(fromJSON(config2));
|
||||
|
||||
// Verify that the configuration parses without error.
|
||||
answer_ = cfg_mgr_->parseConfig(config_set_);
|
||||
answer_ = cfg_mgr_->parseConfig(config_set_, false);
|
||||
EXPECT_TRUE(checkAnswer(0));
|
||||
context = getStubContext();
|
||||
ASSERT_TRUE(context);
|
||||
@@ -352,7 +361,7 @@ TEST_F(DStubCfgMgrTest, rollBackTest) {
|
||||
ASSERT_TRUE(fromJSON(config));
|
||||
|
||||
// Verify that the configuration parses without error.
|
||||
answer_ = cfg_mgr_->parseConfig(config_set_);
|
||||
answer_ = cfg_mgr_->parseConfig(config_set_, false);
|
||||
EXPECT_TRUE(checkAnswer(0));
|
||||
DStubContextPtr context = getStubContext();
|
||||
ASSERT_TRUE(context);
|
||||
@@ -389,7 +398,7 @@ TEST_F(DStubCfgMgrTest, rollBackTest) {
|
||||
|
||||
// Force a failure on the last element
|
||||
SimFailure::set(SimFailure::ftElementUnknown);
|
||||
answer_ = cfg_mgr_->parseConfig(config_set_);
|
||||
answer_ = cfg_mgr_->parseConfig(config_set_, false);
|
||||
EXPECT_TRUE(checkAnswer(1));
|
||||
context = getStubContext();
|
||||
ASSERT_TRUE(context);
|
||||
@@ -414,6 +423,76 @@ TEST_F(DStubCfgMgrTest, rollBackTest) {
|
||||
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.
|
||||
TEST_F(DStubCfgMgrTest, paramPosition) {
|
||||
// Create a configuration with one of each scalar types. We end them
|
||||
@@ -424,7 +503,7 @@ TEST_F(DStubCfgMgrTest, paramPosition) {
|
||||
ASSERT_TRUE(fromJSON(config));
|
||||
|
||||
// Verify that the configuration parses without error.
|
||||
answer_ = cfg_mgr_->parseConfig(config_set_);
|
||||
answer_ = cfg_mgr_->parseConfig(config_set_, false);
|
||||
ASSERT_TRUE(checkAnswer(0));
|
||||
DStubContextPtr context = getStubContext();
|
||||
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
|
||||
// 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);
|
||||
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.
|
||||
SimFailure::set(SimFailure::ftProcessConfigure);
|
||||
answer = updateConfig(config_set);
|
||||
isc::config::parseAnswer(rcode, answer);
|
||||
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.
|
||||
|
@@ -68,18 +68,13 @@ DStubProcess::shutdown(isc::data::ConstElementPtr /* args */) {
|
||||
|
||||
isc::data::ConstElementPtr
|
||||
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)) {
|
||||
// Simulates a process configure failure.
|
||||
return (isc::config::createAnswer(1,
|
||||
"Simulated process configuration error."));
|
||||
}
|
||||
|
||||
return (getCfgMgr()->parseConfig(config_set));
|
||||
return (getCfgMgr()->parseConfig(config_set, check_only));
|
||||
}
|
||||
|
||||
isc::data::ConstElementPtr
|
||||
|
@@ -492,6 +492,13 @@ public:
|
||||
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
|
||||
/// refer to DControllerBase::executeCommand for details.
|
||||
isc::data::ConstElementPtr executeCommand(const std::string& command,
|
||||
|
Reference in New Issue
Block a user