From c30447ac903a938faabe058e6fb2cc1a21c8101c Mon Sep 17 00:00:00 2001 From: Ian Barwick Date: Thu, 30 Jun 2016 12:51:54 +0900 Subject: [PATCH] repmgr: add option `-B/--remote-pg_bindir` for standby switchover This enables the switchover operation to function if the remote server (current primary) has a different binary directory to the current server, and addresses the issue reported in GitHub #172. --- repmgr.c | 64 ++++++++++++++++++++++++++++++++++++++++++++------------ repmgr.h | 5 +++-- 2 files changed, 54 insertions(+), 15 deletions(-) diff --git a/repmgr.c b/repmgr.c index 62d8cb29..75dfac64 100644 --- a/repmgr.c +++ b/repmgr.c @@ -99,6 +99,7 @@ static bool check_upstream_config(PGconn *conn, int server_version_num, bool exi static bool update_node_record_set_master(PGconn *conn, int this_node_id); static char *make_pg_path(char *file); +static char *make_path(char *path, char *file); static void do_master_register(void); static void do_standby_register(void); @@ -180,6 +181,7 @@ main(int argc, char **argv) {"terse", required_argument, NULL, 't'}, {"mode", required_argument, NULL, 'm'}, {"remote-config-file", required_argument, NULL, 'C'}, + {"remote-pg_bindir", required_argument, NULL, 'B'}, /* deprecated from 3.2; replaced with -P/--pwprompt */ {"initdb-no-pwprompt", no_argument, NULL, 1}, {"check-upstream-config", no_argument, NULL, 2}, @@ -382,10 +384,13 @@ main(int argc, char **argv) termPQExpBuffer(&invalid_mode); } } - break; + break; case 'C': strncpy(runtime_options.remote_config_file, optarg, MAXLEN); break; + case 'B': + strncpy(runtime_options.remote_pg_bindir, optarg, MAXLEN); + break; case 1: runtime_options.initdb_no_pwprompt = true; break; @@ -2734,7 +2739,7 @@ do_standby_follow(void) * * TODO: * - make connection test timeouts/intervals configurable (see below) - * - add command line option --remote_pg_bindir or similar to + * - add command line option --remote-pg_bindir or similar to * optionally handle cases where the remote pg_bindir is different */ @@ -2751,7 +2756,8 @@ do_standby_switchover(void) char remote_host[MAXLEN]; char remote_data_directory[MAXLEN]; int remote_node_id; - char remote_node_replication_state[MAXLEN] = ""; + char remote_node_replication_state[MAXLEN] = ""; + char remote_pg_bindir[MAXLEN] = ""; char remote_archive_config_dir[MAXLEN]; char remote_pg_rewind[MAXLEN]; int i, @@ -2766,6 +2772,20 @@ do_standby_switchover(void) bool connection_success; + /* + * If --remote_pg_bindir supplied, use that to build the path on the + * remote host; if not default to whatever value is set in pg_bindir + */ + + if (strlen(runtime_options.remote_pg_bindir)) + { + strncpy(remote_pg_bindir, runtime_options.remote_pg_bindir, MAXLEN); + } + else + { + strncpy(remote_pg_bindir, pg_bindir, MAXLEN); + } + /* * SANITY CHECKS * @@ -2895,7 +2915,7 @@ do_standby_switchover(void) use_pg_rewind = true; maxlen_snprintf(remote_pg_rewind, "%s", - make_pg_path("pg_rewind")); + make_path(remote_pg_bindir, "pg_rewind")); } else { @@ -2916,7 +2936,7 @@ do_standby_switchover(void) { maxlen_snprintf(remote_pg_rewind, "%s", - make_pg_path("pg_rewind")); + make_path(remote_pg_bindir, "pg_rewind")); } } else @@ -3112,7 +3132,7 @@ do_standby_switchover(void) maxlen_snprintf(command, "%s standby archive-config -f %s --config-archive-dir=%s", - make_pg_path("repmgr"), + make_path(remote_pg_bindir, "repmgr"), runtime_options.remote_config_file, remote_archive_config_dir); @@ -3151,7 +3171,7 @@ do_standby_switchover(void) maxlen_snprintf(command, "%s -D %s -m %s -W stop >/dev/null 2>&1 && echo 1 || echo 0", - make_pg_path("pg_ctl"), + make_path(remote_pg_bindir, "pg_ctl"), remote_data_directory, runtime_options.pg_ctl_mode); @@ -3247,7 +3267,7 @@ do_standby_switchover(void) /* Restore any previously archived config files */ maxlen_snprintf(command, "%s standby restore-config -D %s --config-archive-dir=%s", - make_pg_path("repmgr"), + make_path(remote_pg_bindir, "repmgr"), remote_data_directory, remote_archive_config_dir); @@ -3305,7 +3325,7 @@ do_standby_switchover(void) format_db_cli_params(options.conninfo, repmgr_db_cli_params); maxlen_snprintf(command, "%s -D %s -f %s %s --rsync-only --force --ignore-external-config-files standby clone", - make_pg_path("repmgr"), + make_path(remote_pg_bindir, "repmgr"), remote_data_directory, runtime_options.remote_config_file, repmgr_db_cli_params @@ -3331,7 +3351,7 @@ do_standby_switchover(void) format_db_cli_params(options.conninfo, repmgr_db_cli_params); maxlen_snprintf(command, "%s -D %s -f %s %s standby follow", - make_pg_path("repmgr"), + make_path(remote_pg_bindir, "repmgr"), remote_data_directory, runtime_options.remote_config_file, repmgr_db_cli_params @@ -3355,13 +3375,15 @@ do_standby_switchover(void) for(i = 0; i < options.reconnect_attempts; i++) { - /* Check whether primary is available */ + /* Check whether new standby available */ remote_conn = test_db_connection(remote_conninfo, false); /* don't fail on error */ if (PQstatus(remote_conn) == CONNECTION_OK) { log_debug("connected to new standby (old master)\n"); + + /* make sure it's actually a standby */ if (is_standby(remote_conn) == 0) { log_err(_("new standby (old master) is not a standby\n")); @@ -4201,6 +4223,8 @@ do_help(void) printf(_(" -m, --mode (standby switchover) shutdown mode (smart|fast|immediate)\n")); printf(_(" -C, --remote-config-file (standby switchover) path to the configuration file on\n" \ " the current master\n")); + printf(_(" -B, --remote-pg_bindir (standby switchover) path to PostgreSQL binaries on\n" \ + " the current master\n")); printf(_(" --pg_rewind[=VALUE] (standby switchover) 9.3/9.4 only - use pg_rewind if available,\n" \ " optionally providing a path to the binary\n")); printf(_(" -k, --keep-history=VALUE (cluster cleanup) retain indicated number of days of history (default: 0)\n")); @@ -4743,6 +4767,14 @@ check_parameters_for_action(const int action) } } + if (action != STANDBY_SWITCHOVER) + { + if (strlen(runtime_options.remote_pg_bindir)) + { + error_list_append(&cli_warnings, _("--remote-pg_bindir an only be used when executing STANDBY_SWITCHOVER")); + } + } + return; } @@ -5496,12 +5528,18 @@ do_check_upstream_config(void) static char * make_pg_path(char *file) { - maxlen_snprintf(path_buf, "%s%s", pg_bindir, file); + return make_path(pg_bindir, file); +} + + +static char * +make_path(char *path, char *file) +{ + maxlen_snprintf(path_buf, "%s%s", path, file); return path_buf; } - static void exit_with_errors(void) { diff --git a/repmgr.h b/repmgr.h index 358dec92..4ce9c6bd 100644 --- a/repmgr.h +++ b/repmgr.h @@ -79,8 +79,9 @@ typedef struct */ char loglevel[MAXLEN]; - /* parameter used by STANDBY SWITCHOVER */ + /* parameters used by STANDBY SWITCHOVER */ char remote_config_file[MAXLEN]; + char remote_pg_bindir[MAXLEN]; char pg_rewind[MAXPGPATH]; /* parameter used by STANDBY {ARCHIVE_CONFIG | RESTORE_CONFIG} */ char config_archive_dir[MAXLEN]; @@ -96,7 +97,7 @@ typedef struct bool initdb_no_pwprompt; } t_runtime_options; -#define T_RUNTIME_OPTIONS_INITIALIZER { "", "", "", "", "", "", "", DEFAULT_WAL_KEEP_SEGMENTS, false, false, false, false, false, false, false, false, false, false, "smart", "", "", "", "", "", 0, "", "", "", false } +#define T_RUNTIME_OPTIONS_INITIALIZER { "", "", "", "", "", "", "", DEFAULT_WAL_KEEP_SEGMENTS, false, false, false, false, false, false, false, false, false, false, "smart", "", "", "", "", "", "", 0, "", "", "", false } struct BackupLabel {