diff --git a/repmgr-action-daemon.c b/repmgr-action-daemon.c
index 16c30404..50b26a27 100644
--- a/repmgr-action-daemon.c
+++ b/repmgr-action-daemon.c
@@ -18,6 +18,8 @@
* along with this program. If not, see .
*/
+#include /* for stat() */
+
#include "repmgr.h"
#include "repmgr-client-global.h"
@@ -390,7 +392,7 @@ do_daemon_start(void)
PGconn *conn = NULL;
PQExpBufferData repmgrd_command;
PQExpBufferData output_buf;
- bool success;
+ bool success;
/*
* if local connection available, check if repmgr.so is installed, and
@@ -405,20 +407,23 @@ do_daemon_start(void)
if (PQstatus(conn) != CONNECTION_OK)
{
- log_warning(_("unable to connect to local node"));
+ /* TODO: if PostgreSQL is not available, have repmgrd loop and retry connection */
+ log_error(_("unable to connect to local node"));
+ log_detail(_("PostgreSQL must be running before \"repmgrd\" can be started"));
+ exit(ERR_REPMGRD_SERVICE);
}
- else
- {
- check_shared_library(conn);
- if (is_repmgrd_running(conn) == true)
- {
- log_error(_("repmgrd appears to be running already"));
- PQfinish(conn);
- exit(ERR_REPMGRD_SERVICE);
- }
+ check_shared_library(conn);
+
+ if (is_repmgrd_running(conn) == true)
+ {
+ log_error(_("repmgrd appears to be running already"));
+ PQfinish(conn);
+ exit(ERR_REPMGRD_SERVICE);
}
+ PQfinish(conn);
+
initPQExpBuffer(&repmgrd_command);
if (config_file_options.repmgrd_service_start_command[0] != '\0')
@@ -434,11 +439,11 @@ do_daemon_start(void)
if (runtime_options.dry_run == true)
{
log_info(_("prerequisites for starting repmgrd met"));
- log_detail("%s", repmgrd_command.data);
+ log_detail("following command would be executed:\n %s", repmgrd_command.data);
exit(SUCCESS);
}
- log_debug("repmgrd start command: '%s'", repmgrd_command.data);
+ log_notice(_("executing: \"%s\""), repmgrd_command.data);
initPQExpBuffer(&output_buf);
@@ -460,8 +465,150 @@ do_daemon_start(void)
void do_daemon_stop(void)
{
+ PGconn *conn = NULL;
+ PQExpBufferData repmgrd_command;
+ PQExpBufferData output_buf;
+ bool success;
+ pid_t pid = UNKNOWN_PID;
+
+ /*
+ * if local connection available, check if repmgr.so is installed, and
+ * whether repmgrd is running
+ */
+ log_verbose(LOG_INFO, _("connecting to local node"));
+
+ if (strlen(config_file_options.conninfo))
+ conn = establish_db_connection(config_file_options.conninfo, false);
+ else
+ conn = establish_db_connection_by_params(&source_conninfo, false);
+
+ if (PQstatus(conn) != CONNECTION_OK)
+ {
+ log_warning(_("unable to connect to local node"));
+ }
+ else
+ {
+ check_shared_library(conn);
+
+ if (is_repmgrd_running(conn) == false)
+ {
+ log_error(_("repmgrd appears to be stopped already"));
+ PQfinish(conn);
+ exit(ERR_REPMGRD_SERVICE);
+ }
+
+ /* Attempt to fetch the PID, in case we need it later */
+ pid = repmgrd_get_pid(conn);
+ log_debug("retrieved pid is %i", pid);
+ }
+
+ PQfinish(conn);
+
+ initPQExpBuffer(&repmgrd_command);
+
+ if (config_file_options.repmgrd_service_start_command[0] != '\0')
+ {
+ appendPQExpBufferStr(&repmgrd_command,
+ config_file_options.repmgrd_service_stop_command);
+ }
+ else
+ {
+ /* PID not known - attempt to retrieve repmgrd default PID */
+ if (pid == UNKNOWN_PID)
+ {
+ PQExpBufferData repmgrd_pid_command;
+ char pidfile[MAXPGPATH] = "";
+ int pidfile_pathlen;
+ struct stat stat_pidfile;
+
+ initPQExpBuffer(&repmgrd_pid_command);
+
+ make_repmgrd_path(&repmgrd_pid_command);
+ appendPQExpBufferStr(&repmgrd_pid_command, " --show-pid-file 2>/dev/null");
+
+ initPQExpBuffer(&output_buf);
+ log_debug("%s", repmgrd_pid_command.data);
+ success = local_command(repmgrd_pid_command.data, &output_buf);
+ termPQExpBuffer(&repmgrd_pid_command);
+
+ if (success == false)
+ {
+ log_error(_("unable to execute \"repmgrd --show-pid-file\""));
+
+ if (output_buf.data[0] != '\0')
+ log_detail("%s", output_buf.data);
+
+ termPQExpBuffer(&output_buf);
+ exit(ERR_REPMGRD_SERVICE);
+ }
+
+ if (output_buf.data[0] == '\0')
+ {
+ log_error(_("\"repmgrd --show-pid-file\" did not return a file"));
+ termPQExpBuffer(&output_buf);
+ exit(ERR_REPMGRD_SERVICE);
+ }
+
+ pidfile_pathlen = strlen(output_buf.data);
+
+ if (pidfile_pathlen > MAXPGPATH)
+ pidfile_pathlen = MAXPGPATH;
+ else
+ pidfile_pathlen --;
+
+ strncpy(pidfile, output_buf.data, pidfile_pathlen);
+
+ /* check if pid file actually exists */
+
+ if (stat(pidfile, &stat_pidfile) != 0)
+ {
+ log_error(_("PID file \"%s\" not found"),
+ pidfile);
+ log_detail("%s", strerror(errno));
+
+ if (config_file_options.repmgrd_pid_file == '\0')
+ log_hint(_("set \"repmgrd_pid_file\" in \"%s\""), config_file_path);
+ exit(ERR_REPMGRD_SERVICE);
+ }
+
+ appendPQExpBuffer(&repmgrd_command,
+ "kill `cat %s`", pidfile);
+ termPQExpBuffer(&output_buf);
+ }
+ else
+ {
+ appendPQExpBuffer(&repmgrd_command,
+ "kill %i", pid);
+ }
+ }
+
+ if (runtime_options.dry_run == true)
+ {
+ log_info(_("prerequisites for stopping repmgrd met"));
+ log_detail("following command would be executed:\n %s", repmgrd_command.data);
+ exit(SUCCESS);
+ }
+
+ log_notice(_("executing: \"%s\""), repmgrd_command.data);
+
+ initPQExpBuffer(&output_buf);
+
+ success = local_command(repmgrd_command.data, &output_buf);
+ termPQExpBuffer(&repmgrd_command);
+
+ if (success == false)
+ {
+ log_error(_("unable to stop repmgrd"));
+ if (output_buf.data[0] != '\0')
+ log_detail("%s", output_buf.data);
+ termPQExpBuffer(&output_buf);
+ exit(ERR_REPMGRD_SERVICE);
+ }
+
+ termPQExpBuffer(&output_buf);
}
+
void do_daemon_help(void)
{
print_help_header();
@@ -482,6 +629,20 @@ void do_daemon_help(void)
printf(_(" --verbose show text of database connection error messages\n"));
puts("");
+ printf(_("DAEMON START\n"));
+ puts("");
+ printf(_(" \"daemon start\" attempts to start repmgrd"));
+ puts("");
+ printf(_(" --dry-run check prerequisites but don't start repmgrd\n"));
+ puts("");
+
+ printf(_("DAEMON STOP\n"));
+ puts("");
+ printf(_(" \"daemon stop\" attempts to stop repmgrd"));
+ puts("");
+ printf(_(" --dry-run check prerequisites but don't stop repmgrd\n"));
+ puts("");
+
printf(_("DAEMON PAUSE\n"));
puts("");
printf(_(" \"daemon pause\" instructs repmgrd on each node to pause failover detection\n"));
@@ -496,13 +657,5 @@ void do_daemon_help(void)
printf(_(" --dry-run check if nodes are reachable but don't unpause repmgrd\n"));
puts("");
- printf(_("DAEMON START\n"));
- puts("");
- puts("XXX");
-
- printf(_("DAEMON STOP\n"));
- puts("");
- puts("XXX");
-
puts("");
}
diff --git a/repmgr-client.c b/repmgr-client.c
index f2302321..90fe2f9e 100644
--- a/repmgr-client.c
+++ b/repmgr-client.c
@@ -1351,6 +1351,7 @@ main(int argc, char **argv)
break;
case DAEMON_START:
do_daemon_start();
+ break;
case DAEMON_STOP:
do_daemon_stop();
break;