mirror of
https://github.com/EnterpriseDB/repmgr.git
synced 2026-03-23 07:06:30 +00:00
Compare commits
34 Commits
v3.2
...
REL3_2_STA
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
54a4d1e444 | ||
|
|
d4b8c034e9 | ||
|
|
b8f4c35810 | ||
|
|
0cde0068dd | ||
|
|
20d66df0ef | ||
|
|
3f7c30b84d | ||
|
|
a63baf7fcb | ||
|
|
e19c643389 | ||
|
|
f058833451 | ||
|
|
96c14adfdb | ||
|
|
d2c09a1f71 | ||
|
|
2389101ae9 | ||
|
|
cbc2841433 | ||
|
|
50119056a5 | ||
|
|
a279c42df9 | ||
|
|
f70b6ea136 | ||
|
|
2bc877114c | ||
|
|
e4cb6d7130 | ||
|
|
502c056753 | ||
|
|
871ec47ff5 | ||
|
|
30c5cc86f3 | ||
|
|
f435abb3ec | ||
|
|
b977b48aee | ||
|
|
a217b4d0a9 | ||
|
|
108bdeb269 | ||
|
|
2dcb75f889 | ||
|
|
b509ce6382 | ||
|
|
1150bf272a | ||
|
|
09ac6cd145 | ||
|
|
2fae788bc4 | ||
|
|
eb90f864c9 | ||
|
|
ba89758366 | ||
|
|
84595fe711 | ||
|
|
9523894808 |
13
HISTORY
13
HISTORY
@@ -1,3 +1,12 @@
|
||||
3.2.1 2016-10-24
|
||||
repmgr: require a valid repmgr cluster name unless -F/--force
|
||||
supplied (Ian)
|
||||
repmgr: check master server is registered with repmgr before
|
||||
cloning (Ian)
|
||||
repmgr: ensure data directory defaults to that of the source node (Ian)
|
||||
repmgr: various fixes to Barman cloning mode (Gianni, Ian)
|
||||
repmgr: fix `repmgr cluster crosscheck` output (Ian)
|
||||
|
||||
3.2 2016-10-05
|
||||
repmgr: add support for cloning from a Barman backup (Gianni)
|
||||
repmgr: add commands `standby matrix` and `standby crosscheck` (Gianni)
|
||||
@@ -15,12 +24,12 @@
|
||||
the standby (Ian)
|
||||
repmgr: add option `--copy-external-config-files` for files outside
|
||||
of the data directory (Ian)
|
||||
repmgr: add configuration options to override the default pg_ctl
|
||||
commands (Jarkko Oranen, Ian)
|
||||
repmgr: only require `wal_keep_segments` to be set in certain corner
|
||||
cases (Ian)
|
||||
repmgr: better support cloning from a node other than the one to
|
||||
stream from (Ian)
|
||||
repmgrd: add configuration options to override the default pg_ctl
|
||||
commands (Jarkko Oranen, Ian)
|
||||
repmgrd: don't start if node is inactive and failover=automatic (Ian)
|
||||
packaging: improve "repmgr-auto" Debian package (Gianni)
|
||||
|
||||
|
||||
12
README.md
12
README.md
@@ -8,7 +8,7 @@ replication, and perform administrative tasks such as failover or switchover
|
||||
operations.
|
||||
|
||||
The current `repmgr` version, 3.2, supports all PostgreSQL versions from
|
||||
9.3, including the upcoming 9.6.
|
||||
9.3 to 9.6.
|
||||
|
||||
Overview
|
||||
--------
|
||||
@@ -121,7 +121,8 @@ views:
|
||||
status for each node
|
||||
|
||||
The `repmgr` metadata schema can be stored in an existing database or in its own
|
||||
dedicated database.
|
||||
dedicated database. Note that the `repmgr` metadata schema cannot reside on a database
|
||||
server which is not part of the replication cluster managed by `repmgr`.
|
||||
|
||||
A dedicated database superuser is required to own the meta-database as well as carry
|
||||
out administrative actions.
|
||||
@@ -600,7 +601,7 @@ ensure that:
|
||||
hostname of the Barman server;
|
||||
- the `restore_command` setting in `repmgr.conf` is configured to
|
||||
use a copy of the `barman-wal-restore` script shipped with the
|
||||
`barman-cli package` (see below);
|
||||
`barman-cli` package (see below);
|
||||
- the Barman catalogue includes at least one valid backup for this
|
||||
server.
|
||||
|
||||
@@ -1072,8 +1073,9 @@ This will remove the standby record from `repmgr`'s internal metadata
|
||||
table (`repl_nodes`). A `standby_unregister` event notification will be
|
||||
recorded in the `repl_events` table.
|
||||
|
||||
Note that this command will not stop the server itself or remove
|
||||
it from the replication cluster.
|
||||
Note that this command will not stop the server itself or remove it from
|
||||
the replication cluster. Note that if the standby was using a replication
|
||||
slot, this will not be removed.
|
||||
|
||||
If the standby is not running, the command can be executed on another
|
||||
node by providing the id of the node to be unregistered using
|
||||
|
||||
241
repmgr.c
241
repmgr.c
@@ -178,12 +178,6 @@ static bool config_file_required = true;
|
||||
t_runtime_options runtime_options = T_RUNTIME_OPTIONS_INITIALIZER;
|
||||
t_configuration_options options = T_CONFIGURATION_OPTIONS_INITIALIZER;
|
||||
|
||||
static bool wal_keep_segments_used = false;
|
||||
static bool conninfo_provided = false;
|
||||
static bool connection_param_provided = false;
|
||||
static bool host_param_provided = false;
|
||||
static bool pg_rewind_supplied = false;
|
||||
|
||||
static char *server_mode = NULL;
|
||||
static char *server_cmd = NULL;
|
||||
|
||||
@@ -365,13 +359,13 @@ main(int argc, char **argv)
|
||||
case 'd':
|
||||
strncpy(runtime_options.dbname, optarg, MAXLEN);
|
||||
/* we'll set the dbname parameter below if we detect it's not a conninfo string */
|
||||
connection_param_provided = true;
|
||||
runtime_options.connection_param_provided = true;
|
||||
break;
|
||||
case 'h':
|
||||
strncpy(runtime_options.host, optarg, MAXLEN);
|
||||
param_set(&source_conninfo, "host", optarg);
|
||||
connection_param_provided = true;
|
||||
host_param_provided = true;
|
||||
runtime_options.connection_param_provided = true;
|
||||
runtime_options.host_param_provided = true;
|
||||
break;
|
||||
case 'p':
|
||||
repmgr_atoi(optarg, "-p/--port", &cli_errors, false);
|
||||
@@ -379,12 +373,12 @@ main(int argc, char **argv)
|
||||
strncpy(runtime_options.masterport,
|
||||
optarg,
|
||||
MAXLEN);
|
||||
connection_param_provided = true;
|
||||
runtime_options.connection_param_provided = true;
|
||||
break;
|
||||
case 'U':
|
||||
strncpy(runtime_options.username, optarg, MAXLEN);
|
||||
param_set(&source_conninfo, "user", optarg);
|
||||
connection_param_provided = true;
|
||||
runtime_options.connection_param_provided = true;
|
||||
break;
|
||||
case 'S':
|
||||
strncpy(runtime_options.superuser, optarg, MAXLEN);
|
||||
@@ -403,7 +397,7 @@ main(int argc, char **argv)
|
||||
strncpy(runtime_options.wal_keep_segments,
|
||||
optarg,
|
||||
MAXLEN);
|
||||
wal_keep_segments_used = true;
|
||||
runtime_options.wal_keep_segments_used = true;
|
||||
break;
|
||||
case 'k':
|
||||
runtime_options.keep_history = repmgr_atoi(optarg, "-k/--keep-history", &cli_errors, false);
|
||||
@@ -519,7 +513,7 @@ main(int argc, char **argv)
|
||||
{
|
||||
strncpy(runtime_options.pg_rewind, optarg, MAXPGPATH);
|
||||
}
|
||||
pg_rewind_supplied = true;
|
||||
runtime_options.pg_rewind_supplied = true;
|
||||
break;
|
||||
case OPT_PWPROMPT:
|
||||
runtime_options.witness_pwprompt = true;
|
||||
@@ -586,7 +580,7 @@ main(int argc, char **argv)
|
||||
{
|
||||
char *errmsg = NULL;
|
||||
|
||||
conninfo_provided = true;
|
||||
runtime_options.conninfo_provided = true;
|
||||
|
||||
opts = PQconninfoParse(runtime_options.dbname, &errmsg);
|
||||
|
||||
@@ -620,13 +614,13 @@ main(int argc, char **argv)
|
||||
(opt->val != NULL && opt->val[0] != '\0'))
|
||||
{
|
||||
strncpy(runtime_options.host, opt->val, MAXLEN);
|
||||
host_param_provided = true;
|
||||
runtime_options.host_param_provided = true;
|
||||
}
|
||||
if (strcmp(opt->keyword, "hostaddr") == 0 &&
|
||||
(opt->val != NULL && opt->val[0] != '\0'))
|
||||
{
|
||||
strncpy(runtime_options.host, opt->val, MAXLEN);
|
||||
host_param_provided = true;
|
||||
runtime_options.host_param_provided = true;
|
||||
}
|
||||
else if (strcmp(opt->keyword, "port") == 0 &&
|
||||
(opt->val != NULL && opt->val[0] != '\0'))
|
||||
@@ -762,7 +756,7 @@ main(int argc, char **argv)
|
||||
initPQExpBuffer(&additional_host_arg);
|
||||
appendPQExpBuffer(&additional_host_arg,
|
||||
_("Conflicting parameters: you can't use %s while providing a node separately."),
|
||||
conninfo_provided == true ? "host=" : "-h/--host");
|
||||
runtime_options.conninfo_provided == true ? "host=" : "-h/--host");
|
||||
item_list_append(&cli_errors, additional_host_arg.data);
|
||||
}
|
||||
else
|
||||
@@ -884,7 +878,7 @@ main(int argc, char **argv)
|
||||
* the version check for 9.4 or later is done in check_upstream_config()
|
||||
*/
|
||||
|
||||
if (options.use_replication_slots && wal_keep_segments_used)
|
||||
if (options.use_replication_slots && runtime_options.wal_keep_segments_used)
|
||||
{
|
||||
log_warning(_("-w/--wal-keep-segments has no effect when replication slots in use\n"));
|
||||
}
|
||||
@@ -904,6 +898,7 @@ main(int argc, char **argv)
|
||||
}
|
||||
|
||||
/* Initialise the repmgr schema name */
|
||||
|
||||
if (strlen(repmgr_cluster))
|
||||
/* --cluster parameter provided */
|
||||
maxlen_snprintf(repmgr_schema, "%s%s", DEFAULT_REPMGR_SCHEMA_PREFIX,
|
||||
@@ -912,6 +907,16 @@ main(int argc, char **argv)
|
||||
maxlen_snprintf(repmgr_schema, "%s%s", DEFAULT_REPMGR_SCHEMA_PREFIX,
|
||||
options.cluster_name);
|
||||
|
||||
/*
|
||||
* If no value for the repmgr_schema provided, continue only under duress.
|
||||
*/
|
||||
if (strcmp(repmgr_schema, DEFAULT_REPMGR_SCHEMA_PREFIX) == 0 && !runtime_options.force)
|
||||
{
|
||||
log_err(_("unable to determine cluster name - please provide a valid configuration file with -c/--config-file\n"));
|
||||
log_hint(_("Use -F/--force to continue anyway\n"));
|
||||
exit(ERR_BAD_CONFIG);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialise slot name, if required (9.4 and later)
|
||||
*
|
||||
@@ -1646,7 +1651,7 @@ do_cluster_crosscheck(void)
|
||||
|
||||
printf("%*s | Id ", name_length, node_header);
|
||||
for (i = 0; i < n; i++)
|
||||
printf("| %2d ", i+1);
|
||||
printf("| %2d ", cube[i]->node_id);
|
||||
printf("\n");
|
||||
|
||||
for (i = 0; i < name_length; i++)
|
||||
@@ -2512,7 +2517,7 @@ do_standby_clone(void)
|
||||
r = test_ssh_connection(runtime_options.host, runtime_options.remote_user);
|
||||
if (r != 0)
|
||||
{
|
||||
log_err(_("aborting, remote host %s is not reachable.\n"),
|
||||
log_err(_("aborting, remote host %s is not reachable via SSH.\n"),
|
||||
runtime_options.host);
|
||||
exit(ERR_BAD_SSH);
|
||||
}
|
||||
@@ -2522,9 +2527,14 @@ 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)
|
||||
* 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.dest_dir[0])
|
||||
{
|
||||
target_directory_provided = true;
|
||||
@@ -2547,26 +2557,7 @@ do_standby_clone(void)
|
||||
{
|
||||
strncpy(local_data_directory, runtime_options.dest_dir, MAXPGPATH);
|
||||
}
|
||||
/*
|
||||
* Otherwise use the same data directory as on the remote host
|
||||
*/
|
||||
else
|
||||
{
|
||||
strncpy(local_data_directory, master_data_directory, MAXPGPATH);
|
||||
|
||||
log_notice(_("setting data directory to: %s\n"), local_data_directory);
|
||||
log_hint(_("use -D/--data-dir to explicitly specify a data directory\n"));
|
||||
}
|
||||
|
||||
/* Check the local data directory can be used */
|
||||
|
||||
if (!create_pg_dir(local_data_directory, runtime_options.force))
|
||||
{
|
||||
log_err(_("unable to use directory %s ...\n"),
|
||||
local_data_directory);
|
||||
log_hint(_("use -F/--force option to force this directory to be overwritten\n"));
|
||||
exit(ERR_BAD_CONFIG);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialise list of conninfo parameters which will later be used
|
||||
@@ -2639,7 +2630,7 @@ do_standby_clone(void)
|
||||
|
||||
if (!create_pg_dir(local_repmgr_directory, runtime_options.force))
|
||||
{
|
||||
log_err(_("unable to use directory %s ...\n"),
|
||||
log_err(_("unable to use directory \"%s\" ...\n"),
|
||||
local_repmgr_directory);
|
||||
log_hint(_("use -F/--force option to force this directory to be overwritten\n"));
|
||||
|
||||
@@ -2738,6 +2729,51 @@ do_standby_clone(void)
|
||||
primary_conn = source_conn;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Sanity-check that the master node has a repmgr schema - if not
|
||||
* present, fail with an error (unless -F/--force is used)
|
||||
*/
|
||||
|
||||
if (check_cluster_schema(primary_conn) == false)
|
||||
{
|
||||
if (!runtime_options.force)
|
||||
{
|
||||
/* schema doesn't exist */
|
||||
log_err(_("expected repmgr schema '%s' not found on master server\n"), get_repmgr_schema());
|
||||
log_hint(_("check that the master server was correctly registered\n"));
|
||||
PQfinish(source_conn);
|
||||
exit(ERR_BAD_CONFIG);
|
||||
}
|
||||
|
||||
log_warning(_("expected repmgr schema '%s' not found on master server\n"), get_repmgr_schema());
|
||||
}
|
||||
|
||||
|
||||
/* Fetch the source's data directory */
|
||||
if (get_pg_setting(source_conn, "data_directory", master_data_directory) == false)
|
||||
{
|
||||
log_err(_("Unable to retrieve upstream node's data directory\n"));
|
||||
log_hint(_("STANDBY CLONE must be run as a database superuser"));
|
||||
PQfinish(source_conn);
|
||||
exit(ERR_BAD_CONFIG);
|
||||
}
|
||||
|
||||
/*
|
||||
* If no target directory was explicitly provided, we'll default to
|
||||
* the same directory as on the source host.
|
||||
*/
|
||||
if (target_directory_provided == false)
|
||||
{
|
||||
strncpy(local_data_directory, master_data_directory, MAXPGPATH);
|
||||
|
||||
log_notice(_("setting data directory to: \"%s\"\n"), local_data_directory);
|
||||
log_hint(_("use -D/--data-dir to explicitly specify a data directory\n"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Copy the source connection so that we have some default values,
|
||||
* particularly stuff like passwords extracted from PGPASSFILE;
|
||||
@@ -2898,8 +2934,24 @@ do_standby_clone(void)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (mode != barman)
|
||||
{
|
||||
|
||||
/*
|
||||
* Check the destination data directory can be used
|
||||
* (in Barman mode, this directory will already have been created)
|
||||
*/
|
||||
|
||||
if (!create_pg_dir(local_data_directory, runtime_options.force))
|
||||
{
|
||||
log_err(_("unable to use directory %s ...\n"),
|
||||
local_data_directory);
|
||||
log_hint(_("use -F/--force option to force this directory to be overwritten\n"));
|
||||
exit(ERR_BAD_CONFIG);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that tablespaces named in any `tablespace_mapping` configuration
|
||||
* file parameters exist.
|
||||
@@ -2949,14 +3001,6 @@ do_standby_clone(void)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (get_pg_setting(source_conn, "data_directory", master_data_directory) == false)
|
||||
{
|
||||
log_err(_("Unable to retrieve upstream node's data directory\n"));
|
||||
log_hint(_("STANDBY CLONE must be run as a database superuser"));
|
||||
exit(ERR_BAD_CONFIG);
|
||||
}
|
||||
|
||||
/*
|
||||
* Obtain configuration file locations
|
||||
* We'll check to see whether the configuration files are in the data
|
||||
@@ -3315,14 +3359,14 @@ do_standby_clone(void)
|
||||
/* Only from 9.5 */
|
||||
"pg_commit_ts",
|
||||
/* Only from 9.4 */
|
||||
"pg_dynshmem", "pg_logical", "pg_replslot",
|
||||
"pg_dynshmem", "pg_logical", "pg_logical/snapshots", "pg_logical/mappings", "pg_replslot",
|
||||
/* Already in 9.3 */
|
||||
"pg_serial", "pg_snapshots", "pg_stat", "pg_stat_tmp", "pg_tblspc",
|
||||
"pg_twophase", "pg_xlog", 0
|
||||
};
|
||||
const int vers[] = {
|
||||
90500,
|
||||
90400, 90400, 90400,
|
||||
90400, 90400, 90400, 90400, 90400,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0
|
||||
};
|
||||
@@ -3656,7 +3700,7 @@ do_standby_clone(void)
|
||||
file->filepath, dest_path, false, server_version_num);
|
||||
if (r != 0)
|
||||
{
|
||||
log_err(_("standby clone: unable to copying config file '%s'\n"),
|
||||
log_err(_("standby clone: unable to copy config file '%s'\n"),
|
||||
file->filename);
|
||||
}
|
||||
}
|
||||
@@ -3900,29 +3944,31 @@ stop_backup:
|
||||
exit(retval);
|
||||
}
|
||||
|
||||
static bool
|
||||
static void
|
||||
parse_lsn(XLogRecPtr *ptr, const char *str)
|
||||
{
|
||||
uint32 high, low;
|
||||
|
||||
if (sscanf(str, "%x/%x", &high, &low) != 2)
|
||||
return false;
|
||||
return;
|
||||
|
||||
*ptr = (((XLogRecPtr)high) << 32) + (XLogRecPtr)low;
|
||||
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
static XLogRecPtr
|
||||
parse_label_lsn(const char *label_key, const char *label_value)
|
||||
{
|
||||
XLogRecPtr ptr;
|
||||
XLogRecPtr ptr = InvalidXLogRecPtr;
|
||||
|
||||
if (!parse_lsn(&ptr, label_value))
|
||||
parse_lsn(&ptr, label_value);
|
||||
|
||||
/* parse_lsn() will not modify ptr if it can't parse the label value */
|
||||
if (ptr == InvalidXLogRecPtr)
|
||||
{
|
||||
log_err(_("Couldn't parse backup label entry \"%s: %s\" as lsn"),
|
||||
label_key, label_value);
|
||||
return InvalidXLogRecPtr;
|
||||
}
|
||||
|
||||
return ptr;
|
||||
@@ -4266,7 +4312,7 @@ do_standby_follow(void)
|
||||
* to determine primary, and carry out some other checks while we're
|
||||
* at it.
|
||||
*/
|
||||
if (host_param_provided == false)
|
||||
if (runtime_options.host_param_provided == false)
|
||||
{
|
||||
/* We need to connect to check configuration */
|
||||
log_info(_("connecting to standby database\n"));
|
||||
@@ -4560,7 +4606,7 @@ do_standby_switchover(void)
|
||||
* Add a friendly notice if --pg_rewind supplied for 9.5 and later - we'll
|
||||
* be ignoring it anyway
|
||||
*/
|
||||
if (pg_rewind_supplied == true && server_version_num >= 90500)
|
||||
if (runtime_options.pg_rewind_supplied == true && server_version_num >= 90500)
|
||||
{
|
||||
log_notice(_("--pg_rewind not required for PostgreSQL 9.5 and later\n"));
|
||||
}
|
||||
@@ -4610,7 +4656,7 @@ do_standby_switchover(void)
|
||||
|
||||
if (r != 0)
|
||||
{
|
||||
log_err(_("unable to connect via ssh to host %s, user %s\n"), remote_host, runtime_options.remote_user);
|
||||
log_err(_("unable to connect via SSH to host %s, user %s\n"), remote_host, runtime_options.remote_user);
|
||||
}
|
||||
|
||||
if (get_pg_setting(remote_conn, "data_directory", remote_data_directory) == false)
|
||||
@@ -4675,7 +4721,7 @@ do_standby_switchover(void)
|
||||
else
|
||||
{
|
||||
/* 9.3/9.4 - user can use separately-compiled pg_rewind */
|
||||
if (pg_rewind_supplied == true)
|
||||
if (runtime_options.pg_rewind_supplied == true)
|
||||
{
|
||||
use_pg_rewind = true;
|
||||
|
||||
@@ -4824,7 +4870,7 @@ do_standby_switchover(void)
|
||||
else
|
||||
{
|
||||
int i;
|
||||
bool config_file_found = false;
|
||||
bool remote_config_file_found = false;
|
||||
|
||||
const char *config_paths[] = {
|
||||
runtime_options.config_file,
|
||||
@@ -4834,7 +4880,7 @@ do_standby_switchover(void)
|
||||
|
||||
log_verbose(LOG_INFO, _("no remote configuration file provided - checking default locations\n"));
|
||||
|
||||
for (i = 0; config_paths[i] && config_file_found == false; ++i)
|
||||
for (i = 0; config_paths[i] && remote_config_file_found == false; ++i)
|
||||
{
|
||||
/*
|
||||
* Don't attempt to check for an empty filename - this might be the case
|
||||
@@ -4866,13 +4912,13 @@ do_standby_switchover(void)
|
||||
strncpy(runtime_options.remote_config_file, config_paths[i], MAXLEN);
|
||||
log_verbose(LOG_INFO, _("configuration file \"%s\" found on remote server\n"),
|
||||
runtime_options.remote_config_file);
|
||||
config_file_found = true;
|
||||
remote_config_file_found = true;
|
||||
}
|
||||
|
||||
termPQExpBuffer(&command_output);
|
||||
}
|
||||
|
||||
if (config_file_found == false)
|
||||
if (remote_config_file_found == false)
|
||||
{
|
||||
log_err(_("no remote configuration file supplied or found in a default location - terminating\n"));
|
||||
log_hint(_("specify the remote configuration file with -C/--remote-config-file\n"));
|
||||
@@ -6083,6 +6129,7 @@ do_witness_register(PGconn *masterconn)
|
||||
log_notice(_("configuration has been successfully copied to the witness\n"));
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
do_witness_unregister(void)
|
||||
{
|
||||
@@ -6254,7 +6301,10 @@ do_help(void)
|
||||
printf(_(" witness register - registers a witness server\n"));
|
||||
printf(_(" witness unregister - unregisters a witness server\n"));
|
||||
printf(_(" cluster show - displays information about cluster nodes\n"));
|
||||
printf(_(" cluster matrix - displays the cluster's connection matrix\n"));
|
||||
printf(_(" cluster matrix - displays the cluster's connection matrix\n" \
|
||||
" as seen from the current node\n"));
|
||||
printf(_(" cluster crosscheck - displays the cluster's connection matrix\n" \
|
||||
" as seen from all nodes\n"));
|
||||
printf(_(" cluster cleanup - prunes or truncates monitoring history\n" \
|
||||
" (monitoring history creation requires repmgrd\n" \
|
||||
" with --monitoring-history option)\n"));
|
||||
@@ -6569,7 +6619,7 @@ run_basebackup(const char *data_dir, int server_version)
|
||||
* consistency with other applications accepts a conninfo string
|
||||
* under -d/--dbname)
|
||||
*/
|
||||
if (conninfo_provided == true)
|
||||
if (runtime_options.conninfo_provided == true)
|
||||
{
|
||||
appendPQExpBuffer(¶ms, " -d '%s'", runtime_options.dbname);
|
||||
}
|
||||
@@ -6690,7 +6740,7 @@ check_parameters_for_action(const int action)
|
||||
* parameters are at least useless and could be confusing so
|
||||
* reject them
|
||||
*/
|
||||
if (connection_param_provided)
|
||||
if (runtime_options.connection_param_provided)
|
||||
{
|
||||
item_list_append(&cli_warnings, _("master connection parameters not required when executing MASTER REGISTER"));
|
||||
}
|
||||
@@ -6707,7 +6757,7 @@ check_parameters_for_action(const int action)
|
||||
* need connection parameters to the master because we can detect
|
||||
* the master in repl_nodes
|
||||
*/
|
||||
if (connection_param_provided)
|
||||
if (runtime_options.connection_param_provided)
|
||||
{
|
||||
item_list_append(&cli_warnings, _("master connection parameters not required when executing STANDBY REGISTER"));
|
||||
}
|
||||
@@ -6724,7 +6774,7 @@ check_parameters_for_action(const int action)
|
||||
* need connection parameters to the master because we can detect
|
||||
* the master in repl_nodes
|
||||
*/
|
||||
if (connection_param_provided)
|
||||
if (runtime_options.connection_param_provided)
|
||||
{
|
||||
item_list_append(&cli_warnings, _("master connection parameters not required when executing STANDBY UNREGISTER"));
|
||||
}
|
||||
@@ -6742,7 +6792,7 @@ check_parameters_for_action(const int action)
|
||||
* detect the master in repl_nodes if we can't find it then the
|
||||
* promote action will be cancelled
|
||||
*/
|
||||
if (connection_param_provided)
|
||||
if (runtime_options.connection_param_provided)
|
||||
{
|
||||
item_list_append(&cli_warnings, _("master connection parameters not required when executing STANDBY PROMOTE"));
|
||||
}
|
||||
@@ -6768,7 +6818,7 @@ check_parameters_for_action(const int action)
|
||||
item_list_append(&cli_errors, _("master hostname (-h/--host) required when executing STANDBY FOLLOW with -D/--data-dir option"));
|
||||
}
|
||||
|
||||
if (host_param_provided && !runtime_options.dest_dir[0])
|
||||
if (runtime_options.host_param_provided && !runtime_options.dest_dir[0])
|
||||
{
|
||||
item_list_append(&cli_errors, _("local data directory (-D/--data-dir) required when executing STANDBY FOLLOW with -h/--host option"));
|
||||
}
|
||||
@@ -6878,7 +6928,7 @@ check_parameters_for_action(const int action)
|
||||
item_list_append(&cli_warnings, _("-r/--rsync-only can only be used when executing STANDBY CLONE"));
|
||||
}
|
||||
|
||||
if (wal_keep_segments_used)
|
||||
if (runtime_options.wal_keep_segments_used)
|
||||
{
|
||||
item_list_append(&cli_warnings, _("-w/--wal-keep-segments can only be used when executing STANDBY CLONE"));
|
||||
}
|
||||
@@ -6901,7 +6951,7 @@ check_parameters_for_action(const int action)
|
||||
/* Warn about parameters which apply to STANDBY SWITCHOVER only */
|
||||
if (action != STANDBY_SWITCHOVER)
|
||||
{
|
||||
if (pg_rewind_supplied == true)
|
||||
if (runtime_options.pg_rewind_supplied == true)
|
||||
{
|
||||
item_list_append(&cli_warnings, _("--pg_rewind can only be used when executing STANDBY SWITCHOVER"));
|
||||
}
|
||||
@@ -7312,10 +7362,10 @@ check_master_standby_version_match(PGconn *conn, PGconn *master_conn)
|
||||
/*
|
||||
* check_upstream_config()
|
||||
*
|
||||
* Perform sanity check on upstream server configuration
|
||||
* Perform sanity check on upstream server configuration before starting cloning
|
||||
* process
|
||||
*
|
||||
* TODO:
|
||||
* - check replication connection is possble
|
||||
* - check user is qualified to perform base backup
|
||||
*/
|
||||
|
||||
@@ -7328,14 +7378,33 @@ check_upstream_config(PGconn *conn, int server_version_num, bool exit_on_error)
|
||||
t_basebackup_options backup_options = T_BASEBACKUP_OPTIONS_INITIALIZER;
|
||||
bool xlog_stream = true;
|
||||
|
||||
enum {
|
||||
barman,
|
||||
rsync,
|
||||
pg_basebackup
|
||||
} mode;
|
||||
|
||||
|
||||
/*
|
||||
* Detecting the intended cloning mode
|
||||
*/
|
||||
if (runtime_options.rsync_only)
|
||||
mode = rsync;
|
||||
else if (strcmp(options.barman_server, "") != 0 && ! runtime_options.without_barman)
|
||||
mode = barman;
|
||||
else
|
||||
mode = pg_basebackup;
|
||||
|
||||
/*
|
||||
* Parse `pg_basebackup_options`, if set, to detect whether --xlog-method
|
||||
* has been set to something other than `stream` (i.e. `fetch`), as
|
||||
* this will influence some checks
|
||||
*/
|
||||
|
||||
parse_pg_basebackup_options(options.pg_basebackup_options, &backup_options);
|
||||
if (strlen(backup_options.xlog_method) && strcmp(backup_options.xlog_method, "stream") != 0)
|
||||
xlog_stream = false;
|
||||
|
||||
/* Check that WAL level is set correctly */
|
||||
if (server_version_num < 90400)
|
||||
{
|
||||
@@ -7442,7 +7511,7 @@ check_upstream_config(PGconn *conn, int server_version_num, bool exit_on_error)
|
||||
* physical replication slots not available or not requested - check if
|
||||
* there are any circumstances where `wal_keep_segments` should be set
|
||||
*/
|
||||
else if (! runtime_options.without_barman && strcmp(options.barman_server, "") == 0)
|
||||
else if (mode != barman)
|
||||
{
|
||||
bool check_wal_keep_segments = false;
|
||||
char min_wal_keep_segments[MAXLEN] = "1";
|
||||
@@ -7450,7 +7519,7 @@ check_upstream_config(PGconn *conn, int server_version_num, bool exit_on_error)
|
||||
/*
|
||||
* -w/--wal-keep-segments was supplied - check against that value
|
||||
*/
|
||||
if (wal_keep_segments_used == true)
|
||||
if (runtime_options.wal_keep_segments_used == true)
|
||||
{
|
||||
check_wal_keep_segments = true;
|
||||
strncpy(min_wal_keep_segments, runtime_options.wal_keep_segments, MAXLEN);
|
||||
@@ -7573,7 +7642,12 @@ check_upstream_config(PGconn *conn, int server_version_num, bool exit_on_error)
|
||||
config_ok = false;
|
||||
}
|
||||
|
||||
if (!runtime_options.rsync_only)
|
||||
/*
|
||||
* If using pg_basebackup, ensure sufficient replication connections can be made.
|
||||
* There's no guarantee they'll still be available by the time pg_basebackup
|
||||
* is executed, but there's nothing we can do about that.
|
||||
*/
|
||||
if (mode == pg_basebackup)
|
||||
{
|
||||
|
||||
PGconn **connections;
|
||||
@@ -7595,11 +7669,6 @@ check_upstream_config(PGconn *conn, int server_version_num, bool exit_on_error)
|
||||
* work out how many replication connections are required (1 or 2)
|
||||
*/
|
||||
|
||||
/*
|
||||
* --xlog-method set by user to something other than "stream" (should be "fetch",
|
||||
* but we're just checking it's not "stream")
|
||||
*/
|
||||
|
||||
if (xlog_stream == true)
|
||||
min_replication_connections += 1;
|
||||
|
||||
|
||||
100
repmgr.h
100
repmgr.h
@@ -64,9 +64,10 @@
|
||||
#define OPT_CLUSTER 13
|
||||
|
||||
/* deprecated command line options */
|
||||
#define OPT_INITDB_NO_PWPROMPT 999
|
||||
#define OPT_IGNORE_EXTERNAL_CONFIG_FILES 998
|
||||
#define OPT_INITDB_NO_PWPROMPT 998
|
||||
#define OPT_IGNORE_EXTERNAL_CONFIG_FILES 999
|
||||
|
||||
/* values for --copy-external-config-files */
|
||||
#define CONFIG_FILE_SAMEPATH 1
|
||||
#define CONFIG_FILE_PGDATA 2
|
||||
|
||||
@@ -74,53 +75,94 @@
|
||||
/* Run time options type */
|
||||
typedef struct
|
||||
{
|
||||
/* general repmgr options */
|
||||
char config_file[MAXPGPATH];
|
||||
bool verbose;
|
||||
bool terse;
|
||||
bool force;
|
||||
|
||||
/* options which override setting in repmgr.conf */
|
||||
char loglevel[MAXLEN];
|
||||
char pg_bindir[MAXLEN];
|
||||
|
||||
/* connection parameters */
|
||||
char dbname[MAXLEN];
|
||||
char host[MAXLEN];
|
||||
char username[MAXLEN];
|
||||
char dest_dir[MAXPGPATH];
|
||||
char config_file[MAXPGPATH];
|
||||
char remote_user[MAXLEN];
|
||||
char superuser[MAXLEN];
|
||||
char masterport[MAXLEN];
|
||||
bool conninfo_provided;
|
||||
bool connection_param_provided;
|
||||
bool host_param_provided;
|
||||
|
||||
/* standby clone parameters */
|
||||
bool wal_keep_segments_used;
|
||||
char wal_keep_segments[MAXLEN];
|
||||
bool verbose;
|
||||
bool terse;
|
||||
bool force;
|
||||
bool wait_for_master;
|
||||
bool ignore_rsync_warn;
|
||||
bool witness_pwprompt;
|
||||
bool rsync_only;
|
||||
bool fast_checkpoint;
|
||||
bool csv_mode;
|
||||
bool without_barman;
|
||||
bool no_upstream_connection;
|
||||
bool copy_external_config_files;
|
||||
int copy_external_config_files_destination;
|
||||
bool wait_register_sync;
|
||||
int wait_register_sync_seconds;
|
||||
char masterport[MAXLEN];
|
||||
/*
|
||||
* configuration file parameters which can be overridden on the
|
||||
* command line
|
||||
*/
|
||||
char loglevel[MAXLEN];
|
||||
|
||||
/* parameter used by STANDBY SWITCHOVER */
|
||||
char remote_config_file[MAXLEN];
|
||||
char pg_rewind[MAXPGPATH];
|
||||
char pg_ctl_mode[MAXLEN];
|
||||
/* parameter used by STANDBY {ARCHIVE_CONFIG | RESTORE_CONFIG} */
|
||||
char config_archive_dir[MAXLEN];
|
||||
/* parameter used by CLUSTER CLEANUP */
|
||||
int keep_history;
|
||||
/* parameter used by {STANDBY|WITNESS} UNREGISTER */
|
||||
int node;
|
||||
|
||||
char pg_bindir[MAXLEN];
|
||||
|
||||
char recovery_min_apply_delay[MAXLEN];
|
||||
|
||||
/* witness create parameters */
|
||||
bool witness_pwprompt;
|
||||
|
||||
/* standby follow parameters */
|
||||
bool wait_for_master;
|
||||
|
||||
/* cluster {show|matrix|crosscheck} parameters */
|
||||
bool csv_mode;
|
||||
|
||||
/* cluster cleanup parameters */
|
||||
int keep_history;
|
||||
|
||||
/* standby switchover parameters */
|
||||
char remote_config_file[MAXLEN];
|
||||
bool pg_rewind_supplied;
|
||||
char pg_rewind[MAXPGPATH];
|
||||
char pg_ctl_mode[MAXLEN];
|
||||
|
||||
/* standby {archive_config | restore_config} parameters */
|
||||
char config_archive_dir[MAXLEN];
|
||||
|
||||
/* {standby|witness} unregister parameters */
|
||||
int node;
|
||||
|
||||
} t_runtime_options;
|
||||
|
||||
#define T_RUNTIME_OPTIONS_INITIALIZER { "", "", "", "", "", "", "", DEFAULT_WAL_KEEP_SEGMENTS, false, false, false, false, false, false, false, false, false, false, false, false, CONFIG_FILE_SAMEPATH, false, 0, "", "", "", "", "fast", "", 0, UNKNOWN_NODE_ID, "", ""}
|
||||
#define T_RUNTIME_OPTIONS_INITIALIZER { \
|
||||
/* general repmgr options */ \
|
||||
"", false, false, false, \
|
||||
/* options which override setting in repmgr.conf */ \
|
||||
"", "", \
|
||||
/* connection parameters */ \
|
||||
"", "", "", "", "", "", "", \
|
||||
false, false, false, \
|
||||
/* standby clone parameters */ \
|
||||
false, DEFAULT_WAL_KEEP_SEGMENTS, false, false, false, false, false, false, \
|
||||
CONFIG_FILE_SAMEPATH, false, 0, "", \
|
||||
/* witness create parameters */ \
|
||||
false, \
|
||||
/* standby follow parameters */ \
|
||||
false, \
|
||||
/* cluster {show|matrix|crosscheck} parameters */ \
|
||||
false, \
|
||||
/* cluster cleanup parameters */ \
|
||||
0, \
|
||||
/* standby switchover parameters */ \
|
||||
"", false, "", "fast", \
|
||||
/* standby {archive_config | restore_config} parameters */ \
|
||||
"", \
|
||||
/* {standby|witness} unregister parameters */ \
|
||||
UNKNOWN_NODE_ID }
|
||||
|
||||
struct BackupLabel
|
||||
{
|
||||
|
||||
@@ -647,7 +647,7 @@ witness_monitor(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
log_debug(_("new master found with node ID: %i\n"), master_options.node);
|
||||
log_info(_("new master found with node ID: %i\n"), master_options.node);
|
||||
connection_ok = true;
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user