Generate "primary_conninfo" using the primary connection's parameters

Having successfully connected to the primary, we can use the actual parameters
reported by libpq to create "primary_conninfo", rather than the limited
subset previously defined by repmgr. Assuming that the user can
pass a conninfo string to repmgr (see following commit), this makes it
possible to provide other connection parameters, e.g. related to
SSL usage.
This commit is contained in:
Ian Barwick
2016-07-04 17:41:42 +09:00
parent 92a84bd950
commit 0888fbc538

View File

@@ -83,14 +83,14 @@
#define CLUSTER_CLEANUP 12 #define CLUSTER_CLEANUP 12
static bool create_recovery_file(const char *data_dir);
static int test_ssh_connection(char *host, char *remote_user); static int test_ssh_connection(char *host, char *remote_user);
static int copy_remote_files(char *host, char *remote_user, char *remote_path, static int copy_remote_files(char *host, char *remote_user, char *remote_path,
char *local_path, bool is_directory, int server_version_num); char *local_path, bool is_directory, int server_version_num);
static int run_basebackup(const char *data_dir, int server_version); static int run_basebackup(const char *data_dir, int server_version);
static void check_parameters_for_action(const int action); static void check_parameters_for_action(const int action);
static bool create_schema(PGconn *conn); static bool create_schema(PGconn *conn);
static void write_primary_conninfo(char *line); static bool create_recovery_file(const char *data_dir, PGconn *primary_conn);
static void write_primary_conninfo(char *line, PGconn *primary_conn);
static bool write_recovery_file_line(FILE *recovery_file, char *recovery_file_path, char *line); static bool write_recovery_file_line(FILE *recovery_file, char *recovery_file_path, char *line);
static void check_master_standby_version_match(PGconn *conn, PGconn *master_conn); static void check_master_standby_version_match(PGconn *conn, PGconn *master_conn);
static int check_server_version(PGconn *conn, char *server_type, bool exit_on_error, char *server_version_string); static int check_server_version(PGconn *conn, char *server_type, bool exit_on_error, char *server_version_string);
@@ -2101,7 +2101,7 @@ stop_backup:
} }
/* Finally, write the recovery.conf file */ /* Finally, write the recovery.conf file */
create_recovery_file(local_data_directory); create_recovery_file(local_data_directory, primary_conn);
if (runtime_options.rsync_only) if (runtime_options.rsync_only)
{ {
@@ -2626,6 +2626,7 @@ do_standby_follow(void)
* closing the connection because we will need them to recreate the * closing the connection because we will need them to recreate the
* recovery.conf file * recovery.conf file
*/ */
// ZZZ not any more?
strncpy(runtime_options.host, PQhost(master_conn), MAXLEN); strncpy(runtime_options.host, PQhost(master_conn), MAXLEN);
strncpy(runtime_options.masterport, PQport(master_conn), MAXLEN); strncpy(runtime_options.masterport, PQport(master_conn), MAXLEN);
strncpy(runtime_options.username, PQuser(master_conn), MAXLEN); strncpy(runtime_options.username, PQuser(master_conn), MAXLEN);
@@ -2667,7 +2668,7 @@ do_standby_follow(void)
log_info(_("changing standby's master\n")); log_info(_("changing standby's master\n"));
/* write the recovery.conf file */ /* write the recovery.conf file */
if (!create_recovery_file(data_dir)) if (!create_recovery_file(data_dir, master_conn))
exit(ERR_BAD_CONFIG); exit(ERR_BAD_CONFIG);
/* Finally, restart the service */ /* Finally, restart the service */
@@ -4250,7 +4251,7 @@ do_help(void)
* Creates a recovery file for a standby. * Creates a recovery file for a standby.
*/ */
static bool static bool
create_recovery_file(const char *data_dir) create_recovery_file(const char *data_dir, PGconn *primary_conn)
{ {
FILE *recovery_file; FILE *recovery_file;
char recovery_file_path[MAXLEN]; char recovery_file_path[MAXLEN];
@@ -4276,7 +4277,7 @@ create_recovery_file(const char *data_dir)
log_debug(_("recovery.conf: %s"), line); log_debug(_("recovery.conf: %s"), line);
/* primary_conninfo = '...' */ /* primary_conninfo = '...' */
write_primary_conninfo(line); write_primary_conninfo(line, primary_conn);
if (write_recovery_file_line(recovery_file, recovery_file_path, line) == false) if (write_recovery_file_line(recovery_file, recovery_file_path, line) == false)
return false; return false;
@@ -5059,43 +5060,44 @@ create_schema(PGconn *conn)
/* This function uses global variables to determine connection settings. Special /* This function uses global variables to determine connection settings. Special
* usage of the PGPASSWORD variable is handled, but strongly discouraged */ * usage of the PGPASSWORD variable is handled, but strongly discouraged */
static void static void
write_primary_conninfo(char *line) write_primary_conninfo(char *line, PGconn *primary_conn)
{ {
char host_buf[MAXLEN] = ""; PQconninfoOption *connOptions;
char conn_buf[MAXLEN] = ""; PQconninfoOption *option;
char user_buf[MAXLEN] = ""; PQExpBufferData conninfo_buf;
char appname_buf[MAXLEN] = ""; bool application_name_provided = false;
char password_buf[MAXLEN] = "";
/* Environment variable for password (UGLY, please use .pgpass!) */ connOptions = PQconninfo(primary_conn);
const char *password = getenv("PGPASSWORD");
if (password != NULL) initPQExpBuffer(&conninfo_buf);
for (option = connOptions; option && option->keyword; option++)
{ {
maxlen_snprintf(password_buf, " password=%s", password); /*
* Skip empty settings and ones which don't make any sense in
* recovery.conf
*/
if (strcmp(option->keyword, "dbname") == 0 ||
strcmp(option->keyword, "replication") == 0 ||
(option->val == NULL) ||
(option->val != NULL && option->val[0] == '\0'))
continue;
if (conninfo_buf.len != 0)
appendPQExpBufferChar(&conninfo_buf, ' ');
if (strcmp(option->keyword, "application_name") == 0)
application_name_provided = true;
/* XXX escape option->val */
appendPQExpBuffer(&conninfo_buf, "%s=%s", option->keyword, option->val);
} }
if (runtime_options.host[0]) /* `application_name` not provided - default to repmgr node name */
{ if (application_name_provided == false)
maxlen_snprintf(host_buf, " host=%s", runtime_options.host); appendPQExpBuffer(&conninfo_buf, "application_name=%s", options.node_name);
}
if (runtime_options.username[0]) maxlen_snprintf(line, "primary_conninfo = '%s'\n", conninfo_buf.data);
{
maxlen_snprintf(user_buf, " user=%s", runtime_options.username);
}
if (options.node_name[0])
{
maxlen_snprintf(appname_buf, " application_name=%s", options.node_name);
}
maxlen_snprintf(conn_buf, "port=%s%s%s%s%s",
(runtime_options.masterport[0]) ? runtime_options.masterport : DEF_PGPORT_STR,
host_buf, user_buf, password_buf,
appname_buf);
maxlen_snprintf(line, "primary_conninfo = '%s'\n", conn_buf);
} }