diff --git a/dbutils.c b/dbutils.c index c89fe175..25a14f1f 100644 --- a/dbutils.c +++ b/dbutils.c @@ -163,18 +163,30 @@ get_cluster_size(PGconn *conn) /* * get a connection to master by reading repl_nodes, creating a connection * to each node (one at a time) and finding if it is a master or a standby + * + * NB: If master_conninfo_out may be NULL. If it is non-null, it is assumed to + * point to allocated memory of MAXCONNINFO in length, and the master server + * connection string is placed there. */ PGconn * getMasterConnection(PGconn *standby_conn, int id, char *cluster, - int *master_id) + int *master_id, char *master_conninfo_out) { PGconn *master_conn = NULL; PGresult *res1; PGresult *res2; char sqlquery[QUERY_STR_LEN]; - char master_conninfo[MAXCONNINFO]; + char master_conninfo_stack[MAXCONNINFO]; + char *master_conninfo = &*master_conninfo_stack; int i; + /* + * If the caller wanted to get a copy of the connection info string, sub + * out the local stack pointer for the pointer passed by the caller. + */ + if (master_conninfo_out != NULL) + master_conninfo = master_conninfo_out; + /* find all nodes belonging to this cluster */ sqlquery_snprintf(sqlquery, "SELECT * FROM repmgr_%s.repl_nodes " " WHERE cluster = '%s' and id <> %d", diff --git a/dbutils.h b/dbutils.h index 5da99c36..10ee1900 100644 --- a/dbutils.h +++ b/dbutils.h @@ -10,5 +10,5 @@ char *pg_version(PGconn *conn, char* major_version); bool guc_setted(PGconn *conn, const char *parameter, const char *op, const char *value); const char *get_cluster_size(PGconn *conn); -PGconn * getMasterConnection(PGconn *standby_conn, int id, char *cluster, - int *master_id); +PGconn *getMasterConnection(PGconn *standby_conn, int id, char *cluster, + int *master_id, char *master_conninfo_out); diff --git a/repmgr.c b/repmgr.c index c98e7148..4403215c 100644 --- a/repmgr.c +++ b/repmgr.c @@ -35,7 +35,7 @@ static void help(const char *progname); -static bool create_recovery_file(const char *data_dir); +static bool create_recovery_file(const char *data_dir, char *master_conninfo); static int copy_remote_files(char *host, char *remote_user, char *remote_path, char *local_path, bool is_directory); static bool check_parameters_for_action(const int action); @@ -428,7 +428,8 @@ do_master_register(void) int id; /* Ensure there isn't any other master already registered */ - master_conn = getMasterConnection(conn, myLocalId, myClusterName, &id); + master_conn = getMasterConnection(conn, myLocalId, myClusterName, &id, + NULL); if (master_conn != NULL) { PQfinish(master_conn); @@ -543,7 +544,7 @@ do_standby_register(void) /* check if there is a master in this cluster */ master_conn = getMasterConnection(conn, myLocalId, myClusterName, - &master_id); + &master_id, NULL); if (!master_conn) return; @@ -1018,7 +1019,7 @@ stop_backup: } /* Finally, write the recovery.conf file */ - create_recovery_file(dest_dir); + create_recovery_file(dest_dir, NULL); /* * We don't start the service because we still may want to move the @@ -1084,7 +1085,7 @@ do_standby_promote(void) /* we also need to check if there isn't any master already */ old_master_conn = getMasterConnection(conn, myLocalId, myClusterName, - &old_master_id); + &old_master_id, NULL); if (old_master_conn != NULL) { PQfinish(old_master_conn); @@ -1153,6 +1154,7 @@ do_standby_follow(void) char myClusterName[MAXLEN]; int myLocalId = -1; char conninfo[MAXLEN]; + char master_conninfo[MAXLEN]; PGconn *master_conn; int master_id; @@ -1193,7 +1195,7 @@ do_standby_follow(void) /* we also need to check if there is any master in the cluster */ master_conn = getMasterConnection(conn, myLocalId, myClusterName, - &master_id); + &master_id, master_conninfo); if (master_conn == NULL) { PQfinish(conn); @@ -1273,7 +1275,7 @@ do_standby_follow(void) PQfinish(conn); /* write the recovery.conf file */ - if (!create_recovery_file(data_dir)) + if (!create_recovery_file(data_dir, master_conninfo)) return; /* Finally, restart the service */ @@ -1326,8 +1328,13 @@ help(const char *progname) } +/* + * Creates a recovery file for a standby. + * + * Writes master_conninfo to recovery.conf if is non-NULL + */ static bool -create_recovery_file(const char *data_dir) +create_recovery_file(const char *data_dir, char *master_conninfo) { FILE *recovery_file; char recovery_file_path[MAXLEN]; @@ -1350,6 +1357,28 @@ create_recovery_file(const char *data_dir) return false; } + if (master_conninfo == NULL) + { + char *password = getenv("PGPASSWORD"); + + if (password == NULL) + { + fprintf(stderr, + _("%s: Panic! PGPASSWORD not set, how can we get here?\n"), + progname); + exit(255); + } + + maxlen_snprintf(line, + "primary_conninfo = 'host=%s port=%s' password=%s\n", + host, ((masterport==NULL) ? "5432" : masterport), + password); + } + else + { + maxlen_snprintf(line, "primary_conninfo = '%s'\n", master_conninfo); + } + maxlen_snprintf(line, "primary_conninfo = 'host=%s port=%s'\n", host, ((masterport==NULL) ? "5432" : masterport)); if (fputs(line, recovery_file) == EOF) diff --git a/repmgrd.c b/repmgrd.c index 02df064f..16790566 100644 --- a/repmgrd.c +++ b/repmgrd.c @@ -168,7 +168,7 @@ main(int argc, char **argv) { /* I need the id of the primary as well as a connection to it */ primaryConn = getMasterConnection(myLocalConn, myLocalId, - myClusterName, &primaryId); + myClusterName, &primaryId, NULL); if (primaryConn == NULL) exit(1); } @@ -240,7 +240,7 @@ MonitorExecute(void) connection_retries++) { primaryConn = getMasterConnection(myLocalConn, myLocalId, - myClusterName, &primaryId); + myClusterName, &primaryId, NULL); if (PQstatus(primaryConn) == CONNECTION_OK) { /* Connected, we can continue the process so break the loop */