Commit 33353283 authored by Marcin Siodelski's avatar Marcin Siodelski

[#103,!277] Add failure count for the CB fetch timer.

parent 227bdc64
......@@ -690,10 +690,12 @@ ControlledDhcpv4Srv::processConfig(isc::data::ConstElementPtr config) {
fetch_time = 1000 * fetch_time;
}
boost::shared_ptr<unsigned> failure_count(new unsigned(0));
TimerMgr::instance()->
registerTimer("Dhcp4CBFetchTimer",
boost::bind(&ControlledDhcpv4Srv::cbFetchUpdates,
server_, CfgMgr::instance().getStagingCfg()),
server_, CfgMgr::instance().getStagingCfg(),
failure_count),
fetch_time,
asiolink::IntervalTimer::ONE_SHOT);
TimerMgr::instance()->setup("Dhcp4CBFetchTimer");
......@@ -968,17 +970,27 @@ ControlledDhcpv4Srv::dbLostCallback(ReconnectCtlPtr db_reconnect_ctl) {
}
void
ControlledDhcpv4Srv::cbFetchUpdates(const SrvConfigPtr& srv_cfg) {
ControlledDhcpv4Srv::cbFetchUpdates(const SrvConfigPtr& srv_cfg,
boost::shared_ptr<unsigned> failure_count) {
try {
// The true value indicates that the server should not reconnect
// to the configuration backends and should take into account
// audit entries stored in the database since last fetch.
server_->getCBControl()->databaseConfigFetch(srv_cfg,
CBControlDHCPv4::FetchMode::FETCH_UPDATE);
(*failure_count) = 0;
} catch (const std::exception& ex) {
LOG_ERROR(dhcp4_logger, DHCP4_CB_FETCH_UPDATES_FAIL)
.arg(ex.what());
// We allow at most 10 consecutive failures after which we stop
// making further attempts to fetch the configuration updates.
// Let's return without re-scheduling the timer.
if (++(*failure_count) > 10) {
LOG_ERROR(dhcp4_logger, DHCP4_CB_FETCH_UPDATES_RETRIES_EXHAUSTED);
return;
}
}
// Reschedule the timer to fetch new updates or re-try if
......
......@@ -368,7 +368,11 @@ private:
///
/// @param srv_cfg Server configuration holding the database credentials
/// and server tag.
void cbFetchUpdates(const SrvConfigPtr& srv_cfg);
/// @param failure_count pointer to failure counter which causes this
/// callback to stop scheduling the timer after 10 consecutive failures
/// to fetch the updates.
void cbFetchUpdates(const SrvConfigPtr& srv_cfg,
boost::shared_ptr<unsigned> failure_count);
/// @brief Static pointer to the sole instance of the DHCP server.
///
......
// File created from ../../../src/bin/dhcp4/dhcp4_messages.mes on Wed Mar 20 2019 11:09
// File created from ../../../src/bin/dhcp4/dhcp4_messages.mes on Mon Mar 25 2019 20:13
#include <cstddef>
#include <log/message_types.h>
......@@ -14,6 +14,7 @@ extern const isc::log::MessageID DHCP4_BUFFER_RECEIVE_FAIL = "DHCP4_BUFFER_RECEI
extern const isc::log::MessageID DHCP4_BUFFER_UNPACK = "DHCP4_BUFFER_UNPACK";
extern const isc::log::MessageID DHCP4_BUFFER_WAIT_SIGNAL = "DHCP4_BUFFER_WAIT_SIGNAL";
extern const isc::log::MessageID DHCP4_CB_FETCH_UPDATES_FAIL = "DHCP4_CB_FETCH_UPDATES_FAIL";
extern const isc::log::MessageID DHCP4_CB_FETCH_UPDATES_RETRIES_EXHAUSTED = "DHCP4_CB_FETCH_UPDATES_RETRIES_EXHAUSTED";
extern const isc::log::MessageID DHCP4_CLASS_ASSIGNED = "DHCP4_CLASS_ASSIGNED";
extern const isc::log::MessageID DHCP4_CLASS_UNCONFIGURED = "DHCP4_CLASS_UNCONFIGURED";
extern const isc::log::MessageID DHCP4_CLASS_UNDEFINED = "DHCP4_CLASS_UNDEFINED";
......@@ -146,6 +147,7 @@ const char* values[] = {
"DHCP4_BUFFER_UNPACK", "parsing buffer received from %1 to %2 over interface %3",
"DHCP4_BUFFER_WAIT_SIGNAL", "signal received while waiting for next packet, next waiting signal is %1",
"DHCP4_CB_FETCH_UPDATES_FAIL", "error on attempt to fetch configuration updates from the configuration backend(s): %1",
"DHCP4_CB_FETCH_UPDATES_RETRIES_EXHAUSTED", "maximum number of configuration fetch attempts: 10, has been exhausted without success",
"DHCP4_CLASS_ASSIGNED", "%1: client packet has been assigned to the following class(es): %2",
"DHCP4_CLASS_UNCONFIGURED", "%1: client packet belongs to an unconfigured class: %2",
"DHCP4_CLASS_UNDEFINED", "required class %1 has no definition",
......
// File created from ../../../src/bin/dhcp4/dhcp4_messages.mes on Wed Mar 20 2019 11:09
// File created from ../../../src/bin/dhcp4/dhcp4_messages.mes on Mon Mar 25 2019 20:13
#ifndef DHCP4_MESSAGES_H
#define DHCP4_MESSAGES_H
......@@ -15,6 +15,7 @@ extern const isc::log::MessageID DHCP4_BUFFER_RECEIVE_FAIL;
extern const isc::log::MessageID DHCP4_BUFFER_UNPACK;
extern const isc::log::MessageID DHCP4_BUFFER_WAIT_SIGNAL;
extern const isc::log::MessageID DHCP4_CB_FETCH_UPDATES_FAIL;
extern const isc::log::MessageID DHCP4_CB_FETCH_UPDATES_RETRIES_EXHAUSTED;
extern const isc::log::MessageID DHCP4_CLASS_ASSIGNED;
extern const isc::log::MessageID DHCP4_CLASS_UNCONFIGURED;
extern const isc::log::MessageID DHCP4_CLASS_UNDEFINED;
......
......@@ -53,6 +53,13 @@ The server will re-try according to the configured value of the
config-fetch-wait-time parameter. The sole argument contains the
reason for failure.
% DHCP4_CB_FETCH_UPDATES_RETRIES_EXHAUSTED maximum number of configuration fetch attempts: 10, has been exhausted without success
This error indicates that the server has made a number of unsuccessful
attempts to fetch configuration updates from a configuration backend.
The server will continue to operate but won't make any further attempts
to fetch configuration updates. The administrator must fix the configuration
in the database and reload (or restart) the server.
% DHCP4_CLASS_ASSIGNED %1: client packet has been assigned to the following class(es): %2
This debug message informs that incoming packet has been assigned to specified
class or classes. This is a normal behavior and indicates successful operation.
......
......@@ -259,7 +259,7 @@ public:
EXPECT_EQ(1, cb_control->getDatabaseConfigFetchCalls());
if (config_wait_fetch_time > 0) {
if ((config_wait_fetch_time > 0) && (!throw_during_fetch)) {
// If we're configured to run the timer, we expect that it was
// invoked at least 3 times. This is sufficient to verify that
// the timer was scheduled and that the timer continued to run
......@@ -274,10 +274,21 @@ public:
EXPECT_GE(cb_control->getDatabaseConfigFetchCalls(), 3);
} else {
// If the server is not configured to schedule the timer,
// we should still have one fetch attempt recorded.
ASSERT_NO_THROW(runTimersWithTimeout(srv->getIOService(), 500));
EXPECT_EQ(1, cb_control->getDatabaseConfigFetchCalls());
if (throw_during_fetch) {
// If we're simulating the failure condition the number
// of consecutive failures should not exceed 10. Therefore
// the number of recorded fetches should be 12. One at
// startup, 10 failures and one that causes the timer
// to stop.
EXPECT_EQ(12, cb_control->getDatabaseConfigFetchCalls());
} else {
// If the server is not configured to schedule the timer,
// we should still have one fetch attempt recorded.
EXPECT_EQ(1, cb_control->getDatabaseConfigFetchCalls());
}
}
}
......
......@@ -590,6 +590,8 @@ TEST_F(CBControlBaseTest, fetchNoUpdates) {
ASSERT_EQ(0, cb_ctl_.getMergesNum());
}
// This test verifies that database config fetch failures are handled
// gracefully.
TEST_F(CBControlBaseTest, fetchFailure) {
auto config_base = makeConfigBase("type=db1");
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment