mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-22 09:57:41 +00:00
[#1671] the -t parameter now loads and checks hook libraries config
This commit is contained in:
parent
9cba85e911
commit
35238f03aa
@ -357,8 +357,56 @@ Since Kea 1.9.6, the ``kea-shell`` tool supports TLS.
|
|||||||
|
|
||||||
.. _agent-launch:
|
.. _agent-launch:
|
||||||
|
|
||||||
Starting the Control Agent
|
Starting and Stopping the Control Agent
|
||||||
==========================
|
=======================================
|
||||||
|
|
||||||
|
``kea-ctrl-agent`` accepts the following command-line switches:
|
||||||
|
|
||||||
|
- ``-c file`` - specifies the configuration file.
|
||||||
|
|
||||||
|
- ``-d`` - specifies whether the agent logging should be switched to
|
||||||
|
debug/verbose mode. In verbose mode, the logging severity and
|
||||||
|
debuglevel specified in the configuration file are ignored and
|
||||||
|
"debug" severity and the maximum debuglevel (99) are assumed. The
|
||||||
|
flag is convenient for temporarily switching the server into maximum
|
||||||
|
verbosity, e.g. when debugging.
|
||||||
|
|
||||||
|
- ``-t file`` - specifies the configuration file to be tested.
|
||||||
|
``kea-netconf`` attempts to load it and conducts sanity checks;
|
||||||
|
certain checks are possible only while running the actual server. The
|
||||||
|
actual status is reported with exit code (0 = configuration appears valid,
|
||||||
|
1 = error encountered). Kea prints out log messages to standard
|
||||||
|
output and error to standard error when testing the configuration.
|
||||||
|
|
||||||
|
- ``-v`` - displays the version of ``kea-ctrl-agent`` and exits.
|
||||||
|
|
||||||
|
- ``-V`` - displays the extended version information for ``kea-ctrl-agent``
|
||||||
|
and exits. The listing includes the versions of the libraries
|
||||||
|
dynamically linked to Kea.
|
||||||
|
|
||||||
|
- ``-W`` - displays the Kea configuration report and exits. The report
|
||||||
|
is a copy of the ``config.report`` file produced by ``./configure``;
|
||||||
|
it is embedded in the executable binary.
|
||||||
|
|
||||||
|
The ``config.report`` file may also be accessed directly, via the
|
||||||
|
following command. The binary ``path`` may be found in the install
|
||||||
|
directory or in the ``.libs`` subdirectory in the source tree. For
|
||||||
|
example: ``kea/src/lib/process/.libs/``.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
strings path/libkea-process.so | sed -n 's/;;;; //p'
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
strings path/libkea-process.a | sed -n 's/;;;; //p'
|
||||||
|
|
||||||
|
The libcfgrpt.a library can also be used from the source tree with path:
|
||||||
|
``src/lib/process/cfgrpt/.libs/``.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
strings path/libcfgrpt.a | sed -n 's/;;;; //p'
|
||||||
|
|
||||||
The CA is started by running its binary and specifying the configuration
|
The CA is started by running its binary and specifying the configuration
|
||||||
file it should use. For example:
|
file it should use. For example:
|
||||||
|
@ -141,11 +141,22 @@ directly. It accepts the following command-line switches:
|
|||||||
The ``config.report`` file may also be accessed directly, via the
|
The ``config.report`` file may also be accessed directly, via the
|
||||||
following command. The binary ``path`` may be found in the install
|
following command. The binary ``path`` may be found in the install
|
||||||
directory or in the ``.libs`` subdirectory in the source tree. For
|
directory or in the ``.libs`` subdirectory in the source tree. For
|
||||||
example: ``kea/src/bin/d2/.libs/kea-dhcp-ddns``.
|
example: ``kea/src/lib/process/.libs/``.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
strings path/kea-dhcp-ddns | sed -n 's/;;;; //p'
|
strings path/libkea-process.so | sed -n 's/;;;; //p'
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
strings path/libkea-process.a | sed -n 's/;;;; //p'
|
||||||
|
|
||||||
|
The libcfgrpt.a library can also be used from the source tree with path:
|
||||||
|
``src/lib/process/cfgrpt/.libs/``.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
strings path/libcfgrpt.a | sed -n 's/;;;; //p'
|
||||||
|
|
||||||
Upon startup, the module loads its configuration and begins listening
|
Upon startup, the module loads its configuration and begins listening
|
||||||
for NCRs based on that configuration.
|
for NCRs based on that configuration.
|
||||||
|
@ -42,6 +42,14 @@ the following command-line switches:
|
|||||||
comprehensive; certain checks are possible only when running the
|
comprehensive; certain checks are possible only when running the
|
||||||
server.
|
server.
|
||||||
|
|
||||||
|
- ``-T file`` - specifies a configuration file to be tested. ``kea-dhcp4``
|
||||||
|
loads it, checks it, and exits. It performs extra checks beside ``-t`` is
|
||||||
|
doing, like establising database connections (lease db, host db, CB db,
|
||||||
|
forensic logging db), hook libraries loading and configuration parsing, etc.
|
||||||
|
It does not open unix or TCP/UDP sockets, neither does it open or rotate
|
||||||
|
files, as all these actions could interfere with a running process on the
|
||||||
|
same machine.
|
||||||
|
|
||||||
- ``-v`` - displays the Kea version and exits.
|
- ``-v`` - displays the Kea version and exits.
|
||||||
|
|
||||||
- ``-V`` - displays the Kea extended version with additional parameters
|
- ``-V`` - displays the Kea extended version with additional parameters
|
||||||
@ -52,6 +60,26 @@ the following command-line switches:
|
|||||||
is a copy of the ``config.report`` file produced by ``./configure``;
|
is a copy of the ``config.report`` file produced by ``./configure``;
|
||||||
it is embedded in the executable binary.
|
it is embedded in the executable binary.
|
||||||
|
|
||||||
|
The ``config.report`` file may also be accessed directly, via the
|
||||||
|
following command. The binary ``path`` may be found in the install
|
||||||
|
directory or in the ``.libs`` subdirectory in the source tree. For
|
||||||
|
example: ``kea/src/lib/process/.libs/``.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
strings path/libkea-process.so | sed -n 's/;;;; //p'
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
strings path/libkea-process.a | sed -n 's/;;;; //p'
|
||||||
|
|
||||||
|
The libcfgrpt.a library can also be used from the source tree with path:
|
||||||
|
``src/lib/process/cfgrpt/.libs/``.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
strings path/libcfgrpt.a | sed -n 's/;;;; //p'
|
||||||
|
|
||||||
On startup, the server detects available network interfaces and
|
On startup, the server detects available network interfaces and
|
||||||
attempts to open UDP sockets on all interfaces listed in the
|
attempts to open UDP sockets on all interfaces listed in the
|
||||||
configuration file. Since the DHCPv4 server opens privileged ports, it
|
configuration file. Since the DHCPv4 server opens privileged ports, it
|
||||||
|
@ -42,6 +42,14 @@ the following command-line switches:
|
|||||||
comprehensive; certain checks are possible only when running the
|
comprehensive; certain checks are possible only when running the
|
||||||
server.
|
server.
|
||||||
|
|
||||||
|
- ``-T file`` - specifies a configuration file to be tested. ``kea-dhcp4``
|
||||||
|
loads it, checks it, and exits. It performs extra checks beside ``-t`` is
|
||||||
|
doing, like establising database connections (lease db, host db, CB db,
|
||||||
|
forensic logging db), hook libraries loading and configuration parsing, etc.
|
||||||
|
It does not open unix or TCP/UDP sockets, neither does it open or rotate
|
||||||
|
files, as all these actions could interfere with a running process on the
|
||||||
|
same machine.
|
||||||
|
|
||||||
- ``-v`` - displays the Kea version and exits.
|
- ``-v`` - displays the Kea version and exits.
|
||||||
|
|
||||||
- ``-V`` - displays the Kea extended version with additional parameters
|
- ``-V`` - displays the Kea extended version with additional parameters
|
||||||
@ -52,6 +60,26 @@ the following command-line switches:
|
|||||||
is a copy of the ``config.report`` file produced by ``./configure``;
|
is a copy of the ``config.report`` file produced by ``./configure``;
|
||||||
it is embedded in the executable binary.
|
it is embedded in the executable binary.
|
||||||
|
|
||||||
|
The ``config.report`` file may also be accessed directly, via the
|
||||||
|
following command. The binary ``path`` may be found in the install
|
||||||
|
directory or in the ``.libs`` subdirectory in the source tree. For
|
||||||
|
example: ``kea/src/lib/process/.libs/``.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
strings path/libkea-process.so | sed -n 's/;;;; //p'
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
strings path/libkea-process.a | sed -n 's/;;;; //p'
|
||||||
|
|
||||||
|
The libcfgrpt.a library can also be used from the source tree with path:
|
||||||
|
``src/lib/process/cfgrpt/.libs/``.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
strings path/libcfgrpt.a | sed -n 's/;;;; //p'
|
||||||
|
|
||||||
On startup, the server detects available network interfaces and
|
On startup, the server detects available network interfaces and
|
||||||
attempts to open UDP sockets on all interfaces listed in the
|
attempts to open UDP sockets on all interfaces listed in the
|
||||||
configuration file. Since the DHCPv6 server opens privileged ports, it
|
configuration file. Since the DHCPv6 server opens privileged ports, it
|
||||||
|
@ -686,6 +686,26 @@ Starting and Stopping the NETCONF Agent
|
|||||||
is a copy of the ``config.report`` file produced by ``./configure``;
|
is a copy of the ``config.report`` file produced by ``./configure``;
|
||||||
it is embedded in the executable binary.
|
it is embedded in the executable binary.
|
||||||
|
|
||||||
|
The ``config.report`` file may also be accessed directly, via the
|
||||||
|
following command. The binary ``path`` may be found in the install
|
||||||
|
directory or in the ``.libs`` subdirectory in the source tree. For
|
||||||
|
example: ``kea/src/lib/process/.libs/``.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
strings path/libkea-process.so | sed -n 's/;;;; //p'
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
strings path/libkea-process.a | sed -n 's/;;;; //p'
|
||||||
|
|
||||||
|
The libcfgrpt.a library can also be used from the source tree with path:
|
||||||
|
``src/lib/process/cfgrpt/.libs/``.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
strings path/libcfgrpt.a | sed -n 's/;;;; //p'
|
||||||
|
|
||||||
.. _operation-example:
|
.. _operation-example:
|
||||||
|
|
||||||
A Step-by-Step NETCONF Agent Operation Example
|
A Step-by-Step NETCONF Agent Operation Example
|
||||||
|
@ -49,6 +49,14 @@ The arguments are as follows:
|
|||||||
service and control channel sockets are not opened, and hook
|
service and control channel sockets are not opened, and hook
|
||||||
libraries are not loaded.
|
libraries are not loaded.
|
||||||
|
|
||||||
|
``-T config-file``
|
||||||
|
Checks the configuration file and reports the first error, if any.
|
||||||
|
It performs extra checks beside ``-t`` is doing, like establising database
|
||||||
|
connections (lease db, host db, CB db, forensic logging db), hook libraries
|
||||||
|
loading and configuration parsing, etc. It does not open unix or TCP/UDP
|
||||||
|
sockets, neither does it open or rotate files, as all these actions could
|
||||||
|
interfere with a running process on the same machine.
|
||||||
|
|
||||||
``-p server-port-number``
|
``-p server-port-number``
|
||||||
Specifies the server port number (1-65535) on which the server listens. This is
|
Specifies the server port number (1-65535) on which the server listens. This is
|
||||||
useful for testing purposes only.
|
useful for testing purposes only.
|
||||||
|
@ -49,6 +49,14 @@ The arguments are as follows:
|
|||||||
service and control channel sockets are not opened, and hook
|
service and control channel sockets are not opened, and hook
|
||||||
libraries are not loaded.
|
libraries are not loaded.
|
||||||
|
|
||||||
|
``-T config-file``
|
||||||
|
Checks the configuration file and reports the first error, if any.
|
||||||
|
It performs extra checks beside ``-t`` is doing, like establising database
|
||||||
|
connections (lease db, host db, CB db, forensic logging db), hook libraries
|
||||||
|
loading and configuration parsing, etc. It does not open unix or TCP/UDP
|
||||||
|
sockets, neither does it open or rotate files, as all these actions could
|
||||||
|
interfere with a running process on the same machine.
|
||||||
|
|
||||||
``-p server-port-number``
|
``-p server-port-number``
|
||||||
Specifies the server port number (1-65535) on which the server listens. This is
|
Specifies the server port number (1-65535) on which the server listens. This is
|
||||||
useful for testing purposes only.
|
useful for testing purposes only.
|
||||||
|
@ -1025,6 +1025,29 @@ ControlledDhcpv4Srv::processConfig(isc::data::ConstElementPtr config) {
|
|||||||
// exception free.
|
// exception free.
|
||||||
LibDHCP::commitRuntimeOptionDefs();
|
LibDHCP::commitRuntimeOptionDefs();
|
||||||
|
|
||||||
|
auto notify_libraries = ControlledDhcpv4Srv::finishConfigHookLibraries(config);
|
||||||
|
if (notify_libraries) {
|
||||||
|
return (notify_libraries);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply multi threading settings.
|
||||||
|
// @note These settings are applied/updated only if no errors occur while
|
||||||
|
// applying the new configuration.
|
||||||
|
// @todo This should be fixed.
|
||||||
|
try {
|
||||||
|
CfgMultiThreading::apply(CfgMgr::instance().getStagingCfg()->getDHCPMultiThreading());
|
||||||
|
} catch (const std::exception& ex) {
|
||||||
|
err << "Error applying multi threading settings: "
|
||||||
|
<< ex.what();
|
||||||
|
return (isc::config::createAnswer(CONTROL_RESULT_ERROR, err.str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return (answer);
|
||||||
|
}
|
||||||
|
|
||||||
|
isc::data::ConstElementPtr
|
||||||
|
ControlledDhcpv4Srv::finishConfigHookLibraries(isc::data::ConstElementPtr config) {
|
||||||
|
ControlledDhcpv4Srv* srv = ControlledDhcpv4Srv::getInstance();
|
||||||
// This hook point notifies hooks libraries that the configuration of the
|
// This hook point notifies hooks libraries that the configuration of the
|
||||||
// DHCPv4 server has completed. It provides the hook library with the pointer
|
// DHCPv4 server has completed. It provides the hook library with the pointer
|
||||||
// to the common IO service object, new server configuration in the JSON
|
// to the common IO service object, new server configuration in the JSON
|
||||||
@ -1053,27 +1076,11 @@ ControlledDhcpv4Srv::processConfig(isc::data::ConstElementPtr config) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply multi threading settings.
|
return (ConstElementPtr());
|
||||||
// @note These settings are applied/updated only if no errors occur while
|
|
||||||
// applying the new configuration.
|
|
||||||
// @todo This should be fixed.
|
|
||||||
try {
|
|
||||||
CfgMultiThreading::apply(CfgMgr::instance().getStagingCfg()->getDHCPMultiThreading());
|
|
||||||
} catch (const std::exception& ex) {
|
|
||||||
err << "Error applying multi threading settings: "
|
|
||||||
<< ex.what();
|
|
||||||
return (isc::config::createAnswer(CONTROL_RESULT_ERROR, err.str()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return (answer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isc::data::ConstElementPtr
|
isc::data::ConstElementPtr
|
||||||
ControlledDhcpv4Srv::checkConfig(isc::data::ConstElementPtr config) {
|
ControlledDhcpv4Srv::checkConfig(isc::data::ConstElementPtr config) {
|
||||||
|
|
||||||
LOG_DEBUG(dhcp4_logger, DBG_DHCP4_COMMAND, DHCP4_CONFIG_RECEIVED)
|
|
||||||
.arg(redactConfig(config)->str());
|
|
||||||
|
|
||||||
ControlledDhcpv4Srv* srv = ControlledDhcpv4Srv::getInstance();
|
ControlledDhcpv4Srv* srv = ControlledDhcpv4Srv::getInstance();
|
||||||
|
|
||||||
if (!srv) {
|
if (!srv) {
|
||||||
@ -1082,6 +1089,9 @@ ControlledDhcpv4Srv::checkConfig(isc::data::ConstElementPtr config) {
|
|||||||
return (no_srv);
|
return (no_srv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOG_DEBUG(dhcp4_logger, DBG_DHCP4_COMMAND, DHCP4_CONFIG_RECEIVED)
|
||||||
|
.arg(srv->redactConfig(config)->str());
|
||||||
|
|
||||||
return (configureDhcp4Server(*srv, config, true));
|
return (configureDhcp4Server(*srv, config, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,21 +105,32 @@ public:
|
|||||||
/// As pointer to this method is used a callback in ASIO used in
|
/// As pointer to this method is used a callback in ASIO used in
|
||||||
/// ModuleCCSession, it has to be static.
|
/// ModuleCCSession, it has to be static.
|
||||||
///
|
///
|
||||||
/// @param new_config textual representation of the new configuration
|
/// @param config textual representation of the new configuration
|
||||||
///
|
///
|
||||||
/// @return status of the config update
|
/// @return status of the config update
|
||||||
static isc::data::ConstElementPtr
|
static isc::data::ConstElementPtr
|
||||||
processConfig(isc::data::ConstElementPtr new_config);
|
processConfig(isc::data::ConstElementPtr config);
|
||||||
|
|
||||||
/// @brief Configuration checker
|
/// @brief Configuration checker
|
||||||
///
|
///
|
||||||
/// This is a method for checking incoming configuration.
|
/// This is a method for checking incoming configuration.
|
||||||
///
|
///
|
||||||
/// @param new_config JSON representation of the new configuration
|
/// @param config JSON representation of the new configuration
|
||||||
///
|
///
|
||||||
/// @return status of the config check
|
/// @return status of the config check
|
||||||
isc::data::ConstElementPtr
|
static isc::data::ConstElementPtr
|
||||||
checkConfig(isc::data::ConstElementPtr new_config);
|
checkConfig(isc::data::ConstElementPtr config);
|
||||||
|
|
||||||
|
/// @brief Configuration checker for hook libraries
|
||||||
|
///
|
||||||
|
/// This is a method for checking incoming configuration in the hooks
|
||||||
|
/// libraries. It calls dhcp4_srv_configured hook point for all hooks.
|
||||||
|
///
|
||||||
|
/// @param config JSON representation of the new configuration
|
||||||
|
///
|
||||||
|
/// @return status of the config check
|
||||||
|
static isc::data::ConstElementPtr
|
||||||
|
finishConfigHookLibraries(isc::data::ConstElementPtr config);
|
||||||
|
|
||||||
/// @brief Returns pointer to the sole instance of Dhcpv4Srv
|
/// @brief Returns pointer to the sole instance of Dhcpv4Srv
|
||||||
///
|
///
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include <database/dbaccess_parser.h>
|
#include <database/dbaccess_parser.h>
|
||||||
#include <database/backend_selector.h>
|
#include <database/backend_selector.h>
|
||||||
#include <database/server_selector.h>
|
#include <database/server_selector.h>
|
||||||
|
#include <dhcp4/ctrl_dhcp4_srv.h>
|
||||||
#include <dhcp4/dhcp4_log.h>
|
#include <dhcp4/dhcp4_log.h>
|
||||||
#include <dhcp4/dhcp4_srv.h>
|
#include <dhcp4/dhcp4_srv.h>
|
||||||
#include <dhcp4/json_config_parser.h>
|
#include <dhcp4/json_config_parser.h>
|
||||||
@ -738,7 +739,7 @@ processDhcp4Config(isc::data::ConstElementPtr config_set) {
|
|||||||
|
|
||||||
isc::data::ConstElementPtr
|
isc::data::ConstElementPtr
|
||||||
configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set,
|
configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set,
|
||||||
bool check_only) {
|
bool check_only, bool extra_checks) {
|
||||||
if (!config_set) {
|
if (!config_set) {
|
||||||
ConstElementPtr answer = isc::config::createAnswer(CONTROL_RESULT_ERROR,
|
ConstElementPtr answer = isc::config::createAnswer(CONTROL_RESULT_ERROR,
|
||||||
"Can't parse NULL config");
|
"Can't parse NULL config");
|
||||||
@ -748,21 +749,14 @@ configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set,
|
|||||||
LOG_DEBUG(dhcp4_logger, DBG_DHCP4_COMMAND, DHCP4_CONFIG_START)
|
LOG_DEBUG(dhcp4_logger, DBG_DHCP4_COMMAND, DHCP4_CONFIG_START)
|
||||||
.arg(server.redactConfig(config_set)->str());
|
.arg(server.redactConfig(config_set)->str());
|
||||||
|
|
||||||
// Rollback informs whether error occurred and original data
|
|
||||||
// have to be restored to global storages.
|
|
||||||
bool rollback = false;
|
|
||||||
|
|
||||||
auto answer = processDhcp4Config(config_set);
|
auto answer = processDhcp4Config(config_set);
|
||||||
|
|
||||||
int status_code = 0;
|
int status_code = CONTROL_RESULT_SUCCESS;
|
||||||
isc::config::parseAnswer(status_code, answer);
|
isc::config::parseAnswer(status_code, answer);
|
||||||
if (status_code != CONTROL_RESULT_SUCCESS) {
|
|
||||||
rollback = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
SrvConfigPtr srv_config;
|
SrvConfigPtr srv_config;
|
||||||
|
|
||||||
if (!rollback) {
|
if (status_code == CONTROL_RESULT_SUCCESS) {
|
||||||
if (!check_only) {
|
if (!check_only) {
|
||||||
string parameter_name;
|
string parameter_name;
|
||||||
ElementPtr mutable_cfg;
|
ElementPtr mutable_cfg;
|
||||||
@ -803,20 +797,33 @@ configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set,
|
|||||||
LOG_ERROR(dhcp4_logger, DHCP4_PARSER_FAIL)
|
LOG_ERROR(dhcp4_logger, DHCP4_PARSER_FAIL)
|
||||||
.arg(parameter_name).arg(ex.what());
|
.arg(parameter_name).arg(ex.what());
|
||||||
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, ex.what());
|
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, ex.what());
|
||||||
|
status_code = CONTROL_RESULT_ERROR;
|
||||||
// An error occurred, so make sure that we restore original data.
|
|
||||||
rollback = true;
|
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
// For things like bad_cast in boost::lexical_cast
|
// For things like bad_cast in boost::lexical_cast
|
||||||
LOG_ERROR(dhcp4_logger, DHCP4_PARSER_EXCEPTION).arg(parameter_name);
|
LOG_ERROR(dhcp4_logger, DHCP4_PARSER_EXCEPTION).arg(parameter_name);
|
||||||
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, "undefined configuration"
|
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, "undefined configuration"
|
||||||
" processing error");
|
" processing error");
|
||||||
|
status_code = CONTROL_RESULT_ERROR;
|
||||||
// An error occurred, so make sure that we restore original data.
|
|
||||||
rollback = true;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rollback = true;
|
if (extra_checks) {
|
||||||
|
// Re-open lease and host database with new parameters.
|
||||||
|
try {
|
||||||
|
// Get the staging configuration.
|
||||||
|
srv_config = CfgMgr::instance().getStagingCfg();
|
||||||
|
|
||||||
|
CfgDbAccessPtr cfg_db = CfgMgr::instance().getStagingCfg()->getCfgDbAccess();
|
||||||
|
string params = "universe=4 persist=false";
|
||||||
|
if (cfg_db->getExtendedInfoTablesEnabled()) {
|
||||||
|
params += " extended-info-tables=true";
|
||||||
|
}
|
||||||
|
cfg_db->setAppendedParameters(params);
|
||||||
|
cfg_db->createManagers();
|
||||||
|
} catch (const std::exception& ex) {
|
||||||
|
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, ex.what());
|
||||||
|
status_code = CONTROL_RESULT_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -824,12 +831,26 @@ configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set,
|
|||||||
// configuration. This will add created subnets and option values into
|
// configuration. This will add created subnets and option values into
|
||||||
// the server's configuration.
|
// the server's configuration.
|
||||||
// This operation should be exception safe but let's make sure.
|
// This operation should be exception safe but let's make sure.
|
||||||
if (!rollback) {
|
if (status_code == CONTROL_RESULT_SUCCESS && !check_only) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
// Setup the command channel.
|
// Setup the command channel.
|
||||||
configureCommandChannel();
|
configureCommandChannel();
|
||||||
|
} catch (const isc::Exception& ex) {
|
||||||
|
LOG_ERROR(dhcp4_logger, DHCP4_PARSER_COMMIT_FAIL).arg(ex.what());
|
||||||
|
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, ex.what());
|
||||||
|
status_code = CONTROL_RESULT_ERROR;
|
||||||
|
} catch (...) {
|
||||||
|
// For things like bad_cast in boost::lexical_cast
|
||||||
|
LOG_ERROR(dhcp4_logger, DHCP4_PARSER_COMMIT_EXCEPTION);
|
||||||
|
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, "undefined configuration"
|
||||||
|
" parsing error");
|
||||||
|
status_code = CONTROL_RESULT_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status_code == CONTROL_RESULT_SUCCESS && (!check_only || extra_checks)) {
|
||||||
|
try {
|
||||||
// No need to commit interface names as this is handled by the
|
// No need to commit interface names as this is handled by the
|
||||||
// CfgMgr::commit() function.
|
// CfgMgr::commit() function.
|
||||||
|
|
||||||
@ -837,7 +858,21 @@ configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set,
|
|||||||
D2ClientConfigPtr cfg;
|
D2ClientConfigPtr cfg;
|
||||||
cfg = CfgMgr::instance().getStagingCfg()->getD2ClientConfig();
|
cfg = CfgMgr::instance().getStagingCfg()->getD2ClientConfig();
|
||||||
CfgMgr::instance().setD2ClientConfig(cfg);
|
CfgMgr::instance().setD2ClientConfig(cfg);
|
||||||
|
} catch (const isc::Exception& ex) {
|
||||||
|
LOG_ERROR(dhcp4_logger, DHCP4_PARSER_COMMIT_FAIL).arg(ex.what());
|
||||||
|
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, ex.what());
|
||||||
|
status_code = CONTROL_RESULT_ERROR;
|
||||||
|
} catch (...) {
|
||||||
|
// For things like bad_cast in boost::lexical_cast
|
||||||
|
LOG_ERROR(dhcp4_logger, DHCP4_PARSER_COMMIT_EXCEPTION);
|
||||||
|
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, "undefined configuration"
|
||||||
|
" parsing error");
|
||||||
|
status_code = CONTROL_RESULT_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status_code == CONTROL_RESULT_SUCCESS && (!check_only || extra_checks)) {
|
||||||
|
try {
|
||||||
// This occurs last as if it succeeds, there is no easy way to
|
// This occurs last as if it succeeds, there is no easy way to
|
||||||
// revert it. As a result, the failure to commit a subsequent
|
// revert it. As a result, the failure to commit a subsequent
|
||||||
// change causes problems when trying to roll back.
|
// change causes problems when trying to roll back.
|
||||||
@ -849,35 +884,32 @@ configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set,
|
|||||||
} catch (const isc::Exception& ex) {
|
} catch (const isc::Exception& ex) {
|
||||||
LOG_ERROR(dhcp4_logger, DHCP4_PARSER_COMMIT_FAIL).arg(ex.what());
|
LOG_ERROR(dhcp4_logger, DHCP4_PARSER_COMMIT_FAIL).arg(ex.what());
|
||||||
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, ex.what());
|
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, ex.what());
|
||||||
|
status_code = CONTROL_RESULT_ERROR;
|
||||||
// An error occurred, so make sure to restore the original data.
|
|
||||||
rollback = true;
|
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
// For things like bad_cast in boost::lexical_cast
|
// For things like bad_cast in boost::lexical_cast
|
||||||
LOG_ERROR(dhcp4_logger, DHCP4_PARSER_COMMIT_EXCEPTION);
|
LOG_ERROR(dhcp4_logger, DHCP4_PARSER_COMMIT_EXCEPTION);
|
||||||
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, "undefined configuration"
|
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, "undefined configuration"
|
||||||
" parsing error");
|
" parsing error");
|
||||||
|
status_code = CONTROL_RESULT_ERROR;
|
||||||
// An error occurred, so make sure to restore the original data.
|
|
||||||
rollback = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Moved from the commit block to add the config backend indication.
|
// Moved from the commit block to add the config backend indication.
|
||||||
if (!rollback) {
|
if (status_code == CONTROL_RESULT_SUCCESS && (!check_only || extra_checks)) {
|
||||||
try {
|
try {
|
||||||
|
if (extra_checks) {
|
||||||
// If there are config backends, fetch and merge into staging config
|
server.getCBControl()->databaseConfigConnect(srv_config);
|
||||||
server.getCBControl()->databaseConfigFetch(srv_config,
|
} else {
|
||||||
CBControlDHCPv4::FetchMode::FETCH_ALL);
|
// If there are config backends, fetch and merge into staging config
|
||||||
|
server.getCBControl()->databaseConfigFetch(srv_config,
|
||||||
|
CBControlDHCPv4::FetchMode::FETCH_ALL);
|
||||||
|
}
|
||||||
} catch (const isc::Exception& ex) {
|
} catch (const isc::Exception& ex) {
|
||||||
std::ostringstream err;
|
std::ostringstream err;
|
||||||
err << "during update from config backend database: " << ex.what();
|
err << "during update from config backend database: " << ex.what();
|
||||||
LOG_ERROR(dhcp4_logger, DHCP4_PARSER_COMMIT_FAIL).arg(err.str());
|
LOG_ERROR(dhcp4_logger, DHCP4_PARSER_COMMIT_FAIL).arg(err.str());
|
||||||
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, err.str());
|
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, err.str());
|
||||||
|
status_code = CONTROL_RESULT_ERROR;
|
||||||
// An error occurred, so make sure to restore the original data.
|
|
||||||
rollback = true;
|
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
// For things like bad_cast in boost::lexical_cast
|
// For things like bad_cast in boost::lexical_cast
|
||||||
std::ostringstream err;
|
std::ostringstream err;
|
||||||
@ -885,17 +917,23 @@ configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set,
|
|||||||
<< "undefined configuration parsing error";
|
<< "undefined configuration parsing error";
|
||||||
LOG_ERROR(dhcp4_logger, DHCP4_PARSER_COMMIT_FAIL).arg(err.str());
|
LOG_ERROR(dhcp4_logger, DHCP4_PARSER_COMMIT_FAIL).arg(err.str());
|
||||||
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, err.str());
|
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, err.str());
|
||||||
|
status_code = CONTROL_RESULT_ERROR;
|
||||||
// An error occurred, so make sure to restore the original data.
|
|
||||||
rollback = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rollback changes as the configuration parsing failed.
|
// Rollback changes as the configuration parsing failed.
|
||||||
if (rollback) {
|
if (check_only || status_code != CONTROL_RESULT_SUCCESS) {
|
||||||
// Revert to original configuration of runtime option definitions
|
// Revert to original configuration of runtime option definitions
|
||||||
// in the libdhcp++.
|
// in the libdhcp++.
|
||||||
LibDHCP::revertRuntimeOptionDefs();
|
LibDHCP::revertRuntimeOptionDefs();
|
||||||
|
|
||||||
|
if (status_code == CONTROL_RESULT_SUCCESS && extra_checks) {
|
||||||
|
auto notify_libraries = ControlledDhcpv4Srv::finishConfigHookLibraries(config_set);
|
||||||
|
if (notify_libraries) {
|
||||||
|
return (notify_libraries);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (answer);
|
return (answer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,15 +8,13 @@
|
|||||||
#define DHCP4_CONFIG_PARSER_H
|
#define DHCP4_CONFIG_PARSER_H
|
||||||
|
|
||||||
#include <cc/data.h>
|
#include <cc/data.h>
|
||||||
#include <cc/stamped_value.h>
|
|
||||||
#include <dhcpsrv/parsers/dhcp_parsers.h>
|
#include <dhcpsrv/parsers/dhcp_parsers.h>
|
||||||
#include <exceptions/exceptions.h>
|
#include <exceptions/exceptions.h>
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
/// @todo: This header file and its .cc counterpart are very similar between
|
/// @todo: This header file and its .cc counterpart are very similar between
|
||||||
/// DHCPv4 and DHCPv6. They should be merged. A ticket #2355.
|
/// DHCPv4 and DHCPv6. They should be merged.
|
||||||
|
|
||||||
namespace isc {
|
namespace isc {
|
||||||
namespace dhcp {
|
namespace dhcp {
|
||||||
@ -41,9 +39,9 @@ class Dhcpv4Srv;
|
|||||||
/// extra parameter is a reference to DHCPv4 server component. It is currently
|
/// extra parameter is a reference to DHCPv4 server component. It is currently
|
||||||
/// not used and CfgMgr::instance() is accessed instead.
|
/// not used and CfgMgr::instance() is accessed instead.
|
||||||
///
|
///
|
||||||
/// Test-only mode added. If check_only flag is set to true, the configuration
|
/// Test-only mode is supported. If check_only flag is set to true, the
|
||||||
/// is parsed, but the actual change is not applied. The goal is to have
|
/// configuration is parsed, but the actual change is not applied. The goal is
|
||||||
/// the ability to test configuration.
|
/// to have the ability to test configuration.
|
||||||
///
|
///
|
||||||
/// This method does not throw. It catches all exceptions and returns them as
|
/// This method does not throw. It catches all exceptions and returns them as
|
||||||
/// reconfiguration statuses. It may return the following response codes:
|
/// reconfiguration statuses. It may return the following response codes:
|
||||||
@ -52,13 +50,16 @@ class Dhcpv4Srv;
|
|||||||
/// 2 - commit failed (parsing was successful, but failed to store the
|
/// 2 - commit failed (parsing was successful, but failed to store the
|
||||||
/// values in to server's configuration)
|
/// values in to server's configuration)
|
||||||
///
|
///
|
||||||
/// @param server the server object
|
/// @param server DHCPv4 server object.
|
||||||
/// @param config_set a new configuration (JSON) for DHCPv4 server
|
/// @param config_set a new configuration (JSON) for DHCPv4 server.
|
||||||
/// @param check_only whether this configuration is for testing only
|
/// @param check_only whether this configuration is for testing only.
|
||||||
/// @return answer that contains result of reconfiguration
|
/// @param extra_checks load hooks and perform extra checks if this flag is true
|
||||||
|
/// and check_only is also true, otherwise perform simple check if
|
||||||
|
/// check_only is true.
|
||||||
|
/// @return answer that contains result of the reconfiguration.
|
||||||
isc::data::ConstElementPtr
|
isc::data::ConstElementPtr
|
||||||
configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set,
|
configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set,
|
||||||
bool check_only = false);
|
bool check_only = false, bool extra_checks = false);
|
||||||
|
|
||||||
} // namespace dhcp
|
} // namespace dhcp
|
||||||
} // namespace isc
|
} // namespace isc
|
||||||
|
@ -52,13 +52,15 @@ usage() {
|
|||||||
<< endl;
|
<< endl;
|
||||||
cerr << endl;
|
cerr << endl;
|
||||||
cerr << "Usage: " << DHCP4_NAME
|
cerr << "Usage: " << DHCP4_NAME
|
||||||
<< " -[v|V|W] [-d] [-{c|t} cfgfile] [-p number] [-P number]" << endl;
|
<< " -[v|V|W] [-d] [-{c|t|T} cfgfile] [-p number] [-P number]" << endl;
|
||||||
cerr << " -v: print version number and exit" << endl;
|
cerr << " -v: print version number and exit" << endl;
|
||||||
cerr << " -V: print extended version and exit" << endl;
|
cerr << " -V: print extended version and exit" << endl;
|
||||||
cerr << " -W: display the configuration report and exit" << endl;
|
cerr << " -W: display the configuration report and exit" << endl;
|
||||||
cerr << " -d: debug mode with extra verbosity (former -v)" << endl;
|
cerr << " -d: debug mode with extra verbosity (former -v)" << endl;
|
||||||
cerr << " -c file: specify configuration file" << endl;
|
cerr << " -c file: specify configuration file" << endl;
|
||||||
cerr << " -t file: check the configuration file syntax and exit" << endl;
|
cerr << " -t file: check the configuration file syntax and exit" << endl;
|
||||||
|
cerr << " -T file: check the configuration file doing hooks load and extra "
|
||||||
|
<< "checks and exit" << endl;
|
||||||
cerr << " -p number: specify non-standard server port number 1-65535 "
|
cerr << " -p number: specify non-standard server port number 1-65535 "
|
||||||
<< "(useful for testing only)" << endl;
|
<< "(useful for testing only)" << endl;
|
||||||
cerr << " -P number: specify non-standard client port number 1-65535 "
|
cerr << " -P number: specify non-standard client port number 1-65535 "
|
||||||
@ -76,11 +78,12 @@ main(int argc, char* argv[]) {
|
|||||||
int client_port_number = 0;
|
int client_port_number = 0;
|
||||||
bool verbose_mode = false; // Should server be verbose?
|
bool verbose_mode = false; // Should server be verbose?
|
||||||
bool check_mode = false; // Check syntax
|
bool check_mode = false; // Check syntax
|
||||||
|
bool load_hooks = false; // Check hooks config
|
||||||
|
|
||||||
// The standard config file
|
// The standard config file
|
||||||
std::string config_file("");
|
std::string config_file("");
|
||||||
|
|
||||||
while ((ch = getopt(argc, argv, "dvVWc:p:P:t:")) != -1) {
|
while ((ch = getopt(argc, argv, "dvVWc:p:P:t:T:")) != -1) {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 'd':
|
case 'd':
|
||||||
verbose_mode = true;
|
verbose_mode = true;
|
||||||
@ -98,9 +101,16 @@ main(int argc, char* argv[]) {
|
|||||||
cout << isc::detail::getConfigReport() << endl;
|
cout << isc::detail::getConfigReport() << endl;
|
||||||
return (EXIT_SUCCESS);
|
return (EXIT_SUCCESS);
|
||||||
|
|
||||||
|
case 'T':
|
||||||
|
load_hooks = true;
|
||||||
|
check_mode = true;
|
||||||
|
config_file = optarg;
|
||||||
|
break;
|
||||||
|
|
||||||
case 't':
|
case 't':
|
||||||
check_mode = true;
|
check_mode = true;
|
||||||
// falls through
|
config_file = optarg;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'c': // config file
|
case 'c': // config file
|
||||||
config_file = optarg;
|
config_file = optarg;
|
||||||
@ -184,9 +194,11 @@ main(int argc, char* argv[]) {
|
|||||||
ControlledDhcpv4Srv server(0);
|
ControlledDhcpv4Srv server(0);
|
||||||
ConstElementPtr answer;
|
ConstElementPtr answer;
|
||||||
|
|
||||||
|
server.setProcName(DHCP4_NAME);
|
||||||
|
|
||||||
// Now we pass the Dhcp4 configuration to the server, but
|
// Now we pass the Dhcp4 configuration to the server, but
|
||||||
// tell it to check the configuration only (check_only = true)
|
// tell it to check the configuration only (check_only = true)
|
||||||
answer = configureDhcp4Server(server, dhcp4, true);
|
answer = configureDhcp4Server(server, dhcp4, true, load_hooks);
|
||||||
|
|
||||||
int status_code = 0;
|
int status_code = 0;
|
||||||
answer = isc::config::parseAnswer(status_code, answer);
|
answer = isc::config::parseAnswer(status_code, answer);
|
||||||
|
@ -20,6 +20,10 @@ static const int LIBRARY_NUMBER = 1;
|
|||||||
// issues related to namespaces.
|
// issues related to namespaces.
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
|
int (*do_load)(isc::hooks::LibraryHandle& handle);
|
||||||
|
|
||||||
|
int (*do_unload)(isc::hooks::LibraryHandle& handle);
|
||||||
|
|
||||||
/// @brief This function is called to retrieve the multi-threading compatibility.
|
/// @brief This function is called to retrieve the multi-threading compatibility.
|
||||||
///
|
///
|
||||||
/// @return 1 which means compatible with multi-threading.
|
/// @return 1 which means compatible with multi-threading.
|
||||||
|
@ -14,3 +14,11 @@ static const int LIBRARY_NUMBER = 2;
|
|||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
#include <dhcp4/tests/callout_library_common.h>
|
#include <dhcp4/tests/callout_library_common.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
int (*do_load)(isc::hooks::LibraryHandle& handle);
|
||||||
|
|
||||||
|
int (*do_unload)(isc::hooks::LibraryHandle& handle);
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -25,6 +25,23 @@ using namespace isc::hooks;
|
|||||||
// issues related to namespaces.
|
// issues related to namespaces.
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
|
int
|
||||||
|
do_load_impl(LibraryHandle& handle) {
|
||||||
|
// Determine if this callout is configured to fail.
|
||||||
|
isc::dhcp::SrvConfigPtr config;
|
||||||
|
isc::data::ConstElementPtr const& parameters(handle.getParameters());
|
||||||
|
isc::data::ConstElementPtr mode_element(parameters ? parameters->get("mode") : 0);
|
||||||
|
std::string mode(mode_element ? mode_element->stringValue() : "");
|
||||||
|
if (mode == "fail-on-load") {
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int (*do_load)(isc::hooks::LibraryHandle& handle) = do_load_impl;
|
||||||
|
|
||||||
|
int (*do_unload)(isc::hooks::LibraryHandle& handle);
|
||||||
|
|
||||||
/// @brief Callout which appends library number and provided arguments to
|
/// @brief Callout which appends library number and provided arguments to
|
||||||
/// the marker file for dhcp4_srv_configured callout.
|
/// the marker file for dhcp4_srv_configured callout.
|
||||||
///
|
///
|
||||||
|
@ -33,6 +33,10 @@
|
|||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
|
extern int (*do_load)(isc::hooks::LibraryHandle& handle);
|
||||||
|
|
||||||
|
extern int (*do_unload)(isc::hooks::LibraryHandle& handle);
|
||||||
|
|
||||||
/// @brief Append digit to marker file
|
/// @brief Append digit to marker file
|
||||||
///
|
///
|
||||||
/// If the marker file does not exist, create it. Then append the single
|
/// If the marker file does not exist, create it. Then append the single
|
||||||
@ -84,13 +88,23 @@ version() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
load(isc::hooks::LibraryHandle&) {
|
load(isc::hooks::LibraryHandle& handle) {
|
||||||
return (appendDigit(LOAD_MARKER_FILE));
|
int result = 0;
|
||||||
|
result = appendDigit(LOAD_MARKER_FILE);
|
||||||
|
if (result == 0 && do_load) {
|
||||||
|
result = do_load(handle);
|
||||||
|
}
|
||||||
|
return (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
unload() {
|
unload(isc::hooks::LibraryHandle& handle) {
|
||||||
return (appendDigit(UNLOAD_MARKER_FILE));
|
int result = 0;
|
||||||
|
result = appendDigit(UNLOAD_MARKER_FILE);
|
||||||
|
if (result == 0 && do_unload) {
|
||||||
|
result = do_unload(handle);
|
||||||
|
}
|
||||||
|
return (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -24,6 +24,8 @@ LOG_FILE="@abs_top_builddir@/src/bin/dhcp4/tests/test.log"
|
|||||||
LEASE_FILE="@abs_top_builddir@/src/bin/dhcp4/tests/test_leases.csv"
|
LEASE_FILE="@abs_top_builddir@/src/bin/dhcp4/tests/test_leases.csv"
|
||||||
# Path to the Kea LFC application
|
# Path to the Kea LFC application
|
||||||
export KEA_LFC_EXECUTABLE="@abs_top_builddir@/src/bin/lfc/kea-lfc"
|
export KEA_LFC_EXECUTABLE="@abs_top_builddir@/src/bin/lfc/kea-lfc"
|
||||||
|
# Path to test hooks library
|
||||||
|
HOOK_PATH="@abs_top_builddir@/src/bin/dhcp4/tests/.libs/libco3.so"
|
||||||
# Kea configuration to be stored in the configuration file.
|
# Kea configuration to be stored in the configuration file.
|
||||||
CONFIG="{
|
CONFIG="{
|
||||||
\"Dhcp4\":
|
\"Dhcp4\":
|
||||||
@ -46,7 +48,7 @@ CONFIG="{
|
|||||||
\"subnet\": \"10.0.0.0/8\",
|
\"subnet\": \"10.0.0.0/8\",
|
||||||
\"pools\": [ { \"pool\": \"10.0.0.10-10.0.0.100\" } ]
|
\"pools\": [ { \"pool\": \"10.0.0.10-10.0.0.100\" } ]
|
||||||
} ],
|
} ],
|
||||||
\"dhcp-ddns\": {
|
\"dhcp-ddns\": {
|
||||||
\"enable-updates\": true,
|
\"enable-updates\": true,
|
||||||
\"qualifying-suffix\": \"\"
|
\"qualifying-suffix\": \"\"
|
||||||
},
|
},
|
||||||
@ -63,6 +65,7 @@ CONFIG="{
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
|
|
||||||
# Invalid configuration (syntax error) to check that Kea can check syntax.
|
# Invalid configuration (syntax error) to check that Kea can check syntax.
|
||||||
# This config has following errors:
|
# This config has following errors:
|
||||||
# - it should be interfaces-config/interfaces, not interfaces
|
# - it should be interfaces-config/interfaces, not interfaces
|
||||||
@ -168,6 +171,108 @@ CONFIG_INVALID="{
|
|||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
|
|
||||||
|
# Invalid configuration (hook explicitly fails to load) to check that performing
|
||||||
|
# extra configuration checks detects the error.
|
||||||
|
INVALID_CONFIG_HOOKS_LOAD="{
|
||||||
|
\"Dhcp4\":
|
||||||
|
{
|
||||||
|
\"interfaces-config\": {
|
||||||
|
\"interfaces\": [ ]
|
||||||
|
},
|
||||||
|
\"multi-threading\": {
|
||||||
|
\"enable-multi-threading\": false
|
||||||
|
},
|
||||||
|
\"valid-lifetime\": 4000,
|
||||||
|
\"renew-timer\": 1000,
|
||||||
|
\"rebind-timer\": 2000,
|
||||||
|
\"lease-database\":
|
||||||
|
{
|
||||||
|
\"type\": \"memfile\",
|
||||||
|
\"name\": \"$LEASE_FILE\",
|
||||||
|
\"persist\": false,
|
||||||
|
\"lfc-interval\": 0
|
||||||
|
},
|
||||||
|
\"subnet4\": [
|
||||||
|
{
|
||||||
|
\"subnet\": \"10.0.0.0/8\",
|
||||||
|
\"pools\": [ { \"pool\": \"10.0.0.10-10.0.0.100\" } ]
|
||||||
|
} ],
|
||||||
|
\"dhcp-ddns\": {
|
||||||
|
\"enable-updates\": true,
|
||||||
|
\"qualifying-suffix\": \"\"
|
||||||
|
},
|
||||||
|
\"hooks-libraries\": [
|
||||||
|
{
|
||||||
|
\"library\": \"$HOOK_PATH\",
|
||||||
|
\"parameters\": {
|
||||||
|
\"mode\": \"fail-on-load\"
|
||||||
|
}
|
||||||
|
} ],
|
||||||
|
\"loggers\": [
|
||||||
|
{
|
||||||
|
\"name\": \"kea-dhcp4\",
|
||||||
|
\"output_options\": [
|
||||||
|
{
|
||||||
|
\"output\": \"$LOG_FILE\"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\"severity\": \"INFO\"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
|
||||||
|
# Invalid configuration (hook point returns error) to check that performing
|
||||||
|
# extra configuration checks detects the error.
|
||||||
|
INVALID_CONFIG_HOOKS_CALLOUT_FAIL="{
|
||||||
|
\"Dhcp4\":
|
||||||
|
{
|
||||||
|
\"interfaces-config\": {
|
||||||
|
\"interfaces\": [ ]
|
||||||
|
},
|
||||||
|
\"multi-threading\": {
|
||||||
|
\"enable-multi-threading\": false
|
||||||
|
},
|
||||||
|
\"valid-lifetime\": 4000,
|
||||||
|
\"renew-timer\": 1000,
|
||||||
|
\"rebind-timer\": 2000,
|
||||||
|
\"lease-database\":
|
||||||
|
{
|
||||||
|
\"type\": \"memfile\",
|
||||||
|
\"name\": \"$LEASE_FILE\",
|
||||||
|
\"persist\": false,
|
||||||
|
\"lfc-interval\": 0
|
||||||
|
},
|
||||||
|
\"subnet4\": [
|
||||||
|
{
|
||||||
|
\"subnet\": \"10.0.0.0/8\",
|
||||||
|
\"pools\": [ { \"pool\": \"10.0.0.10-10.0.0.100\" } ]
|
||||||
|
} ],
|
||||||
|
\"dhcp-ddns\": {
|
||||||
|
\"enable-updates\": true,
|
||||||
|
\"qualifying-suffix\": \"\"
|
||||||
|
},
|
||||||
|
\"hooks-libraries\": [
|
||||||
|
{
|
||||||
|
\"library\": \"$HOOK_PATH\",
|
||||||
|
\"parameters\": {
|
||||||
|
\"mode\": \"fail-without-error\"
|
||||||
|
}
|
||||||
|
} ],
|
||||||
|
\"loggers\": [
|
||||||
|
{
|
||||||
|
\"name\": \"kea-dhcp4\",
|
||||||
|
\"output_options\": [
|
||||||
|
{
|
||||||
|
\"output\": \"$LOG_FILE\"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\"severity\": \"INFO\"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
|
||||||
# Set the location of the executable.
|
# Set the location of the executable.
|
||||||
bin="kea-dhcp4"
|
bin="kea-dhcp4"
|
||||||
bin_path="@abs_top_builddir@/src/bin/dhcp4"
|
bin_path="@abs_top_builddir@/src/bin/dhcp4"
|
||||||
@ -184,15 +289,22 @@ syntax_check_test() {
|
|||||||
local test_name="${1}"
|
local test_name="${1}"
|
||||||
local config="${2}"
|
local config="${2}"
|
||||||
local expected_code="${3}"
|
local expected_code="${3}"
|
||||||
|
local extra_check="${4}"
|
||||||
|
|
||||||
# Log the start of the test and print test name.
|
# Log the start of the test and print test name.
|
||||||
test_start "${test_name}"
|
test_start "${test_name}"
|
||||||
# Create correct configuration file.
|
# Create correct configuration file.
|
||||||
create_config "${config}"
|
create_config "${config}"
|
||||||
# Check it
|
# Check it
|
||||||
printf "Running command %s.\n" "\"${bin_path}/${bin} -t ${CFG_FILE}\""
|
if [ "${extra_check}" -eq 1 ]; then
|
||||||
run_command \
|
printf "Running command %s.\n" "\"${bin_path}/${bin} -T ${CFG_FILE}\""
|
||||||
"${bin_path}/${bin}" -t "${CFG_FILE}"
|
run_command \
|
||||||
|
"${bin_path}/${bin}" -T "${CFG_FILE}"
|
||||||
|
else
|
||||||
|
printf "Running command %s.\n" "\"${bin_path}/${bin} -t ${CFG_FILE}\""
|
||||||
|
run_command \
|
||||||
|
"${bin_path}/${bin}" -t "${CFG_FILE}"
|
||||||
|
fi
|
||||||
if [ "${EXIT_CODE}" -ne "${expected_code}" ]; then
|
if [ "${EXIT_CODE}" -ne "${expected_code}" ]; then
|
||||||
printf 'ERROR: expected exit code %s, got %s\n' "${expected_code}" "${EXIT_CODE}"
|
printf 'ERROR: expected exit code %s, got %s\n' "${expected_code}" "${EXIT_CODE}"
|
||||||
clean_exit 1
|
clean_exit 1
|
||||||
@ -471,7 +583,9 @@ shutdown_test "dhcpv4.sigint_test" 2
|
|||||||
version_test "dhcpv4.version"
|
version_test "dhcpv4.version"
|
||||||
logger_vars_test "dhcpv4.variables"
|
logger_vars_test "dhcpv4.variables"
|
||||||
lfc_timer_test
|
lfc_timer_test
|
||||||
syntax_check_test "dhcpv4.syntax_check_success" "${CONFIG}" 0
|
syntax_check_test "dhcpv4.syntax_check_success" "${CONFIG}" 0 0
|
||||||
syntax_check_test "dhcpv4.syntax_check_bad_syntax" "${CONFIG_BAD_SYNTAX}" 1
|
syntax_check_test "dhcpv4.syntax_check_bad_syntax" "${CONFIG_BAD_SYNTAX}" 1 0
|
||||||
syntax_check_test "dhcpv4.syntax_check_bad_values" "${CONFIG_BAD_VALUES}" 1
|
syntax_check_test "dhcpv4.syntax_check_bad_values" "${CONFIG_BAD_VALUES}" 1 0
|
||||||
|
syntax_check_test "dhcpv4.syntax_check_hooks_load_fail" "${INVALID_CONFIG_HOOKS_LOAD}" 1 1
|
||||||
|
syntax_check_test "dhcpv4.syntax_check_hooks_callout_fail" "${INVALID_CONFIG_HOOKS_CALLOUT_FAIL}" 1 1
|
||||||
password_redact_test "dhcpv4.password_redact_test" "$(kea_dhcp_config 4)" 0
|
password_redact_test "dhcpv4.password_redact_test" "$(kea_dhcp_config 4)" 0
|
||||||
|
@ -880,7 +880,6 @@ ControlledDhcpv6Srv::processCommand(const string& command,
|
|||||||
|
|
||||||
isc::data::ConstElementPtr
|
isc::data::ConstElementPtr
|
||||||
ControlledDhcpv6Srv::processConfig(isc::data::ConstElementPtr config) {
|
ControlledDhcpv6Srv::processConfig(isc::data::ConstElementPtr config) {
|
||||||
|
|
||||||
ControlledDhcpv6Srv* srv = ControlledDhcpv6Srv::getInstance();
|
ControlledDhcpv6Srv* srv = ControlledDhcpv6Srv::getInstance();
|
||||||
|
|
||||||
// Single stream instance used in all error clauses
|
// Single stream instance used in all error clauses
|
||||||
@ -1046,6 +1045,29 @@ ControlledDhcpv6Srv::processConfig(isc::data::ConstElementPtr config) {
|
|||||||
// exception free.
|
// exception free.
|
||||||
LibDHCP::commitRuntimeOptionDefs();
|
LibDHCP::commitRuntimeOptionDefs();
|
||||||
|
|
||||||
|
auto notify_libraries = ControlledDhcpv6Srv::finishConfigHookLibraries(config);
|
||||||
|
if (notify_libraries) {
|
||||||
|
return (notify_libraries);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply multi threading settings.
|
||||||
|
// @note These settings are applied/updated only if no errors occur while
|
||||||
|
// applying the new configuration.
|
||||||
|
// @todo This should be fixed.
|
||||||
|
try {
|
||||||
|
CfgMultiThreading::apply(CfgMgr::instance().getStagingCfg()->getDHCPMultiThreading());
|
||||||
|
} catch (const std::exception& ex) {
|
||||||
|
err << "Error applying multi threading settings: "
|
||||||
|
<< ex.what();
|
||||||
|
return (isc::config::createAnswer(CONTROL_RESULT_ERROR, err.str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return (answer);
|
||||||
|
}
|
||||||
|
|
||||||
|
isc::data::ConstElementPtr
|
||||||
|
ControlledDhcpv6Srv::finishConfigHookLibraries(isc::data::ConstElementPtr config) {
|
||||||
|
ControlledDhcpv6Srv* srv = ControlledDhcpv6Srv::getInstance();
|
||||||
// This hook point notifies hooks libraries that the configuration of the
|
// This hook point notifies hooks libraries that the configuration of the
|
||||||
// DHCPv6 server has completed. It provides the hook library with the pointer
|
// DHCPv6 server has completed. It provides the hook library with the pointer
|
||||||
// to the common IO service object, new server configuration in the JSON
|
// to the common IO service object, new server configuration in the JSON
|
||||||
@ -1074,27 +1096,11 @@ ControlledDhcpv6Srv::processConfig(isc::data::ConstElementPtr config) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply multi threading settings.
|
return (ConstElementPtr());
|
||||||
// @note These settings are applied/updated only if no errors occur while
|
|
||||||
// applying the new configuration.
|
|
||||||
// @todo This should be fixed.
|
|
||||||
try {
|
|
||||||
CfgMultiThreading::apply(CfgMgr::instance().getStagingCfg()->getDHCPMultiThreading());
|
|
||||||
} catch (const std::exception& ex) {
|
|
||||||
err << "Error applying multi threading settings: "
|
|
||||||
<< ex.what();
|
|
||||||
return (isc::config::createAnswer(CONTROL_RESULT_ERROR, err.str()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return (answer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isc::data::ConstElementPtr
|
isc::data::ConstElementPtr
|
||||||
ControlledDhcpv6Srv::checkConfig(isc::data::ConstElementPtr config) {
|
ControlledDhcpv6Srv::checkConfig(isc::data::ConstElementPtr config) {
|
||||||
|
|
||||||
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_COMMAND, DHCP6_CONFIG_RECEIVED)
|
|
||||||
.arg(redactConfig(config)->str());
|
|
||||||
|
|
||||||
ControlledDhcpv6Srv* srv = ControlledDhcpv6Srv::getInstance();
|
ControlledDhcpv6Srv* srv = ControlledDhcpv6Srv::getInstance();
|
||||||
|
|
||||||
if (!srv) {
|
if (!srv) {
|
||||||
@ -1103,6 +1109,9 @@ ControlledDhcpv6Srv::checkConfig(isc::data::ConstElementPtr config) {
|
|||||||
return (no_srv);
|
return (no_srv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_COMMAND, DHCP6_CONFIG_RECEIVED)
|
||||||
|
.arg(srv->redactConfig(config)->str());
|
||||||
|
|
||||||
return (configureDhcp6Server(*srv, config, true));
|
return (configureDhcp6Server(*srv, config, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,21 +105,32 @@ public:
|
|||||||
/// As pointer to this method is used a callback in ASIO used in
|
/// As pointer to this method is used a callback in ASIO used in
|
||||||
/// ModuleCCSession, it has to be static.
|
/// ModuleCCSession, it has to be static.
|
||||||
///
|
///
|
||||||
/// @param new_config textual representation of the new configuration
|
/// @param config textual representation of the new configuration
|
||||||
///
|
///
|
||||||
/// @return status of the config update
|
/// @return status of the config update
|
||||||
static isc::data::ConstElementPtr
|
static isc::data::ConstElementPtr
|
||||||
processConfig(isc::data::ConstElementPtr new_config);
|
processConfig(isc::data::ConstElementPtr config);
|
||||||
|
|
||||||
/// @brief Configuration checker
|
/// @brief Configuration checker
|
||||||
///
|
///
|
||||||
/// This is a method for checking incoming configuration.
|
/// This is a method for checking incoming configuration.
|
||||||
///
|
///
|
||||||
/// @param new_config JSON representation of the new configuration
|
/// @param config JSON representation of the new configuration
|
||||||
///
|
///
|
||||||
/// @return status of the config check
|
/// @return status of the config check
|
||||||
isc::data::ConstElementPtr
|
static isc::data::ConstElementPtr
|
||||||
checkConfig(isc::data::ConstElementPtr new_config);
|
checkConfig(isc::data::ConstElementPtr config);
|
||||||
|
|
||||||
|
/// @brief Configuration checker for hook libraries
|
||||||
|
///
|
||||||
|
/// This is a method for checking incoming configuration in the hooks
|
||||||
|
/// libraries. It calls dhcp4_srv_configured hook point for all hooks.
|
||||||
|
///
|
||||||
|
/// @param config JSON representation of the new configuration
|
||||||
|
///
|
||||||
|
/// @return status of the config check
|
||||||
|
static isc::data::ConstElementPtr
|
||||||
|
finishConfigHookLibraries(isc::data::ConstElementPtr config);
|
||||||
|
|
||||||
/// @brief Returns pointer to the sole instance of Dhcpv6Srv
|
/// @brief Returns pointer to the sole instance of Dhcpv6Srv
|
||||||
///
|
///
|
||||||
|
@ -11,9 +11,10 @@
|
|||||||
#include <cc/command_interpreter.h>
|
#include <cc/command_interpreter.h>
|
||||||
#include <config/command_mgr.h>
|
#include <config/command_mgr.h>
|
||||||
#include <database/dbaccess_parser.h>
|
#include <database/dbaccess_parser.h>
|
||||||
#include <dhcp6/json_config_parser.h>
|
#include <dhcp6/ctrl_dhcp6_srv.h>
|
||||||
#include <dhcp6/dhcp6_log.h>
|
#include <dhcp6/dhcp6_log.h>
|
||||||
#include <dhcp6/dhcp6_srv.h>
|
#include <dhcp6/dhcp6_srv.h>
|
||||||
|
#include <dhcp6/json_config_parser.h>
|
||||||
#include <dhcp/libdhcp++.h>
|
#include <dhcp/libdhcp++.h>
|
||||||
#include <dhcp/iface_mgr.h>
|
#include <dhcp/iface_mgr.h>
|
||||||
#include <dhcpsrv/cb_ctl_dhcp4.h>
|
#include <dhcpsrv/cb_ctl_dhcp4.h>
|
||||||
@ -867,7 +868,7 @@ processDhcp6Config(isc::data::ConstElementPtr config_set) {
|
|||||||
|
|
||||||
isc::data::ConstElementPtr
|
isc::data::ConstElementPtr
|
||||||
configureDhcp6Server(Dhcpv6Srv& server, isc::data::ConstElementPtr config_set,
|
configureDhcp6Server(Dhcpv6Srv& server, isc::data::ConstElementPtr config_set,
|
||||||
bool check_only) {
|
bool check_only, bool extra_checks) {
|
||||||
if (!config_set) {
|
if (!config_set) {
|
||||||
ConstElementPtr answer = isc::config::createAnswer(CONTROL_RESULT_ERROR,
|
ConstElementPtr answer = isc::config::createAnswer(CONTROL_RESULT_ERROR,
|
||||||
"Can't parse NULL config");
|
"Can't parse NULL config");
|
||||||
@ -877,21 +878,14 @@ configureDhcp6Server(Dhcpv6Srv& server, isc::data::ConstElementPtr config_set,
|
|||||||
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_COMMAND, DHCP6_CONFIG_START)
|
LOG_DEBUG(dhcp6_logger, DBG_DHCP6_COMMAND, DHCP6_CONFIG_START)
|
||||||
.arg(server.redactConfig(config_set)->str());
|
.arg(server.redactConfig(config_set)->str());
|
||||||
|
|
||||||
// Rollback informs whether error occurred and original data
|
|
||||||
// have to be restored to global storages.
|
|
||||||
bool rollback = false;
|
|
||||||
|
|
||||||
auto answer = processDhcp6Config(config_set);
|
auto answer = processDhcp6Config(config_set);
|
||||||
|
|
||||||
int status_code = 0;
|
int status_code = CONTROL_RESULT_SUCCESS;
|
||||||
isc::config::parseAnswer(status_code, answer);
|
isc::config::parseAnswer(status_code, answer);
|
||||||
if (status_code != CONTROL_RESULT_SUCCESS) {
|
|
||||||
rollback = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
SrvConfigPtr srv_config;
|
SrvConfigPtr srv_config;
|
||||||
|
|
||||||
if (!rollback) {
|
if (status_code == CONTROL_RESULT_SUCCESS) {
|
||||||
if (!check_only) {
|
if (!check_only) {
|
||||||
string parameter_name;
|
string parameter_name;
|
||||||
ElementPtr mutable_cfg;
|
ElementPtr mutable_cfg;
|
||||||
@ -932,20 +926,33 @@ configureDhcp6Server(Dhcpv6Srv& server, isc::data::ConstElementPtr config_set,
|
|||||||
LOG_ERROR(dhcp6_logger, DHCP6_PARSER_FAIL)
|
LOG_ERROR(dhcp6_logger, DHCP6_PARSER_FAIL)
|
||||||
.arg(parameter_name).arg(ex.what());
|
.arg(parameter_name).arg(ex.what());
|
||||||
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, ex.what());
|
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, ex.what());
|
||||||
|
status_code = CONTROL_RESULT_ERROR;
|
||||||
// An error occurred, so make sure that we restore original data.
|
|
||||||
rollback = true;
|
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
// For things like bad_cast in boost::lexical_cast
|
// For things like bad_cast in boost::lexical_cast
|
||||||
LOG_ERROR(dhcp6_logger, DHCP6_PARSER_EXCEPTION).arg(parameter_name);
|
LOG_ERROR(dhcp6_logger, DHCP6_PARSER_EXCEPTION).arg(parameter_name);
|
||||||
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, "undefined configuration"
|
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, "undefined configuration"
|
||||||
" processing error");
|
" processing error");
|
||||||
|
status_code = CONTROL_RESULT_ERROR;
|
||||||
// An error occurred, so make sure that we restore original data.
|
|
||||||
rollback = true;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rollback = true;
|
if (extra_checks) {
|
||||||
|
// Re-open lease and host database with new parameters.
|
||||||
|
try {
|
||||||
|
// Get the staging configuration.
|
||||||
|
srv_config = CfgMgr::instance().getStagingCfg();
|
||||||
|
|
||||||
|
CfgDbAccessPtr cfg_db = CfgMgr::instance().getStagingCfg()->getCfgDbAccess();
|
||||||
|
string params = "universe=6 persist=false";
|
||||||
|
if (cfg_db->getExtendedInfoTablesEnabled()) {
|
||||||
|
params += " extended-info-tables=true";
|
||||||
|
}
|
||||||
|
cfg_db->setAppendedParameters(params);
|
||||||
|
cfg_db->createManagers();
|
||||||
|
} catch (const std::exception& ex) {
|
||||||
|
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, ex.what());
|
||||||
|
status_code = CONTROL_RESULT_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -953,12 +960,26 @@ configureDhcp6Server(Dhcpv6Srv& server, isc::data::ConstElementPtr config_set,
|
|||||||
// configuration. This will add created subnets and option values into
|
// configuration. This will add created subnets and option values into
|
||||||
// the server's configuration.
|
// the server's configuration.
|
||||||
// This operation should be exception safe but let's make sure.
|
// This operation should be exception safe but let's make sure.
|
||||||
if (!rollback) {
|
if (status_code == CONTROL_RESULT_SUCCESS && (!check_only || extra_checks)) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
// Setup the command channel.
|
// Setup the command channel.
|
||||||
configureCommandChannel();
|
configureCommandChannel();
|
||||||
|
} catch (const isc::Exception& ex) {
|
||||||
|
LOG_ERROR(dhcp6_logger, DHCP6_PARSER_COMMIT_FAIL).arg(ex.what());
|
||||||
|
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, ex.what());
|
||||||
|
status_code = CONTROL_RESULT_ERROR;
|
||||||
|
} catch (...) {
|
||||||
|
// For things like bad_cast in boost::lexical_cast
|
||||||
|
LOG_ERROR(dhcp6_logger, DHCP6_PARSER_COMMIT_EXCEPTION);
|
||||||
|
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, "undefined configuration"
|
||||||
|
" parsing error");
|
||||||
|
status_code = CONTROL_RESULT_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status_code == CONTROL_RESULT_SUCCESS && (!check_only || extra_checks)) {
|
||||||
|
try {
|
||||||
// No need to commit interface names as this is handled by the
|
// No need to commit interface names as this is handled by the
|
||||||
// CfgMgr::commit() function.
|
// CfgMgr::commit() function.
|
||||||
|
|
||||||
@ -966,7 +987,21 @@ configureDhcp6Server(Dhcpv6Srv& server, isc::data::ConstElementPtr config_set,
|
|||||||
D2ClientConfigPtr cfg;
|
D2ClientConfigPtr cfg;
|
||||||
cfg = CfgMgr::instance().getStagingCfg()->getD2ClientConfig();
|
cfg = CfgMgr::instance().getStagingCfg()->getD2ClientConfig();
|
||||||
CfgMgr::instance().setD2ClientConfig(cfg);
|
CfgMgr::instance().setD2ClientConfig(cfg);
|
||||||
|
} catch (const isc::Exception& ex) {
|
||||||
|
LOG_ERROR(dhcp6_logger, DHCP6_PARSER_COMMIT_FAIL).arg(ex.what());
|
||||||
|
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, ex.what());
|
||||||
|
status_code = CONTROL_RESULT_ERROR;
|
||||||
|
} catch (...) {
|
||||||
|
// For things like bad_cast in boost::lexical_cast
|
||||||
|
LOG_ERROR(dhcp6_logger, DHCP6_PARSER_COMMIT_EXCEPTION);
|
||||||
|
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, "undefined configuration"
|
||||||
|
" parsing error");
|
||||||
|
status_code = CONTROL_RESULT_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status_code == CONTROL_RESULT_SUCCESS && (!check_only || extra_checks)) {
|
||||||
|
try {
|
||||||
// This occurs last as if it succeeds, there is no easy way to
|
// This occurs last as if it succeeds, there is no easy way to
|
||||||
// revert it. As a result, the failure to commit a subsequent
|
// revert it. As a result, the failure to commit a subsequent
|
||||||
// change causes problems when trying to roll back.
|
// change causes problems when trying to roll back.
|
||||||
@ -978,35 +1013,32 @@ configureDhcp6Server(Dhcpv6Srv& server, isc::data::ConstElementPtr config_set,
|
|||||||
} catch (const isc::Exception& ex) {
|
} catch (const isc::Exception& ex) {
|
||||||
LOG_ERROR(dhcp6_logger, DHCP6_PARSER_COMMIT_FAIL).arg(ex.what());
|
LOG_ERROR(dhcp6_logger, DHCP6_PARSER_COMMIT_FAIL).arg(ex.what());
|
||||||
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, ex.what());
|
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, ex.what());
|
||||||
|
status_code = CONTROL_RESULT_ERROR;
|
||||||
// An error occurred, so make sure to restore the original data.
|
|
||||||
rollback = true;
|
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
// For things like bad_cast in boost::lexical_cast
|
// For things like bad_cast in boost::lexical_cast
|
||||||
LOG_ERROR(dhcp6_logger, DHCP6_PARSER_COMMIT_EXCEPTION);
|
LOG_ERROR(dhcp6_logger, DHCP6_PARSER_COMMIT_EXCEPTION);
|
||||||
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, "undefined configuration"
|
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, "undefined configuration"
|
||||||
" parsing error");
|
" parsing error");
|
||||||
|
status_code = CONTROL_RESULT_ERROR;
|
||||||
// An error occurred, so make sure to restore the original data.
|
|
||||||
rollback = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Moved from the commit block to add the config backend indication.
|
// Moved from the commit block to add the config backend indication.
|
||||||
if (!rollback) {
|
if (status_code == CONTROL_RESULT_SUCCESS && (!check_only || extra_checks)) {
|
||||||
try {
|
try {
|
||||||
|
if (extra_checks) {
|
||||||
// If there are config backends, fetch and merge into staging config
|
server.getCBControl()->databaseConfigConnect(srv_config);
|
||||||
server.getCBControl()->databaseConfigFetch(srv_config,
|
} else {
|
||||||
CBControlDHCPv6::FetchMode::FETCH_ALL);
|
// If there are config backends, fetch and merge into staging config
|
||||||
|
server.getCBControl()->databaseConfigFetch(srv_config,
|
||||||
|
CBControlDHCPv6::FetchMode::FETCH_ALL);
|
||||||
|
}
|
||||||
} catch (const isc::Exception& ex) {
|
} catch (const isc::Exception& ex) {
|
||||||
std::ostringstream err;
|
std::ostringstream err;
|
||||||
err << "during update from config backend database: " << ex.what();
|
err << "during update from config backend database: " << ex.what();
|
||||||
LOG_ERROR(dhcp6_logger, DHCP6_PARSER_COMMIT_FAIL).arg(err.str());
|
LOG_ERROR(dhcp6_logger, DHCP6_PARSER_COMMIT_FAIL).arg(err.str());
|
||||||
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, err.str());
|
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, err.str());
|
||||||
|
status_code = CONTROL_RESULT_ERROR;
|
||||||
// An error occurred, so make sure to restore the original data.
|
|
||||||
rollback = true;
|
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
// For things like bad_cast in boost::lexical_cast
|
// For things like bad_cast in boost::lexical_cast
|
||||||
std::ostringstream err;
|
std::ostringstream err;
|
||||||
@ -1014,17 +1046,23 @@ configureDhcp6Server(Dhcpv6Srv& server, isc::data::ConstElementPtr config_set,
|
|||||||
<< "undefined configuration parsing error";
|
<< "undefined configuration parsing error";
|
||||||
LOG_ERROR(dhcp6_logger, DHCP6_PARSER_COMMIT_FAIL).arg(err.str());
|
LOG_ERROR(dhcp6_logger, DHCP6_PARSER_COMMIT_FAIL).arg(err.str());
|
||||||
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, err.str());
|
answer = isc::config::createAnswer(CONTROL_RESULT_ERROR, err.str());
|
||||||
|
status_code = CONTROL_RESULT_ERROR;
|
||||||
// An error occurred, so make sure to restore the original data.
|
|
||||||
rollback = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rollback changes as the configuration parsing failed.
|
// Rollback changes as the configuration parsing failed.
|
||||||
if (rollback) {
|
if (check_only || status_code != CONTROL_RESULT_SUCCESS) {
|
||||||
// Revert to original configuration of runtime option definitions
|
// Revert to original configuration of runtime option definitions
|
||||||
// in the libdhcp++.
|
// in the libdhcp++.
|
||||||
LibDHCP::revertRuntimeOptionDefs();
|
LibDHCP::revertRuntimeOptionDefs();
|
||||||
|
|
||||||
|
if (status_code == CONTROL_RESULT_SUCCESS && extra_checks) {
|
||||||
|
auto notify_libraries = ControlledDhcpv6Srv::finishConfigHookLibraries(config_set);
|
||||||
|
if (notify_libraries) {
|
||||||
|
return (notify_libraries);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (answer);
|
return (answer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,12 +13,27 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
/// @todo: This header file and its .cc counterpart are very similar between
|
||||||
|
/// DHCPv4 and DHCPv6. They should be merged.
|
||||||
|
|
||||||
namespace isc {
|
namespace isc {
|
||||||
namespace dhcp {
|
namespace dhcp {
|
||||||
|
|
||||||
class Dhcpv6Srv;
|
class Dhcpv6Srv;
|
||||||
|
|
||||||
/// @brief Configures DHCPv6 server
|
/// @brief Configure DHCPv6 server (@c Dhcpv6Srv) with a set of configuration
|
||||||
|
/// values.
|
||||||
|
///
|
||||||
|
/// This function parses configuration information stored in @c config_set
|
||||||
|
/// and configures the @c server by applying the configuration to it.
|
||||||
|
/// It provides the strong exception guarantee as long as the underlying
|
||||||
|
/// derived class implementations of @c DhcpConfigParser meet the assumption,
|
||||||
|
/// that is, it ensures that either configuration is fully applied or the
|
||||||
|
/// state of the server is intact.
|
||||||
|
///
|
||||||
|
/// If a syntax or semantics level error happens during the configuration
|
||||||
|
/// (such as malformed configuration or invalid configuration parameter),
|
||||||
|
/// this function returns appropriate error code.
|
||||||
///
|
///
|
||||||
/// This function is called every time a new configuration is received. The
|
/// This function is called every time a new configuration is received. The
|
||||||
/// extra parameter is a reference to DHCPv6 server component. It is currently
|
/// extra parameter is a reference to DHCPv6 server component. It is currently
|
||||||
@ -32,17 +47,19 @@ class Dhcpv6Srv;
|
|||||||
/// reconfiguration statuses. It may return the following response codes:
|
/// reconfiguration statuses. It may return the following response codes:
|
||||||
/// 0 - configuration successful
|
/// 0 - configuration successful
|
||||||
/// 1 - malformed configuration (parsing failed)
|
/// 1 - malformed configuration (parsing failed)
|
||||||
/// 2 - commit failed (parsing was successful, but the values could not be
|
/// 2 - commit failed (parsing was successful, but failed to store the
|
||||||
/// stored in the configuration).
|
/// values in to server's configuration)
|
||||||
///
|
///
|
||||||
/// @param server DHCPv6 server object.
|
/// @param server DHCPv6 server object.
|
||||||
/// @param config_set a new configuration for DHCPv6 server.
|
/// @param config_set a new configuration (JSON) for DHCPv6 server.
|
||||||
/// @param check_only whether this configuration is for testing only
|
/// @param check_only whether this configuration is for testing only.
|
||||||
|
/// @param extra_checks load hooks and perform extra checks if this flag is true
|
||||||
|
/// and check_only is also true, otherwise perform simple check if
|
||||||
|
/// check_only is true.
|
||||||
/// @return answer that contains result of the reconfiguration.
|
/// @return answer that contains result of the reconfiguration.
|
||||||
/// @throw Dhcp6ConfigError if trying to create a parser for NULL config.
|
|
||||||
isc::data::ConstElementPtr
|
isc::data::ConstElementPtr
|
||||||
configureDhcp6Server(Dhcpv6Srv& server, isc::data::ConstElementPtr config_set,
|
configureDhcp6Server(Dhcpv6Srv& server, isc::data::ConstElementPtr config_set,
|
||||||
bool check_only = false);
|
bool check_only = false, bool extra_checks = false);
|
||||||
|
|
||||||
} // namespace dhcp
|
} // namespace dhcp
|
||||||
} // namespace isc
|
} // namespace isc
|
||||||
|
@ -52,13 +52,15 @@ usage() {
|
|||||||
<< endl;
|
<< endl;
|
||||||
cerr << endl;
|
cerr << endl;
|
||||||
cerr << "Usage: " << DHCP6_NAME
|
cerr << "Usage: " << DHCP6_NAME
|
||||||
<< " -[v|V|W] [-d] [-{c|t} cfgfile] [-p number] [-P number]" << endl;
|
<< " -[v|V|W] [-d] [-{c|t|T} cfgfile] [-p number] [-P number]" << endl;
|
||||||
cerr << " -v: print version number and exit" << endl;
|
cerr << " -v: print version number and exit" << endl;
|
||||||
cerr << " -V: print extended version and exit" << endl;
|
cerr << " -V: print extended version and exit" << endl;
|
||||||
cerr << " -W: display the configuration report and exit" << endl;
|
cerr << " -W: display the configuration report and exit" << endl;
|
||||||
cerr << " -d: debug mode with extra verbosity (former -v)" << endl;
|
cerr << " -d: debug mode with extra verbosity (former -v)" << endl;
|
||||||
cerr << " -c file: specify configuration file" << endl;
|
cerr << " -c file: specify configuration file" << endl;
|
||||||
cerr << " -t file: check the configuration file syntax and exit" << endl;
|
cerr << " -t file: check the configuration file syntax and exit" << endl;
|
||||||
|
cerr << " -T file: check the configuration file doing hooks load and extra "
|
||||||
|
<< "checks and exit" << endl;
|
||||||
cerr << " -p number: specify non-standard server port number 1-65535 "
|
cerr << " -p number: specify non-standard server port number 1-65535 "
|
||||||
<< "(useful for testing only)" << endl;
|
<< "(useful for testing only)" << endl;
|
||||||
cerr << " -P number: specify non-standard client port number 1-65535 "
|
cerr << " -P number: specify non-standard client port number 1-65535 "
|
||||||
@ -76,11 +78,12 @@ main(int argc, char* argv[]) {
|
|||||||
int client_port_number = 0;
|
int client_port_number = 0;
|
||||||
bool verbose_mode = false; // Should server be verbose?
|
bool verbose_mode = false; // Should server be verbose?
|
||||||
bool check_mode = false; // Check syntax
|
bool check_mode = false; // Check syntax
|
||||||
|
bool load_hooks = false; // Check hooks config
|
||||||
|
|
||||||
// The standard config file
|
// The standard config file
|
||||||
std::string config_file("");
|
std::string config_file("");
|
||||||
|
|
||||||
while ((ch = getopt(argc, argv, "dvVWc:p:P:t:")) != -1) {
|
while ((ch = getopt(argc, argv, "dvVWc:p:P:t:T:")) != -1) {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 'd':
|
case 'd':
|
||||||
verbose_mode = true;
|
verbose_mode = true;
|
||||||
@ -98,9 +101,16 @@ main(int argc, char* argv[]) {
|
|||||||
cout << isc::detail::getConfigReport() << endl;
|
cout << isc::detail::getConfigReport() << endl;
|
||||||
return (EXIT_SUCCESS);
|
return (EXIT_SUCCESS);
|
||||||
|
|
||||||
|
case 'T':
|
||||||
|
load_hooks = true;
|
||||||
|
check_mode = true;
|
||||||
|
config_file = optarg;
|
||||||
|
break;
|
||||||
|
|
||||||
case 't':
|
case 't':
|
||||||
check_mode = true;
|
check_mode = true;
|
||||||
// falls through
|
config_file = optarg;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'c': // config file
|
case 'c': // config file
|
||||||
config_file = optarg;
|
config_file = optarg;
|
||||||
@ -184,9 +194,11 @@ main(int argc, char* argv[]) {
|
|||||||
ControlledDhcpv6Srv server(0);
|
ControlledDhcpv6Srv server(0);
|
||||||
ConstElementPtr answer;
|
ConstElementPtr answer;
|
||||||
|
|
||||||
|
server.setProcName(DHCP6_NAME);
|
||||||
|
|
||||||
// Now we pass the Dhcp6 configuration to the server, but
|
// Now we pass the Dhcp6 configuration to the server, but
|
||||||
// tell it to check the configuration only (check_only = true)
|
// tell it to check the configuration only (check_only = true)
|
||||||
answer = configureDhcp6Server(server, dhcp6, true);
|
answer = configureDhcp6Server(server, dhcp6, true, load_hooks);
|
||||||
|
|
||||||
int status_code = 0;
|
int status_code = 0;
|
||||||
answer = isc::config::parseAnswer(status_code, answer);
|
answer = isc::config::parseAnswer(status_code, answer);
|
||||||
|
@ -20,6 +20,10 @@ static const int LIBRARY_NUMBER = 1;
|
|||||||
// issues related to namespaces.
|
// issues related to namespaces.
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
|
int (*do_load)(isc::hooks::LibraryHandle& handle);
|
||||||
|
|
||||||
|
int (*do_unload)(isc::hooks::LibraryHandle& handle);
|
||||||
|
|
||||||
/// @brief This function is called to retrieve the multi-threading compatibility.
|
/// @brief This function is called to retrieve the multi-threading compatibility.
|
||||||
///
|
///
|
||||||
/// @return 1 which means compatible with multi-threading.
|
/// @return 1 which means compatible with multi-threading.
|
||||||
|
@ -14,3 +14,11 @@ static const int LIBRARY_NUMBER = 2;
|
|||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
#include <dhcp6/tests/callout_library_common.h>
|
#include <dhcp6/tests/callout_library_common.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
int (*do_load)(isc::hooks::LibraryHandle& handle);
|
||||||
|
|
||||||
|
int (*do_unload)(isc::hooks::LibraryHandle& handle);
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -24,6 +24,23 @@ using namespace isc::hooks;
|
|||||||
// issues related to namespaces.
|
// issues related to namespaces.
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
|
int
|
||||||
|
do_load_impl(LibraryHandle& handle) {
|
||||||
|
// Determine if this callout is configured to fail.
|
||||||
|
isc::dhcp::SrvConfigPtr config;
|
||||||
|
isc::data::ConstElementPtr const& parameters(handle.getParameters());
|
||||||
|
isc::data::ConstElementPtr mode_element(parameters ? parameters->get("mode") : 0);
|
||||||
|
std::string mode(mode_element ? mode_element->stringValue() : "");
|
||||||
|
if (mode == "fail-on-load") {
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int (*do_load)(isc::hooks::LibraryHandle& handle) = do_load_impl;
|
||||||
|
|
||||||
|
int (*do_unload)(isc::hooks::LibraryHandle& handle);
|
||||||
|
|
||||||
/// @brief Callout which appends library number and provided arguments to
|
/// @brief Callout which appends library number and provided arguments to
|
||||||
/// the marker file for dhcp6_srv_configured callout.
|
/// the marker file for dhcp6_srv_configured callout.
|
||||||
///
|
///
|
||||||
|
@ -33,6 +33,10 @@
|
|||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
|
extern int (*do_load)(isc::hooks::LibraryHandle& handle);
|
||||||
|
|
||||||
|
extern int (*do_unload)(isc::hooks::LibraryHandle& handle);
|
||||||
|
|
||||||
/// @brief Append digit to marker file
|
/// @brief Append digit to marker file
|
||||||
///
|
///
|
||||||
/// If the marker file does not exist, create it. Then append the single
|
/// If the marker file does not exist, create it. Then append the single
|
||||||
@ -84,13 +88,23 @@ version() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
load(isc::hooks::LibraryHandle&) {
|
load(isc::hooks::LibraryHandle& handle) {
|
||||||
return (appendDigit(LOAD_MARKER_FILE));
|
int result = 0;
|
||||||
|
result = appendDigit(LOAD_MARKER_FILE);
|
||||||
|
if (result == 0 && do_load) {
|
||||||
|
result = do_load(handle);
|
||||||
|
}
|
||||||
|
return (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
unload() {
|
unload(isc::hooks::LibraryHandle& handle) {
|
||||||
return (appendDigit(UNLOAD_MARKER_FILE));
|
int result = 0;
|
||||||
|
result = appendDigit(UNLOAD_MARKER_FILE);
|
||||||
|
if (result == 0 && do_unload) {
|
||||||
|
result = do_unload(handle);
|
||||||
|
}
|
||||||
|
return (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -24,10 +24,13 @@ LOG_FILE="@abs_top_builddir@/src/bin/dhcp6/tests/test.log"
|
|||||||
LEASE_FILE="@abs_top_builddir@/src/bin/dhcp6/tests/test_leases.csv"
|
LEASE_FILE="@abs_top_builddir@/src/bin/dhcp6/tests/test_leases.csv"
|
||||||
# Path to the Kea LFC application
|
# Path to the Kea LFC application
|
||||||
export KEA_LFC_EXECUTABLE="@abs_top_builddir@/src/bin/lfc/kea-lfc"
|
export KEA_LFC_EXECUTABLE="@abs_top_builddir@/src/bin/lfc/kea-lfc"
|
||||||
|
# Path to test hooks library
|
||||||
|
HOOK_PATH="@abs_top_builddir@/src/bin/dhcp6/tests/.libs/libco3.so"
|
||||||
# Kea configuration to be stored in the configuration file.
|
# Kea configuration to be stored in the configuration file.
|
||||||
CONFIG="{
|
CONFIG="{
|
||||||
\"Dhcp6\":
|
\"Dhcp6\":
|
||||||
{ \"interfaces-config\": {
|
{
|
||||||
|
\"interfaces-config\": {
|
||||||
\"interfaces\": [ ]
|
\"interfaces\": [ ]
|
||||||
},
|
},
|
||||||
\"server-id\": {
|
\"server-id\": {
|
||||||
@ -67,6 +70,7 @@ CONFIG="{
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
|
|
||||||
# Invalid configuration (syntax error) to check that Kea can check syntax.
|
# Invalid configuration (syntax error) to check that Kea can check syntax.
|
||||||
# This config has following errors:
|
# This config has following errors:
|
||||||
# - it should be interfaces-config/interfaces, not interfaces
|
# - it should be interfaces-config/interfaces, not interfaces
|
||||||
@ -102,6 +106,7 @@ CONFIG_BAD_SYNTAX="{
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
|
|
||||||
# Invalid configuration (negative preferred-lifetime) to check that Kea
|
# Invalid configuration (negative preferred-lifetime) to check that Kea
|
||||||
# gracefully handles reconfiguration errors.
|
# gracefully handles reconfiguration errors.
|
||||||
CONFIG_INVALID="{
|
CONFIG_INVALID="{
|
||||||
@ -142,7 +147,8 @@ CONFIG_INVALID="{
|
|||||||
# it is defined in. Syntactically the config is correct, though.
|
# it is defined in. Syntactically the config is correct, though.
|
||||||
CONFIG_BAD_VALUES="{
|
CONFIG_BAD_VALUES="{
|
||||||
\"Dhcp6\":
|
\"Dhcp6\":
|
||||||
{ \"interfaces-config\": {
|
{
|
||||||
|
\"interfaces-config\": {
|
||||||
\"interfaces\": [ ]
|
\"interfaces\": [ ]
|
||||||
},
|
},
|
||||||
\"server-id\": {
|
\"server-id\": {
|
||||||
@ -172,6 +178,117 @@ CONFIG_BAD_VALUES="{
|
|||||||
}
|
}
|
||||||
}"
|
}"
|
||||||
|
|
||||||
|
# Invalid configuration (hook explicitly fails to load) to check that performing
|
||||||
|
# extra configuration checks detects the error.
|
||||||
|
INVALID_CONFIG_HOOKS_LOAD="{
|
||||||
|
\"Dhcp6\":
|
||||||
|
{
|
||||||
|
\"interfaces-config\": {
|
||||||
|
\"interfaces\": [ ]
|
||||||
|
},
|
||||||
|
\"multi-threading\": {
|
||||||
|
\"enable-multi-threading\": false
|
||||||
|
},
|
||||||
|
\"server-id\": {
|
||||||
|
\"type\": \"LLT\",
|
||||||
|
\"persist\": false
|
||||||
|
},
|
||||||
|
\"preferred-lifetime\": 3000,
|
||||||
|
\"valid-lifetime\": 4000,
|
||||||
|
\"renew-timer\": 1000,
|
||||||
|
\"rebind-timer\": 2000,
|
||||||
|
\"lease-database\":
|
||||||
|
{
|
||||||
|
\"type\": \"memfile\",
|
||||||
|
\"name\": \"$LEASE_FILE\",
|
||||||
|
\"persist\": false,
|
||||||
|
\"lfc-interval\": 0
|
||||||
|
},
|
||||||
|
\"subnet6\": [
|
||||||
|
{
|
||||||
|
\"subnet\": \"2001:db8:1::/64\",
|
||||||
|
\"pools\": [ { \"pool\": \"2001:db8:1::10-2001:db8:1::100\" } ]
|
||||||
|
} ],
|
||||||
|
\"dhcp-ddns\": {
|
||||||
|
\"enable-updates\": true,
|
||||||
|
\"qualifying-suffix\": \"\"
|
||||||
|
},
|
||||||
|
\"hooks-libraries\": [
|
||||||
|
{
|
||||||
|
\"library\": \"$HOOK_PATH\",
|
||||||
|
\"parameters\": {
|
||||||
|
\"mode\": \"fail-on-load\"
|
||||||
|
}
|
||||||
|
} ],
|
||||||
|
\"loggers\": [
|
||||||
|
{
|
||||||
|
\"name\": \"kea-dhcp6\",
|
||||||
|
\"output_options\": [
|
||||||
|
{
|
||||||
|
\"output\": \"$LOG_FILE\"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\"severity\": \"INFO\"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
|
||||||
|
# Invalid configuration (hook point returns error) to check that performing
|
||||||
|
# extra configuration checks detects the error.
|
||||||
|
INVALID_CONFIG_HOOKS_CALLOUT_FAIL="{
|
||||||
|
\"Dhcp6\":
|
||||||
|
{
|
||||||
|
\"interfaces-config\": {
|
||||||
|
\"interfaces\": [ ]
|
||||||
|
},
|
||||||
|
\"multi-threading\": {
|
||||||
|
\"enable-multi-threading\": false
|
||||||
|
},
|
||||||
|
\"server-id\": {
|
||||||
|
\"type\": \"LLT\",
|
||||||
|
\"persist\": false
|
||||||
|
},
|
||||||
|
\"preferred-lifetime\": 3000,
|
||||||
|
\"valid-lifetime\": 4000,
|
||||||
|
\"renew-timer\": 1000,
|
||||||
|
\"rebind-timer\": 2000,
|
||||||
|
\"lease-database\":
|
||||||
|
{
|
||||||
|
\"type\": \"memfile\",
|
||||||
|
\"name\": \"$LEASE_FILE\",
|
||||||
|
\"persist\": false,
|
||||||
|
\"lfc-interval\": 0
|
||||||
|
},
|
||||||
|
\"subnet6\": [
|
||||||
|
{
|
||||||
|
\"subnet\": \"2001:db8:1::/64\",
|
||||||
|
\"pools\": [ { \"pool\": \"2001:db8:1::10-2001:db8:1::100\" } ]
|
||||||
|
} ],
|
||||||
|
\"dhcp-ddns\": {
|
||||||
|
\"enable-updates\": true,
|
||||||
|
\"qualifying-suffix\": \"\"
|
||||||
|
},
|
||||||
|
\"hooks-libraries\": [
|
||||||
|
{
|
||||||
|
\"library\": \"$HOOK_PATH\",
|
||||||
|
\"parameters\": {
|
||||||
|
\"mode\": \"fail-without-error\"
|
||||||
|
}
|
||||||
|
} ],
|
||||||
|
\"loggers\": [
|
||||||
|
{
|
||||||
|
\"name\": \"kea-dhcp6\",
|
||||||
|
\"output_options\": [
|
||||||
|
{
|
||||||
|
\"output\": \"$LOG_FILE\"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
\"severity\": \"INFO\"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
|
||||||
# Set the location of the executable.
|
# Set the location of the executable.
|
||||||
bin="kea-dhcp6"
|
bin="kea-dhcp6"
|
||||||
@ -189,15 +306,22 @@ syntax_check_test() {
|
|||||||
local test_name="${1}"
|
local test_name="${1}"
|
||||||
local config="${2}"
|
local config="${2}"
|
||||||
local expected_code="${3}"
|
local expected_code="${3}"
|
||||||
|
local extra_check="${4}"
|
||||||
|
|
||||||
# Log the start of the test and print test name.
|
# Log the start of the test and print test name.
|
||||||
test_start "${test_name}"
|
test_start "${test_name}"
|
||||||
# Create correct configuration file.
|
# Create correct configuration file.
|
||||||
create_config "${config}"
|
create_config "${config}"
|
||||||
# Check it
|
# Check it
|
||||||
printf "Running command %s.\n" "\"${bin_path}/${bin} -t ${CFG_FILE}\""
|
if [ "${extra_check}" -eq 1 ]; then
|
||||||
run_command \
|
printf "Running command %s.\n" "\"${bin_path}/${bin} -T ${CFG_FILE}\""
|
||||||
"${bin_path}/${bin}" -t "${CFG_FILE}"
|
run_command \
|
||||||
|
"${bin_path}/${bin}" -T "${CFG_FILE}"
|
||||||
|
else
|
||||||
|
printf "Running command %s.\n" "\"${bin_path}/${bin} -t ${CFG_FILE}\""
|
||||||
|
run_command \
|
||||||
|
"${bin_path}/${bin}" -t "${CFG_FILE}"
|
||||||
|
fi
|
||||||
if [ "${EXIT_CODE}" -ne "${expected_code}" ]; then
|
if [ "${EXIT_CODE}" -ne "${expected_code}" ]; then
|
||||||
printf 'ERROR: expected exit code %s, got %s\n' "${expected_code}" "${EXIT_CODE}"
|
printf 'ERROR: expected exit code %s, got %s\n' "${expected_code}" "${EXIT_CODE}"
|
||||||
clean_exit 1
|
clean_exit 1
|
||||||
@ -479,7 +603,9 @@ shutdown_test "dhcpv6.sigint_test" 2
|
|||||||
version_test "dhcpv6.version"
|
version_test "dhcpv6.version"
|
||||||
logger_vars_test "dhcpv6.variables"
|
logger_vars_test "dhcpv6.variables"
|
||||||
lfc_timer_test
|
lfc_timer_test
|
||||||
syntax_check_test "dhcpv6.syntax_check_success" "${CONFIG}" 0
|
syntax_check_test "dhcpv6.syntax_check_success" "${CONFIG}" 0 0
|
||||||
syntax_check_test "dhcpv6.syntax_check_bad_syntax" "${CONFIG_BAD_SYNTAX}" 1
|
syntax_check_test "dhcpv6.syntax_check_bad_syntax" "${CONFIG_BAD_SYNTAX}" 1 0
|
||||||
syntax_check_test "dhcpv6.syntax_check_bad_values" "${CONFIG_BAD_VALUES}" 1
|
syntax_check_test "dhcpv6.syntax_check_bad_values" "${CONFIG_BAD_VALUES}" 1 0
|
||||||
|
syntax_check_test "dhcpv6.syntax_check_hooks_load_fail" "${INVALID_CONFIG_HOOKS_LOAD}" 1 1
|
||||||
|
syntax_check_test "dhcpv6.syntax_check_hooks_callout_fail" "${INVALID_CONFIG_HOOKS_CALLOUT_FAIL}" 1 1
|
||||||
password_redact_test "dhcpv6.password_redact_test" "$(kea_dhcp_config 6)" 0
|
password_redact_test "dhcpv6.password_redact_test" "$(kea_dhcp_config 6)" 0
|
||||||
|
@ -186,7 +186,7 @@ is internal server error and a bug report should be created.
|
|||||||
|
|
||||||
% HA_DHCP6_START_SERVICE_FAILED failed to start DHCPv4 HA service in dhcp6_srv_configured callout: %1
|
% HA_DHCP6_START_SERVICE_FAILED failed to start DHCPv4 HA service in dhcp6_srv_configured callout: %1
|
||||||
This error message is issued when an attempt to start High Availability service
|
This error message is issued when an attempt to start High Availability service
|
||||||
for the DHCPv4 server failed in the dhcp4_srv_configured callout. This
|
for the DHCPv6 server failed in the dhcp6_srv_configured callout. This
|
||||||
is internal server error and a bug report should be created.
|
is internal server error and a bug report should be created.
|
||||||
|
|
||||||
% HA_DHCP_DISABLE_COMMUNICATIONS_FAILED failed to send request to disable DHCP service of %1: %2
|
% HA_DHCP_DISABLE_COMMUNICATIONS_FAILED failed to send request to disable DHCP service of %1: %2
|
||||||
@ -242,7 +242,7 @@ servers to resume the HA service.
|
|||||||
|
|
||||||
% HA_INIT_OK loading High Availability hooks library successful
|
% HA_INIT_OK loading High Availability hooks library successful
|
||||||
This informational message indicates that the High Availability hooks library
|
This informational message indicates that the High Availability hooks library
|
||||||
has been loaded successfully.
|
has been loaded successfully. Enjoy!
|
||||||
|
|
||||||
% HA_INVALID_PARTNER_STATE_COMMUNICATION_RECOVERY partner is in the communication-recovery state unexpectedly
|
% HA_INVALID_PARTNER_STATE_COMMUNICATION_RECOVERY partner is in the communication-recovery state unexpectedly
|
||||||
This warning message is issued when a partner is in the communication-recovery
|
This warning message is issued when a partner is in the communication-recovery
|
||||||
|
@ -545,7 +545,7 @@ Debug message issued when triggered an action to retrieve type
|
|||||||
|
|
||||||
% MYSQL_CB_INIT_OK loading MYSQL CB hooks library successful
|
% MYSQL_CB_INIT_OK loading MYSQL CB hooks library successful
|
||||||
This informational message indicates that the MySQL Configuration Backend hooks
|
This informational message indicates that the MySQL Configuration Backend hooks
|
||||||
library has been loaded successfully.
|
library has been loaded successfully. Enjoy!
|
||||||
|
|
||||||
% MYSQL_CB_NO_TLS TLS was required but is not used
|
% MYSQL_CB_NO_TLS TLS was required but is not used
|
||||||
This error message is issued when TLS for the connection was required but
|
This error message is issued when TLS for the connection was required but
|
||||||
|
@ -545,7 +545,7 @@ Debug message issued when triggered an action to retrieve type
|
|||||||
|
|
||||||
% PGSQL_CB_INIT_OK loading Postgres CB hooks library successful
|
% PGSQL_CB_INIT_OK loading Postgres CB hooks library successful
|
||||||
This informational message indicates that the Postgres Configuration Backend hooks
|
This informational message indicates that the Postgres Configuration Backend hooks
|
||||||
library has been loaded successfully.
|
library has been loaded successfully. Enjoy!
|
||||||
|
|
||||||
% PGSQL_CB_NO_TLS_SUPPORT Attempt to configure TLS (unsupported for PostgreSQL): %1
|
% PGSQL_CB_NO_TLS_SUPPORT Attempt to configure TLS (unsupported for PostgreSQL): %1
|
||||||
This error message is printed when TLS support was required in the Kea
|
This error message is printed when TLS support was required in the Kea
|
||||||
|
@ -41,6 +41,12 @@ EXPECTED_VERSION="@PACKAGE_VERSION@"
|
|||||||
export KEA_LFC_EXECUTABLE="@abs_top_builddir@/src/bin/lfc/kea-lfc"
|
export KEA_LFC_EXECUTABLE="@abs_top_builddir@/src/bin/lfc/kea-lfc"
|
||||||
export KEA_LOCKFILE_DIR="@abs_top_builddir@/test_lockfile_dir"
|
export KEA_LOCKFILE_DIR="@abs_top_builddir@/test_lockfile_dir"
|
||||||
export KEA_PIDFILE_DIR="@abs_top_builddir@/test_pidfile_dir"
|
export KEA_PIDFILE_DIR="@abs_top_builddir@/test_pidfile_dir"
|
||||||
|
KEA_DHCP4_LOAD_MARKER_FILE="@abs_top_builddir@/src/bin/dhcp4/tests/load_marker.txt"
|
||||||
|
KEA_DHCP4_UNLOAD_MARKER_FILE="@abs_top_builddir@/src/bin/dhcp4/tests/unload_marker.txt"
|
||||||
|
KEA_DHCP4_SRV_CONFIG_MARKER_FILE="@abs_top_builddir@/src/bin/dhcp4/tests/srv_config_marker_file.txt"
|
||||||
|
KEA_DHCP6_LOAD_MARKER_FILE="@abs_top_builddir@/src/bin/dhcp6/tests/load_marker.txt"
|
||||||
|
KEA_DHCP6_UNLOAD_MARKER_FILE="@abs_top_builddir@/src/bin/dhcp6/tests/unload_marker.txt"
|
||||||
|
KEA_DHCP6_SRV_CONFIG_MARKER_FILE="@abs_top_builddir@/src/bin/dhcp6/tests/srv_config_marker_file.txt"
|
||||||
|
|
||||||
# A list of Kea processes, mainly used by the cleanup functions.
|
# A list of Kea processes, mainly used by the cleanup functions.
|
||||||
KEA_PROCS="kea-dhcp4 kea-dhcp6 kea-dhcp-ddns kea-ctrl-agent"
|
KEA_PROCS="kea-dhcp4 kea-dhcp6 kea-dhcp-ddns kea-ctrl-agent"
|
||||||
@ -656,7 +662,13 @@ cleanup() {
|
|||||||
"${CFG_FILE-}" \
|
"${CFG_FILE-}" \
|
||||||
"${D2_CFG_FILE-}" \
|
"${D2_CFG_FILE-}" \
|
||||||
"${DHCP4_CFG_FILE-}" \
|
"${DHCP4_CFG_FILE-}" \
|
||||||
|
"${KEA_DHCP4_LOAD_MARKER_FILE-}" \
|
||||||
|
"${KEA_DHCP4_UNLOAD_MARKER_FILE-}" \
|
||||||
|
"${KEA_DHCP4_SRV_CONFIG_MARKER_FILE-}" \
|
||||||
"${DHCP6_CFG_FILE-}" \
|
"${DHCP6_CFG_FILE-}" \
|
||||||
|
"${KEA_DHCP6_LOAD_MARKER_FILE-}" \
|
||||||
|
"${KEA_DHCP6_UNLOAD_MARKER_FILE-}" \
|
||||||
|
"${KEA_DHCP6_SRV_CONFIG_MARKER_FILE-}" \
|
||||||
"${KEACTRL_CFG_FILE-}" \
|
"${KEACTRL_CFG_FILE-}" \
|
||||||
"${KEA_LOCKFILE_DIR-}" \
|
"${KEA_LOCKFILE_DIR-}" \
|
||||||
"${KEA_PIDFILE_DIR-}" \
|
"${KEA_PIDFILE_DIR-}" \
|
||||||
|
Loading…
x
Reference in New Issue
Block a user