mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-09-02 15:05:16 +00:00
[3971] Better handling errors when thread is stopped/started.
Also, improved some LFC unit tests.
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (C) 2014 Internet Systems Consortium, Inc. ("ISC")
|
// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC")
|
||||||
//
|
//
|
||||||
// Permission to use, copy, modify, and/or distribute this software for any
|
// Permission to use, copy, modify, and/or distribute this software for any
|
||||||
// purpose with or without fee is hereby granted, provided that the above
|
// purpose with or without fee is hereby granted, provided that the above
|
||||||
@@ -19,7 +19,6 @@
|
|||||||
#include <hooks/hooks_manager.h>
|
#include <hooks/hooks_manager.h>
|
||||||
#include <dhcp4/json_config_parser.h>
|
#include <dhcp4/json_config_parser.h>
|
||||||
#include <dhcpsrv/cfgmgr.h>
|
#include <dhcpsrv/cfgmgr.h>
|
||||||
#include <dhcpsrv/timer_mgr.h>
|
|
||||||
#include <config/command_mgr.h>
|
#include <config/command_mgr.h>
|
||||||
#include <stats/stats_mgr.h>
|
#include <stats/stats_mgr.h>
|
||||||
|
|
||||||
@@ -124,9 +123,31 @@ ControlledDhcpv4Srv::processConfig(isc::data::ConstElementPtr config) {
|
|||||||
return (isc::config::createAnswer(1, err.str()));
|
return (isc::config::createAnswer(1, err.str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
TimerMgr::instance()->stopThread();
|
// We're going to modify the timers configuration. This is not allowed
|
||||||
|
// when the thread is running.
|
||||||
|
try {
|
||||||
|
TimerMgr::instance()->stopThread();
|
||||||
|
} catch (const std::exception& ex) {
|
||||||
|
err << "Unable to stop worker thread running timers: "
|
||||||
|
<< ex.what() << ".";
|
||||||
|
return (isc::config::createAnswer(1, err.str()));
|
||||||
|
}
|
||||||
|
|
||||||
ConstElementPtr answer = configureDhcp4Server(*srv, config);
|
ConstElementPtr answer = configureDhcp4Server(*srv, config);
|
||||||
TimerMgr::instance()->startThread();
|
|
||||||
|
// Start worker thread if there are any timers installed. Note that
|
||||||
|
// we also start worker thread when the reconfiguration failed, because
|
||||||
|
// in that case we continue using an old configuration and the server
|
||||||
|
// should still run installed timers.
|
||||||
|
if (TimerMgr::instance()->timersCount() > 0) {
|
||||||
|
try {
|
||||||
|
TimerMgr::instance()->startThread();
|
||||||
|
} catch (const std::exception& ex) {
|
||||||
|
err << "Unable to start worker thread running timers: "
|
||||||
|
<< ex.what() << ".";
|
||||||
|
return (isc::config::createAnswer(1, err.str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check that configuration was successful. If not, do not reopen sockets
|
// Check that configuration was successful. If not, do not reopen sockets
|
||||||
// and don't bother with DDNS stuff.
|
// and don't bother with DDNS stuff.
|
||||||
@@ -165,7 +186,7 @@ ControlledDhcpv4Srv::processConfig(isc::data::ConstElementPtr config) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ControlledDhcpv4Srv::ControlledDhcpv4Srv(uint16_t port /*= DHCP4_SERVER_PORT*/)
|
ControlledDhcpv4Srv::ControlledDhcpv4Srv(uint16_t port /*= DHCP4_SERVER_PORT*/)
|
||||||
:Dhcpv4Srv(port) {
|
: Dhcpv4Srv(port), io_service_(), timer_mgr_(TimerMgr::instance()) {
|
||||||
if (getInstance()) {
|
if (getInstance()) {
|
||||||
isc_throw(InvalidOperation,
|
isc_throw(InvalidOperation,
|
||||||
"There is another Dhcpv4Srv instance already.");
|
"There is another Dhcpv4Srv instance already.");
|
||||||
@@ -207,6 +228,9 @@ void ControlledDhcpv4Srv::shutdown() {
|
|||||||
ControlledDhcpv4Srv::~ControlledDhcpv4Srv() {
|
ControlledDhcpv4Srv::~ControlledDhcpv4Srv() {
|
||||||
cleanup();
|
cleanup();
|
||||||
|
|
||||||
|
// Stop worker thread running timers, if it is running.
|
||||||
|
timer_mgr_->stopThread();
|
||||||
|
|
||||||
// Close the command socket (if it exists).
|
// Close the command socket (if it exists).
|
||||||
CommandMgr::instance().closeCommandSocket();
|
CommandMgr::instance().closeCommandSocket();
|
||||||
|
|
||||||
|
@@ -18,6 +18,7 @@
|
|||||||
#include <asiolink/asiolink.h>
|
#include <asiolink/asiolink.h>
|
||||||
#include <cc/data.h>
|
#include <cc/data.h>
|
||||||
#include <cc/command_interpreter.h>
|
#include <cc/command_interpreter.h>
|
||||||
|
#include <dhcpsrv/timer_mgr.h>
|
||||||
#include <dhcp4/dhcp4_srv.h>
|
#include <dhcp4/dhcp4_srv.h>
|
||||||
|
|
||||||
namespace isc {
|
namespace isc {
|
||||||
@@ -102,13 +103,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
/// @brief Static pointer to the sole instance of the DHCP server.
|
|
||||||
///
|
|
||||||
/// This is required for config and command handlers to gain access to
|
|
||||||
/// the server
|
|
||||||
static ControlledDhcpv4Srv* server_;
|
|
||||||
|
|
||||||
/// @brief Callback that will be called from iface_mgr when data
|
/// @brief Callback that will be called from iface_mgr when data
|
||||||
/// is received over control socket.
|
/// is received over control socket.
|
||||||
///
|
///
|
||||||
@@ -117,9 +112,6 @@ protected:
|
|||||||
/// (that was sent from some yet unspecified sender).
|
/// (that was sent from some yet unspecified sender).
|
||||||
static void sessionReader(void);
|
static void sessionReader(void);
|
||||||
|
|
||||||
/// @brief IOService object, used for all ASIO operations.
|
|
||||||
isc::asiolink::IOService io_service_;
|
|
||||||
|
|
||||||
/// @brief Handler for processing 'shutdown' command
|
/// @brief Handler for processing 'shutdown' command
|
||||||
///
|
///
|
||||||
/// This handler processes shutdown command, which initializes shutdown
|
/// This handler processes shutdown command, which initializes shutdown
|
||||||
@@ -157,6 +149,21 @@ protected:
|
|||||||
isc::data::ConstElementPtr
|
isc::data::ConstElementPtr
|
||||||
commandConfigReloadHandler(const std::string& command,
|
commandConfigReloadHandler(const std::string& command,
|
||||||
isc::data::ConstElementPtr args);
|
isc::data::ConstElementPtr args);
|
||||||
|
|
||||||
|
/// @brief Static pointer to the sole instance of the DHCP server.
|
||||||
|
///
|
||||||
|
/// This is required for config and command handlers to gain access to
|
||||||
|
/// the server
|
||||||
|
static ControlledDhcpv4Srv* server_;
|
||||||
|
|
||||||
|
/// @brief IOService object, used for all ASIO operations.
|
||||||
|
isc::asiolink::IOService io_service_;
|
||||||
|
|
||||||
|
/// @brief Instance of the @c TimerMgr.
|
||||||
|
///
|
||||||
|
/// Shared pointer to the instance of timer @c TimerMgr is held here to
|
||||||
|
/// make sure that the @c TimerMgr outlives instance of this class.
|
||||||
|
TimerMgrPtr timer_mgr_;
|
||||||
};
|
};
|
||||||
|
|
||||||
}; // namespace isc::dhcp
|
}; // namespace isc::dhcp
|
||||||
|
@@ -27,6 +27,7 @@
|
|||||||
#include <dhcpsrv/parsers/host_reservation_parser.h>
|
#include <dhcpsrv/parsers/host_reservation_parser.h>
|
||||||
#include <dhcpsrv/parsers/host_reservations_list_parser.h>
|
#include <dhcpsrv/parsers/host_reservations_list_parser.h>
|
||||||
#include <dhcpsrv/parsers/ifaces_config_parser.h>
|
#include <dhcpsrv/parsers/ifaces_config_parser.h>
|
||||||
|
#include <dhcpsrv/timer_mgr.h>
|
||||||
#include <config/command_mgr.h>
|
#include <config/command_mgr.h>
|
||||||
#include <util/encode/hex.h>
|
#include <util/encode/hex.h>
|
||||||
#include <util/strutil.h>
|
#include <util/strutil.h>
|
||||||
@@ -461,6 +462,9 @@ configureDhcp4Server(Dhcpv4Srv&, isc::data::ConstElementPtr config_set) {
|
|||||||
// so newly recreated configuration starts with first subnet-id equal 1.
|
// so newly recreated configuration starts with first subnet-id equal 1.
|
||||||
Subnet::resetSubnetID();
|
Subnet::resetSubnetID();
|
||||||
|
|
||||||
|
// Remove any existing timers.
|
||||||
|
TimerMgr::instance()->unregisterTimers();
|
||||||
|
|
||||||
// Some of the values specified in the configuration depend on
|
// Some of the values specified in the configuration depend on
|
||||||
// other values. Typically, the values in the subnet4 structure
|
// other values. Typically, the values in the subnet4 structure
|
||||||
// depend on the global values. Also, option values configuration
|
// depend on the global values. Also, option values configuration
|
||||||
|
@@ -282,17 +282,17 @@ shutdown_test() {
|
|||||||
test_finish 0
|
test_finish 0
|
||||||
}
|
}
|
||||||
|
|
||||||
# This test verifies that DHCPv4 can be reconfigured with a SIGHUP signal.
|
# This test verifies that DHCPv4 can be configured to run lease file cleanup
|
||||||
|
# periodially.
|
||||||
lfc_timer_test() {
|
lfc_timer_test() {
|
||||||
# Log the start of the test and print test name.
|
# Log the start of the test and print test name.
|
||||||
test_start "dhcpv4_srv.lfc_timer_test"
|
test_start "dhcpv4_srv.lfc_timer_test"
|
||||||
# Remove dangling Kea instances and remove log files.
|
# Remove dangling Kea instances and remove log files.
|
||||||
cleanup
|
cleanup
|
||||||
# Create a configuration with the LFC enabled, by replacing the section
|
# Create a configuration with the LFC enabled, by replacing the section
|
||||||
# with the lfc-interval parameter.
|
# with the lfc-interval and persist parameters.
|
||||||
LFC_CONFIG=$(printf "${CONFIG}" | sed -e 's/\"lfc-interval\": 0/\"lfc-interval\": 1/g' \
|
LFC_CONFIG=$(printf "${CONFIG}" | sed -e 's/\"lfc-interval\": 0/\"lfc-interval\": 1/g' \
|
||||||
| sed -e 's/\"persist\": false/\"persist\": true/g')
|
| sed -e 's/\"persist\": false/\"persist\": true/g')
|
||||||
echo ${LFC_CONFIG}
|
|
||||||
# Create new configuration file.
|
# Create new configuration file.
|
||||||
create_config "${LFC_CONFIG}"
|
create_config "${LFC_CONFIG}"
|
||||||
# Instruct Kea to log to the specific file.
|
# Instruct Kea to log to the specific file.
|
||||||
@@ -315,13 +315,51 @@ lfc_timer_test() {
|
|||||||
clean_exit 1
|
clean_exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Check if Kea emits the log message indicating that LFC is started.
|
||||||
wait_for_message 10 "DHCPSRV_MEMFILE_LFC_EXECUTE" 1
|
wait_for_message 10 "DHCPSRV_MEMFILE_LFC_EXECUTE" 1
|
||||||
if [ ${_WAIT_FOR_MESSAGE} -eq 0 ]; then
|
if [ ${_WAIT_FOR_MESSAGE} -eq 0 ]; then
|
||||||
printf "ERROR: Server did not execute LFC.\n"
|
printf "ERROR: Server did not execute LFC.\n"
|
||||||
clean_exit 1
|
clean_exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
sleep 3
|
# Give it a short time to run.
|
||||||
|
sleep 1
|
||||||
|
|
||||||
|
# Modify the interval.
|
||||||
|
LFC_CONFIG=$(printf "${CONFIG}" | sed -e 's/\"lfc-interval\": 1/\"lfc-interval\": 2/g')
|
||||||
|
# Create new configuration file.
|
||||||
|
create_config "${LFC_CONFIG}"
|
||||||
|
|
||||||
|
# Reconfigure the server with SIGHUP.
|
||||||
|
send_signal 1 ${bin}
|
||||||
|
|
||||||
|
# There should be two occurrences of the DHCP4_CONFIG_COMPLETE messages.
|
||||||
|
# Wait for it up to 10s.
|
||||||
|
wait_for_message 10 "DHCP4_CONFIG_COMPLETE" 2
|
||||||
|
|
||||||
|
# After receiving SIGHUP the server should get reconfigured and the
|
||||||
|
# reconfiguration should be noted in the log file. We should now
|
||||||
|
# have two configurations logged in the log file.
|
||||||
|
if [ ${_WAIT_FOR_MESSAGE} -eq 0 ]; then
|
||||||
|
printf "ERROR: server hasn't been reconfigured.\n"
|
||||||
|
clean_exit 1
|
||||||
|
else
|
||||||
|
printf "Server successfully reconfigured.\n"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Make sure the server is still operational.
|
||||||
|
get_pids ${bin}
|
||||||
|
if [ ${_GET_PIDS_NUM} -ne 1 ]; then
|
||||||
|
printf "ERROR: Kea process was killed when attempting reconfiguration.\n"
|
||||||
|
clean_exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Wait for the LFC to run the second time.
|
||||||
|
wait_for_message 10 "DHCPSRV_MEMFILE_LFC_EXECUTE" 2
|
||||||
|
if [ ${_WAIT_FOR_MESSAGE} -eq 0 ]; then
|
||||||
|
printf "ERROR: Server did not execute LFC.\n"
|
||||||
|
clean_exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
# Send signal to Kea SIGTERM
|
# Send signal to Kea SIGTERM
|
||||||
send_signal 15 ${bin}
|
send_signal 15 ${bin}
|
||||||
|
Reference in New Issue
Block a user