Browse Source

[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
Thomas Markwalder 9 years ago
parent
commit
24267d20dd

+ 17 - 17
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.

+ 1 - 42
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

+ 10 - 0
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

+ 0 - 3
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);
 

+ 16 - 2
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;

+ 1 - 0
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
 

+ 1 - 0
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

+ 1 - 0
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);

+ 5 - 3
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_);
 };
 

+ 3 - 3
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

+ 2 - 1
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("");
     }
 };
 

+ 46 - 0
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
+}