|
@@ -25,11 +25,18 @@ using namespace isc::asiolink;
|
|
|
using namespace isc::dhcp;
|
|
|
using namespace std;
|
|
|
|
|
|
-namespace isc {
|
|
|
-namespace dhcp {
|
|
|
-
|
|
|
-void
|
|
|
-ControlledDhcpv4Srv::init(const std::string& file_name) {
|
|
|
+namespace {
|
|
|
+
|
|
|
+/// @brief Configure DHCPv4 server using the configuration file specified.
|
|
|
+///
|
|
|
+/// This function is used to both configure the DHCP server on its startup
|
|
|
+/// and dynamically reconfigure the server when SIGHUP signal is received.
|
|
|
+///
|
|
|
+/// It fetches DHCPv6 server's configuration from the 'Dhcp4' section of
|
|
|
+/// the JSON configuration file.
|
|
|
+///
|
|
|
+/// @param file_name Configuration file location.
|
|
|
+void configure(const std::string& file_name) {
|
|
|
// This is a configuration backend implementation that reads the
|
|
|
// configuration from a JSON file.
|
|
|
|
|
@@ -41,8 +48,8 @@ ControlledDhcpv4Srv::init(const std::string& file_name) {
|
|
|
try {
|
|
|
if (file_name.empty()) {
|
|
|
// Basic sanity check: file name must not be empty.
|
|
|
- isc_throw(BadValue, "JSON configuration file not specified. Please "
|
|
|
- "use -c command line option.");
|
|
|
+ isc_throw(isc::BadValue, "JSON configuration file not specified."
|
|
|
+ " Please use -c command line option.");
|
|
|
}
|
|
|
|
|
|
// Read contents of the file and parse it as JSON
|
|
@@ -51,8 +58,8 @@ ControlledDhcpv4Srv::init(const std::string& file_name) {
|
|
|
if (!json) {
|
|
|
LOG_ERROR(dhcp4_logger, DHCP4_CONFIG_LOAD_FAIL)
|
|
|
.arg("Config file " + file_name + " missing or empty.");
|
|
|
- isc_throw(BadValue, "Unable to process JSON configuration file:"
|
|
|
- + file_name);
|
|
|
+ isc_throw(isc::BadValue, "Unable to process JSON configuration"
|
|
|
+ " file: " << file_name);
|
|
|
}
|
|
|
|
|
|
// Get Dhcp4 component from the config
|
|
@@ -60,29 +67,30 @@ ControlledDhcpv4Srv::init(const std::string& file_name) {
|
|
|
|
|
|
if (!dhcp4) {
|
|
|
LOG_ERROR(dhcp4_logger, DHCP4_CONFIG_LOAD_FAIL)
|
|
|
- .arg("Config file " + file_name + " does not include 'Dhcp4' entry.");
|
|
|
- isc_throw(BadValue, "Unable to process JSON configuration file:"
|
|
|
- + file_name);
|
|
|
+ .arg("Config file " + file_name + " does not include 'Dhcp4'"
|
|
|
+ " entry.");
|
|
|
+ isc_throw(isc::BadValue, "Unable to process JSON configuration"
|
|
|
+ " file: " << file_name);
|
|
|
}
|
|
|
|
|
|
// Use parsed JSON structures to configure the server
|
|
|
- result = processCommand("config-reload", dhcp4);
|
|
|
+ result = ControlledDhcpv4Srv::processCommand("config-reload", dhcp4);
|
|
|
|
|
|
} catch (const std::exception& ex) {
|
|
|
LOG_ERROR(dhcp4_logger, DHCP4_CONFIG_LOAD_FAIL).arg(ex.what());
|
|
|
- isc_throw(BadValue, "Unable to process JSON configuration file:"
|
|
|
- + file_name);
|
|
|
+ isc_throw(isc::BadValue, "Unable to process JSON configuration file: "
|
|
|
+ << file_name);
|
|
|
}
|
|
|
|
|
|
if (!result) {
|
|
|
// Undetermined status of the configuration. This should never happen,
|
|
|
- // but as the configureDhcp4Server returns a pointer, it is theoretically
|
|
|
- // possible that it will return NULL.
|
|
|
+ // but as the configureDhcp4Server returns a pointer, it is
|
|
|
+ // theoretically possible that it will return NULL.
|
|
|
LOG_ERROR(dhcp4_logger, DHCP4_CONFIG_LOAD_FAIL)
|
|
|
.arg("Configuration failed: Undefined result of processCommand("
|
|
|
"config-reload, " + file_name + ")");
|
|
|
- isc_throw(BadValue, "Configuration failed: Undefined result of "
|
|
|
- "processCommand('config-reload', " + file_name + ")");
|
|
|
+ isc_throw(isc::BadValue, "Configuration failed: Undefined result of "
|
|
|
+ "processCommand('config-reload', " << file_name << ")");
|
|
|
}
|
|
|
|
|
|
// Now check is the returned result is successful (rcode=0) or not
|
|
@@ -95,12 +103,64 @@ ControlledDhcpv4Srv::init(const std::string& file_name) {
|
|
|
reason = string(" (") + comment->stringValue() + string(")");
|
|
|
}
|
|
|
LOG_ERROR(dhcp4_logger, DHCP4_CONFIG_LOAD_FAIL).arg(reason);
|
|
|
- isc_throw(BadValue, "Failed to apply configuration:" << reason);
|
|
|
+ isc_throw(isc::BadValue, "Failed to apply configuration: " << reason);
|
|
|
}
|
|
|
+}
|
|
|
+
|
|
|
+/// @brief Signals handler for DHCPv4 server.
|
|
|
+///
|
|
|
+/// This signal handler handles the following signals received by the DHCPv4
|
|
|
+/// server process:
|
|
|
+/// - SIGHUP - triggers server's dynamic reconfiguration.
|
|
|
+/// - SIGTERM - triggers server's shut down.
|
|
|
+/// - SIGINT - triggers server's shut down.
|
|
|
+///
|
|
|
+/// @param signo Signal number received.
|
|
|
+void signalHandler(int signo) {
|
|
|
+ // SIGHUP signals a request to reconfigure the server.
|
|
|
+ if (signo == SIGHUP) {
|
|
|
+ // Get configuration file name.
|
|
|
+ std::string file = ControlledDhcpv4Srv::getInstance()->getConfigFile();
|
|
|
+ try {
|
|
|
+ LOG_INFO(dhcp4_logger, DHCP4_DYNAMIC_RECONFIGURATION).arg(file);
|
|
|
+ configure(file);
|
|
|
+ } catch (const std::exception& ex) {
|
|
|
+ // Log the unsuccessful reconfiguration. The reason for failure
|
|
|
+ // should be already logged. Don't rethrow an exception so as
|
|
|
+ // the server keeps working.
|
|
|
+ LOG_ERROR(dhcp4_logger, DHCP4_DYNAMIC_RECONFIGURATION_FAIL)
|
|
|
+ .arg(file);
|
|
|
+ }
|
|
|
+ } else if ((signo == SIGTERM) || (signo == SIGINT)) {
|
|
|
+ isc::data::ElementPtr params(new isc::data::MapElement());
|
|
|
+ ControlledDhcpv4Srv::processCommand("shutdown", params);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+namespace isc {
|
|
|
+namespace dhcp {
|
|
|
+
|
|
|
+void
|
|
|
+ControlledDhcpv4Srv::init(const std::string& file_name) {
|
|
|
+ // Call parent class's init to initialize file name.
|
|
|
+ Daemon::init(file_name);
|
|
|
+
|
|
|
+ // Configure the server using JSON file.
|
|
|
+ configure(file_name);
|
|
|
|
|
|
// We don't need to call openActiveSockets() or startD2() as these
|
|
|
// methods are called in processConfig() which is called by
|
|
|
// processCommand("reload-config", ...)
|
|
|
+
|
|
|
+ // Set signal handlers. When the SIGHUP is received by the process
|
|
|
+ // the server reconfiguration will be triggered. When SIGTERM or
|
|
|
+ // SIGINT will be received, the server will start shutting down.
|
|
|
+ signal_set_.reset(new isc::util::io::SignalSet(SIGINT, SIGHUP, SIGTERM));
|
|
|
+ // Set the pointer to the handler function.
|
|
|
+ signal_handler_ = signalHandler;
|
|
|
+
|
|
|
}
|
|
|
|
|
|
void ControlledDhcpv4Srv::cleanup() {
|