mirror of
https://github.com/EnterpriseDB/repmgr.git
synced 2026-03-26 16:46:28 +00:00
Additional "standby clone" code
We'll break up the unwieldy "do_standby_clone()" function into discrete unit for easier maintenance.
This commit is contained in:
@@ -7,10 +7,19 @@
|
||||
*/
|
||||
|
||||
#include "repmgr.h"
|
||||
#include "dirutil.h"
|
||||
|
||||
#include "repmgr-client-global.h"
|
||||
#include "repmgr-action-standby.h"
|
||||
|
||||
static char local_data_directory[MAXPGPATH];
|
||||
|
||||
/* used by barman mode */
|
||||
static char local_repmgr_tmp_directory[MAXPGPATH];
|
||||
|
||||
|
||||
static void check_barman_config(void);
|
||||
static char *make_barman_ssh_command(char *buf);
|
||||
|
||||
|
||||
void
|
||||
@@ -20,7 +29,7 @@ do_standby_clone(void)
|
||||
PGconn *source_conn = NULL;
|
||||
PGresult *res;
|
||||
|
||||
int server_version_num = -1;
|
||||
int server_version_num = UNKNOWN_SERVER_VERSION_NUM;
|
||||
char cluster_size[MAXLEN];
|
||||
|
||||
/*
|
||||
@@ -32,6 +41,8 @@ do_standby_clone(void)
|
||||
bool upstream_record_found = false;
|
||||
int upstream_node_id = UNKNOWN_NODE_ID;
|
||||
|
||||
char upstream_data_directory[MAXPGPATH];
|
||||
bool local_data_directory_provided = false;
|
||||
|
||||
enum {
|
||||
barman,
|
||||
@@ -39,19 +50,13 @@ do_standby_clone(void)
|
||||
pg_basebackup
|
||||
} mode;
|
||||
|
||||
/* used by barman mode */
|
||||
char datadir_list_filename[MAXLEN];
|
||||
char local_repmgr_tmp_directory[MAXPGPATH];
|
||||
|
||||
puts("standby clone");
|
||||
|
||||
|
||||
/*
|
||||
* detecting the cloning mode
|
||||
*/
|
||||
if (runtime_options.rsync_only)
|
||||
mode = rsync;
|
||||
else if (strcmp(config_file_options.barman_server, "") != 0 && ! runtime_options.without_barman)
|
||||
else if (strcmp(config_file_options.barman_host, "") != 0 && ! runtime_options.without_barman)
|
||||
mode = barman;
|
||||
else
|
||||
mode = pg_basebackup;
|
||||
@@ -72,4 +77,179 @@ do_standby_clone(void)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If dest_dir (-D/--pgdata) was provided, this will become the new data
|
||||
* directory (otherwise repmgr will default to using the same directory
|
||||
* path as on the source host).
|
||||
*
|
||||
* Note that barman mode requires -D/--pgdata.
|
||||
*
|
||||
* If -D/--pgdata is not supplied, and we're not cloning from barman,
|
||||
* the source host's data directory will be fetched later, after
|
||||
* we've connected to it.
|
||||
*/
|
||||
if (runtime_options.data_dir[0])
|
||||
{
|
||||
local_data_directory_provided = true;
|
||||
log_notice(_("destination directory '%s' provided"),
|
||||
runtime_options.data_dir);
|
||||
}
|
||||
else if (mode == barman)
|
||||
{
|
||||
log_error(_("Barman mode requires a data directory"));
|
||||
log_hint(_("use -D/--pgdata to explicitly specify a data directory"));
|
||||
exit(ERR_BAD_CONFIG);
|
||||
}
|
||||
|
||||
/* Sanity-check barman connection and installation */
|
||||
if (mode == barman)
|
||||
{
|
||||
/* this will exit with ERR_BARMAN if problems found */
|
||||
check_barman_config();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* target directory (-D/--pgdata) provided - use that as new data directory
|
||||
* (useful when executing backup on local machine only or creating the backup
|
||||
* in a different local directory when backup source is a remote host)
|
||||
*/
|
||||
if (local_data_directory_provided == true)
|
||||
{
|
||||
strncpy(local_data_directory, runtime_options.data_dir, MAXPGPATH);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialise list of conninfo parameters which will later be used
|
||||
* to create the `primary_conninfo` string in recovery.conf .
|
||||
*
|
||||
* We'll initialise it with the default values as seen by libpq,
|
||||
* and overwrite them with the host settings specified on the command
|
||||
* line. As it's possible the standby will be cloned from a node different
|
||||
* to its intended upstream, we'll later attempt to fetch the
|
||||
* upstream node record and overwrite the values set here with
|
||||
* those from the upstream node record (excluding that record's
|
||||
* application_name)
|
||||
*/
|
||||
initialize_conninfo_params(&recovery_conninfo, true);
|
||||
|
||||
copy_conninfo_params(&recovery_conninfo, &source_conninfo);
|
||||
|
||||
/*
|
||||
* If application_name is set in repmgr.conf's conninfo parameter, use
|
||||
* this value (if the source host was provided as a conninfo string, any
|
||||
* application_name values set there will be overridden; we assume the only
|
||||
* reason to pass an application_name via the command line is in the
|
||||
* rare corner case where a user wishes to clone a server without
|
||||
* providing repmgr.conf)
|
||||
*/
|
||||
if (strlen(config_file_options.conninfo))
|
||||
{
|
||||
char application_name[MAXLEN] = "";
|
||||
|
||||
get_conninfo_value(config_file_options.conninfo, "application_name", application_name);
|
||||
if (strlen(application_name))
|
||||
{
|
||||
param_set(&recovery_conninfo, "application_name", application_name);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
check_barman_config(void)
|
||||
{
|
||||
char datadir_list_filename[MAXLEN];
|
||||
char barman_command_buf[MAXLEN] = "";
|
||||
|
||||
char command[MAXLEN];
|
||||
bool command_ok;
|
||||
|
||||
/*
|
||||
* Check that there is at least one valid backup
|
||||
*/
|
||||
|
||||
log_info(_("connecting to Barman server to verify backup for %s"), config_file_options.barman_server);
|
||||
|
||||
maxlen_snprintf(command, "%s show-backup %s latest > /dev/null",
|
||||
make_barman_ssh_command(barman_command_buf),
|
||||
config_file_options.barman_server);
|
||||
|
||||
command_ok = local_command(command, NULL);
|
||||
|
||||
if (command_ok == false)
|
||||
{
|
||||
log_error(_("no valid backup for server %s was found in the Barman catalogue"),
|
||||
config_file_options.barman_server);
|
||||
log_hint(_("refer to the Barman documentation for more information\n"));
|
||||
|
||||
exit(ERR_BARMAN);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create the local repmgr subdirectory
|
||||
*/
|
||||
|
||||
maxlen_snprintf(local_repmgr_tmp_directory,
|
||||
"%s/repmgr", local_data_directory);
|
||||
|
||||
maxlen_snprintf(datadir_list_filename,
|
||||
"%s/data.txt", local_repmgr_tmp_directory);
|
||||
|
||||
if (!create_pg_dir(local_data_directory, runtime_options.force))
|
||||
{
|
||||
log_error(_("unable to use directory %s"),
|
||||
local_data_directory);
|
||||
log_hint(_("use -F/--force option to force this directory to be overwritten\n"));
|
||||
exit(ERR_BAD_CONFIG);
|
||||
}
|
||||
|
||||
if (!create_pg_dir(local_repmgr_tmp_directory, runtime_options.force))
|
||||
{
|
||||
log_error(_("unable to create directory \"%s\""),
|
||||
local_repmgr_tmp_directory);
|
||||
|
||||
exit(ERR_BAD_CONFIG);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fetch server parameters from Barman
|
||||
*/
|
||||
log_info(_("connecting to Barman server to fetch server parameters"));
|
||||
|
||||
maxlen_snprintf(command, "%s show-server %s > %s/show-server.txt",
|
||||
make_barman_ssh_command(barman_command_buf),
|
||||
config_file_options.barman_server,
|
||||
local_repmgr_tmp_directory);
|
||||
|
||||
command_ok = local_command(command, NULL);
|
||||
|
||||
if (command_ok == false)
|
||||
{
|
||||
log_error(_("unable to fetch server parameters from Barman server"));
|
||||
|
||||
exit(ERR_BARMAN);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
make_barman_ssh_command(char *buf)
|
||||
{
|
||||
static char config_opt[MAXLEN] = "";
|
||||
|
||||
if (strlen(config_file_options.barman_config))
|
||||
maxlen_snprintf(config_opt,
|
||||
" --config=%s",
|
||||
config_file_options.barman_config);
|
||||
|
||||
maxlen_snprintf(buf,
|
||||
"ssh %s barman%s",
|
||||
config_file_options.barman_server,
|
||||
config_opt);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user