From: Thomas Markwalder Date: Thu, 2 Jul 2015 20:49:53 +0000 (-0400) Subject: [3769] DHPCv4 now uses PID file, made pid test common X-Git-Tag: trac3785_base~2^2~5 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=24267d20dd09ab1432b099d33b7e0597e18d040d;p=thirdparty%2Fkea.git [3769] DHPCv4 now uses PID file, made pid test common src/lib/testutils/dhcp_test_lib.sh.in - server_pid_file_test() - common test for any server to verify PID file management src/bin/d2/tests/d2_process_tests.sh.in remmoved duplicate_server_start_test now calls server_pid_file_test Added PID file creation to DHCP4 src/bin/dhcp4/dhcp4_messages.mes - added log DHCP4_ALREADY_RUNNING src/bin/dhcp4/main.cc - added logic to create the PID and catch exception specific to PID conflict src/bin/dhcp4/tests/Makefile.am - exports KEA_PIDFILE_DIR src/bin/dhcp4/tests/dhcp4_process_tests.sh.in - added call to server_pid_file_test src/bin/dhcp4/tests/dhcp4_unittests.cc - main(int argc, char* argv[]) sets env var KEA_PIDFILE_DIR --- diff --git a/src/bin/d2/d2_messages.mes b/src/bin/d2/d2_messages.mes index a0193a7683..383c64f13c 100644 --- a/src/bin/d2/d2_messages.mes +++ b/src/bin/d2/d2_messages.mes @@ -100,6 +100,15 @@ documented in preceding log entries. This is an informational message issued after DHCP_DDNS has submitted DNS mapping additions which were received and accepted by an appropriate DNS server. +% DHCP_DDNS_ALREADY_RUNNING %1 already running? %2 +This is an error message that occurs when DHCP_DDNS encounters a pre-existing +PID file which contains the PID of a running process. This most likely +indicates an attempt to start a second instance of DHCP_DDNS using the +same configuration file. It is possible, though unlikely, that the PID file +is a remnant left behind by a server crash or power failure and the PID +it contains refers to a process other than DHCP_DDNS. In such an event, +it would be necessary to manually remove the PID file. + % DHCP_DDNS_AT_MAX_TRANSACTIONS application has %1 queued requests but has reached maximum number of %2 concurrent transactions This is a debug message that indicates that the application has DHCP_DDNS requests in the queue but is working as many concurrent requests as allowed. @@ -277,6 +286,14 @@ no configured DDNS domains in the DHCP_DDNS configuration. Either the DHCP_DDNS configuration needs to be updated or the source of the FQDN itself should be investigated. +% DHCP_DDNS_PID_FILE_ERROR %1 could not create a PID file: %2 +This is an error message that occurs when DHCP_DDNS is unable to create +its PID file. The log message should contain details sufficient to +determine the underlying cause. The most likely culprits are that +some portion of the pathname does not exist or a permissions issue. The +default path is determined by --localstatedir configure paramter but +may be overridden by setting environment variable, KEA_PIDFILE_DIR. + % DHCP_DDNS_PROCESS_INIT application init invoked This is a debug message issued when the DHCP-DDNS application enters its initialization method. @@ -492,20 +509,3 @@ server. % DHCP_DDNS_UPDATE_RESPONSE_RECEIVED Request ID %1: to server: %2 status: %3 This is a debug message issued when DHCP_DDNS receives sends a DNS update response from a DNS server. - -% DHCP_DDNS_ALREADY_RUNNING %1 already running? %2 -This is an error message that occurs when DHCP_DDNS encounters a pre-existing -PID file which contains the PID of a running process. This most likely -indicates an attempt to start a second instance of DHCP_DDNS using the -same configuration file. It is possible, the unlikely that the PID file -is a remnant left behind by a server crash or power failure and the PID -it contains refers to a process other than DHCP_DDNS. In such an event, -it would be necessary to manually remove the PID file. - -% DHCP_DDNS_PID_FILE_ERROR %1 could not create a PID file: %2 -This is an error message that occurs when DHCP_DDNS is unable to create -its PID file. The log message should contain details sufficient to -determine the underlying cause. The most likely culprits are that -some portion of the pathname does not exist or a permissions issue. The -default path is determined by --localstatedir configure paramter but -may be overridden by setting environment variable, KEA_PIDFILE_DIR. diff --git a/src/bin/d2/tests/d2_process_tests.sh.in b/src/bin/d2/tests/d2_process_tests.sh.in index 1233b30701..3a6aa83d3b 100755 --- a/src/bin/d2/tests/d2_process_tests.sh.in +++ b/src/bin/d2/tests/d2_process_tests.sh.in @@ -235,50 +235,9 @@ shutdown_test() { test_finish 0 } -# This test verifies if only one D2 per config can be started. -dupcliate_server_start_test() { - # Log the start of the test and print test name. - test_start "dhcp_ddns.duplicate_server_start_test" - # Remove dangling D2 instances and remove log files. - cleanup - # Create new configuration file. - create_config "${CONFIG}" - # Instruct D2 to log to the specific file. - set_logger - # Start D2. - start_kea ${bin_path}/${bin} - # Wait up to 20s for D2 to start. - wait_for_kea 20 - if [ ${_WAIT_FOR_KEA} -eq 0 ]; then - printf "ERROR: timeout waiting for D2 to start.\n" - clean_exit 1 - fi - - # Verify server is still running - verify_server_pid ${bin} ${CFG_FILE} - - printf "PID file is [%s], PID is [%d]" ${_SERVER_PID_FILE} ${_SERVER_PID} - - # Now try to start a second one - start_kea ${bin_path}/${bin} - - wait_for_message 10 "DHCP_DDNS_ALREADY_RUNNING" 1 - if [ ${_WAIT_FOR_MESSAGE} -eq 0 ]; then - printf "ERROR: Second D2 instance started? PID conflict not reported.\n" - clean_exit 1 - fi - - # Verify server is still running - verify_server_pid ${bin} ${CFG_FILE} - - # All ok. Shut down D2 and exit. - test_finish 0 -} - - +server_pid_file_test "${CONFIG}" DHCP_DDNS_ALREADY_RUNNING dynamic_reconfiguration_test shutdown_test "dhcp-ddns.sigterm_test" 15 shutdown_test "dhcp-ddns.sigint_test" 2 version_test "dhcp-ddns.version" logger_vars_test "dhcp-ddns.variables" -dupcliate_server_start_test diff --git a/src/bin/dhcp4/dhcp4_messages.mes b/src/bin/dhcp4/dhcp4_messages.mes index d820896b6d..9c358abbf4 100644 --- a/src/bin/dhcp4/dhcp4_messages.mes +++ b/src/bin/dhcp4/dhcp4_messages.mes @@ -19,6 +19,16 @@ This message is printed when DHCPv4 server enabled an interface to be used to receive DHCPv4 traffic. IPv4 socket on this interface will be opened once Interface Manager starts up procedure of opening sockets. +% DHCP4_ALREADY_RUNNING %1 already running? %2 +This is an error message that occurs when the DHCPv4 server encounters +a pre-existing PID file which contains the PID of a running process. +This most likely indicates an attempt to start a second instance of +the server using the same configuration file. It is possible, though +unlikely that the PID file is a remnant left behind by a server crash or +power failure and the PID it contains refers to a process other than +the server. In such an event, it would be necessary to manually remove +the PID file. + % DHCP4_BUFFER_RECEIVED received buffer from %1:%2 to %3:%4 over interface %5 This debug message is logged when the server has received a packet over the socket. When the message is logged the contents of the received diff --git a/src/bin/dhcp4/kea_controller.cc b/src/bin/dhcp4/kea_controller.cc index ea43d88935..92503d5cf0 100644 --- a/src/bin/dhcp4/kea_controller.cc +++ b/src/bin/dhcp4/kea_controller.cc @@ -168,9 +168,6 @@ 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); diff --git a/src/bin/dhcp4/main.cc b/src/bin/dhcp4/main.cc index 0635086950..ca49d30eee 100644 --- a/src/bin/dhcp4/main.cc +++ b/src/bin/dhcp4/main.cc @@ -118,6 +118,7 @@ main(int argc, char* argv[]) { usage(); } + // Configuration file is required. if (config_file.empty()) { cerr << "Configuration file not specified." << endl; @@ -125,7 +126,6 @@ main(int argc, char* argv[]) { } int ret = EXIT_SUCCESS; - try { // It is important that we set a default logger name because this name // will be used when the user doesn't provide the logging configuration @@ -145,6 +145,10 @@ main(int argc, char* argv[]) { // Remember verbose-mode server.setVerbose(verbose_mode); + Daemon::setProcName(DHCP4_NAME); + Daemon::setConfigFile(config_file); + server.createPIDFile(); + try { // Initialize the server. server.init(config_file); @@ -173,8 +177,18 @@ main(int argc, char* argv[]) { LOG_INFO(dhcp4_logger, DHCP4_SHUTDOWN); - } catch (const std::exception& ex) { + } catch (const isc::dhcp::DaemonPIDExists& ex) { + // First, we print the error on stderr (that should always work) + cerr << DHCP4_NAME << " already running? " << ex.what() + << endl; + // Let's also try to log it using logging system, but we're not + // sure if it's usable (the exception may have been thrown from + // the logger subsystem) + LOG_FATAL(dhcp4_logger, DHCP4_ALREADY_RUNNING) + .arg(DHCP4_NAME).arg(ex.what()); + ret = EXIT_FAILURE; + } catch (const std::exception& ex) { // First, we print the error on stderr (that should always work) cerr << DHCP4_NAME << ": Fatal error during start up: " << ex.what() << endl; diff --git a/src/bin/dhcp4/tests/Makefile.am b/src/bin/dhcp4/tests/Makefile.am index 2752ecdef9..65098c98f5 100644 --- a/src/bin/dhcp4/tests/Makefile.am +++ b/src/bin/dhcp4/tests/Makefile.am @@ -12,6 +12,7 @@ check-local: for shtest in $(SHTESTS) ; do \ echo Running test: $$shtest ; \ export KEA_LOCKFILE_DIR=$(abs_top_builddir); \ + export KEA_PIDFILE_DIR=$(abs_top_builddir); \ ${SHELL} $(abs_builddir)/$$shtest || exit ; \ done diff --git a/src/bin/dhcp4/tests/dhcp4_process_tests.sh.in b/src/bin/dhcp4/tests/dhcp4_process_tests.sh.in index 4bf8fb67b1..91bca88538 100755 --- a/src/bin/dhcp4/tests/dhcp4_process_tests.sh.in +++ b/src/bin/dhcp4/tests/dhcp4_process_tests.sh.in @@ -272,6 +272,7 @@ shutdown_test() { test_finish 0 } +server_pid_file_test "${CONFIG}" DHCP4_ALREADY_RUNNING dynamic_reconfiguration_test shutdown_test "dhcpv4.sigterm_test" 15 shutdown_test "dhcpv4.sigint_test" 2 diff --git a/src/bin/dhcp4/tests/dhcp4_unittests.cc b/src/bin/dhcp4/tests/dhcp4_unittests.cc index f57cfa429f..2beea84252 100644 --- a/src/bin/dhcp4/tests/dhcp4_unittests.cc +++ b/src/bin/dhcp4/tests/dhcp4_unittests.cc @@ -25,6 +25,7 @@ main(int argc, char* argv[]) { // src/lib/log/README for info on how to tweak logging isc::log::initLogger(); + setenv("KEA_PIDFILE_DIR", TEST_DATA_BUILDDIR, 1); int result = RUN_ALL_TESTS(); return (result); diff --git a/src/lib/dhcpsrv/daemon.cc b/src/lib/dhcpsrv/daemon.cc index 6fe0172057..49868c3ee1 100644 --- a/src/lib/dhcpsrv/daemon.cc +++ b/src/lib/dhcpsrv/daemon.cc @@ -37,9 +37,11 @@ namespace dhcp { // This is an initial config file location. std::string Daemon::config_file_ = ""; +std::string Daemon::proc_name_ = ""; + Daemon::Daemon() - : signal_set_(), signal_handler_(), proc_name_(""), - pid_file_dir_(DHCP_DATA_DIR), pid_file_(), am_file_author_(false) { + : signal_set_(), signal_handler_(), pid_file_dir_(DHCP_DATA_DIR), + pid_file_(), am_file_author_(false) { // The pid_file_dir can be overridden via environment variable // This is primarily intended to simplify testing @@ -117,7 +119,7 @@ Daemon::setConfigFile(const std::string& config_file) { } std::string -Daemon::getProcName() const { +Daemon::getProcName() { return (proc_name_); }; diff --git a/src/lib/dhcpsrv/daemon.h b/src/lib/dhcpsrv/daemon.h index 7d8ffe7673..77035dbb69 100644 --- a/src/lib/dhcpsrv/daemon.h +++ b/src/lib/dhcpsrv/daemon.h @@ -177,11 +177,11 @@ public: /// @brief returns the process name /// This value is used as when forming the default PID file name /// @return text string - std::string getProcName() const; + static std::string getProcName(); /// @brief Sets the process name /// @param proc_name name the process by which the process is recognized - void setProcName(const std::string& proc_name); + static void setProcName(const std::string& proc_name); /// @brief Returns the directory used when forming default PID file name /// @return text string @@ -255,7 +255,7 @@ private: static std::string config_file_; /// @brief Name of this process, used when creating its pid file - std::string proc_name_; + static std::string proc_name_; /// @brief Pointer to the directory where PID file(s) are written /// It defaults to --localstatedir diff --git a/src/lib/dhcpsrv/tests/daemon_unittest.cc b/src/lib/dhcpsrv/tests/daemon_unittest.cc index f28819a371..b6618e539b 100644 --- a/src/lib/dhcpsrv/tests/daemon_unittest.cc +++ b/src/lib/dhcpsrv/tests/daemon_unittest.cc @@ -65,8 +65,9 @@ public: /// the default after each test completes. ~DaemonTest() { isc::log::setDefaultLoggingOutput(); - // Since it's static we need to clear it between tests + // Since they're static we need to clear them between tests Daemon::setConfigFile(""); + Daemon::setProcName(""); } }; diff --git a/src/lib/testutils/dhcp_test_lib.sh.in b/src/lib/testutils/dhcp_test_lib.sh.in index f81a3a63ed..a07cc47339 100644 --- a/src/lib/testutils/dhcp_test_lib.sh.in +++ b/src/lib/testutils/dhcp_test_lib.sh.in @@ -590,3 +590,49 @@ logger_vars_test() { test_finish 0 } + +# This test verifies server PID file management +# 1. It verifies that upon startup, the server creates a PID file +# 2. It verifies the an attempt to start a second instance fails +# due to pre-existing PID File/PID detection +server_pid_file_test() { + local server_cfg="${1}" + local log_id="${2}" + + # Log the start of the test and print test name. + test_start "${bin}.server_pid_file_test" + # Remove dangling DHCP4 instances and remove log files. + cleanup + # Create new configuration file. + create_config "${CONFIG}" + # Instruct server to log to the specific file. + set_logger + # Start server + start_kea ${bin_path}/${bin} + # Wait up to 20s for server to start. + wait_for_kea 20 + if [ ${_WAIT_FOR_KEA} -eq 0 ]; then + printf "ERROR: timeout waiting for %s to start.\n" ${bin} + clean_exit 1 + fi + + # Verify server is still running + verify_server_pid ${bin} ${CFG_FILE} + + printf "PID file is [%s], PID is [%d]" ${_SERVER_PID_FILE} ${_SERVER_PID} + + # Now try to start a second one + start_kea ${bin_path}/${bin} + + wait_for_message 10 "${log_id}" 1 + if [ ${_WAIT_FOR_MESSAGE} -eq 0 ]; then + printf "ERROR: Second %s instance started? PID conflict not reported.\n" ${bin} + clean_exit 1 + fi + + # Verify server is still running + verify_server_pid ${bin} ${CFG_FILE} + + # All ok. Shut down the server and exit. + test_finish 0 +}