mirror of
https://github.com/EnterpriseDB/repmgr.git
synced 2026-03-22 22:56:29 +00:00
Move create_recovery_file() et al to repmgr-action-standby.c
As they're only ever called from there.
This commit is contained in:
@@ -96,6 +96,11 @@ static void get_barman_property(char *dst, char *name, char *local_repmgr_direct
|
|||||||
static int get_tablespace_data_barman(char *, TablespaceDataList *);
|
static int get_tablespace_data_barman(char *, TablespaceDataList *);
|
||||||
static char *make_barman_ssh_command(char *buf);
|
static char *make_barman_ssh_command(char *buf);
|
||||||
|
|
||||||
|
static bool create_recovery_file(t_node_info *node_record, t_conninfo_param_list *recovery_conninfo, const char *data_dir);
|
||||||
|
static void write_primary_conninfo(char *line, t_conninfo_param_list *param_list);
|
||||||
|
static bool write_recovery_file_line(FILE *recovery_file, char *recovery_file_path, char *line);
|
||||||
|
|
||||||
|
|
||||||
static NodeStatus parse_node_status_is_shutdown_cleanly(const char *node_status_output, XLogRecPtr *checkPoint);
|
static NodeStatus parse_node_status_is_shutdown_cleanly(const char *node_status_output, XLogRecPtr *checkPoint);
|
||||||
static CheckStatus parse_node_check_archiver(const char *node_check_output, int *files, int *threshold);
|
static CheckStatus parse_node_check_archiver(const char *node_check_output, int *files, int *threshold);
|
||||||
static CheckStatus parse_node_check_replication_lag(const char *node_check_output, int *seconds, int *threshold);
|
static CheckStatus parse_node_check_replication_lag(const char *node_check_output, int *seconds, int *threshold);
|
||||||
@@ -4751,6 +4756,225 @@ drop_replication_slot_if_exists(PGconn *conn, int node_id, char *slot_name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Creates a recovery.conf file for a standby
|
||||||
|
*
|
||||||
|
* A database connection pointer is required for escaping primary_conninfo
|
||||||
|
* parameters. When cloning from Barman and --no-upstream-connection ) this
|
||||||
|
* might not be available.
|
||||||
|
*/
|
||||||
|
bool
|
||||||
|
create_recovery_file(t_node_info *node_record, t_conninfo_param_list *recovery_conninfo, const char *data_dir)
|
||||||
|
{
|
||||||
|
FILE *recovery_file;
|
||||||
|
char recovery_file_path[MAXPGPATH] = "";
|
||||||
|
char line[MAXLEN] = "";
|
||||||
|
mode_t um;
|
||||||
|
|
||||||
|
maxpath_snprintf(recovery_file_path, "%s/%s", data_dir, RECOVERY_COMMAND_FILE);
|
||||||
|
|
||||||
|
/* Set umask to 0600 */
|
||||||
|
um = umask((~(S_IRUSR | S_IWUSR)) & (S_IRWXG | S_IRWXO));
|
||||||
|
recovery_file = fopen(recovery_file_path, "w");
|
||||||
|
umask(um);
|
||||||
|
|
||||||
|
if (recovery_file == NULL)
|
||||||
|
{
|
||||||
|
log_error(_("unable to create recovery.conf file at \"%s\""),
|
||||||
|
recovery_file_path);
|
||||||
|
log_detail("%s", strerror(errno));
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_debug("create_recovery_file(): creating \"%s\"...",
|
||||||
|
recovery_file_path);
|
||||||
|
|
||||||
|
/* standby_mode = 'on' */
|
||||||
|
maxlen_snprintf(line, "standby_mode = 'on'\n");
|
||||||
|
|
||||||
|
if (write_recovery_file_line(recovery_file, recovery_file_path, line) == false)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
trim(line);
|
||||||
|
log_debug("recovery.conf: %s", line);
|
||||||
|
|
||||||
|
/* primary_conninfo = '...' */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* the user specified --upstream-conninfo string - copy that
|
||||||
|
*/
|
||||||
|
if (strlen(runtime_options.upstream_conninfo))
|
||||||
|
{
|
||||||
|
char *escaped = escape_recovery_conf_value(runtime_options.upstream_conninfo);
|
||||||
|
|
||||||
|
maxlen_snprintf(line, "primary_conninfo = '%s'\n",
|
||||||
|
escaped);
|
||||||
|
free(escaped);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* otherwise use the conninfo inferred from the upstream connection and/or
|
||||||
|
* node record
|
||||||
|
*/
|
||||||
|
else
|
||||||
|
{
|
||||||
|
write_primary_conninfo(line, recovery_conninfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (write_recovery_file_line(recovery_file, recovery_file_path, line) == false)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
trim(line);
|
||||||
|
log_debug("recovery.conf: %s", line);
|
||||||
|
|
||||||
|
/* recovery_target_timeline = 'latest' */
|
||||||
|
maxlen_snprintf(line, "recovery_target_timeline = 'latest'\n");
|
||||||
|
|
||||||
|
if (write_recovery_file_line(recovery_file, recovery_file_path, line) == false)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
trim(line);
|
||||||
|
log_debug("recovery.conf: %s", line);
|
||||||
|
|
||||||
|
/* recovery_min_apply_delay = ... (optional) */
|
||||||
|
if (*config_file_options.recovery_min_apply_delay)
|
||||||
|
{
|
||||||
|
maxlen_snprintf(line, "recovery_min_apply_delay = %s\n",
|
||||||
|
config_file_options.recovery_min_apply_delay);
|
||||||
|
if (write_recovery_file_line(recovery_file, recovery_file_path, line) == false)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
trim(line);
|
||||||
|
log_debug("recovery.conf: %s", line);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* primary_slot_name = '...' (optional, for 9.4 and later) */
|
||||||
|
if (config_file_options.use_replication_slots)
|
||||||
|
{
|
||||||
|
maxlen_snprintf(line, "primary_slot_name = %s\n",
|
||||||
|
node_record->slot_name);
|
||||||
|
if (write_recovery_file_line(recovery_file, recovery_file_path, line) == false)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
trim(line);
|
||||||
|
log_debug("recovery.conf: %s", line);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If restore_command is set, we use it as restore_command in
|
||||||
|
* recovery.conf
|
||||||
|
*/
|
||||||
|
if (strcmp(config_file_options.restore_command, "") != 0)
|
||||||
|
{
|
||||||
|
maxlen_snprintf(line, "restore_command = '%s'\n",
|
||||||
|
config_file_options.restore_command);
|
||||||
|
if (write_recovery_file_line(recovery_file, recovery_file_path, line) == false)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
trim(line);
|
||||||
|
log_debug("recovery.conf: %s", line);
|
||||||
|
}
|
||||||
|
fclose(recovery_file);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool
|
||||||
|
write_recovery_file_line(FILE *recovery_file, char *recovery_file_path, char *line)
|
||||||
|
{
|
||||||
|
if (fputs(line, recovery_file) == EOF)
|
||||||
|
{
|
||||||
|
log_error(_("unable to write to recovery file at \"%s\""), recovery_file_path);
|
||||||
|
fclose(recovery_file);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
write_primary_conninfo(char *line, t_conninfo_param_list *param_list)
|
||||||
|
{
|
||||||
|
PQExpBufferData conninfo_buf;
|
||||||
|
bool application_name_provided = false;
|
||||||
|
bool password_provided = false;
|
||||||
|
int c;
|
||||||
|
char *escaped = NULL;
|
||||||
|
t_conninfo_param_list env_conninfo;
|
||||||
|
|
||||||
|
initialize_conninfo_params(&env_conninfo, true);
|
||||||
|
|
||||||
|
initPQExpBuffer(&conninfo_buf);
|
||||||
|
|
||||||
|
for (c = 0; c < param_list->size && param_list->keywords[c] != NULL; c++)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Skip empty settings and ones which don't make any sense in
|
||||||
|
* recovery.conf
|
||||||
|
*/
|
||||||
|
if (strcmp(param_list->keywords[c], "dbname") == 0 ||
|
||||||
|
strcmp(param_list->keywords[c], "replication") == 0 ||
|
||||||
|
(param_list->values[c] == NULL) ||
|
||||||
|
(param_list->values[c] != NULL && param_list->values[c][0] == '\0'))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* only include "password" if explicitly requested */
|
||||||
|
if (strcmp(param_list->keywords[c], "password") == 0)
|
||||||
|
{
|
||||||
|
password_provided = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conninfo_buf.len != 0)
|
||||||
|
appendPQExpBufferChar(&conninfo_buf, ' ');
|
||||||
|
|
||||||
|
if (strcmp(param_list->keywords[c], "application_name") == 0)
|
||||||
|
application_name_provided = true;
|
||||||
|
|
||||||
|
appendPQExpBuffer(&conninfo_buf, "%s=", param_list->keywords[c]);
|
||||||
|
appendConnStrVal(&conninfo_buf, param_list->values[c]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* "application_name" not provided - default to repmgr node name */
|
||||||
|
if (application_name_provided == false)
|
||||||
|
{
|
||||||
|
if (strlen(config_file_options.node_name))
|
||||||
|
{
|
||||||
|
appendPQExpBuffer(&conninfo_buf, " application_name=");
|
||||||
|
appendConnStrVal(&conninfo_buf, config_file_options.node_name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
appendPQExpBuffer(&conninfo_buf, " application_name=repmgr");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* no password provided explicitly */
|
||||||
|
if (password_provided == false)
|
||||||
|
{
|
||||||
|
if (config_file_options.use_primary_conninfo_password == true)
|
||||||
|
{
|
||||||
|
const char *password = param_get(&env_conninfo, "password");
|
||||||
|
|
||||||
|
if (password != NULL)
|
||||||
|
{
|
||||||
|
appendPQExpBuffer(&conninfo_buf, " password=");
|
||||||
|
appendConnStrVal(&conninfo_buf, password);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
escaped = escape_recovery_conf_value(conninfo_buf.data);
|
||||||
|
maxlen_snprintf(line, "primary_conninfo = '%s'\n", escaped);
|
||||||
|
|
||||||
|
free(escaped);
|
||||||
|
free_conninfo_params(&env_conninfo);
|
||||||
|
termPQExpBuffer(&conninfo_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* TODO: consolidate code in below functions */
|
/* TODO: consolidate code in below functions */
|
||||||
static NodeStatus
|
static NodeStatus
|
||||||
parse_node_status_is_shutdown_cleanly(const char *node_status_output, XLogRecPtr *checkPoint)
|
parse_node_status_is_shutdown_cleanly(const char *node_status_output, XLogRecPtr *checkPoint)
|
||||||
|
|||||||
@@ -211,8 +211,6 @@ extern void print_error_list(ItemList *error_list, int log_level);
|
|||||||
|
|
||||||
extern char *make_pg_path(const char *file);
|
extern char *make_pg_path(const char *file);
|
||||||
|
|
||||||
extern bool create_recovery_file(t_node_info *node_record, t_conninfo_param_list *recovery_conninfo, const char *data_dir);
|
|
||||||
|
|
||||||
extern void get_superuser_connection(PGconn **conn, PGconn **superuser_conn, PGconn **privileged_conn);
|
extern void get_superuser_connection(PGconn **conn, PGconn **superuser_conn, PGconn **privileged_conn);
|
||||||
|
|
||||||
extern bool remote_command(const char *host, const char *user, const char *command, PQExpBufferData *outputbuf);
|
extern bool remote_command(const char *host, const char *user, const char *command, PQExpBufferData *outputbuf);
|
||||||
|
|||||||
217
repmgr-client.c
217
repmgr-client.c
@@ -2272,223 +2272,6 @@ copy_remote_files(char *host, char *remote_user, char *remote_path,
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Creates a recovery.conf file for a standby
|
|
||||||
*
|
|
||||||
* A database connection pointer is required for escaping primary_conninfo
|
|
||||||
* parameters. When cloning from Barman and --no-upstream-connection ) this
|
|
||||||
* might not be available.
|
|
||||||
*/
|
|
||||||
bool
|
|
||||||
create_recovery_file(t_node_info *node_record, t_conninfo_param_list *recovery_conninfo, const char *data_dir)
|
|
||||||
{
|
|
||||||
FILE *recovery_file;
|
|
||||||
char recovery_file_path[MAXPGPATH] = "";
|
|
||||||
char line[MAXLEN] = "";
|
|
||||||
mode_t um;
|
|
||||||
|
|
||||||
maxpath_snprintf(recovery_file_path, "%s/%s", data_dir, RECOVERY_COMMAND_FILE);
|
|
||||||
|
|
||||||
/* Set umask to 0600 */
|
|
||||||
um = umask((~(S_IRUSR | S_IWUSR)) & (S_IRWXG | S_IRWXO));
|
|
||||||
recovery_file = fopen(recovery_file_path, "w");
|
|
||||||
umask(um);
|
|
||||||
|
|
||||||
if (recovery_file == NULL)
|
|
||||||
{
|
|
||||||
log_error(_("unable to create recovery.conf file at \"%s\""),
|
|
||||||
recovery_file_path);
|
|
||||||
log_detail("%s", strerror(errno));
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
log_debug("create_recovery_file(): creating \"%s\"...",
|
|
||||||
recovery_file_path);
|
|
||||||
|
|
||||||
/* standby_mode = 'on' */
|
|
||||||
maxlen_snprintf(line, "standby_mode = 'on'\n");
|
|
||||||
|
|
||||||
if (write_recovery_file_line(recovery_file, recovery_file_path, line) == false)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
trim(line);
|
|
||||||
log_debug("recovery.conf: %s", line);
|
|
||||||
|
|
||||||
/* primary_conninfo = '...' */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* the user specified --upstream-conninfo string - copy that
|
|
||||||
*/
|
|
||||||
if (strlen(runtime_options.upstream_conninfo))
|
|
||||||
{
|
|
||||||
char *escaped = escape_recovery_conf_value(runtime_options.upstream_conninfo);
|
|
||||||
|
|
||||||
maxlen_snprintf(line, "primary_conninfo = '%s'\n",
|
|
||||||
escaped);
|
|
||||||
free(escaped);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* otherwise use the conninfo inferred from the upstream connection and/or
|
|
||||||
* node record
|
|
||||||
*/
|
|
||||||
else
|
|
||||||
{
|
|
||||||
write_primary_conninfo(line, recovery_conninfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (write_recovery_file_line(recovery_file, recovery_file_path, line) == false)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
trim(line);
|
|
||||||
log_debug("recovery.conf: %s", line);
|
|
||||||
|
|
||||||
/* recovery_target_timeline = 'latest' */
|
|
||||||
maxlen_snprintf(line, "recovery_target_timeline = 'latest'\n");
|
|
||||||
|
|
||||||
if (write_recovery_file_line(recovery_file, recovery_file_path, line) == false)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
trim(line);
|
|
||||||
log_debug("recovery.conf: %s", line);
|
|
||||||
|
|
||||||
/* recovery_min_apply_delay = ... (optional) */
|
|
||||||
if (*config_file_options.recovery_min_apply_delay)
|
|
||||||
{
|
|
||||||
maxlen_snprintf(line, "recovery_min_apply_delay = %s\n",
|
|
||||||
config_file_options.recovery_min_apply_delay);
|
|
||||||
if (write_recovery_file_line(recovery_file, recovery_file_path, line) == false)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
trim(line);
|
|
||||||
log_debug("recovery.conf: %s", line);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* primary_slot_name = '...' (optional, for 9.4 and later) */
|
|
||||||
if (config_file_options.use_replication_slots)
|
|
||||||
{
|
|
||||||
maxlen_snprintf(line, "primary_slot_name = %s\n",
|
|
||||||
node_record->slot_name);
|
|
||||||
if (write_recovery_file_line(recovery_file, recovery_file_path, line) == false)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
trim(line);
|
|
||||||
log_debug("recovery.conf: %s", line);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If restore_command is set, we use it as restore_command in
|
|
||||||
* recovery.conf
|
|
||||||
*/
|
|
||||||
if (strcmp(config_file_options.restore_command, "") != 0)
|
|
||||||
{
|
|
||||||
maxlen_snprintf(line, "restore_command = '%s'\n",
|
|
||||||
config_file_options.restore_command);
|
|
||||||
if (write_recovery_file_line(recovery_file, recovery_file_path, line) == false)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
trim(line);
|
|
||||||
log_debug("recovery.conf: %s", line);
|
|
||||||
}
|
|
||||||
fclose(recovery_file);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static bool
|
|
||||||
write_recovery_file_line(FILE *recovery_file, char *recovery_file_path, char *line)
|
|
||||||
{
|
|
||||||
if (fputs(line, recovery_file) == EOF)
|
|
||||||
{
|
|
||||||
log_error(_("unable to write to recovery file at \"%s\""), recovery_file_path);
|
|
||||||
fclose(recovery_file);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
write_primary_conninfo(char *line, t_conninfo_param_list *param_list)
|
|
||||||
{
|
|
||||||
PQExpBufferData conninfo_buf;
|
|
||||||
bool application_name_provided = false;
|
|
||||||
bool password_provided = false;
|
|
||||||
int c;
|
|
||||||
char *escaped = NULL;
|
|
||||||
t_conninfo_param_list env_conninfo;
|
|
||||||
|
|
||||||
initialize_conninfo_params(&env_conninfo, true);
|
|
||||||
|
|
||||||
initPQExpBuffer(&conninfo_buf);
|
|
||||||
|
|
||||||
for (c = 0; c < param_list->size && param_list->keywords[c] != NULL; c++)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Skip empty settings and ones which don't make any sense in
|
|
||||||
* recovery.conf
|
|
||||||
*/
|
|
||||||
if (strcmp(param_list->keywords[c], "dbname") == 0 ||
|
|
||||||
strcmp(param_list->keywords[c], "replication") == 0 ||
|
|
||||||
(param_list->values[c] == NULL) ||
|
|
||||||
(param_list->values[c] != NULL && param_list->values[c][0] == '\0'))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* only include "password" if explicitly requested */
|
|
||||||
if (strcmp(param_list->keywords[c], "password") == 0)
|
|
||||||
{
|
|
||||||
password_provided = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (conninfo_buf.len != 0)
|
|
||||||
appendPQExpBufferChar(&conninfo_buf, ' ');
|
|
||||||
|
|
||||||
if (strcmp(param_list->keywords[c], "application_name") == 0)
|
|
||||||
application_name_provided = true;
|
|
||||||
|
|
||||||
appendPQExpBuffer(&conninfo_buf, "%s=", param_list->keywords[c]);
|
|
||||||
appendConnStrVal(&conninfo_buf, param_list->values[c]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* "application_name" not provided - default to repmgr node name */
|
|
||||||
if (application_name_provided == false)
|
|
||||||
{
|
|
||||||
if (strlen(config_file_options.node_name))
|
|
||||||
{
|
|
||||||
appendPQExpBuffer(&conninfo_buf, " application_name=");
|
|
||||||
appendConnStrVal(&conninfo_buf, config_file_options.node_name);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
appendPQExpBuffer(&conninfo_buf, " application_name=repmgr");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* no password provided explicitly */
|
|
||||||
if (password_provided == false)
|
|
||||||
{
|
|
||||||
if (config_file_options.use_primary_conninfo_password == true)
|
|
||||||
{
|
|
||||||
const char *password = param_get(&env_conninfo, "password");
|
|
||||||
|
|
||||||
if (password != NULL)
|
|
||||||
{
|
|
||||||
appendPQExpBuffer(&conninfo_buf, " password=");
|
|
||||||
appendConnStrVal(&conninfo_buf, password);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
escaped = escape_recovery_conf_value(conninfo_buf.data);
|
|
||||||
maxlen_snprintf(line, "primary_conninfo = '%s'\n", escaped);
|
|
||||||
|
|
||||||
free(escaped);
|
|
||||||
free_conninfo_params(&env_conninfo);
|
|
||||||
termPQExpBuffer(&conninfo_buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -204,7 +204,4 @@ static const char *action_name(const int action);
|
|||||||
|
|
||||||
static void check_cli_parameters(const int action);
|
static void check_cli_parameters(const int action);
|
||||||
|
|
||||||
static void write_primary_conninfo(char *line, t_conninfo_param_list *param_list);
|
|
||||||
static bool write_recovery_file_line(FILE *recovery_file, char *recovery_file_path, char *line);
|
|
||||||
|
|
||||||
#endif /* _REPMGR_CLIENT_H_ */
|
#endif /* _REPMGR_CLIENT_H_ */
|
||||||
|
|||||||
Reference in New Issue
Block a user