standby switchover: add hint for diagnosing remote DB connection failure

Output a command, which when excuted on the local node (promotion
candidate) will attempt to remotely connect to the demotion candidate
and display both the connection message encountered and the connection
parameters used.

This is useful for corner-cases where the connection normally succeeds if a
particular environment variable (e.g. PGPORT) is normally set, but is
not set in the environment where SSH is executed.
This commit is contained in:
Ian Barwick
2020-04-17 11:20:02 +09:00
parent 45e96f21a5
commit 97d83bd443
3 changed files with 49 additions and 16 deletions

View File

@@ -4064,10 +4064,31 @@ do_standby_switchover(void)
if (remote_error == REMOTE_ERROR_DB_CONNECTION) if (remote_error == REMOTE_ERROR_DB_CONNECTION)
{ {
PQExpBufferData ssh_command;
/* can happen if the connection configuration is not consistent across nodes */ /* can happen if the connection configuration is not consistent across nodes */
log_detail(_("an error was encountered when attempting to connect to PostgreSQL on node \"%s\" (ID: %i)"), log_detail(_("an error was encountered when attempting to connect to PostgreSQL on node \"%s\" (ID: %i)"),
remote_node_record.node_name, remote_node_record.node_name,
remote_node_record.node_id); remote_node_record.node_id);
/* output a helpful hint to help diagnose the issue */
initPQExpBuffer(&remote_command_str);
make_remote_repmgr_path(&remote_command_str, &remote_node_record);
appendPQExpBufferStr(&remote_command_str, "node check --db-connection");
initPQExpBuffer(&ssh_command);
make_remote_command(remote_host,
runtime_options.remote_user,
remote_command_str.data,
config_file_options.ssh_options,
&ssh_command);
log_hint(_("diagnose with:\n %s"), ssh_command.data);
termPQExpBuffer(&remote_command_str);
termPQExpBuffer(&ssh_command);
} }
else if (remote_error == REMOTE_ERROR_CONNINFO_PARSE) else if (remote_error == REMOTE_ERROR_CONNINFO_PARSE)
{ {

View File

@@ -118,28 +118,13 @@ remote_command(const char *host, const char *user, const char *command, const ch
{ {
FILE *fp; FILE *fp;
PQExpBufferData ssh_command; PQExpBufferData ssh_command;
PQExpBufferData ssh_host;
char output[MAXLEN] = ""; char output[MAXLEN] = "";
initPQExpBuffer(&ssh_host);
if (*user != '\0')
{
appendPQExpBuffer(&ssh_host, "%s@", user);
}
appendPQExpBufferStr(&ssh_host, host);
initPQExpBuffer(&ssh_command); initPQExpBuffer(&ssh_command);
appendPQExpBuffer(&ssh_command, make_remote_command(host, user, command, ssh_options, &ssh_command);
"ssh -o Batchmode=yes %s %s %s",
ssh_options,
ssh_host.data,
command);
termPQExpBuffer(&ssh_host);
log_debug("remote_command():\n %s", ssh_command.data); log_debug("remote_command():\n %s", ssh_command.data);
@@ -187,6 +172,32 @@ remote_command(const char *host, const char *user, const char *command, const ch
} }
void
make_remote_command(const char *host, const char *user, const char *command, const char *ssh_options, PQExpBufferData *ssh_command)
{
PQExpBufferData ssh_host;
initPQExpBuffer(&ssh_host);
if (*user != '\0')
{
appendPQExpBuffer(&ssh_host, "%s@", user);
}
appendPQExpBufferStr(&ssh_host, host);
appendPQExpBuffer(ssh_command,
"ssh -o Batchmode=yes %s %s %s",
ssh_options,
ssh_host.data,
command);
termPQExpBuffer(&ssh_host);
}
pid_t pid_t
disable_wal_receiver(PGconn *conn) disable_wal_receiver(PGconn *conn)
{ {

View File

@@ -24,6 +24,7 @@ extern bool local_command_return_value(const char *command, PQExpBufferData *out
extern bool local_command_simple(const char *command, PQExpBufferData *outputbuf); extern bool local_command_simple(const char *command, PQExpBufferData *outputbuf);
extern bool remote_command(const char *host, const char *user, const char *command, const char *ssh_options, PQExpBufferData *outputbuf); extern bool remote_command(const char *host, const char *user, const char *command, const char *ssh_options, PQExpBufferData *outputbuf);
extern void make_remote_command(const char *host, const char *user, const char *command, const char *ssh_options, PQExpBufferData *ssh_command);
extern pid_t disable_wal_receiver(PGconn *conn); extern pid_t disable_wal_receiver(PGconn *conn);
extern pid_t enable_wal_receiver(PGconn *conn, bool wait_startup); extern pid_t enable_wal_receiver(PGconn *conn, bool wait_startup);