mirror of
https://github.com/EnterpriseDB/repmgr.git
synced 2026-03-22 22:56:29 +00:00
Compare commits
300 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cb1bf892e6 | ||
|
|
b1b5fe1193 | ||
|
|
af0e141859 | ||
|
|
580c1a9170 | ||
|
|
b624fc7efa | ||
|
|
67ccd4dcb3 | ||
|
|
6de3a5a997 | ||
|
|
f86e89ba45 | ||
|
|
a6d0ba07ed | ||
|
|
b553a70ad5 | ||
|
|
3364f8bdf0 | ||
|
|
242fa287b4 | ||
|
|
fa908432c8 | ||
|
|
afa942fef6 | ||
|
|
94cfc66b04 | ||
|
|
87eae9a50f | ||
|
|
82a37f4865 | ||
|
|
a38f727b7d | ||
|
|
e6df936c1b | ||
|
|
91ca997d40 | ||
|
|
65c90a2a64 | ||
|
|
90cba78f52 | ||
|
|
f8908d7e31 | ||
|
|
478bbcccbf | ||
|
|
a03d41de28 | ||
|
|
f1e527adcb | ||
|
|
09e597dcdd | ||
|
|
94a7f0c719 | ||
|
|
6ac42f1593 | ||
|
|
94b72382e5 | ||
|
|
18c12f58a4 | ||
|
|
cf3fa18085 | ||
|
|
a5281d93dc | ||
|
|
0d73d3c2b5 | ||
|
|
23c99304a6 | ||
|
|
1ab16bc6c2 | ||
|
|
7f1f04636d | ||
|
|
6a1797cadd | ||
|
|
94d26dbe9f | ||
|
|
ae655eb4fd | ||
|
|
65371489c6 | ||
|
|
28c7737dc0 | ||
|
|
505d72d19c | ||
|
|
b292ac61f8 | ||
|
|
293d66bf71 | ||
|
|
3e1f0ec168 | ||
|
|
6f9a1f975e | ||
|
|
deea4f69f7 | ||
|
|
37e53108a2 | ||
|
|
96cf06204c | ||
|
|
381e22c2c7 | ||
|
|
7e2af17783 | ||
|
|
b4272853e7 | ||
|
|
562b6ddfc2 | ||
|
|
a15e5c9d52 | ||
|
|
d9cc09cee4 | ||
|
|
c4f6abe951 | ||
|
|
e454fb77d3 | ||
|
|
b76e5852d3 | ||
|
|
0674364ffd | ||
|
|
b2eb9b8525 | ||
|
|
71c5d10a8c | ||
|
|
1476b21cd4 | ||
|
|
b17993abdb | ||
|
|
8f68344f9a | ||
|
|
125ac6c297 | ||
|
|
955860923f | ||
|
|
50626f90cc | ||
|
|
9aea5b8aa7 | ||
|
|
ed1bcb159e | ||
|
|
9c72c0d66e | ||
|
|
0ddc226c2a | ||
|
|
93830cad61 | ||
|
|
bca1660d5e | ||
|
|
5a52917421 | ||
|
|
70752d7d4a | ||
|
|
c29d1efc37 | ||
|
|
6fbbe2a97a | ||
|
|
ce42d6827e | ||
|
|
98384559a6 | ||
|
|
4a1477343b | ||
|
|
d2b9d20393 | ||
|
|
fe594c95ad | ||
|
|
60e63feaca | ||
|
|
ae4d0f2622 | ||
|
|
5e8b41e221 | ||
|
|
c7a585c555 | ||
|
|
a27dd8c49c | ||
|
|
9365bf3474 | ||
|
|
e8ae0831fe | ||
|
|
518866eba5 | ||
|
|
ed0330c334 | ||
|
|
1f021dc9fa | ||
|
|
425839d764 | ||
|
|
3a764f678a | ||
|
|
829cf5cca4 | ||
|
|
14420d83fa | ||
|
|
a80e22f0ed | ||
|
|
832993bfbc | ||
|
|
f1ea5e62df | ||
|
|
b47448d0e5 | ||
|
|
a8232337d8 | ||
|
|
c9eb1bfcc0 | ||
|
|
db552dfbc7 | ||
|
|
9732f78565 | ||
|
|
eb7dca2919 | ||
|
|
c113102926 | ||
|
|
ed6a167915 | ||
|
|
fbbe7afd61 | ||
|
|
ae1fc93e48 | ||
|
|
7b4ee80af2 | ||
|
|
0b8755e278 | ||
|
|
d3e1937808 | ||
|
|
871d6fdee3 | ||
|
|
c7dfe9e040 | ||
|
|
5c92a9e057 | ||
|
|
aa5f025738 | ||
|
|
5b91a2d409 | ||
|
|
596a19ee37 | ||
|
|
23ff83b3b4 | ||
|
|
ba1f6bee0d | ||
|
|
da9c8f2491 | ||
|
|
64035ef701 | ||
|
|
da3a5ab1dc | ||
|
|
9d301b4789 | ||
|
|
c070c649f7 | ||
|
|
3b823396eb | ||
|
|
c19e7f1025 | ||
|
|
e4b5a1e19f | ||
|
|
f96cc3b906 | ||
|
|
a481ca7ce2 | ||
|
|
32dc450a09 | ||
|
|
34dbf64f50 | ||
|
|
ea653a8dbc | ||
|
|
50894b6124 | ||
|
|
94e187c476 | ||
|
|
de6284ae79 | ||
|
|
c54045bcd8 | ||
|
|
c0a53471e1 | ||
|
|
2eec8b5d79 | ||
|
|
c11e92cf2a | ||
|
|
f294d09034 | ||
|
|
26c597ef5a | ||
|
|
b8efbb7a15 | ||
|
|
3044696c05 | ||
|
|
6dc1969ad5 | ||
|
|
cb41ef1733 | ||
|
|
d10f1f289e | ||
|
|
5731ba6043 | ||
|
|
3d6437c8f8 | ||
|
|
54b5c8ad94 | ||
|
|
0eca08ffaf | ||
|
|
05c1dc2b92 | ||
|
|
2bd300073d | ||
|
|
01e020df8e | ||
|
|
ae7963dc64 | ||
|
|
faffb2a6e7 | ||
|
|
5d57044118 | ||
|
|
07a88c78a5 | ||
|
|
f7df8b9c80 | ||
|
|
20920b3da1 | ||
|
|
683f4de182 | ||
|
|
0c62821ffb | ||
|
|
6b70e8bbe6 | ||
|
|
6b223698c9 | ||
|
|
aee12dc2c7 | ||
|
|
c5c86e1ada | ||
|
|
7476dc84f2 | ||
|
|
f6d63f5216 | ||
|
|
a608b0bc18 | ||
|
|
469ebba656 | ||
|
|
647c21ad0e | ||
|
|
3d2530d6f9 | ||
|
|
b26e400199 | ||
|
|
152e9545a4 | ||
|
|
83b8f05221 | ||
|
|
486f8e5a2c | ||
|
|
e517cc74d1 | ||
|
|
26285b470f | ||
|
|
1521657965 | ||
|
|
041604e303 | ||
|
|
0be0100a7c | ||
|
|
2133834dda | ||
|
|
d5fd93c350 | ||
|
|
5804778b58 | ||
|
|
407a7ea2f4 | ||
|
|
4d2eca0978 | ||
|
|
9d25544ab5 | ||
|
|
8506607388 | ||
|
|
e8e059c26d | ||
|
|
38d293694d | ||
|
|
54a10a0c3f | ||
|
|
a8016f602f | ||
|
|
de57ecdad1 | ||
|
|
1fde81cf3f | ||
|
|
146c412061 | ||
|
|
e9cb61ae7a | ||
|
|
50e9460b3e | ||
|
|
47e7cbe147 | ||
|
|
bf0be3eb43 | ||
|
|
270da1294c | ||
|
|
d3c47f450f | ||
|
|
c20475f94a | ||
|
|
e0560c3e70 | ||
|
|
3fa2bef6f4 | ||
|
|
f8a0b051c8 | ||
|
|
3e4a5e6ff5 | ||
|
|
020b5b6982 | ||
|
|
932326e4a0 | ||
|
|
019cd081e8 | ||
|
|
3ace908126 | ||
|
|
2ad174489c | ||
|
|
9124e0f0a2 | ||
|
|
060b746743 | ||
|
|
bdb82d3aba | ||
|
|
f6a6df3600 | ||
|
|
67e27f9ecd | ||
|
|
454c0b7bd9 | ||
|
|
faf297b07f | ||
|
|
0dae8c9f0b | ||
|
|
3f872cde0c | ||
|
|
e331069f53 | ||
|
|
53ebde8f33 | ||
|
|
5e9d50f8ca | ||
|
|
347e753c27 | ||
|
|
2f978847b1 | ||
|
|
3014f72fda | ||
|
|
e02ddd0f37 | ||
|
|
29fcee2209 | ||
|
|
f61f7f82eb | ||
|
|
efe28cbbeb | ||
|
|
6131c1d8ce | ||
|
|
c907b7b33d | ||
|
|
e6644305d3 | ||
|
|
31b856dd9f | ||
|
|
dff2bcc5de | ||
|
|
688e609169 | ||
|
|
3e68c9fcc6 | ||
|
|
d459b92186 | ||
|
|
2a898721c0 | ||
|
|
35782d83c0 | ||
|
|
e16eb42693 | ||
|
|
4d6dc57589 | ||
|
|
cbc97d84ac | ||
|
|
96fe7dd2d6 | ||
|
|
13935a88c9 | ||
|
|
5275890467 | ||
|
|
7f865fdaf3 | ||
|
|
9e2fb7ea13 | ||
|
|
a3428e4d8a | ||
|
|
03b9475755 | ||
|
|
de1eb3c459 | ||
|
|
a13eccccc5 | ||
|
|
158f132bc0 | ||
|
|
cdf54d217a | ||
|
|
1a8a82f207 | ||
|
|
60e877ca39 | ||
|
|
91531bffe4 | ||
|
|
fc5f46ca5a | ||
|
|
b76952e136 | ||
|
|
c3a1969f55 | ||
|
|
11d856a1ec | ||
|
|
fbf357947d | ||
|
|
47eaa99537 | ||
|
|
aeee11d1b7 | ||
|
|
e4713c5eca | ||
|
|
e55e5a0581 | ||
|
|
fb0aae183d | ||
|
|
52655e9cd5 | ||
|
|
c5d91ca88c | ||
|
|
9f5edd07ad | ||
|
|
f58b102d51 | ||
|
|
90733aecf7 | ||
|
|
e0be228c89 | ||
|
|
a9759cf6ca | ||
|
|
6852ac82c6 | ||
|
|
c27bd2a135 | ||
|
|
5045e2eb9d | ||
|
|
23f7af17a2 | ||
|
|
93936c090d | ||
|
|
564c951f0c | ||
|
|
3f5e8f6aec | ||
|
|
a6a97cda86 | ||
|
|
18c8e4c529 | ||
|
|
6984fe7029 | ||
|
|
5ecc3a0a8f | ||
|
|
febde097be | ||
|
|
19ea248226 | ||
|
|
acdbd1110a | ||
|
|
946683182c | ||
|
|
c9fbb7febf | ||
|
|
ff966fe533 | ||
|
|
7001960cc1 | ||
|
|
1cfba44799 | ||
|
|
d1f9ca4b43 | ||
|
|
f6c253f8a6 | ||
|
|
95ec8d8b21 | ||
|
|
041f1b7667 | ||
|
|
104279016a | ||
|
|
901a7603b1 |
63
HISTORY
63
HISTORY
@@ -1,66 +1,3 @@
|
||||
4.1.1 2018-09-05
|
||||
logging: explicitly log the text of failed queries as ERRORs to
|
||||
assist logfile analysis; GitHub #498
|
||||
repmgr: truncate version string, if necessary; GitHub #490 (Ian)
|
||||
repmgr: improve messages emitted during "standby promote" (Ian)
|
||||
repmgr: "standby clone" - don't copy external config files in --dry-run
|
||||
mode; GitHub #491 (Ian)
|
||||
repmgr: add "cluster_cleanup" event; GitHub #492 (Ian)
|
||||
repmgr: (standby switchover) improve detection of free walsenders;
|
||||
GitHub #495 (Ian)
|
||||
repmgr: (node rejoin) improve replication slot handling; GitHub #499 (Ian)
|
||||
repmgrd: ensure that sending SIGHUP always results in the log file
|
||||
being reopened; GitHub #485 (Ian)
|
||||
repmgrd: report version number *after* logger initialisation; GitHub #487 (Ian)
|
||||
repmgrd: fix startup on witness node when local data is stale; GitHub #488/#489 (Ian)
|
||||
repmgrd: improve cascaded standby failover handling; GitHub #480 (Ian)
|
||||
repmgrd: improve reconnection handling (Ian)
|
||||
|
||||
4.1.0 2018-07-31
|
||||
repmgr: change default log_level to INFO, add documentation; GitHub #470 (Ian)
|
||||
repmgr: add "--missing-slots" check to "repmgr node check" (Ian)
|
||||
repmgr: improve command line error handling; GitHub #464 (Ian)
|
||||
repmgr: fix "standby register --wait-sync" when no timeout provided (Ian)
|
||||
repmgr: "cluster show" returns non-zero value if an issue encountered;
|
||||
GitHub #456 (Ian)
|
||||
repmgr: "node check" and "node status" returns non-zero value if an issue
|
||||
encountered (Ian)
|
||||
repmgr: add CSV output mode to "cluster event"; GitHub #471 (Ian)
|
||||
repmgr: add -q/--quiet option to suppress non-error output; GitHub #468 (Ian)
|
||||
repmgr: "node status" returns non-zero value if an issue encountered (Ian)
|
||||
repmgr: enable "recovery_min_apply_delay" to be 0; GitHub #448 (Ian)
|
||||
repmgr: "cluster cleanup" - add missing help options; GitHub #461/#462 (gclough)
|
||||
repmgr: ensure witness node follows new primary after switchover;
|
||||
GitHub #453 (Ian)
|
||||
repmgr: fix witness node handling in "node check"/"node status";
|
||||
GitHub #451 (Ian)
|
||||
repmgr: fix "primary_slot_name" when using "standby clone" with --recovery-conf-only;
|
||||
GitHub #474 (Ian)
|
||||
repmgr: don't perform a switchover if an exclusive backup is running;
|
||||
GitHub #476 (Martín)
|
||||
repmgr: enable "witness unregister" to be run on any node; GitHub #472 (Ian)
|
||||
repmgrd: create a PID file by default; GitHub #457 (Ian)
|
||||
repmgrd: daemonize process by default; GitHub #458 (Ian)
|
||||
|
||||
4.0.6 2018-06-14
|
||||
repmgr: (witness register) prevent registration of a witness server with the
|
||||
same name as an existing node (Ian)
|
||||
repmgr: (standby follow) check node has actually connected to new primary
|
||||
before reporting success; GitHub #444 (Ian)
|
||||
repmgr: (standby clone) improve handling of external configuration file copying,
|
||||
including consideration in --dry-run check; GitHub #443 (Ian)
|
||||
repmgr: (standby clone) don't require presence of "user" parameter in
|
||||
conninfo string; GitHub #437 (Ian)
|
||||
repmgr: (standby clone) improve documentation of --recovery-conf-only
|
||||
mode; GitHub #438 (Ian)
|
||||
repmgr: (node rejoin) fix bug when parsing --config-files parameter;
|
||||
GitHub #442 (Ian)
|
||||
repmgr: when using --dry-run, force log level to INFO to ensure output
|
||||
will always be displayed; GitHub #441 (Ian)
|
||||
repmgr: (cluster matrix/crosscheck) return non-zero exit code if node
|
||||
connection issues detected; GitHub #447 (Ian)
|
||||
repmgrd: ensure local node is counted as quorum member; GitHub #439 (Ian)
|
||||
|
||||
4.0.5 2018-05-02
|
||||
repmgr: poll demoted primary after restart as a standby during a
|
||||
switchover operation; GitHub #408 (Ian)
|
||||
|
||||
@@ -11,10 +11,7 @@ EXTENSION = repmgr
|
||||
|
||||
DATA = \
|
||||
repmgr--unpackaged--4.0.sql \
|
||||
repmgr--4.0.sql \
|
||||
repmgr--4.0--4.1.sql \
|
||||
repmgr--4.1.sql
|
||||
|
||||
repmgr--4.0.sql
|
||||
|
||||
REGRESS = repmgr_extension
|
||||
|
||||
|
||||
137
configfile.c
137
configfile.c
@@ -28,8 +28,10 @@ char config_file_path[MAXPGPATH] = "";
|
||||
static bool config_file_provided = false;
|
||||
bool config_file_found = false;
|
||||
|
||||
static void parse_config(t_configuration_options *options, bool terse);
|
||||
static void _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *warning_list);
|
||||
static bool parse_bool(const char *s,
|
||||
const char *config_item,
|
||||
ItemList *error_list);
|
||||
|
||||
static void _parse_line(char *buf, char *name, char *value);
|
||||
static void parse_event_notifications_list(t_configuration_options *options, const char *arg);
|
||||
@@ -239,7 +241,7 @@ end_search:
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
void
|
||||
parse_config(t_configuration_options *options, bool terse)
|
||||
{
|
||||
/* Collate configuration file errors here for friendlier reporting */
|
||||
@@ -317,26 +319,13 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *
|
||||
options->use_primary_conninfo_password = false;
|
||||
memset(options->passfile, 0, sizeof(options->passfile));
|
||||
|
||||
/*-------------------------
|
||||
/*-----------------------
|
||||
* standby promote settings
|
||||
*-------------------------
|
||||
*------------------------
|
||||
*/
|
||||
options->promote_check_timeout = DEFAULT_PROMOTE_CHECK_TIMEOUT;
|
||||
options->promote_check_interval = DEFAULT_PROMOTE_CHECK_INTERVAL;
|
||||
|
||||
/*------------------------
|
||||
* standby follow settings
|
||||
*------------------------
|
||||
*/
|
||||
options->primary_follow_timeout = DEFAULT_PRIMARY_FOLLOW_TIMEOUT;
|
||||
options->standby_follow_timeout = DEFAULT_STANDBY_FOLLOW_TIMEOUT;
|
||||
|
||||
/*------------------------
|
||||
* standby switchover settings
|
||||
*------------------------
|
||||
*/
|
||||
options->standby_reconnect_timeout = DEFAULT_STANDBY_RECONNECT_TIMEOUT;
|
||||
|
||||
/*-----------------
|
||||
* repmgrd settings
|
||||
*-----------------
|
||||
@@ -356,8 +345,8 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *
|
||||
options->degraded_monitoring_timeout = -1;
|
||||
options->async_query_timeout = DEFAULT_ASYNC_QUERY_TIMEOUT;
|
||||
options->primary_notification_timeout = DEFAULT_PRIMARY_NOTIFICATION_TIMEOUT;
|
||||
options->repmgrd_standby_startup_timeout = -1; /* defaults to "standby_reconnect_timeout" if not set */
|
||||
memset(options->repmgrd_pid_file, 0, sizeof(options->repmgrd_pid_file));
|
||||
options->primary_follow_timeout = DEFAULT_PRIMARY_FOLLOW_TIMEOUT;
|
||||
options->standby_reconnect_timeout = DEFAULT_STANDBY_RECONNECT_TIMEOUT;
|
||||
|
||||
/*-------------
|
||||
* witness settings
|
||||
@@ -538,20 +527,6 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *
|
||||
else if (strcmp(name, "promote_check_interval") == 0)
|
||||
options->promote_check_interval = repmgr_atoi(value, name, error_list, 1);
|
||||
|
||||
/* standby follow settings */
|
||||
else if (strcmp(name, "primary_follow_timeout") == 0)
|
||||
options->primary_follow_timeout = repmgr_atoi(value, name, error_list, 0);
|
||||
else if (strcmp(name, "standby_follow_timeout") == 0)
|
||||
options->standby_follow_timeout = repmgr_atoi(value, name, error_list, 0);
|
||||
|
||||
/* standby switchover settings */
|
||||
else if (strcmp(name, "standby_reconnect_timeout") == 0)
|
||||
options->standby_reconnect_timeout = repmgr_atoi(value, name, error_list, 0);
|
||||
|
||||
/* node rejoin settings */
|
||||
else if (strcmp(name, "node_rejoin_timeout") == 0)
|
||||
options->node_rejoin_timeout = repmgr_atoi(value, name, error_list, 0);
|
||||
|
||||
/* node check settings */
|
||||
else if (strcmp(name, "archive_ready_warning") == 0)
|
||||
options->archive_ready_warning = repmgr_atoi(value, name, error_list, 1);
|
||||
@@ -601,10 +576,10 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *
|
||||
options->async_query_timeout = repmgr_atoi(value, name, error_list, 0);
|
||||
else if (strcmp(name, "primary_notification_timeout") == 0)
|
||||
options->primary_notification_timeout = repmgr_atoi(value, name, error_list, 0);
|
||||
else if (strcmp(name, "repmgrd_standby_startup_timeout") == 0)
|
||||
options->repmgrd_standby_startup_timeout = repmgr_atoi(value, name, error_list, 0);
|
||||
else if (strcmp(name, "repmgrd_pid_file") == 0)
|
||||
strncpy(options->repmgrd_pid_file, value, MAXPGPATH);
|
||||
else if (strcmp(name, "primary_follow_timeout") == 0)
|
||||
options->primary_follow_timeout = repmgr_atoi(value, name, error_list, 0);
|
||||
else if (strcmp(name, "standby_reconnect_timeout") == 0)
|
||||
options->standby_reconnect_timeout = repmgr_atoi(value, name, error_list, 0);
|
||||
|
||||
/* witness settings */
|
||||
else if (strcmp(name, "witness_sync_interval") == 0)
|
||||
@@ -786,17 +761,6 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *
|
||||
PQconninfoFree(conninfo_options);
|
||||
}
|
||||
|
||||
/* set values for parameters which default to other parameters */
|
||||
|
||||
/*
|
||||
* From 4.1, "repmgrd_standby_startup_timeout" replaces "standby_reconnect_timeout"
|
||||
* in repmgrd; fall back to "standby_reconnect_timeout" if no value explicitly provided
|
||||
*/
|
||||
if (options->repmgrd_standby_startup_timeout == -1)
|
||||
{
|
||||
options->repmgrd_standby_startup_timeout = options->standby_reconnect_timeout;
|
||||
}
|
||||
|
||||
/* add warning about changed "barman_" parameter meanings */
|
||||
if ((options->barman_host[0] == '\0' && options->barman_server[0] != '\0') ||
|
||||
(options->barman_host[0] != '\0' && options->barman_server[0] == '\0'))
|
||||
@@ -821,12 +785,6 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *
|
||||
item_list_append(error_list,
|
||||
_("\replication_lag_critical\" must be greater than \"replication_lag_warning\""));
|
||||
}
|
||||
|
||||
if (options->standby_reconnect_timeout < options->node_rejoin_timeout)
|
||||
{
|
||||
item_list_append(error_list,
|
||||
_("\"standby_reconnect_timeout\" must be equal to or greater than \"node_rejoin_timeout\""));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -991,11 +949,12 @@ parse_time_unit_parameter(const char *name, const char *value, char *dest, ItemL
|
||||
char *ptr = NULL;
|
||||
int targ = strtol(value, &ptr, 10);
|
||||
|
||||
if (targ < 0)
|
||||
if (targ < 1)
|
||||
{
|
||||
if (errors != NULL)
|
||||
{
|
||||
item_list_append_format(errors,
|
||||
item_list_append_format(
|
||||
errors,
|
||||
_("invalid value provided for \"%s\""),
|
||||
name);
|
||||
}
|
||||
@@ -1049,7 +1008,6 @@ parse_time_unit_parameter(const char *name, const char *value, char *dest, ItemL
|
||||
* - promote_delay
|
||||
* - reconnect_attempts
|
||||
* - reconnect_interval
|
||||
* - repmgrd_standby_startup_timeout
|
||||
* - retry_promote_interval_secs
|
||||
*
|
||||
* non-changeable options
|
||||
@@ -1065,7 +1023,7 @@ parse_time_unit_parameter(const char *name, const char *value, char *dest, ItemL
|
||||
|
||||
*/
|
||||
bool
|
||||
reload_config(t_configuration_options *orig_options, t_server_type server_type)
|
||||
reload_config(t_configuration_options *orig_options)
|
||||
{
|
||||
PGconn *conn;
|
||||
t_configuration_options new_options = T_CONFIGURATION_OPTIONS_INITIALIZER;
|
||||
@@ -1075,50 +1033,17 @@ reload_config(t_configuration_options *orig_options, t_server_type server_type)
|
||||
static ItemList config_errors = {NULL, NULL};
|
||||
static ItemList config_warnings = {NULL, NULL};
|
||||
|
||||
PQExpBufferData errors;
|
||||
|
||||
log_info(_("reloading configuration file"));
|
||||
|
||||
_parse_config(&new_options, &config_errors, &config_warnings);
|
||||
|
||||
|
||||
if (server_type == PRIMARY || server_type == STANDBY)
|
||||
{
|
||||
if (new_options.promote_command[0] == '\0')
|
||||
{
|
||||
item_list_append(&config_errors, _("\"promote_command\": required parameter was not found"));
|
||||
}
|
||||
|
||||
if (new_options.follow_command[0] == '\0')
|
||||
{
|
||||
item_list_append(&config_errors, _("\"follow_command\": required parameter was not found"));
|
||||
}
|
||||
}
|
||||
|
||||
if (config_errors.head != NULL)
|
||||
{
|
||||
ItemListCell *cell = NULL;
|
||||
|
||||
/* XXX dump errors to log */
|
||||
log_warning(_("unable to parse new configuration, retaining current configuration"));
|
||||
|
||||
initPQExpBuffer(&errors);
|
||||
|
||||
appendPQExpBuffer(&errors,
|
||||
"following errors were detected:\n");
|
||||
|
||||
for (cell = config_errors.head; cell; cell = cell->next)
|
||||
{
|
||||
appendPQExpBuffer(&errors,
|
||||
" %s\n", cell->string);
|
||||
}
|
||||
|
||||
log_detail("%s", errors.data);
|
||||
termPQExpBuffer(&errors);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* The following options cannot be changed */
|
||||
|
||||
if (new_options.node_id != orig_options->node_id)
|
||||
@@ -1299,15 +1224,6 @@ reload_config(t_configuration_options *orig_options, t_server_type server_type)
|
||||
config_changed = true;
|
||||
}
|
||||
|
||||
/* repmgrd_standby_startup_timeout */
|
||||
if (orig_options->repmgrd_standby_startup_timeout != new_options.repmgrd_standby_startup_timeout)
|
||||
{
|
||||
orig_options->repmgrd_standby_startup_timeout = new_options.repmgrd_standby_startup_timeout;
|
||||
log_info(_("\"repmgrd_standby_startup_timeout\" is now \"%i\""), new_options.repmgrd_standby_startup_timeout);
|
||||
|
||||
config_changed = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle changes to logging configuration
|
||||
*/
|
||||
@@ -1400,23 +1316,13 @@ exit_with_config_file_errors(ItemList *config_errors, ItemList *config_warnings,
|
||||
|
||||
|
||||
void
|
||||
exit_with_cli_errors(ItemList *error_list, const char *repmgr_command)
|
||||
exit_with_cli_errors(ItemList *error_list)
|
||||
{
|
||||
fprintf(stderr, _("The following command line errors were encountered:\n"));
|
||||
|
||||
print_item_list(error_list);
|
||||
|
||||
if (repmgr_command != NULL)
|
||||
{
|
||||
fprintf(stderr, _("Try \"%s --help\" or \"%s %s --help\" for more information.\n"),
|
||||
progname(),
|
||||
progname(),
|
||||
repmgr_command);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname());
|
||||
}
|
||||
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname());
|
||||
|
||||
exit(ERR_BAD_CONFIG);
|
||||
}
|
||||
@@ -1521,7 +1427,7 @@ repmgr_atoi(const char *value, const char *config_item, ItemList *error_list, in
|
||||
*
|
||||
* https://www.postgresql.org/docs/current/static/config-setting.html
|
||||
*/
|
||||
bool
|
||||
static bool
|
||||
parse_bool(const char *s, const char *config_item, ItemList *error_list)
|
||||
{
|
||||
PQExpBufferData errors;
|
||||
@@ -1807,9 +1713,6 @@ free_parsed_argv(char ***argv_array)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool
|
||||
parse_pg_basebackup_options(const char *pg_basebackup_options, t_basebackup_options *backup_options, int server_version_num, ItemList *error_list)
|
||||
{
|
||||
|
||||
34
configfile.h
34
configfile.h
@@ -98,16 +98,6 @@ typedef struct
|
||||
int promote_check_timeout;
|
||||
int promote_check_interval;
|
||||
|
||||
/* standby follow settings */
|
||||
int primary_follow_timeout;
|
||||
int standby_follow_timeout;
|
||||
|
||||
/* standby switchover settings */
|
||||
int standby_reconnect_timeout;
|
||||
|
||||
/* node rejoin settings */
|
||||
int node_rejoin_timeout;
|
||||
|
||||
/* node check settings */
|
||||
int archive_ready_warning;
|
||||
int archive_ready_critical;
|
||||
@@ -130,8 +120,8 @@ typedef struct
|
||||
int degraded_monitoring_timeout;
|
||||
int async_query_timeout;
|
||||
int primary_notification_timeout;
|
||||
int repmgrd_standby_startup_timeout;
|
||||
char repmgrd_pid_file[MAXPGPATH];
|
||||
int primary_follow_timeout;
|
||||
int standby_reconnect_timeout;
|
||||
|
||||
/* BDR settings */
|
||||
bool bdr_local_monitoring_only;
|
||||
@@ -177,13 +167,6 @@ typedef struct
|
||||
false, "", "", { NULL, NULL }, "", false, "", false, "", \
|
||||
/* standby promote settings */ \
|
||||
DEFAULT_PROMOTE_CHECK_TIMEOUT, DEFAULT_PROMOTE_CHECK_INTERVAL, \
|
||||
/* standby follow settings */ \
|
||||
DEFAULT_PRIMARY_FOLLOW_TIMEOUT, \
|
||||
DEFAULT_STANDBY_FOLLOW_TIMEOUT, \
|
||||
/* standby switchover settings */ \
|
||||
DEFAULT_STANDBY_RECONNECT_TIMEOUT, \
|
||||
/* node rejoin settings */ \
|
||||
DEFAULT_NODE_REJOIN_TIMEOUT, \
|
||||
/* node check settings */ \
|
||||
DEFAULT_ARCHIVE_READY_WARNING, DEFAULT_ARCHIVE_READY_CRITICAL, \
|
||||
DEFAULT_REPLICATION_LAG_WARNING, DEFAULT_REPLICATION_LAG_CRITICAL, \
|
||||
@@ -197,7 +180,8 @@ typedef struct
|
||||
false, -1, \
|
||||
DEFAULT_ASYNC_QUERY_TIMEOUT, \
|
||||
DEFAULT_PRIMARY_NOTIFICATION_TIMEOUT, \
|
||||
-1, "", \
|
||||
DEFAULT_PRIMARY_FOLLOW_TIMEOUT, \
|
||||
DEFAULT_STANDBY_RECONNECT_TIMEOUT, \
|
||||
/* BDR settings */ \
|
||||
false, DEFAULT_BDR_RECOVERY_TIMEOUT, \
|
||||
/* service settings */ \
|
||||
@@ -273,20 +257,16 @@ typedef struct
|
||||
"", "", "", "" \
|
||||
}
|
||||
|
||||
#include "dbutils.h"
|
||||
|
||||
void set_progname(const char *argv0);
|
||||
const char *progname(void);
|
||||
|
||||
void load_config(const char *config_file, bool verbose, bool terse, t_configuration_options *options, char *argv0);
|
||||
bool reload_config(t_configuration_options *orig_options, t_server_type server_type);
|
||||
void parse_config(t_configuration_options *options, bool terse);
|
||||
bool reload_config(t_configuration_options *orig_options);
|
||||
|
||||
bool parse_recovery_conf(const char *data_dir, t_recovery_conf *conf);
|
||||
|
||||
bool parse_bool(const char *s,
|
||||
const char *config_item,
|
||||
ItemList *error_list);
|
||||
|
||||
int repmgr_atoi(const char *s,
|
||||
const char *config_item,
|
||||
ItemList *error_list,
|
||||
@@ -302,7 +282,7 @@ void free_parsed_argv(char ***argv_array);
|
||||
|
||||
|
||||
/* called by repmgr-client and repmgrd */
|
||||
void exit_with_cli_errors(ItemList *error_list, const char *repmgr_command);
|
||||
void exit_with_cli_errors(ItemList *error_list);
|
||||
void print_item_list(ItemList *item_list);
|
||||
|
||||
#endif /* _REPMGR_CONFIGFILE_H_ */
|
||||
|
||||
18
configure
vendored
18
configure
vendored
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.69 for repmgr 4.1.1.
|
||||
# Generated by GNU Autoconf 2.69 for repmgr 4.0.5.
|
||||
#
|
||||
# Report bugs to <pgsql-bugs@postgresql.org>.
|
||||
#
|
||||
@@ -582,8 +582,8 @@ MAKEFLAGS=
|
||||
# Identity of this package.
|
||||
PACKAGE_NAME='repmgr'
|
||||
PACKAGE_TARNAME='repmgr'
|
||||
PACKAGE_VERSION='4.1.1'
|
||||
PACKAGE_STRING='repmgr 4.1.1'
|
||||
PACKAGE_VERSION='4.0.5'
|
||||
PACKAGE_STRING='repmgr 4.0.5'
|
||||
PACKAGE_BUGREPORT='pgsql-bugs@postgresql.org'
|
||||
PACKAGE_URL='https://2ndquadrant.com/en/resources/repmgr/'
|
||||
|
||||
@@ -1178,7 +1178,7 @@ if test "$ac_init_help" = "long"; then
|
||||
# Omit some internal or obsolete options to make the list less imposing.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
cat <<_ACEOF
|
||||
\`configure' configures repmgr 4.1.1 to adapt to many kinds of systems.
|
||||
\`configure' configures repmgr 4.0.5 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@@ -1239,7 +1239,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of repmgr 4.1.1:";;
|
||||
short | recursive ) echo "Configuration of repmgr 4.0.5:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@@ -1313,7 +1313,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
repmgr configure 4.1.1
|
||||
repmgr configure 4.0.5
|
||||
generated by GNU Autoconf 2.69
|
||||
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
@@ -1332,7 +1332,7 @@ cat >config.log <<_ACEOF
|
||||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by repmgr $as_me 4.1.1, which was
|
||||
It was created by repmgr $as_me 4.0.5, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
@@ -2359,7 +2359,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
||||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by repmgr $as_me 4.1.1, which was
|
||||
This file was extended by repmgr $as_me 4.0.5, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@@ -2422,7 +2422,7 @@ _ACEOF
|
||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||
ac_cs_version="\\
|
||||
repmgr config.status 4.1.1
|
||||
repmgr config.status 4.0.5
|
||||
configured by $0, generated by GNU Autoconf 2.69,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
AC_INIT([repmgr], [4.1.1], [pgsql-bugs@postgresql.org], [repmgr], [https://2ndquadrant.com/en/resources/repmgr/])
|
||||
AC_INIT([repmgr], [4.0.5], [pgsql-bugs@postgresql.org], [repmgr], [https://2ndquadrant.com/en/resources/repmgr/])
|
||||
|
||||
AC_COPYRIGHT([Copyright (c) 2010-2018, 2ndQuadrant Ltd.])
|
||||
|
||||
|
||||
31
dbutils.h
31
dbutils.h
@@ -29,9 +29,7 @@
|
||||
#include "voting.h"
|
||||
|
||||
#define REPMGR_NODES_COLUMNS "n.node_id, n.type, n.upstream_node_id, n.node_name, n.conninfo, n.repluser, n.slot_name, n.location, n.priority, n.active, n.config_file, '' AS upstream_node_name "
|
||||
#define BDR2_NODES_COLUMNS "node_sysid, node_timeline, node_dboid, node_name, node_local_dsn, ''"
|
||||
#define BDR3_NODES_COLUMNS "ns.node_id, 0, 0, ns.node_name, ns.interface_connstr, ns.peer_state_name"
|
||||
|
||||
#define BDR_NODES_COLUMNS "node_sysid, node_timeline, node_dboid, node_status, node_name, node_local_dsn, node_init_from_dsn, node_read_only, node_seq_id"
|
||||
|
||||
#define ERRBUFF_SIZE 512
|
||||
|
||||
@@ -96,14 +94,6 @@ typedef enum
|
||||
SLOT_ACTIVE
|
||||
} ReplSlotStatus;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
BACKUP_STATE_UNKNOWN = -1,
|
||||
BACKUP_STATE_IN_BACKUP,
|
||||
BACKUP_STATE_NO_BACKUP
|
||||
} BackupState;
|
||||
|
||||
|
||||
/*
|
||||
* Struct to store node information
|
||||
*/
|
||||
@@ -247,14 +237,18 @@ typedef struct s_bdr_node_info
|
||||
char node_sysid[MAXLEN];
|
||||
uint32 node_timeline;
|
||||
uint32 node_dboid;
|
||||
char node_status;
|
||||
char node_name[MAXLEN];
|
||||
char node_local_dsn[MAXLEN];
|
||||
char peer_state_name[MAXLEN];
|
||||
char node_init_from_dsn[MAXLEN];
|
||||
bool read_only;
|
||||
uint32 node_seq_id;
|
||||
} t_bdr_node_info;
|
||||
|
||||
#define T_BDR_NODE_INFO_INITIALIZER { \
|
||||
"", InvalidOid, InvalidOid, \
|
||||
"", "", "" \
|
||||
'?', "", "", "", \
|
||||
false, -1 \
|
||||
}
|
||||
|
||||
|
||||
@@ -363,7 +357,7 @@ void close_connection(PGconn **conn);
|
||||
|
||||
/* conninfo manipulation functions */
|
||||
bool get_conninfo_value(const char *conninfo, const char *keyword, char *output);
|
||||
bool get_conninfo_default_value(const char *param, char *output, int maxlen);
|
||||
|
||||
void initialize_conninfo_params(t_conninfo_param_list *param_list, bool set_defaults);
|
||||
void free_conninfo_params(t_conninfo_param_list *param_list);
|
||||
void copy_conninfo_params(t_conninfo_param_list *dest_list, t_conninfo_param_list *source_list);
|
||||
@@ -375,7 +369,6 @@ bool parse_conninfo_string(const char *conninfo_str, t_conninfo_param_list *par
|
||||
char *param_list_to_string(t_conninfo_param_list *param_list);
|
||||
bool has_passfile(void);
|
||||
|
||||
|
||||
/* transaction functions */
|
||||
bool begin_transaction(PGconn *conn);
|
||||
bool commit_transaction(PGconn *conn);
|
||||
@@ -398,7 +391,6 @@ int get_ready_archive_files(PGconn *conn, const char *data_directory);
|
||||
bool identify_system(PGconn *repl_conn, t_system_identification *identification);
|
||||
bool repmgrd_set_local_node_id(PGconn *conn, int local_node_id);
|
||||
int repmgrd_get_local_node_id(PGconn *conn);
|
||||
BackupState server_in_exclusive_backup_mode(PGconn *conn);
|
||||
|
||||
/* extension functions */
|
||||
ExtensionStatus get_repmgr_extension_status(PGconn *conn);
|
||||
@@ -462,8 +454,7 @@ void create_slot_name(char *slot_name, int node_id);
|
||||
bool create_replication_slot(PGconn *conn, char *slot_name, int server_version_num, PQExpBufferData *error_msg);
|
||||
bool drop_replication_slot(PGconn *conn, char *slot_name);
|
||||
RecordStatus get_slot_record(PGconn *conn, char *slot_name, t_replication_slot *record);
|
||||
int get_free_replication_slot_count(PGconn *conn);
|
||||
int get_inactive_replication_slots(PGconn *conn, KeyValueList *list);
|
||||
int get_free_replication_slots(PGconn *conn);
|
||||
|
||||
/* tablespace functions */
|
||||
bool get_tablespace_name_by_location(PGconn *conn, const char *location, char *name);
|
||||
@@ -475,7 +466,7 @@ int wait_connection_availability(PGconn *conn, long long timeout);
|
||||
/* node availability functions */
|
||||
bool is_server_available(const char *conninfo);
|
||||
bool is_server_available_params(t_conninfo_param_list *param_list);
|
||||
ExecStatusType connection_ping(PGconn *conn);
|
||||
void connection_ping(PGconn *conn);
|
||||
|
||||
/* monitoring functions */
|
||||
void
|
||||
@@ -514,14 +505,12 @@ void get_node_replication_stats(PGconn *conn, int server_version_num, t_node_in
|
||||
bool is_downstream_node_attached(PGconn *conn, char *node_name);
|
||||
|
||||
/* BDR functions */
|
||||
int get_bdr_version_num(void);
|
||||
void get_all_bdr_node_records(PGconn *conn, BdrNodeInfoList *node_list);
|
||||
RecordStatus get_bdr_node_record_by_name(PGconn *conn, const char *node_name, t_bdr_node_info *node_info);
|
||||
bool is_bdr_db(PGconn *conn, PQExpBufferData *output);
|
||||
bool is_bdr_db_quiet(PGconn *conn);
|
||||
bool is_active_bdr_node(PGconn *conn, const char *node_name);
|
||||
bool is_bdr_repmgr(PGconn *conn);
|
||||
char *get_default_bdr_replication_set(PGconn *conn);
|
||||
bool is_table_in_bdr_replication_set(PGconn *conn, const char *tablename, const char *set);
|
||||
bool add_table_to_bdr_replication_set(PGconn *conn, const char *tablename, const char *set);
|
||||
void add_extension_tables_to_bdr_replication_set(PGconn *conn);
|
||||
|
||||
@@ -108,14 +108,6 @@
|
||||
is not possible, contact your vendor for assistance.
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
<sect2 id="faq-old-packages">
|
||||
<title>How can I obtain old versions of &repmgr; packages?</title>
|
||||
<para>
|
||||
See appendix <xref linkend="packages-old-versions"> for details.
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1 id="faq-repmgr" xreflabel="repmgr">
|
||||
@@ -247,22 +239,11 @@
|
||||
Under some circumstances event notifications can be generated for servers
|
||||
which have not yet been registered; it's also useful to retain a record
|
||||
of events which includes servers removed from the replication cluster
|
||||
which no longer have an entry in the <literal>repmgr.nodes</literal> table.
|
||||
which no longer have an entry in the <literal>repmrg.nodes</literal> table.
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
<sect2 id="faq-repmgr-recovery-conf-quoted-values" xreflabel="Quoted values in recovery.conf">
|
||||
<title>Why are some values in <filename>recovery.conf</filename> surrounded by pairs of single quotes?</title>
|
||||
<para>
|
||||
This is to ensure that user-supplied values which are written as parameter values in <filename>recovery.conf</filename>
|
||||
are escaped correctly and do not cause errors when <filename>recovery.conf</filename> is parsed.
|
||||
</para>
|
||||
<para>
|
||||
The escaping is performed by an internal PostgreSQL routine, which leaves strings consisting
|
||||
of digits and alphabetical characters only as-is, but wraps everything else in pairs of single quotes,
|
||||
even if the string does not contain any characters which need escaping.
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
|
||||
|
||||
</sect1>
|
||||
@@ -274,7 +255,7 @@
|
||||
<sect2 id="faq-repmgrd-prevent-promotion" xreflabel="Prevent standby from being promoted to primary">
|
||||
<title>How can I prevent a node from ever being promoted to primary?</title>
|
||||
<para>
|
||||
In <filename>repmgr.conf</filename>, set its priority to a value of <literal>0</literal>; apply the changed setting with
|
||||
In `repmgr.conf`, set its priority to a value of 0 or less; apply the changed setting with
|
||||
<command><link linkend="repmgr-standby-register">repmgr standby register --force</link></command>.
|
||||
</para>
|
||||
<para>
|
||||
@@ -322,36 +303,5 @@
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
<sect2 id="faq-repmgrd-pg-bindir" xreflabel="repmgrd does not apply pg_bindir to promote_command or follow_command">
|
||||
<title>
|
||||
<application>repmgrd</application> ignores pg_bindir when executing <varname>promote_command</varname> or <varname>follow_command</varname>
|
||||
</title>
|
||||
<para>
|
||||
<varname>promote_command</varname> or <varname>follow_command</varname> can be user-defined scripts,
|
||||
so &repmgr; will not apply <option>pg_bindir</option> even if excuting &repmgr;. Always provide the full
|
||||
path; see <xref linkend="repmgrd-automatic-failover-configuration"> for more details.
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
<sect2 id="faq-repmgrd-startup-no-upstream" xreflabel="repmgrd does not start if upstream node is not running">
|
||||
<title>
|
||||
<application>repmgrd</application> aborts startup with the error "<literal>upstream node must be running before repmgrd can start</literal>"
|
||||
</title>
|
||||
<para>
|
||||
<application>repmgrd</application> does this to avoid starting up on a replication cluster
|
||||
which is not in a healthy state. If the upstream is unavailable, <application>repmgrd</application>
|
||||
may initiate a failover immediately after starting up, which could have unintended side-effects,
|
||||
particularly if <application>repmgrd</application> is not running on other nodes.
|
||||
</para>
|
||||
<para>
|
||||
In particular, it's possible that the node's local copy of the <literal>repmgr.nodes</literal> copy
|
||||
is out-of-date, which may lead to incorrect failover behaviour.
|
||||
</para>
|
||||
<para>
|
||||
The onus is therefore on the adminstrator to manually set the cluster to a stable, healthy state before
|
||||
starting <application>repmgrd</application>.
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
</sect1>
|
||||
</appendix>
|
||||
|
||||
@@ -41,23 +41,22 @@
|
||||
<title>CentOS repositories</title>
|
||||
|
||||
<para>
|
||||
&repmgr; packages are available from the public 2ndQuadrant repository, and also the
|
||||
PostgreSQL community repository. The 2ndQuadrant repository is updated immediately
|
||||
after each
|
||||
&repmgr; packages are available from the 2ndQuadrant repository, and also the PostgreSQL
|
||||
community repository. The 2ndQuadrant repository is updated immediately after each
|
||||
&repmgr; release.
|
||||
</para>
|
||||
|
||||
<table id="centos-2ndquadrant-repository">
|
||||
<title>2ndQuadrant public repository</title>
|
||||
<title>2ndQuadrant repository</title>
|
||||
<tgroup cols="2">
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>Repository URL:</entry>
|
||||
<entry><ulink url="https://dl.2ndquadrant.com/">https://dl.2ndquadrant.com/</ulink></entry>
|
||||
<entry><ulink url="http://packages.2ndquadrant.com/repmgr/">http://packages.2ndquadrant.com/repmgr/</ulink></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Repository documentation:</entry>
|
||||
<entry><ulink url="https://repmgr.org/docs/4.1/installation-packages.html#INSTALLATION-PACKAGES-REDHAT-2NDQ">https://repmgr.org/docs/4.1/installation-packages.html#INSTALLATION-PACKAGES-REDHAT-2NDQ</ulink></entry>
|
||||
<entry><ulink url="https://repmgr.org/docs/4.0/installation-packages.html#INSTALLATION-PACKAGES-REDHAT-2NDQ">https://repmgr.org/docs/4.0/installation-packages.html#INSTALLATION-PACKAGES-REDHAT-2NDQ</ulink></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
@@ -253,23 +252,6 @@
|
||||
</para>
|
||||
|
||||
|
||||
<table id="apt-2ndquadrant-repository">
|
||||
<title>2ndQuadrant public repository</title>
|
||||
<tgroup cols="2">
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>Repository URL:</entry>
|
||||
<entry><ulink url="https://dl.2ndquadrant.com/">https://dl.2ndquadrant.com/</ulink></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>Repository documentation:</entry>
|
||||
<entry><ulink url="https://repmgr.org/docs/4.1/installation-packages.html#INSTALLATION-PACKAGES-DEBIAN">https://repmgr.org/docs/4.1/installation-packages.html#INSTALLATION-PACKAGES-DEBIAN</ulink></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
|
||||
|
||||
<table id="apt-repository">
|
||||
<title>PostgreSQL Community APT repository (PGDG)</title>
|
||||
<tgroup cols="2">
|
||||
@@ -381,169 +363,4 @@
|
||||
</sect2>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1 id="packages-snapshot" xreflabel="Snapshot packages">
|
||||
<title>Snapshot packages</title>
|
||||
<indexterm>
|
||||
<primary>snapshot packages</primary>
|
||||
</indexterm>
|
||||
<indexterm>
|
||||
<primary>packages</primary>
|
||||
<secondary>snaphots</secondary>
|
||||
</indexterm>
|
||||
|
||||
<para>
|
||||
For testing new features and bug fixes, from time to time 2ndQuadrant provides
|
||||
so-called "snapshot packages" via its public repository. These packages
|
||||
are built from the &repmgr; source at a particular point in time, and are not formal
|
||||
releases.
|
||||
</para>
|
||||
<note>
|
||||
<para>
|
||||
We do not recommend installing these packages in a production environment
|
||||
unless specifically advised.
|
||||
</para>
|
||||
</note>
|
||||
<para>
|
||||
To install a snapshot package, it's necessary to install the 2ndQuadrant public snapshot repository,
|
||||
following the instructions here: <ulink url="https://dl.2ndquadrant.com/default/release/site/">https://dl.2ndquadrant.com/default/release/site/</ulink> but replace <literal>release</literal> with <literal>snapshot</literal>
|
||||
in the appropriate URL.
|
||||
</para>
|
||||
<para>
|
||||
For example, to install the snapshot RPM repository for PostgreSQL 9.6, execute (as <literal>root</literal>):
|
||||
<programlisting>
|
||||
curl https://dl.2ndquadrant.com/default/snapshot/get/9.6/rpm | bash</programlisting>
|
||||
|
||||
or as a normal user with root sudo access:
|
||||
<programlisting>
|
||||
curl https://dl.2ndquadrant.com/default/snapshot/get/9.6/rpm | sudo bash</programlisting>
|
||||
</para>
|
||||
<para>
|
||||
Alternatively you can browse the repository here:
|
||||
<ulink url="https://dl.2ndquadrant.com/default/snapshot/browse/">https://dl.2ndquadrant.com/default/snapshot/browse/</ulink>.
|
||||
</para>
|
||||
<para>
|
||||
Once the repository is installed, installing or updating &repmgr; will result in the latest snapshot
|
||||
package being installed.
|
||||
</para>
|
||||
<para>
|
||||
The package name will be formatted like this:
|
||||
<programlisting>
|
||||
repmgr96-4.1.1-0.0git320.g5113ab0.1.el7.x86_64.rpm</programlisting>
|
||||
containg the snapshot build number (here: <literal>320</literal>) and the hash
|
||||
of the <application>git</application> commit it was built from (here: <literal>g5113ab0</literal>).
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Note that the next formal release (in the above example <literal>4.1.1</literal>), once available,
|
||||
will install in place of any snapshot builds.
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1 id="packages-old-versions" xreflabel="Installing old package versions">
|
||||
<title>Installing old package versions</title>
|
||||
<indexterm>
|
||||
<primary>old packages</primary>
|
||||
</indexterm>
|
||||
<indexterm>
|
||||
<primary>packages</primary>
|
||||
<secondary>old versions</secondary>
|
||||
</indexterm>
|
||||
|
||||
<sect2 id="packages-old-versions-debian" xreflabel="old Debian package versions">
|
||||
<title>Debian/Ubuntu</title>
|
||||
<para>
|
||||
An archive of old packages (<literal>3.3.2</literal> and later) for Debian/Ubuntu-based systems is available here:
|
||||
<ulink url="http://atalia.postgresql.org/morgue/r/repmgr/">http://atalia.postgresql.org/morgue/r/repmgr/</ulink>
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
<sect2 id="packages-old-versions-rhel-centos" xreflabel="old RHEL/CentOS package versions">
|
||||
<title>RHEL/CentOS</title>
|
||||
<para>
|
||||
Old RPM packages (<literal>3.2</literal> and later) can be retrieved from the
|
||||
(deprecated) 2ndQuadrant repository at
|
||||
<ulink url="http://packages.2ndquadrant.com/">http://packages.2ndquadrant.com/</ulink>
|
||||
by installing the appropriate repository RPM:
|
||||
</para>
|
||||
|
||||
<itemizedlist spacing="compact" mark="bullet">
|
||||
|
||||
<listitem>
|
||||
<simpara>
|
||||
<ulink url="http://packages.2ndquadrant.com/repmgr/yum-repo-rpms/repmgr-fedora-1.0-1.noarch.rpm">http://packages.2ndquadrant.com/repmgr/yum-repo-rpms/repmgr-fedora-1.0-1.noarch.rpm</ulink>
|
||||
</simpara>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<simpara>
|
||||
<ulink url="http://packages.2ndquadrant.com/repmgr/yum-repo-rpms/repmgr-rhel-1.0-1.noarch.rpm">http://packages.2ndquadrant.com/repmgr/yum-repo-rpms/repmgr-rhel-1.0-1.noarch.rpm</ulink>
|
||||
</simpara>
|
||||
</listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
<para>
|
||||
Old versions can be located with e.g.:
|
||||
<programlisting>
|
||||
yum --showduplicates list repmgr96</programlisting>
|
||||
(substitute the appropriate package name; see <xref linkend="packages-centos">) and installed with:
|
||||
<programlisting>
|
||||
yum install {package_name}-{version}</programlisting>
|
||||
where <literal>{package_name}</literal> is the base package name (e.g. <literal>repmgr96</literal>)
|
||||
and <literal>{version}</literal> is the version listed by the
|
||||
<command> yum --showduplicates list ...</command> command, e.g. <literal>4.0.6-1.rhel6</literal>.
|
||||
</para>
|
||||
<para>For example:
|
||||
<programlisting>
|
||||
yum install repmgr96-4.0.6-1.rhel6</programlisting>
|
||||
</para>
|
||||
|
||||
</sect2>
|
||||
</sect1>
|
||||
|
||||
|
||||
<sect1 id="packages-packager-info" xreflabel="Information for packagers">
|
||||
<title>Information for packagers</title>
|
||||
<indexterm>
|
||||
<primary>packages</primary>
|
||||
<secondary>information for packagers</secondary>
|
||||
</indexterm>
|
||||
<para>
|
||||
We recommend patching the following parameters when
|
||||
building the package as built-in default values for user convenience.
|
||||
These values can nevertheless be overridden by the user, if desired.
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
Configuration file location: the default configuration file location
|
||||
can be hard-coded by patching <varname>package_conf_file</varname>
|
||||
in <filename>configfile.c</filename>:
|
||||
<programlisting>
|
||||
/* packagers: if feasible, patch configuration file path into "package_conf_file" */
|
||||
char package_conf_file[MAXPGPATH] = "";</programlisting>
|
||||
</para>
|
||||
<para>
|
||||
See also: <xref linkend="configuration-file">
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
PID file location: the default <application>repmgrd</application> PID file
|
||||
location can be hard-coded by patching <varname>package_pid_file</varname>
|
||||
in <filename>repmgrd.c</filename>:
|
||||
<programlisting>
|
||||
/* packagers: if feasible, patch PID file path into "package_pid_file" */
|
||||
char package_pid_file[MAXPGPATH] = "";</programlisting>
|
||||
</para>
|
||||
<para>
|
||||
See also: <xref linkend="repmgrd-pid-file">
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
</itemizedlist>
|
||||
</sect1>
|
||||
</appendix>
|
||||
|
||||
@@ -15,478 +15,6 @@
|
||||
See also: <xref linkend="upgrading-repmgr">
|
||||
</para>
|
||||
|
||||
<sect1 id="release-4.1.1">
|
||||
<title>Release 4.1.1</title>
|
||||
<para><emphasis>Wed September 5, 2018</emphasis></para>
|
||||
<para>
|
||||
repmgr 4.1.1 contains a number of usability enhancements and bug fixes.
|
||||
</para>
|
||||
<para>
|
||||
We recommend upgrading to this version as soon as possible.
|
||||
This release can be installed as a simple package upgrade from repmgr 4.0 ~ 4.1.0;
|
||||
<application>repmgrd</application> (if running) should be restarted.
|
||||
See <xref linkend="upgrading-repmgr"> for more details.
|
||||
</para>
|
||||
|
||||
<sect2>
|
||||
<title>repmgr enhancements</title>
|
||||
<para>
|
||||
<itemizedlist>
|
||||
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
<command><link linkend="repmgr-standby-clone">repmgr standby switchover --dry-run</link></command>
|
||||
no longer copies external configuration files to test they can be copied; this avoids making
|
||||
any changes to the target system. (GitHub #491).
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
<command><link linkend="repmgr-cluster-cleanup">repmgr cluster cleanup</link></command>:
|
||||
add <literal>cluster_cleanup</literal> event. (GitHub #492)
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
<command><link linkend="repmgr-standby-switchover">repmgr standby switchover</link></command>:
|
||||
improve detection of free walsenders. (GitHub #495).
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
Improve messages emitted during
|
||||
<command><link linkend="repmgr-standby-promote">repmgr standby promote</link></command>.
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
|
||||
<sect2>
|
||||
<title>repmgrd enhancements</title>
|
||||
<para>
|
||||
<itemizedlist>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
Always reopen the log file after
|
||||
receiving <literal>SIGHUP</literal>. Previously this only happened if
|
||||
a configuration file change was detected.
|
||||
(GitHub #485).
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
Report version number <emphasis>after</emphasis>
|
||||
logger initialisation. (GitHub #487).
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
Improve cascaded standby failover handling. (GitHub #480).
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
Improve reconnection handling after brief network outages; if
|
||||
monitoring data being collected, this could lead to orphaned
|
||||
sessions on the primary. (GitHub #480).
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
Check <varname>promote_command</varname> and <varname>follow_command</varname>
|
||||
are defined when reloading configuration. These were checked on startup but
|
||||
not reload by <application>repmgrd</application>, which made it possible to
|
||||
make <application>repmgrd</application> with invalid values. It's unlikely
|
||||
anyone would want to do this, but we should make it impossible anyway.
|
||||
(GitHub #486).
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
<sect2>
|
||||
<title>Other</title>
|
||||
<para>
|
||||
<itemizedlist>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
Text of any failed queries will now be logged as <literal>ERROR</literal> to assist
|
||||
logfile analysis at log levels higher than <literal>DEBUG</literal>.
|
||||
(GitHub #498).
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
<sect2>
|
||||
<title>Bug fixes</title>
|
||||
<para>
|
||||
<itemizedlist>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
<command><link linkend="repmgr-node-rejoin">repmgr node rejoin</link></command>:
|
||||
remove new upstream's replication slot if it still exists on the rejoined
|
||||
standby. (GitHub #499).
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
<application>repmgrd</application>: fix startup on witness node when local data is stale. (GitHub #488, #489).
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
Truncate version string reported by PostgreSQL if necessary; some
|
||||
distributions insert additional detail after the actual version.
|
||||
(GitHub #490).
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
|
||||
</sect1>
|
||||
|
||||
|
||||
|
||||
<sect1 id="release-4.1.0">
|
||||
<title>Release 4.1.0</title>
|
||||
<para><emphasis>Tue July 31, 2018</emphasis></para>
|
||||
<para>
|
||||
&repmgr; 4.1.0 introduces some changes to <application>repmgrd</application>
|
||||
behaviour and some additional configuration parameters.
|
||||
</para>
|
||||
<para>
|
||||
This release can be installed as a simple package upgrade from repmgr 4.0 ~ 4.0.6.
|
||||
The following post-upgrade steps must be carried out:
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
Execute <command>ALTER EXTENSION repmgr UPDATE</command>
|
||||
on the primary server in the database where &repmgr; is installed.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
<application>repmgrd</application> must be restarted on all nodes where it is running.
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
A restart of the PostgreSQL server is <emphasis>not</emphasis> required
|
||||
for this release (unless upgrading from repmgr 3.x).
|
||||
</para>
|
||||
<para>
|
||||
See <xref linkend="upgrading-repmgr-extension"> for more details.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Configuration changes are backwards-compatible and no changes to
|
||||
<filename>repmgr.conf</filename> are required. However users should
|
||||
review the changes listed below.
|
||||
</para>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
<emphasis>Repository changes</emphasis>
|
||||
</para>
|
||||
<para>
|
||||
Coinciding with this release, the 2ndQuadrant repository structure has changed.
|
||||
See section <xref linkend="installation-packages"> for details, particularly
|
||||
if you are using a RPM-based system.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
<sect2>
|
||||
<title>Configuration file changes</title>
|
||||
|
||||
<para>
|
||||
<itemizedlist>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
Default for <xref linkend="repmgr-conf-log-level"> is now <option>INFO</option>.
|
||||
This produces additional informative log output, without creating excessive additional
|
||||
log file volume, and matches the setting assumed for examples in the documentation.
|
||||
(GitHub #470).
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
<varname>recovery_min_apply_delay</varname> now accepts a minimum value
|
||||
of <literal>zero</literal> (GitHub #448).
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
</sect2>
|
||||
|
||||
|
||||
<sect2>
|
||||
<title>repmgr enhancements</title>
|
||||
<para>
|
||||
<itemizedlist>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
<application>repmgr</application>: always exit with an error if an unrecognised
|
||||
command line option is provided. This matches the behaviour of other PostgreSQL
|
||||
utilities such as <application>psql</application>. (GitHub #464).
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
<application>repmgr</application>: add <option>-q/--quiet</option> option to suppress non-error
|
||||
output. (GitHub #468).
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
<command><link linkend="repmgr-cluster-show">repmgr cluster show</link></command>,
|
||||
<command><link linkend="repmgr-node-check">repmgr node check</link></command> and
|
||||
<command><link linkend="repmgr-node-status">repmgr node status</link></command>
|
||||
return non-zero exit code if node status issues detected. (GitHub #456).
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
Add <option>--csv</option> output option for
|
||||
<command><link linkend="repmgr-cluster-event">repmgr cluster event</link></command>.
|
||||
(GitHub #471).
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
<command><link linkend="repmgr-witness-unregister">repmgr witness unregister</link></command>
|
||||
can be run on any node, by providing the ID of the witness node with <option>--node-id</option>.
|
||||
(GitHub #472).
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
<command><link linkend="repmgr-standby-switchover">repmgr standby switchover</link></command>
|
||||
will refuse to run if an exclusive backup is taking place on the current primary.
|
||||
(GitHub #476).
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
<sect2>
|
||||
<title>repmgrd enhancements</title>
|
||||
<para>
|
||||
<itemizedlist>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
<application>repmgrd</application>: create a PID file by default
|
||||
(GitHub #457). For details, see <xref linkend="repmgrd-pid-file">.
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
<application>repmgrd</application>: daemonize process by default.
|
||||
In case, for whatever reason, the user does not wish to daemonize the
|
||||
process, provide <option>--daemonize=false</option>.
|
||||
(GitHub #458).
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
|
||||
<sect2>
|
||||
<title>Bug fixes</title>
|
||||
<para>
|
||||
<itemizedlist>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
<command><link linkend="repmgr-standby-register">repmgr standby register --wait-sync</link></command>:
|
||||
fix behaviour when no timeout provided.
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
<command><link linkend="repmgr-cluster-cleanup">repmgr cluster cleanup</link></command>:
|
||||
add missing help options. (GitHub #461/#462).
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
Ensure witness node follows new primary after switchover. (GitHub #453).
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
<command><link linkend="repmgr-node-check">repmgr node check</link></command> and
|
||||
<command><link linkend="repmgr-node-status">repmgr node status</link></command>:
|
||||
fix witness node handling. (GitHub #451).
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
When using <command><link linkend="repmgr-standby-clone">repmgr standby clone</link></command>
|
||||
with <option>--recovery-conf-only</option> and replication slots, ensure
|
||||
<varname>primary_slot_name</varname> is set correctly. (GitHub #474).
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1 id="release-4.0.6">
|
||||
<title>Release 4.0.6</title>
|
||||
<para><emphasis>Thu June 14, 2018</emphasis></para>
|
||||
<para>
|
||||
&repmgr; 4.0.6 contains a number of bug fixes and usability enhancements.
|
||||
</para>
|
||||
<para>
|
||||
We recommend upgrading to this version as soon as possible.
|
||||
This release can be installed as a simple package upgrade from repmgr 4.0 ~ 4.0.5;
|
||||
<application>repmgrd</application> (if running) should be restarted. See <xref linkend="upgrading-repmgr">
|
||||
for more details.
|
||||
</para>
|
||||
|
||||
<sect2>
|
||||
<title>Usability enhancements</title>
|
||||
|
||||
<para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
<command><link linkend="repmgr-cluster-crosscheck">repmgr cluster crosscheck</link></command> and
|
||||
<command><link linkend="repmgr-cluster-matrix">repmgr cluster matrix</link></command>:
|
||||
return non-zero exit code if node connection issues detected (GitHub #447)
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
<command><link linkend="repmgr-standby-clone">repmgr standby clone</link></command>:
|
||||
Improve handling of external configuration file copying, including consideration in
|
||||
<option>--dry-run</option> check
|
||||
(GitHub #443)
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
When using <option>--dry-run</option>, force log level to <literal>INFO</literal>
|
||||
to ensure output will always be displayed
|
||||
(GitHub #441)
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
<command><link linkend="repmgr-standby-clone">repmgr standby clone</link></command>:
|
||||
Improve documentation of <option>--recovery-conf-only</option> mode
|
||||
(GitHub #438)
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
<command><link linkend="repmgr-standby-clone">repmgr standby clone</link></command>:
|
||||
Don't require presence of <varname>user</varname> parameter in conninfo string
|
||||
(GitHub #437)
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
<sect2>
|
||||
<title>Bug fixes</title>
|
||||
<para>
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
<command><link linkend="repmgr-witness-register">repmgr witness register</link></command>:
|
||||
prevent registration of a witness server with the same name as an existing node
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
<command><link linkend="repmgr-standby-follow">repmgr standby follow</link></command>:
|
||||
check node has actually connected to new primary before reporting success
|
||||
(GitHub #444)
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
<command><link linkend="repmgr-node-rejoin">repmgr node rejoin</link></command>:
|
||||
Fix bug when parsing <option>--config-files</option> parameter
|
||||
(GitHub #442)
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
<application>repmgrd</application>: ensure local node is counted as quorum member
|
||||
(GitHub #439)
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1 id="release-4.0.5">
|
||||
<title>Release 4.0.5</title>
|
||||
<para><emphasis>Wed May 2, 2018</emphasis></para>
|
||||
@@ -496,7 +24,6 @@
|
||||
generation and (in <application>repmgrd</application>) handling of various
|
||||
corner-case situations, as well as a number of bug fixes.
|
||||
</para>
|
||||
|
||||
<sect2>
|
||||
<title>Usability enhancements</title>
|
||||
|
||||
@@ -505,7 +32,7 @@
|
||||
<listitem>
|
||||
<para>
|
||||
Various documentation improvements, with particular emphasis on
|
||||
the importance of setting appropriate <link linkend="configuration-file-service-commands">service commands</link>
|
||||
the importance of setting appropriate <link linkend="configuration-service-commands">service commands</link>
|
||||
instead of relying on <application>pg_ctl</application>.
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
@@ -5,14 +5,14 @@
|
||||
<title>repmgr source code signing key</title>
|
||||
<para>
|
||||
The signing key ID used for <application>repmgr</application> source code bundles is:
|
||||
<ulink url="https://repmgr.org/download/SOURCE-GPG-KEY-repmgr">
|
||||
<ulink url="http://packages.2ndquadrant.com/repmgr/SOURCE-GPG-KEY-repmgr">
|
||||
<literal>0x297F1DCC</literal></ulink>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To download the <application>repmgr</application> source key to your computer:
|
||||
<programlisting>
|
||||
curl -s https://repmgr.org/download/SOURCE-GPG-KEY-repmgr | gpg --import
|
||||
curl -s http://packages.2ndquadrant.com/repmgr/SOURCE-GPG-KEY-repmgr | gpg --import
|
||||
gpg --fingerprint 0x297F1DCC
|
||||
</programlisting>
|
||||
then verify that the fingerprint is the expected value:
|
||||
@@ -33,5 +33,34 @@
|
||||
|
||||
</sect1>
|
||||
|
||||
<sect1 id="repmgr-rpm-key" xreflabel="repmgr rpm key">
|
||||
<title>repmgr RPM signing key</title>
|
||||
<para>
|
||||
The signing key ID used for <application>repmgr</application> source code bundles is:
|
||||
<ulink url="http://packages.2ndquadrant.com/repmgr/RPM-GPG-KEY-repmgr">
|
||||
<literal>0x702D883A</literal></ulink>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To download the <application>repmgr</application> source key to your computer:
|
||||
<programlisting>
|
||||
curl -s http://packages.2ndquadrant.com/repmgr/RPM-GPG-KEY-repmgr | gpg --import
|
||||
gpg --fingerprint 0x702D883A
|
||||
</programlisting>
|
||||
then verify that the fingerprint is the expected value:
|
||||
<programlisting>
|
||||
AE4E 390E A58E 0037 6148 3F29 888D 018B 702D 883A</programlisting>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To check a repository RPM, use <application>rpmkeys</application> to load the
|
||||
packaging signing key into the RPM database then use <literal>rpm -K</literal>, e.g.:
|
||||
<programlisting>
|
||||
sudo rpmkeys --import http://packages.2ndquadrant.com/repmgr/RPM-GPG-KEY-repmgr
|
||||
rpm -K postgresql-bdr94-2ndquadrant-redhat-1.0-2.noarch.rpm
|
||||
</programlisting>
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
|
||||
</appendix>
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
<sect1 id="configuration-file-log-settings" xreflabel="log settings">
|
||||
<indexterm>
|
||||
<primary>repmgr.conf</primary>
|
||||
<secondary>log settings</secondary>
|
||||
</indexterm>
|
||||
<indexterm>
|
||||
<primary>log settings</primary>
|
||||
<secondary>configuration in repmgr.conf</secondary>
|
||||
</indexterm>
|
||||
<title>Log settings</title>
|
||||
|
||||
<para>
|
||||
By default, &repmgr; and <application>repmgrd</application> write log output to
|
||||
<literal>STDERR</literal>. An alternative log destination can be specified
|
||||
(either a file or <literal>syslog</literal>).
|
||||
</para>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
The &repmgr; application itself will continue to write log output to <literal>STDERR</literal>
|
||||
even if another log destination is configured, as otherwise any output resulting from a command
|
||||
line operation will "disappear" into the log.
|
||||
</para>
|
||||
<para>
|
||||
This behaviour can be overriden with the command line option <option>--log-to-file</option>,
|
||||
which will redirect all logging output to the configured log destination. This is recommended
|
||||
when &repmgr; is executed by another application, particularly <application>repmgrd</application>,
|
||||
to enable log output generated by the &repmgr; application to be stored for later reference.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry id="repmgr-conf-log-level" xreflabel="log_level">
|
||||
<term><varname>log_level</varname> (<type>string</type>)
|
||||
<indexterm>
|
||||
<primary><varname>log_level</varname> configuration file parameter</primary>
|
||||
</indexterm>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
One of <option>DEBUG</option>, <option>INFO</option>, <option>NOTICE</option>,
|
||||
<option>WARNING</option>, <option>ERROR</option>, <option>ALERT</option>, <option>CRIT</option>
|
||||
or <option>EMERG</option>.
|
||||
</para>
|
||||
<para>
|
||||
Default is <option>INFO</option>.
|
||||
</para>
|
||||
<para>
|
||||
Note that <option>DEBUG</option> will produce a substantial amount of log output
|
||||
and should not be enabled in normal use.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry id="repmgr-conf-log-facility" xreflabel="log_facility">
|
||||
<term><varname>log_facility</varname> (<type>string</type>)
|
||||
<indexterm>
|
||||
<primary><varname>log_facility</varname> configuration file parameter</primary>
|
||||
</indexterm>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Logging facility: possible values are <option>STDERR</option> (default), or for
|
||||
syslog integration, one of <option>LOCAL0</option>, <option>LOCAL1</option>, <option>...</option>,
|
||||
<option>LOCAL7</option>, <option>USER</option>.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry id="repmgr-conf-log-file" xreflabel="log_file">
|
||||
<term><varname>log_file</varname> (<type>string</type>)
|
||||
<indexterm>
|
||||
<primary><varname>log_file</varname> configuration file parameter</primary>
|
||||
</indexterm>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
If <xref linkend="repmgr-conf-log-facility"> is set to <option>STDERR</option>, log output
|
||||
can be redirected to the specified file.
|
||||
</para>
|
||||
<para>
|
||||
See <xref linkend="repmgrd-log-rotation"> for information on configuring log rotation.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry id="repmgr-conf-log-status-interval" xreflabel="log_status_interval">
|
||||
<term><varname>log_status_interval</varname> (<type>integer</type>)
|
||||
<indexterm>
|
||||
<primary><varname>log_status_interval</varname> configuration file parameter</primary>
|
||||
</indexterm>
|
||||
</term>
|
||||
<listitem>
|
||||
<para>
|
||||
This setting causes <application>repmgrd</application> to emit a status log
|
||||
line at the specified interval (in seconds, default <literal>300</literal>)
|
||||
describing <application>repmgrd</application>'s current state, e.g.:
|
||||
</para>
|
||||
<programlisting>
|
||||
[2018-07-12 00:47:32] [INFO] monitoring connection to upstream node "node1" (node ID: 1)</programlisting>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
|
||||
</sect1>
|
||||
@@ -1,10 +1,10 @@
|
||||
<sect1 id="configuration-file-settings" xreflabel="required configuration file settings">
|
||||
<sect1 id="configuration-file-settings" xreflabel="configuration file settings">
|
||||
<indexterm>
|
||||
<primary>repmgr.conf</primary>
|
||||
<secondary>required settings</secondary>
|
||||
<secondary>basic settings</secondary>
|
||||
</indexterm>
|
||||
|
||||
<title>Required configuration file settings</title>
|
||||
<title>Basic configuration file settings</title>
|
||||
<para>
|
||||
Each <filename>repmgr.conf</filename> file must contain the following parameters:
|
||||
</para>
|
||||
@@ -1,4 +1,4 @@
|
||||
<sect1 id="configuration-file-service-commands" xreflabel="service command settings">
|
||||
<sect1 id="configuration-service-commands" xreflabel="service command settings">
|
||||
<indexterm>
|
||||
<primary>repmgr.conf</primary>
|
||||
<secondary>service command settings</secondary>
|
||||
@@ -50,25 +50,10 @@
|
||||
|
||||
<note>
|
||||
<para>
|
||||
&repmgr; will not apply <option>pg_bindir</option> when executing any of these commands;
|
||||
these can be user-defined scripts so must always be specified with the full path.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
It's also possible to specify a <varname>service_promote_command</varname>.
|
||||
It's also possible to specify a <varname>service_promote_command</varname>;
|
||||
this overrides any value contained in the setting <varname>promote_command</varname>.
|
||||
This is intended for systems which provide a package-level promote command,
|
||||
such as Debian's <application>pg_ctlcluster</application>, to promote the
|
||||
PostgreSQL from standby to primary.
|
||||
</para>
|
||||
<para>
|
||||
If your packaging system does not provide such a command, it can be left empty,
|
||||
and &repmgr; will generate the appropriate `pg_ctl ... promote` command.
|
||||
</para>
|
||||
<para>
|
||||
Do not confuse this with <varname>promote_command</varname>, which is used
|
||||
by <application>repmgrd</application> to execute <xref linkend="repmgr-standby-promote">.
|
||||
such as Debian's <application>pg_ctlcluster</application>.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
@@ -2,17 +2,16 @@
|
||||
<title>repmgr configuration</title>
|
||||
|
||||
&configuration-file;
|
||||
&configuration-file-required-settings;
|
||||
&configuration-file-log-settings;
|
||||
&configuration-file-service-commands;
|
||||
&configuration-file-settings;
|
||||
&configuration-service-commands;
|
||||
|
||||
<sect1 id="configuration-permissions" xreflabel="Database user permissions">
|
||||
<sect1 id="configuration-permissions" xreflabel="User permissions">
|
||||
<indexterm>
|
||||
<primary>configuration</primary>
|
||||
<secondary>database user permissions</secondary>
|
||||
<secondary>user permissions</secondary>
|
||||
</indexterm>
|
||||
|
||||
<title>repmgr database user permissions</title>
|
||||
<title>repmgr user permissions</title>
|
||||
<para>
|
||||
&repmgr; will create an extension database containing objects
|
||||
for administering &repmgr; metadata. The user defined in the <varname>conninfo</varname>
|
||||
|
||||
@@ -16,22 +16,15 @@
|
||||
<para>
|
||||
A typical use case for a witness server is a two-node streaming replication
|
||||
setup, where the primary and standby are in different locations (data centres).
|
||||
By creating a witness server in the same location (data centre) as the primary,
|
||||
if the primary becomes unavailable it's possible for the standby to decide whether
|
||||
it can promote itself without risking a "split brain" scenario: if it can't see either the
|
||||
By creating a witness server in the same location as the primary, if the primary
|
||||
becomes unavailable it's possible for the standby to decide whether it can
|
||||
promote itself without risking a "split brain" scenario: if it can't see either the
|
||||
witness or the primary server, it's likely there's a network-level interruption
|
||||
and it should not promote itself. If it can seen the witness but not the primary,
|
||||
this proves there is no network interruption and the primary itself is unavailable,
|
||||
and it can therefore promote itself (and ideally take action to fence the
|
||||
former primary).
|
||||
</para>
|
||||
<note>
|
||||
<para>
|
||||
<emphasis>Never</emphasis> install a witness server on the same physical host
|
||||
as another node in the replication cluster managed by &repmgr; - it's essential
|
||||
the witness is not affected in any way by failure of another node.
|
||||
</para>
|
||||
</note>
|
||||
<para>
|
||||
For more complex replication scenarios,e.g. with multiple datacentres, it may
|
||||
be preferable to use location-based failover, which ensures that only nodes
|
||||
|
||||
@@ -147,104 +147,34 @@
|
||||
<para>
|
||||
By default, all notification types will be passed to the designated script;
|
||||
the notification types can be filtered to explicitly named ones using the
|
||||
<varname>event_notifications</varname> parameter.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Events generated by the &repmgr; command:
|
||||
<varname>event_notifications</varname> parameter:
|
||||
|
||||
<itemizedlist spacing="compact" mark="bullet">
|
||||
|
||||
<listitem>
|
||||
<simpara><literal><link linkend="repmgr-primary-register-events">cluster_created</link></literal></simpara>
|
||||
<simpara><literal>primary_register</literal></simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara><literal><link linkend="repmgr-primary-register-events">primary_register</link></literal></simpara>
|
||||
<simpara><literal>primary_unregister</literal></simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara><literal><link linkend="repmgr-primary-unregister-events">primary_unregister</link></literal></simpara>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<simpara><literal><link linkend="repmgr-standby-clone-events">standby_clone</link></literal></simpara>
|
||||
<simpara><literal>standby_register</literal></simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara><literal><link linkend="repmgr-standby-register-events">standby_register</link></literal></simpara>
|
||||
<simpara><literal>standby_register_sync</literal></simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara><literal><link linkend="repmgr-standby-register-events">standby_register_sync</link></literal></simpara>
|
||||
<simpara><literal>standby_unregister</literal></simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara><literal><link linkend="repmgr-standby-unregister-events">standby_unregister</link></literal></simpara>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<simpara><literal><link linkend="repmgr-standby-promote-events">standby_promote</link></literal></simpara>
|
||||
<simpara><literal>standby_clone</literal></simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara><literal><link linkend="repmgr-standby-follow-events">standby_follow</link></literal></simpara>
|
||||
<simpara><literal>standby_promote</literal></simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara><literal><link linkend="repmgr-standby-switchover-events">standby_switchover</link></literal></simpara>
|
||||
<simpara><literal>standby_follow</literal></simpara>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<simpara><literal><link linkend="repmgr-witness-register-events">witness_register</link></literal></simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara><literal><link linkend="repmgr-witness-unregister-events">witness_unregister</link></literal></simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara><literal><link linkend="repmgr-node-rejoin-events">node_rejoin</link></literal></simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara><literal><link linkend="repmgr-cluster-cleanup-events">cluster_cleanup</link></literal></simpara>
|
||||
</listitem>
|
||||
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Events generated by <application>repmgrd</application> (streaming replication mode):
|
||||
|
||||
<itemizedlist spacing="compact" mark="bullet">
|
||||
<listitem>
|
||||
<simpara><literal>repmgrd_start</literal></simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara><literal>repmgrd_shutdown</literal></simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara><literal>repmgrd_reload</literal></simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara><literal>repmgrd_failover_promote</literal></simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara><literal>repmgrd_failover_follow</literal></simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara><literal>repmgrd_failover_aborted</literal></simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara><literal>repmgrd_standby_reconnect</literal></simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara><literal>repmgrd_promote_error</literal></simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara><literal>repmgrd_local_disconnect</literal></simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara><literal>repmgrd_local_reconnect</literal></simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara><literal>repmgrd_upstream_disconnect</literal></simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara><literal>repmgrd_upstream_reconnect</literal></simpara>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<simpara><literal>standby_disconnect_manual</literal></simpara>
|
||||
</listitem>
|
||||
@@ -254,13 +184,42 @@
|
||||
<listitem>
|
||||
<simpara><literal>standby_recovery</literal></simpara>
|
||||
</listitem>
|
||||
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Events generated by <application>repmgrd</application> (BDR mode):
|
||||
<itemizedlist spacing="compact" mark="bullet">
|
||||
<listitem>
|
||||
<simpara><literal>witness_register</literal></simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara><literal>witness_unregister</literal></simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara><literal>node_rejoin</literal></simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara><literal>repmgrd_start</literal></simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara><literal>repmgrd_shutdown</literal></simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara><literal>repmgrd_failover_promote</literal></simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara><literal>repmgrd_failover_follow</literal></simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara><literal>repmgrd_failover_aborted</literal></simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara><literal>repmgrd_upstream_disconnect</literal></simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara><literal>repmgrd_upstream_reconnect</literal></simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara><literal>repmgrd_promote_error</literal></simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara><literal>repmgrd_failover_promote</literal></simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara><literal>bdr_failover</literal></simpara>
|
||||
</listitem>
|
||||
|
||||
@@ -38,9 +38,8 @@
|
||||
<!ENTITY quickstart SYSTEM "quickstart.sgml">
|
||||
<!ENTITY configuration SYSTEM "configuration.sgml">
|
||||
<!ENTITY configuration-file SYSTEM "configuration-file.sgml">
|
||||
<!ENTITY configuration-file-required-settings SYSTEM "configuration-file-required-settings.sgml">
|
||||
<!ENTITY configuration-file-log-settings SYSTEM "configuration-file-log-settings.sgml">
|
||||
<!ENTITY configuration-file-service-commands SYSTEM "configuration-file-service-commands.sgml">
|
||||
<!ENTITY configuration-file-settings SYSTEM "configuration-file-settings.sgml">
|
||||
<!ENTITY configuration-service-commands SYSTEM "configuration-service-commands.sgml">
|
||||
<!ENTITY cloning-standbys SYSTEM "cloning-standbys.sgml">
|
||||
<!ENTITY promoting-standby SYSTEM "promoting-standby.sgml">
|
||||
<!ENTITY follow-new-primary SYSTEM "follow-new-primary.sgml">
|
||||
|
||||
@@ -5,27 +5,26 @@
|
||||
system.
|
||||
</para>
|
||||
|
||||
<sect2 id="installation-packages-redhat" xreflabel="Installing from packages on RHEL, CentOS and Fedora">
|
||||
<sect2 id="installation-packages-redhat" xreflabel="Installing from packages on RHEL, Fedora and CentOS">
|
||||
|
||||
<indexterm>
|
||||
<primary>installation</primary>
|
||||
<secondary>on Red Hat/CentOS/Fedora etc.</secondary>
|
||||
</indexterm>
|
||||
|
||||
<title>RedHat/CentOS/Fedora</title>
|
||||
<title>RedHat/Fedora/CentOS</title>
|
||||
<para>
|
||||
&repmgr; RPM packages for RedHat/CentOS variants and Fedora are available from the
|
||||
<ulink url="https://2ndquadrant.com">2ndQuadrant</ulink>
|
||||
<ulink url="https://dl.2ndquadrant.com/">public repository</ulink>; see following
|
||||
section for details.
|
||||
</para>
|
||||
<para>
|
||||
RPM packages for &repmgr; are also available via Yum through
|
||||
RPM packages for &repmgr; are available via Yum through
|
||||
the PostgreSQL Global Development Group RPM repository
|
||||
(<ulink url="https://yum.postgresql.org/">http://yum.postgresql.org/</ulink>).
|
||||
Follow the instructions for your distribution (RedHat, CentOS,
|
||||
Fedora, etc.) and architecture as detailed there. Note that it can take some days
|
||||
for new &repmgr; packages to become available via the this repository.
|
||||
Fedora, etc.) and architecture as detailed there.
|
||||
</para>
|
||||
<para>
|
||||
<ulink url="https://2ndquadrant.com">2ndQuadrant</ulink> also provides its
|
||||
own RPM packages which are made available
|
||||
at the same time as each &repmgr; release, as it can take some days for
|
||||
them to become available via the main PGDG repository. See following section for details:
|
||||
</para>
|
||||
<note>
|
||||
<para>
|
||||
@@ -38,62 +37,65 @@
|
||||
|
||||
<para>
|
||||
For more information on the package contents, including details of installation
|
||||
paths and relevant <link linkend="configuration-file-service-commands">service commands</link>,
|
||||
paths and relevant <link linkend="configuration-service-commands">service commands</link>,
|
||||
see the appendix section <xref linkend="packages-centos">.
|
||||
</para>
|
||||
|
||||
|
||||
<sect3 id="installation-packages-redhat-2ndq">
|
||||
<title>2ndQuadrant public RPM yum repository</title>
|
||||
|
||||
<title>2ndQuadrant repmgr yum repository</title>
|
||||
<para>
|
||||
Beginning with <ulink url="https://repmgr.org/docs/4.0/release-4.0.5.html">repmgr 4.0.5</ulink>,
|
||||
Beginning with <ulink url="http://repmgr.org/release-notes-3.1.3.html">repmgr 3.1.3</ulink>,
|
||||
<ulink url="https://2ndquadrant.com/">2ndQuadrant</ulink> provides a dedicated <literal>yum</literal>
|
||||
<ulink url="https://dl.2ndquadrant.com/">public repository</ulink> for 2ndQuadrant software,
|
||||
including &repmgr;. We recommend using this for all future &repmgr; releases.
|
||||
</para>
|
||||
<para>
|
||||
General instructions for using this repository can be found on its
|
||||
<ulink url="https://dl.2ndquadrant.com/">homepage</ulink>. Specific instructions
|
||||
for installing &repmgr; follow below.
|
||||
</para>
|
||||
repository for &repmgr; releases. This repository complements the main
|
||||
<ulink url="https://yum.postgresql.org/repopackages.php">PGDG community repository</ulink>,
|
||||
but enables repmgr users to access the latest &repmgr; packages before they are
|
||||
available via the PGDG repository, which can take several days to be updated following
|
||||
a fresh &repmgr; release.
|
||||
</para>
|
||||
<para>
|
||||
<emphasis>Installation</emphasis>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
Locate the repository RPM for your PostgreSQL version from the list at:
|
||||
<ulink url="https://dl.2ndquadrant.com/">https://dl.2ndquadrant.com/</ulink>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
Install the repository definition for your distribution and PostgreSQL version
|
||||
(this enables the 2ndQuadrant repository as a source of &repmgr; packages).
|
||||
</para>
|
||||
<para>
|
||||
For example, for PostgreSQL 10 on CentOS, execute:
|
||||
<programlisting>
|
||||
curl https://dl.2ndquadrant.com/default/release/get/10/rpm | sudo bash</programlisting>
|
||||
</para>
|
||||
<para>
|
||||
Verify that the repository is installed with:
|
||||
<programlisting>
|
||||
sudo yum repolist</programlisting>
|
||||
The output should contain two entries like this:
|
||||
<programlisting>
|
||||
2ndquadrant-dl-default-release-pg10/7/x86_64 2ndQuadrant packages (PG10) for 7 - x86_64 4
|
||||
2ndquadrant-dl-default-release-pg10-debug/7/x86_64 2ndQuadrant packages (PG10) for 7 - x86_64 - Debug 3</programlisting>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
Install the &repmgr version appropriate for your PostgreSQL version (e.g. <literal>repmgr10</literal>):
|
||||
Import the repository public key (optional but recommended):
|
||||
<programlisting>
|
||||
$ yum install repmgr10</programlisting>
|
||||
rpm --import http://packages.2ndquadrant.com/repmgr/RPM-GPG-KEY-repmgr</programlisting>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
Install the repository RPM for your distribution (this enables the 2ndQuadrant
|
||||
repository as a source of repmgr packages):
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<simpara>
|
||||
<emphasis>Fedora:</emphasis>
|
||||
<ulink url="http://packages.2ndquadrant.com/repmgr/yum-repo-rpms/repmgr-fedora-1.0-1.noarch.rpm">http://packages.2ndquadrant.com/repmgr/yum-repo-rpms/repmgr-fedora-1.0-1.noarch.rpm</ulink>
|
||||
</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>
|
||||
<emphasis>RHEL, CentOS etc:</emphasis>
|
||||
<ulink url="http://packages.2ndquadrant.com/repmgr/yum-repo-rpms/repmgr-rhel-1.0-1.noarch.rpm">http://packages.2ndquadrant.com/repmgr/yum-repo-rpms/repmgr-rhel-1.0-1.noarch.rpm</ulink>
|
||||
</simpara>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
<para>
|
||||
e.g.:
|
||||
<programlisting>
|
||||
$ yum install http://packages.2ndquadrant.com/repmgr/yum-repo-rpms/repmgr-rhel-1.0-1.noarch.rpm</programlisting>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
Install the repmgr version appropriate for your PostgreSQL version (e.g. <literal>repmgr96</literal>), e.g.:
|
||||
<programlisting>
|
||||
$ yum install repmgr96</programlisting>
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
@@ -103,13 +105,13 @@ $ yum install repmgr10</programlisting>
|
||||
<emphasis>Compatibility with PGDG Repositories</emphasis>
|
||||
</para>
|
||||
<para>
|
||||
The 2ndQuadrant &repmgr; yum repository packages use the same definitions and file system layout as the
|
||||
main PGDG repository.
|
||||
The 2ndQuadrant &repmgr; yum repository uses exactly the same package definitions as the
|
||||
main PGDG repository and is effectively a selective mirror for &repmgr; packages only.
|
||||
</para>
|
||||
<para>
|
||||
Normally <application>yum</application> will prioritize the repository with the most recent &repmgr; version.
|
||||
Once the PGDG repository has been updated, it doesn't matter which repository
|
||||
the packages are installed from.
|
||||
Normally yum should prioritize the repository with the most recent &repmgr; version.
|
||||
Once the PGDG repository has been updated, it doesn't matter which repository
|
||||
the packages are installed from.
|
||||
</para>
|
||||
<para>
|
||||
To ensure the 2ndQuadrant repository is always prioritised, install <literal>yum-plugin-priorities</literal>
|
||||
@@ -123,23 +125,30 @@ $ yum install repmgr10</programlisting>
|
||||
To install a specific package version, execute <command>yum --showduplicates list</command>
|
||||
for the package in question:
|
||||
<programlisting>
|
||||
[root@localhost ~]# yum --showduplicates list repmgr10
|
||||
[root@localhost ~]# yum --showduplicates list repmgr96
|
||||
Loaded plugins: fastestmirror
|
||||
Loading mirror speeds from cached hostfile
|
||||
* base: ftp.iij.ad.jp
|
||||
* extras: ftp.iij.ad.jp
|
||||
* updates: ftp.iij.ad.jp
|
||||
Available Packages
|
||||
repmgr10.x86_64 4.0.3-1.rhel7 pgdg10
|
||||
repmgr10.x86_64 4.0.4-1.rhel7 pgdg10
|
||||
repmgr10.x86_64 4.0.5-1.el7 2ndquadrant-repo-10</programlisting>
|
||||
repmgr96.x86_64 3.2-1.el6 2ndquadrant-repmgr
|
||||
repmgr96.x86_64 3.2.1-1.el6 2ndquadrant-repmgr
|
||||
repmgr96.x86_64 3.3-1.el6 2ndquadrant-repmgr
|
||||
repmgr96.x86_64 3.3.1-1.el6 2ndquadrant-repmgr
|
||||
repmgr96.x86_64 3.3.2-1.el6 2ndquadrant-repmgr
|
||||
repmgr96.x86_64 3.3.2-1.rhel6 pgdg96
|
||||
repmgr96.x86_64 4.0.0-1.el6 2ndquadrant-repmgr
|
||||
repmgr96.x86_64 4.0.0-1.rhel6 pgdg96</programlisting>
|
||||
then append the appropriate version number to the package name with a hyphen, e.g.:
|
||||
<programlisting>
|
||||
[root@localhost ~]# yum install repmgr10-4.0.3-1.rhel7</programlisting>
|
||||
[root@localhost ~]# yum install repmgr96-3.3.2-1.el6</programlisting>
|
||||
</para>
|
||||
</sect3>
|
||||
</sect2>
|
||||
|
||||
|
||||
|
||||
<sect2 id="installation-packages-debian" xreflabel="Installing from packages on Debian or Ubuntu">
|
||||
|
||||
<indexterm>
|
||||
@@ -155,74 +164,10 @@ $ yum install repmgr10</programlisting>
|
||||
</para>
|
||||
<para>
|
||||
For more information on the package contents, including details of installation
|
||||
paths and relevant <link linkend="configuration-file-service-commands">service commands</link>,
|
||||
paths and relevant <link linkend="configuration-service-commands">service commands</link>,
|
||||
see the appendix section <xref linkend="packages-debian-ubuntu">.
|
||||
</para>
|
||||
|
||||
<sect3 id="installation-packages-debian-ubuntu-2ndq">
|
||||
<title>2ndQuadrant public apt repository for Debian/Ubuntu</title>
|
||||
|
||||
<para>
|
||||
Beginning with <ulink url="https://repmgr.org/docs/4.0/release-4.0.5.html">repmgr 4.0.5</ulink>,
|
||||
<ulink url="https://2ndquadrant.com/">2ndQuadrant</ulink> provides a
|
||||
<ulink url="https://dl.2ndquadrant.com/">public apt repository</ulink> for 2ndQuadrant software,
|
||||
including &repmgr;.
|
||||
</para>
|
||||
<para>
|
||||
General instructions for using this repository can be found on its
|
||||
<ulink url="https://dl.2ndquadrant.com/">homepage</ulink>. Specific instructions
|
||||
for installing &repmgr; follow below.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
|
||||
<emphasis>Installation</emphasis>
|
||||
|
||||
<itemizedlist>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
Install the repository definition for your distribution and PostgreSQL version
|
||||
(this enables the 2ndQuadrant repository as a source of &repmgr; packages) by executing:
|
||||
<programlisting>
|
||||
curl https://dl.2ndquadrant.com/default/release/get/deb | sudo bash</programlisting>
|
||||
</para>
|
||||
<note>
|
||||
<para>
|
||||
This will automatically install the following additional packages, if not already present:
|
||||
<itemizedlist spacing="compact" mark="bullet">
|
||||
<listitem>
|
||||
<simpara><literal>lsb-release</literal></simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara><literal>apt-transport-https</literal></simpara>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</note>
|
||||
</listitem>
|
||||
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
Install the &repmgr version appropriate for your PostgreSQL version (e.g. <literal>repmgr10</literal>):
|
||||
<programlisting>
|
||||
$ apt-get install postgresql-10-repmgr</programlisting>
|
||||
</para>
|
||||
<note>
|
||||
<para>
|
||||
For packages for PostgreSQL 9.6 and earlier, the package name includes
|
||||
a period between major and minor version numbers, e.g.
|
||||
<literal>postgresql-9.6-repmgr</literal>.
|
||||
</para>
|
||||
</note>
|
||||
</listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</para>
|
||||
|
||||
</sect3>
|
||||
</sect2>
|
||||
|
||||
</sect1>
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
To install &repmgr; the prerequisites for compiling
|
||||
&postgres; must be installed. These are described in &postgres;'s
|
||||
documentation
|
||||
on <ulink url="https://www.postgresql.org/docs/current/static/install-requirements.html">build requirements</ulink>
|
||||
and <ulink url="https://www.postgresql.org/docs/current/static/docguide-toolsets.html">build requirements for documentation</ulink>.
|
||||
on <ulink url="https://www.postgresql.org/docs/current/install-requirements.html">build requirements</ulink>
|
||||
and <ulink url="https://www.postgresql.org/docs/current/docguide-toolsets.html">build requirements for documentation</ulink>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@@ -80,7 +80,7 @@
|
||||
</para>
|
||||
|
||||
<para>
|
||||
There are also tags for each &repmgr; release, e.g. <filename>4.0.5</filename>.
|
||||
There are also tags for each &repmgr; release, e.g. <filename>REL4_0_STABLE</filename>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
|
||||
@@ -234,34 +234,17 @@
|
||||
<para>
|
||||
<filename>repmgr.conf</filename> should not be stored inside the PostgreSQL data directory,
|
||||
as it could be overwritten when setting up or reinitialising the PostgreSQL
|
||||
server. See sections <xref linkend="configuration"> and <xref linkend="configuration-file">
|
||||
server. See sections on <xref linkend="configuration-file"> and <xref linkend="configuration-file-settings">
|
||||
for further details about <filename>repmgr.conf</filename>.
|
||||
</para>
|
||||
<tip>
|
||||
<simpara>
|
||||
For Debian-based distributions we recommend explictly setting
|
||||
<option>pg_bindir</option> to the directory where <command>pg_ctl</command> and other binaries
|
||||
<literal>pg_bindir</literal> to the directory where <command>pg_ctl</command> and other binaries
|
||||
not in the standard path are located. For PostgreSQL 9.6 this would be <filename>/usr/lib/postgresql/9.6/bin/</filename>.
|
||||
</simpara>
|
||||
</tip>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
&repmgr; only uses <option>pg_bindir</option> when it executes
|
||||
PostgreSQL binaries directly.
|
||||
</para>
|
||||
<para>
|
||||
For user-defined scripts such as <option>promote_command</option> and the
|
||||
various <option>service_*_command</option>s, you <emphasis>must</emphasis>
|
||||
always explicitly provide the full path to the binary or script being
|
||||
executed, even if it is &repmgr; itself.
|
||||
</para>
|
||||
<para>
|
||||
This is because these options can contain user-defined scripts in arbitrary
|
||||
locations, so prepending <option>pg_bindir</option> may break them.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
<para>
|
||||
See the file
|
||||
<ulink url="https://raw.githubusercontent.com/2ndQuadrant/repmgr/master/repmgr.conf.sample">repmgr.conf.sample</>
|
||||
|
||||
@@ -15,14 +15,9 @@
|
||||
<title>Description</title>
|
||||
<para>
|
||||
Purges monitoring history from the <literal>repmgr.monitoring_history</literal> table to
|
||||
prevent excessive table growth.
|
||||
</para>
|
||||
<para>
|
||||
By default <emphasis>all</emphasis> data will be removed; Use the <option>-k/--keep-history</option>
|
||||
option to specify the number of days of monitoring history to retain.
|
||||
</para>
|
||||
<para>
|
||||
This command can be executed manually or as a cronjob.
|
||||
prevent excessive table growth. Use the <literal>-k/--keep-history</literal> to specify the
|
||||
number of days of monitoring history to retain. This command can be used
|
||||
manually or as a cronjob.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
@@ -43,21 +38,4 @@
|
||||
<filename>repmgr.conf</filename>.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 id="repmgr-cluster-cleanup-events">
|
||||
<title>Event notifications</title>
|
||||
<para>
|
||||
A <literal>cluster_cleanup</literal> <link linkend="event-notifications">event notification</link> will be generated.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
|
||||
<refsect1>
|
||||
<title>See also</title>
|
||||
<para>
|
||||
For more details see the sections <xref linkend="repmgrd-monitoring"> and
|
||||
<xref linkend="repmgrd-monitoring-configuration">.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
</refentry>
|
||||
|
||||
@@ -38,34 +38,5 @@
|
||||
and therefore determine the state of outbound connections from that node.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Exit codes</title>
|
||||
<para>
|
||||
Following exit codes can be emitted by <command>repmgr cluster crosscheck</command>:
|
||||
</para>
|
||||
<variablelist>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>SUCCESS (0)</option></term>
|
||||
<listitem>
|
||||
<para>
|
||||
The check completed successfully and all nodes are reachable.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>ERR_NODE_STATUS (25)</option></term>
|
||||
<listitem>
|
||||
<para>
|
||||
One or more nodes could not be reached.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
</refentry>
|
||||
|
||||
|
||||
@@ -49,22 +49,6 @@
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Output format</title>
|
||||
<para>
|
||||
<itemizedlist spacing="compact" mark="bullet">
|
||||
|
||||
<listitem>
|
||||
<simpara>
|
||||
<literal>--csv</literal>: generate output in CSV format. Note that the <literal>Details</literal>
|
||||
column will currently not be emitted in CSV format.
|
||||
</simpara>
|
||||
</listitem>
|
||||
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Example</title>
|
||||
<para>
|
||||
|
||||
@@ -97,35 +97,5 @@
|
||||
useful result.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
|
||||
<refsect1>
|
||||
<title>Exit codes</title>
|
||||
<para>
|
||||
Following exit codes can be emitted by <command>repmgr cluster matrix</command>:
|
||||
</para>
|
||||
<variablelist>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>SUCCESS (0)</option></term>
|
||||
<listitem>
|
||||
<para>
|
||||
The check completed successfully and all nodes are reachable.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>ERR_NODE_STATUS (25)</option></term>
|
||||
<listitem>
|
||||
<para>
|
||||
One or more nodes could not be reached.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
</refentry>
|
||||
|
||||
|
||||
@@ -113,40 +113,4 @@
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
|
||||
<refsect1>
|
||||
<title>Exit codes</title>
|
||||
<para>
|
||||
Following exit codes can be emitted by <command>repmgr cluster show</command>:
|
||||
</para>
|
||||
<variablelist>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>SUCCESS (0)</option></term>
|
||||
<listitem>
|
||||
<para>
|
||||
No issues were detected.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>ERR_NODE_STATUS (25)</option></term>
|
||||
<listitem>
|
||||
<para>
|
||||
One or more issues were detected.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>See also</title>
|
||||
<para>
|
||||
<xref linkend="repmgr-node-status">, <xref linkend="repmgr-node-check">
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
</refentry>
|
||||
|
||||
@@ -61,9 +61,7 @@
|
||||
|
||||
<listitem>
|
||||
<simpara>
|
||||
<literal>--archive-ready</literal>: checks for WAL files which have not yet been archived,
|
||||
and returns <literal>WARNING</literal> or <literal>CRITICAL</literal> if the number
|
||||
exceeds <varname>archive_ready_warning</varname> or <varname>archive_ready_critical</varname> respectively.
|
||||
<literal>--archive-ready</literal>: checks for WAL files which have not yet been archived
|
||||
</simpara>
|
||||
</listitem>
|
||||
|
||||
@@ -79,110 +77,11 @@
|
||||
</simpara>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<simpara>
|
||||
<literal>--missing-slots</literal>: checks there are no missing replication slots
|
||||
</simpara>
|
||||
</listitem>
|
||||
|
||||
</itemizedlist>
|
||||
</para>
|
||||
<para>
|
||||
Individual checks can also be output in a Nagios-compatible format by additionally
|
||||
providing the option <literal>--nagios</literal>.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Output format</title>
|
||||
<para>
|
||||
<itemizedlist spacing="compact" mark="bullet">
|
||||
|
||||
<listitem>
|
||||
<simpara>
|
||||
<literal>--csv</literal>: generate output in CSV format (not available
|
||||
for individual checks)
|
||||
</simpara>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<simpara>
|
||||
<literal>--nagios</literal>: generate output in a Nagios-compatible format
|
||||
</simpara>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Exit codes</title>
|
||||
|
||||
<para>
|
||||
When executing <command>repmgr node check</command> with one of the individual
|
||||
checks listed above, &repmgr; will emit one of the following Nagios-style exit codes
|
||||
(even if <literal>--nagios</literal> is not supplied):
|
||||
|
||||
<itemizedlist spacing="compact" mark="bullet">
|
||||
|
||||
<listitem>
|
||||
<simpara>
|
||||
<literal>0</literal>: OK
|
||||
</simpara>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<simpara>
|
||||
<literal>1</literal>: WARNING
|
||||
</simpara>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<simpara>
|
||||
<literal>2</literal>: ERROR
|
||||
</simpara>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<simpara>
|
||||
<literal>3</literal>: UNKNOWN
|
||||
</simpara>
|
||||
</listitem>
|
||||
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
|
||||
|
||||
<para>
|
||||
Following exit codes can be emitted by <command>repmgr status check</command>
|
||||
if no individual check was specified.
|
||||
</para>
|
||||
<variablelist>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>SUCCESS (0)</option></term>
|
||||
<listitem>
|
||||
<para>
|
||||
No issues were detected.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>ERR_NODE_STATUS (25)</option></term>
|
||||
<listitem>
|
||||
<para>
|
||||
One or more issues were detected.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
|
||||
|
||||
<refsect1>
|
||||
<title>See also</title>
|
||||
<para>
|
||||
<xref linkend="repmgr-node-status">, <xref linkend="repmgr-cluster-show">
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
</refentry>
|
||||
|
||||
@@ -28,10 +28,6 @@
|
||||
If the node is running and needs to be attached to the current primary, use
|
||||
<xref linkend="repmgr-standby-follow">.
|
||||
</para>
|
||||
<para>
|
||||
Note <xref linkend="repmgr-standby-follow"> can only be used for standbys which have not diverged
|
||||
from the rest of the cluster.
|
||||
</para>
|
||||
</tip>
|
||||
</refsect1>
|
||||
|
||||
@@ -119,26 +115,8 @@
|
||||
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Configuration file settings</title>
|
||||
|
||||
<para>
|
||||
<itemizedlist spacing="compact" mark="bullet">
|
||||
<listitem>
|
||||
<simpara>
|
||||
<literal>node_rejoin_timeout</literal>:
|
||||
the maximum length of time (in seconds) to wait for
|
||||
the node to reconnect to the replication cluster (defaults to
|
||||
the value set in <literal>standby_reconnect_timeout</literal>,
|
||||
60 seconds).
|
||||
</simpara>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
|
||||
</refsect1>
|
||||
|
||||
<refsect1 id="repmgr-node-rejoin-events">
|
||||
<title>Event notifications</title>
|
||||
<para>
|
||||
A <literal>node_rejoin</literal> <link linkend="event-notifications">event notification</link> will be generated.
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<title>Example</title>
|
||||
<para>
|
||||
<programlisting>
|
||||
$ repmgr -f /etc/repmgr.conf node status
|
||||
$ repmgr -f /etc/repmgr.comf node status
|
||||
Node "node1":
|
||||
PostgreSQL version: 10beta1
|
||||
Total data size: 30 MB
|
||||
@@ -38,54 +38,10 @@
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Output format</title>
|
||||
<para>
|
||||
<itemizedlist spacing="compact" mark="bullet">
|
||||
|
||||
<listitem>
|
||||
<simpara>
|
||||
<literal>--csv</literal>: generate output in CSV format
|
||||
</simpara>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Exit codes</title>
|
||||
<para>
|
||||
Following exit codes can be emitted by <command>repmgr node status</command>:
|
||||
</para>
|
||||
<variablelist>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>SUCCESS (0)</option></term>
|
||||
<listitem>
|
||||
<para>
|
||||
No issues were detected.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>ERR_NODE_STATUS (25)</option></term>
|
||||
<listitem>
|
||||
<para>
|
||||
One or more issues were detected.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
|
||||
<refsect1>
|
||||
<title>See also</title>
|
||||
<para>
|
||||
See <xref linkend="repmgr-node-check"> to diagnose issues and <xref linkend="repmgr-cluster-show">
|
||||
for an overview of all nodes in the cluster.
|
||||
See <xref linkend="repmgr-node-check"> to diagnose issues.
|
||||
</para>
|
||||
</refsect1>
|
||||
</refentry>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<title>Description</title>
|
||||
<para>
|
||||
<command>repmgr primary register</command> registers a primary node in a
|
||||
streaming replication cluster, and configures it for use with &repmgr;, including
|
||||
streaming replication cluster, and configures it for use with repmgr, including
|
||||
installing the &repmgr; extension. This command needs to be executed before any
|
||||
standby nodes are registered.
|
||||
</para>
|
||||
@@ -75,18 +75,10 @@
|
||||
</refsect1>
|
||||
|
||||
|
||||
<refsect1 id="repmgr-primary-register-events">
|
||||
<refsect1>
|
||||
<title>Event notifications</title>
|
||||
<para>
|
||||
Following <link linkend="event-notifications">event notifications</link> will be generated:
|
||||
<itemizedlist spacing="compact" mark="bullet">
|
||||
<listitem>
|
||||
<simpara><literal>cluster_created</literal></simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara><literal>primary_register</literal></simpara>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
A <literal>primary_register</literal> <link linkend="event-notifications">event notification</link> will be generated.
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
|
||||
</refsect1>
|
||||
|
||||
<refsect1 id="repmgr-primary-unregister-events">
|
||||
<refsect1>
|
||||
<title>Event notifications</title>
|
||||
<para>
|
||||
A <literal>primary_unregister</literal> <link linkend="event-notifications">event notification</link> will be generated.
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
not be copied by default. &repmgr; can copy these files, either to the same
|
||||
location on the standby server (provided appropriate directory and file permissions
|
||||
are available), or into the standby's data directory. This requires passwordless
|
||||
SSH access to the primary server. Add the option <option>--copy-external-config-files</option>
|
||||
SSH access to the primary server. Add the option <literal>--copy-external-config-files</literal>
|
||||
to the <command>repmgr standby clone</command> command; by default files will be copied to
|
||||
the same path as on the upstream server. Note that the user executing <command>repmgr</command>
|
||||
must have write access to those directories.
|
||||
@@ -59,29 +59,12 @@
|
||||
<literal>--copy-external-config-files=pgdata</literal>, but note that
|
||||
any include directives in the copied files may need to be updated.
|
||||
</para>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
When executing <command>repmgr standby clone</command> with the
|
||||
<option>--copy-external-config-files</option> aand <option>--dry-run</option>
|
||||
options, &repmgr; will check the SSH connection to the source node, but
|
||||
will not verify whether the files can actually be copied.
|
||||
</para>
|
||||
<para>
|
||||
During the actual clone operation, a check will be made before the database itself
|
||||
is cloned to determine whether the files can actually be copied; if any problems are
|
||||
encountered, the clone operation will be aborted, enabling the user to fix
|
||||
any issues before retrying the clone operation.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
<tip>
|
||||
<simpara>
|
||||
For reliable configuration file management we recommend using a
|
||||
configuration management tool such as Ansible, Chef, Puppet or Salt.
|
||||
</simpara>
|
||||
</tip>
|
||||
|
||||
</refsect1>
|
||||
|
||||
<refsect1 id="repmgr-standby-clone-recovery-conf">
|
||||
@@ -141,7 +124,7 @@
|
||||
<para>
|
||||
We recommend using <ulink url="https://www.pgbarman.org/">Barman</ulink> to manage
|
||||
WAL file archiving. For more details on combining &repmgr; and <application>Barman</application>,
|
||||
in particular using <varname>restore_command</varname> to configure Barman as a backup source of
|
||||
in particular using <varname>restore_command</varname> to configure Barman as a backu source of
|
||||
WAL files, see <xref linkend="cloning-from-barman">.
|
||||
</para>
|
||||
</note>
|
||||
@@ -194,13 +177,12 @@
|
||||
<title>Using a standby cloned by another method</title>
|
||||
<para>
|
||||
&repmgr; supports standbys cloned by another method (e.g. using <application>barman</application>'s
|
||||
<command><ulink url="http://docs.pgbarman.org/release/2.4/#recover">barman recover</ulink></command> command).
|
||||
<command>barman recover</command> command).
|
||||
</para>
|
||||
<para>
|
||||
To integrate the standby as a &repmgr; node, ensure the <filename>repmgr.conf</filename>
|
||||
file is created for the node, and that it has been registered using
|
||||
<command><link linkend="repmgr-standby-register">repmgr standby register</link></command>.
|
||||
Then execute the command <command>repmgr standby clone --recovery-conf-only</command>.
|
||||
file is created for the node, then execute the command
|
||||
<command>repmgr standby clone --recovery-conf-only</command>.
|
||||
This will create the <filename>recovery.conf</filename> file needed to attach
|
||||
the node to its upstream, and will also create a replication slot on the
|
||||
upstream node if required.
|
||||
@@ -230,15 +212,6 @@
|
||||
|
||||
<variablelist>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>-d, --dbname=CONNINFO</option></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Connection string of the upstream node to use for cloning.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--dry-run</option></term>
|
||||
<listitem>
|
||||
@@ -350,7 +323,7 @@
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 id="repmgr-standby-clone-events">
|
||||
<refsect1>
|
||||
<title>Event notifications</title>
|
||||
<para>
|
||||
A <literal>standby_clone</literal> <link linkend="event-notifications">event notification</link> will be generated.
|
||||
|
||||
@@ -26,18 +26,10 @@
|
||||
running. It can only be used to attach an active standby to the current primary node
|
||||
(and not to another standby).
|
||||
</para>
|
||||
<tip>
|
||||
<para>
|
||||
To re-add an inactive node to the replication cluster, use
|
||||
<xref linkend="repmgr-node-rejoin">.
|
||||
</para>
|
||||
</tip>
|
||||
|
||||
<para>
|
||||
<command>repmgr standby follow</command> will wait up to
|
||||
<varname>standby_follow_timeout</varname> seconds (default: <literal>30</literal>)
|
||||
to verify the standby has actually connected to the new primary.
|
||||
</para>
|
||||
<para>
|
||||
To re-add an inactive node to the replication cluster, see
|
||||
<xref linkend="repmgr-node-rejoin">
|
||||
</para>
|
||||
|
||||
</refsect1>
|
||||
|
||||
@@ -94,13 +86,13 @@
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 id="repmgr-standby-follow-events">
|
||||
<refsect1>
|
||||
<title>Event notifications</title>
|
||||
<para>
|
||||
A <literal>standby_follow</literal> <link linkend="event-notifications">event notification</link> will be generated.
|
||||
</para>
|
||||
<para>
|
||||
If provided, &repmgr; will substitute the placeholders <literal>%p</literal> with the node ID of the primary
|
||||
If provided, &repmgr; will subsitute the placeholders <literal>%p</literal> with the node ID of the primary
|
||||
being followed, <literal>%c</literal> with its <literal>conninfo</literal> string, and
|
||||
<literal>%a</literal> with its node name.
|
||||
</para>
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
check the promotion every <varname>promote_check_interval</varname> seconds (default: 1 second).
|
||||
Both values can be defined in <filename>repmgr.conf</filename>.
|
||||
</para>
|
||||
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
@@ -50,7 +49,7 @@
|
||||
</refsect1>
|
||||
|
||||
|
||||
<refsect1 id="repmgr-standby-promote-events">
|
||||
<refsect1>
|
||||
<title>Event notifications</title>
|
||||
<para>
|
||||
A <literal>standby_promote</literal> <link linkend="event-notifications">event notification</link> will be generated.
|
||||
|
||||
@@ -159,7 +159,7 @@
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 id="repmgr-standby-register-events">
|
||||
<refsect1>
|
||||
<title>Event notifications</title>
|
||||
<para>
|
||||
A <literal>standby_register</literal> <link linkend="event-notifications">event notification</link>
|
||||
@@ -173,7 +173,7 @@
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If provided, &repmgr; will substitute the placeholders <literal>%p</literal> with the node ID of the
|
||||
If provided, &repmgr; will subsitute the placeholders <literal>%p</literal> with the node ID of the
|
||||
primary node, <literal>%c</literal> with its <literal>conninfo</literal> string, and
|
||||
<literal>%a</literal> with its node name.
|
||||
</para>
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
<refpurpose>promote a standby to primary and demote the existing primary to a standby</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
|
||||
<refsect1>
|
||||
<title>Description</title>
|
||||
|
||||
@@ -40,17 +39,6 @@
|
||||
For more details on performing a switchover, including preparation and configuration,
|
||||
see section <xref linkend="performing-switchover">.
|
||||
</para>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
<application>repmgrd</application> should not be active on any nodes while a switchover is being
|
||||
executed. This restriction may be lifted in a later version.
|
||||
</para>
|
||||
<para>
|
||||
&repmgr; will not perform the switchover if an exclusive backup is running on the current primary.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
@@ -166,8 +154,8 @@
|
||||
<listitem>
|
||||
<simpara>
|
||||
<literal>standby_reconnect_timeout</literal>:
|
||||
number of seconds to attempt to wait for the demoted primary
|
||||
to reconnect to the promoted primary (default: 60 seconds)
|
||||
Number of seconds to attempt to reconnect to the demoted primary
|
||||
once it has been restarted.
|
||||
</simpara>
|
||||
</listitem>
|
||||
|
||||
@@ -183,12 +171,10 @@
|
||||
Execute with the <literal>--dry-run</literal> option to test the switchover as far as
|
||||
possible without actually changing the status of either node.
|
||||
</para>
|
||||
<important>
|
||||
<para>
|
||||
<application>repmgrd</application> must be shut down on all nodes while a switchover is being
|
||||
executed. This restriction will be removed in a future &repmgr; version.
|
||||
</para>
|
||||
</important>
|
||||
<para>
|
||||
<application>repmgrd</application> should not be active on any nodes while a switchover is being
|
||||
executed. This restriction may be lifted in a later version.
|
||||
</para>
|
||||
<para>
|
||||
External database connections, e.g. from an application, should not be permitted while
|
||||
the switchover is taking place. In particular, active transactions on the primary
|
||||
@@ -196,7 +182,7 @@
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 id="repmgr-standby-switchover-events">
|
||||
<refsect1>
|
||||
<title>Event notifications</title>
|
||||
<para>
|
||||
<literal>standby_switchover</literal> and <literal>standby_promote</literal>
|
||||
@@ -213,7 +199,7 @@
|
||||
<refsect1>
|
||||
<title>Exit codes</title>
|
||||
<para>
|
||||
Following exit codes can be emitted by <command>repmgr standby switchover</command>:
|
||||
Following exit codes can be emitted by <literal>repmgr standby switchover</literal>:
|
||||
</para>
|
||||
<variablelist>
|
||||
|
||||
@@ -241,7 +227,7 @@
|
||||
<para>
|
||||
The switchover was executed but a problem was encountered.
|
||||
Typically this means the former primary could not be reattached
|
||||
as a standby. Check preceding log messages for more information.
|
||||
as a standby.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
<refsect1 id="repmgr-standby-unregister-events">
|
||||
<refsect1>
|
||||
<title>Event notifications</title>
|
||||
<para>
|
||||
A <literal>standby_unregister</literal> <link linkend="event-notifications">event notification</link> will be generated.
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
</refsect1>
|
||||
|
||||
|
||||
<refsect1 id="repmgr-witness-register-events">
|
||||
<refsect1>
|
||||
<title>Event notifications</title>
|
||||
<para>
|
||||
A <literal>witness_register</literal> <link linkend="event-notifications">event notification</link> will be generated.
|
||||
|
||||
@@ -20,10 +20,7 @@
|
||||
</para>
|
||||
<para>
|
||||
The node does not have to be running to be unregistered, however if this is the
|
||||
case then either provide connection information for the primary server, or
|
||||
execute <command>repmgr witness unregister</command> on a running node and
|
||||
provide the parameter <option>--node-id</option> with the node ID of the
|
||||
witness server.
|
||||
case then connection information for the primary server must be provided.
|
||||
</para>
|
||||
<para>
|
||||
Execute with the <literal>--dry-run</literal> option to check what would happen
|
||||
@@ -39,17 +36,17 @@
|
||||
INFO: connecting to witness node "node3" (ID: 3)
|
||||
INFO: unregistering witness node 3
|
||||
INFO: witness unregistration complete
|
||||
DETAIL: witness node with UD 3 successfully unregistered</programlisting>
|
||||
DETAIL: witness node with id 3 (conninfo: host=node3 dbname=repmgr user=repmgr port=5499) successfully unregistered</programlisting>
|
||||
</para>
|
||||
<para>
|
||||
Unregistering a non-running witness node:
|
||||
<programlisting>
|
||||
$ repmgr -f /etc/repmgr.conf witness unregister -h node1 -p 5501 -F
|
||||
INFO: connecting to node "node3" (ID: 3)
|
||||
NOTICE: unable to connect to node "node3" (ID: 3), removing node record on cluster primary only
|
||||
INFO: connecting to witness node "node3" (ID: 3)
|
||||
NOTICE: unable to connect to witness node "node3" (ID: 3), removing node record on cluster primary only
|
||||
INFO: unregistering witness node 3
|
||||
INFO: witness unregistration complete
|
||||
DETAIL: witness node with id ID 3 successfully unregistered</programlisting>
|
||||
DETAIL: witness node with id 3 (conninfo: host=node3 dbname=repmgr user=repmgr port=5499) successfully unregistered</programlisting>
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
@@ -65,34 +62,8 @@
|
||||
</para>
|
||||
</refsect1>
|
||||
|
||||
|
||||
<refsect1>
|
||||
|
||||
<title>Options</title>
|
||||
<variablelist>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--dry-run</option></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Check prerequisites but don't actually unregister the witness.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--node-id</option></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Unregister witness server with the specified node ID.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
|
||||
<refsect1 id="repmgr-witness-unregister-events">
|
||||
<title>Event notifications</title>
|
||||
<para>
|
||||
A <literal>witness_unregister</literal> <link linkend="event-notifications">event notification</link> will be generated.
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
</para>
|
||||
<note>
|
||||
<simpara>
|
||||
Due to the nature of BDR 1.x/2.x, it's only safe to use this solution for
|
||||
Due to the nature of BDR, it's only safe to use this solution for
|
||||
a two-node scenario. Introducing additional nodes will create an inherent
|
||||
risk of node desynchronisation if a node goes down without being cleanly
|
||||
removed from the cluster.
|
||||
@@ -99,16 +99,15 @@
|
||||
replication cluster. The database must be the BDR-enabled database.
|
||||
</para>
|
||||
<para>
|
||||
If defined, the <varname>event_notifications</varname> parameter will restrict
|
||||
execution of the script defined in <varname>event_notification_command</varname>
|
||||
If defined, the evenr <application>event_notifications</application> parameter
|
||||
will restrict execution of <varname>event_notification_command</varname>
|
||||
to the specified event(s).
|
||||
</para>
|
||||
<note>
|
||||
<simpara>
|
||||
<varname>event_notification_command</varname> is the script which does the actual "heavy lifting"
|
||||
of reconfiguring the proxy server/ connection pooler. It is fully
|
||||
user-definable; see section <xref linkend="bdr-event-notification-command"> for a reference
|
||||
implementation.
|
||||
user-definable; a reference implementation is documented below.
|
||||
</simpara>
|
||||
</note>
|
||||
|
||||
@@ -170,8 +169,8 @@
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
<sect1 id="bdr-event-notification-command" xreflabel="Defining the BDR failover "event_notification command"">
|
||||
<title>Defining the BDR failover "event_notification_command"</title>
|
||||
<sect1 id="bdr-event-notification-command" xreflabel="BDR failover event notification command">
|
||||
<title>Defining the "event_notification_command"</title>
|
||||
<para>
|
||||
Key to "failover" execution is the <literal>event_notification_command</literal>,
|
||||
which is a user-definable script specified in <filename>repmpgr.conf</filename>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
<para>
|
||||
To use <application>repmgrd</application>, its associated function library <emphasis>must</emphasis> be
|
||||
included via <filename>postgresql.conf</filename> with:
|
||||
included in <filename>postgresql.conf</filename> with:
|
||||
|
||||
<programlisting>
|
||||
shared_preload_libraries = 'repmgr'</programlisting>
|
||||
@@ -34,25 +34,6 @@
|
||||
the <ulink url="https://www.postgresql.org/docs/current/static/runtime-config-client.html#GUC-SHARED-PRELOAD-LIBRARIES">PostgreSQL documentation</ulink>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To apply configuration file changes to a running <application>repmgrd</application>
|
||||
daemon, execute the operating system's r<application>repmgrd</application> service reload command
|
||||
(see <xref linkend="appendix-packages"> for examples),
|
||||
or for instances which were manually started, execute <command>kill -HUP</command>, e.g.
|
||||
<command>kill -HUP `cat /tmp/repmgrd.pid`</command>.
|
||||
</para>
|
||||
<note>
|
||||
<para>
|
||||
Check the <application>repmgrd</application> log to see what changes were
|
||||
applied, or if any issues were encountered when reloading the configuration.
|
||||
</para>
|
||||
</note>
|
||||
<para>
|
||||
Note that only a subset of configuration file parameters can be changed on a
|
||||
running <application>repmgrd</application> daemon.
|
||||
</para>
|
||||
|
||||
|
||||
<sect2 id="repmgrd-automatic-failover-configuration">
|
||||
<title>automatic failover configuration</title>
|
||||
<para>
|
||||
@@ -64,17 +45,8 @@
|
||||
follow_command='/usr/bin/repmgr standby follow -f /etc/repmgr.conf --log-to-file --upstream-node-id=%n'</programlisting>
|
||||
</para>
|
||||
<para>
|
||||
Adjust file paths as appropriate; alway specify the full path to the &repmgr; binary.
|
||||
Adjust file paths as appropriate; we recomment specifying the full path to the &repmgr; binary.
|
||||
</para>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
&repmgr; will not apply <option>pg_bindir</option> when executing <option>promote_command</option>
|
||||
or <option>follow_command</option>; these can be user-defined scripts so must always be
|
||||
specified with the full path.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
<para>
|
||||
Note that the <literal>--log-to-file</literal> option will cause
|
||||
output generated by the &repmgr; command, when executed by <application>repmgrd</application>,
|
||||
@@ -140,11 +112,11 @@
|
||||
particularly on <application>systemd</application>-based systems.
|
||||
</para>
|
||||
<para>
|
||||
For more details, see <xref linkend="configuration-file-service-commands">.
|
||||
For more details, see <xref linkend="configuration-service-commands">.
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
<sect2 id="repmgrd-monitoring-configuration" xreflabel="repmgrd monitoring configuration">
|
||||
<sect2 id="repmgrd-monitoring-configuration">
|
||||
<indexterm>
|
||||
<primary>repmgrd</primary>
|
||||
<secondary>monitoring configuration</secondary>
|
||||
@@ -187,62 +159,16 @@
|
||||
<para>
|
||||
<application>repmgrd</application> can be started manually like this:
|
||||
<programlisting>
|
||||
repmgrd -f /etc/repmgr.conf --pid-file /tmp/repmgrd.pid</programlisting>
|
||||
repmgrd -f /etc/repmgr.conf --pid-file /tmp/repmgrd.pid --daemonize</programlisting>
|
||||
and stopped with <command>kill `cat /tmp/repmgrd.pid`</command>. Adjust paths as appropriate.
|
||||
</para>
|
||||
|
||||
<sect2 id="repmgrd-pid-file" xreflabel="repmgrd's PID file">
|
||||
<indexterm>
|
||||
<primary>repmgrd</primary>
|
||||
<secondary>PID file</secondary>
|
||||
</indexterm>
|
||||
<indexterm>
|
||||
<primary>PID file</primary>
|
||||
<secondary>repmgrd</secondary>
|
||||
</indexterm>
|
||||
<title>repmgrd's PID file</title>
|
||||
<para>
|
||||
<application>repmgrd</application> will generate a PID file by default.
|
||||
</para>
|
||||
<note>
|
||||
<simpara>
|
||||
This is a behaviour change from previous versions (earlier than 4.1), where
|
||||
the PID file had to be explicitly specified with the command line
|
||||
parameter <option> --pid-file</option>.
|
||||
</simpara>
|
||||
</note>
|
||||
<para>
|
||||
The PID file can be specified in <filename>repmgr.conf</filename> with the configuration
|
||||
parameter <varname>repmgrd_pid_file</varname>.
|
||||
</para>
|
||||
<para>
|
||||
It can also be specified on the command line (as in previous versions) with
|
||||
the command line parameter <option>--pid-file</option>. Note this will override
|
||||
any value set in <filename>repmgr.conf</filename> with <varname>repmgrd_pid_file</varname>.
|
||||
<option>--pid-file</option> may be deprecated in future releases.
|
||||
</para>
|
||||
<para>
|
||||
If a PID file location was specified by the package maintainer, <application>repmgrd</application>
|
||||
will use that. This only applies if &repmgr; was installed from a package and the package
|
||||
maintainer has specified the PID file location.
|
||||
</para>
|
||||
<para>
|
||||
If none of the above apply, <application>repmgrd</application> will create a PID file
|
||||
in the operating system's temporary directory (das etermined by the environment variable
|
||||
<varname>TMPDIR</varname>, or if that is not set, will use <filename>/tmp</filename>).
|
||||
</para>
|
||||
<para>
|
||||
To prevent a PID file being generated at all, provide the command line option
|
||||
<option>--no-pid-file</option>.
|
||||
</para>
|
||||
<para>
|
||||
To see which PID file <application>repmgrd</application> would use, execute <application>repmgrd</application>
|
||||
with the option <option>--show-pid-file</option>. <application>repmgrd</application>
|
||||
will not start if this option is provided. Note that the value shown is the
|
||||
file <application>repmgrd</application> would use next time it starts, and is
|
||||
not necessarily the PID file currently in use.
|
||||
</para>
|
||||
</sect2>
|
||||
<para>
|
||||
To apply configuration file changes to a running <application>repmgrd</application>
|
||||
daemon, execute the operating system's service reload command (for manually started
|
||||
instances, execute <command>kill -HUP `cat /tmp/repmgrd.pid`</command>).
|
||||
Note that only a subset of configuration file parameters can be changed on a
|
||||
running <application>repmgrd</application> daemon.
|
||||
</para>
|
||||
|
||||
<sect2 id="repmgrd-configuration-debian-ubuntu">
|
||||
<indexterm>
|
||||
@@ -332,34 +258,25 @@ REPMGRD_ENABLED=no
|
||||
<secondary>repmgrd</secondary>
|
||||
</indexterm>
|
||||
|
||||
<indexterm>
|
||||
<primary>repmgrd</primary>
|
||||
<secondary>log rotation</secondary>
|
||||
</indexterm>
|
||||
|
||||
<title>repmgrd log rotation</title>
|
||||
<para>
|
||||
To ensure the current <application>repmgrd</application> logfile
|
||||
(specified in <filename>repmgr.conf</filename> with the parameter
|
||||
<option>log_file</option>) does not grow indefinitely, configure your
|
||||
<option>log_file</option> does not grow indefinitely, configure your
|
||||
system's <command>logrotate</command> to regularly rotate it.
|
||||
</para>
|
||||
<para>
|
||||
Sample configuration to rotate logfiles weekly with retention for
|
||||
up to 52 weeks and rotation forced if a file grows beyond 100Mb:
|
||||
<programlisting>
|
||||
/var/log/repmgr/repmgrd.log {
|
||||
/var/log/postgresql/repmgr-9.6.log {
|
||||
missingok
|
||||
compress
|
||||
rotate 52
|
||||
maxsize 100M
|
||||
weekly
|
||||
create 0600 postgres postgres
|
||||
postrotate
|
||||
/usr/bin/killall -HUP repmgrd
|
||||
endscript
|
||||
}</programlisting>
|
||||
</para>
|
||||
|
||||
</sect1>
|
||||
</chapter>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<chapter id="repmgrd-degraded-monitoring" xreflabel="repmgrd degraded monitoring">
|
||||
<chapter id="repmgrd-degraded-monitoring">
|
||||
<indexterm>
|
||||
<primary>repmgrd</primary>
|
||||
<secondary>degraded monitoring</secondary>
|
||||
@@ -7,8 +7,8 @@
|
||||
<title>"degraded monitoring" mode</title>
|
||||
<para>
|
||||
In certain circumstances, <application>repmgrd</application> is not able to fulfill its primary mission
|
||||
of monitoring the node's upstream server. In these cases it enters "degraded monitoring"
|
||||
mode, where <application>repmgrd</application> remains active but is waiting for the situation
|
||||
of monitoring the nodes' upstream server. In these cases it enters "degraded
|
||||
monitoring" mode, where <application>repmgrd</application> remains active but is waiting for the situation
|
||||
to be resolved.
|
||||
</para>
|
||||
<para>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<chapter id="repmgrd-monitoring" xreflabel="Monitoring with repmgrd">
|
||||
<chapter id="repmgrd-monitoring">
|
||||
<indexterm>
|
||||
<primary>repmgrd</primary>
|
||||
<secondary>monitoring</secondary>
|
||||
|
||||
@@ -40,8 +40,8 @@
|
||||
In a failover situation, <application>repmgrd</application> will check if any servers in the
|
||||
same location as the current primary node are visible. If not, <application>repmgrd</application>
|
||||
will assume a network interruption and not promote any node in any
|
||||
other location (it will however enter <link linkend="repmgrd-degraded-monitoring">degraded monitoring</link>
|
||||
mode until a primary becomes visible).
|
||||
other location (it will however enter <xref linkend="repmgrd-degraded-monitoring"> mode until
|
||||
a primary becomes visible).
|
||||
</para>
|
||||
|
||||
</chapter>
|
||||
|
||||
@@ -57,14 +57,7 @@
|
||||
|
||||
<para>
|
||||
As mentioned in the previous section, success of the switchover operation depends on
|
||||
&repmgr; being able to shut down the current primary server quickly and cleanly.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Ensure that the promotion candidate has sufficient free walsenders available
|
||||
(PostgreSQL configuration item <varname>max_wal_senders</varname>), and if replication
|
||||
slots are in use, at least one free slot is available for the demotion candidate (
|
||||
PostgreSQL configuration item <varname>max_replication_slots</varname>).
|
||||
&repmgr; being able to shut down the current primary server quickly and cleanly.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@@ -111,7 +104,7 @@
|
||||
server.
|
||||
</para>
|
||||
<para>
|
||||
For more details, see <xref linkend="configuration-file-service-commands">.
|
||||
For more details, see <xref linkend="configuration-service-commands">.
|
||||
</para>
|
||||
</important>
|
||||
|
||||
@@ -128,21 +121,15 @@
|
||||
</simpara>
|
||||
</note>
|
||||
|
||||
|
||||
<para>
|
||||
Check that access from applications is minimalized or preferably blocked
|
||||
completely, so applications are not unexpectedly interrupted.
|
||||
Check that access from applications is minimalized or preferably blocked
|
||||
completely, so applications are not unexpectedly interrupted.
|
||||
</para>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
If an exclusive backup is running on the current primary, &repmgr; will not perform the
|
||||
switchover.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
<para>
|
||||
Check there is no significant replication lag on standbys attached to the
|
||||
current primary.
|
||||
Check there is no significant replication lag on standbys attached to the
|
||||
current primary.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@@ -153,13 +140,10 @@
|
||||
manually with <command>repmgr node check --archive-ready</command>.
|
||||
</para>
|
||||
|
||||
<note>
|
||||
<para>
|
||||
Ensure that <application>repmgrd</application> is *not* running anywhere to prevent it unintentionally
|
||||
promoting a node. This restriction will be removed in a future &repmgr; version.
|
||||
</para>
|
||||
</note>
|
||||
|
||||
<para>
|
||||
Ensure that <application>repmgrd</application> is *not* running anywhere to prevent it unintentionally
|
||||
promoting a node.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Finally, consider executing <command>repmgr standby switchover</command> with the
|
||||
|
||||
@@ -29,18 +29,8 @@
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>
|
||||
<application>repmgrd</application> (if running) must be restarted.
|
||||
</simpara>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<simpara>
|
||||
For major releases, e.g. from <literal>4.0.x</literal> to <literal>4.1</literal>,
|
||||
execute <command>ALTER EXTENSION repmgr UPDATE</command>
|
||||
on the primary node in the database where the &repmgr; extension is installed.
|
||||
</simpara>
|
||||
<simpara>
|
||||
This will update the extension metadata and, if necessary, apply
|
||||
changes to the &repmgr; extension objects.
|
||||
In the database where the &repmgr; extension is installed, execute
|
||||
<command>ALTER EXTENSION repmgr UPDATE</command>.
|
||||
</simpara>
|
||||
</listitem>
|
||||
</orderedlist>
|
||||
@@ -51,6 +41,10 @@
|
||||
release as they may contain upgrade instructions particular to individual versions.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If the <application>repmgrd</application> daemon is in use, we recommend stopping it
|
||||
before upgrading &repmgr;.
|
||||
</para>
|
||||
<para>
|
||||
Note that it may be necessary to restart the PostgreSQL server if the upgrade contains
|
||||
changes to the shared object file used by <application>repmgrd</application>; check the
|
||||
|
||||
@@ -1 +1 @@
|
||||
<!ENTITY repmgrversion "4.1.1">
|
||||
<!ENTITY repmgrversion "4.0.5">
|
||||
|
||||
@@ -46,6 +46,5 @@
|
||||
#define ERR_SWITCHOVER_INCOMPLETE 22
|
||||
#define ERR_FOLLOW_FAIL 23
|
||||
#define ERR_REJOIN_FAIL 24
|
||||
#define ERR_NODE_STATUS 25
|
||||
|
||||
#endif /* _ERRCODE_H_ */
|
||||
|
||||
19
log.c
19
log.c
@@ -42,7 +42,7 @@ _stderr_log_with_level(const char *level_name, int level, const char *fmt, va_li
|
||||
__attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 0)));
|
||||
|
||||
int log_type = REPMGR_STDERR;
|
||||
int log_level = LOG_INFO;
|
||||
int log_level = LOG_NOTICE;
|
||||
int last_log_level = LOG_INFO;
|
||||
int verbose_logging = false;
|
||||
int terse_logging = false;
|
||||
@@ -70,7 +70,7 @@ _stderr_log_with_level(const char *level_name, int level, const char *fmt, va_li
|
||||
|
||||
/*
|
||||
* Store the requested level so that if there's a subsequent log_hint() or
|
||||
* log_detail(), we can suppress that if --terse was specified,
|
||||
* log_detail(), we can suppress that if appropriate.
|
||||
*/
|
||||
last_log_level = level;
|
||||
|
||||
@@ -329,21 +329,6 @@ logger_set_terse(void)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
logger_set_level(int new_log_level)
|
||||
{
|
||||
log_level = new_log_level;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
logger_set_min_level(int min_log_level)
|
||||
{
|
||||
if (min_log_level > log_level)
|
||||
log_level = min_log_level;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
detect_log_level(const char *level)
|
||||
{
|
||||
|
||||
2
log.h
2
log.h
@@ -128,8 +128,6 @@ bool logger_shutdown(void);
|
||||
|
||||
void logger_set_verbose(void);
|
||||
void logger_set_terse(void);
|
||||
void logger_set_min_level(int min_log_level);
|
||||
void logger_set_level(int new_log_level);
|
||||
|
||||
void
|
||||
log_detail(const char *fmt,...)
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||
\echo Use "CREATE EXTENSION repmgr" to load this file. \quit
|
||||
167
repmgr--4.1.sql
167
repmgr--4.1.sql
@@ -1,167 +0,0 @@
|
||||
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||
\echo Use "CREATE EXTENSION repmgr" to load this file. \quit
|
||||
|
||||
CREATE TABLE repmgr.nodes (
|
||||
node_id INTEGER PRIMARY KEY,
|
||||
upstream_node_id INTEGER NULL REFERENCES nodes (node_id) DEFERRABLE,
|
||||
active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
node_name TEXT NOT NULL,
|
||||
type TEXT NOT NULL CHECK (type IN('primary','standby','witness','bdr')),
|
||||
location TEXT NOT NULL DEFAULT 'default',
|
||||
priority INT NOT NULL DEFAULT 100,
|
||||
conninfo TEXT NOT NULL,
|
||||
repluser VARCHAR(63) NOT NULL,
|
||||
slot_name TEXT NULL,
|
||||
config_file TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE repmgr.events (
|
||||
node_id INTEGER NOT NULL,
|
||||
event TEXT NOT NULL,
|
||||
successful BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
event_timestamp TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
details TEXT NULL
|
||||
);
|
||||
|
||||
DO $repmgr$
|
||||
DECLARE
|
||||
DECLARE server_version_num INT;
|
||||
BEGIN
|
||||
SELECT setting
|
||||
FROM pg_catalog.pg_settings
|
||||
WHERE name = 'server_version_num'
|
||||
INTO server_version_num;
|
||||
IF server_version_num >= 90400 THEN
|
||||
EXECUTE $repmgr_func$
|
||||
CREATE TABLE repmgr.monitoring_history (
|
||||
primary_node_id INTEGER NOT NULL,
|
||||
standby_node_id INTEGER NOT NULL,
|
||||
last_monitor_time TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
last_apply_time TIMESTAMP WITH TIME ZONE,
|
||||
last_wal_primary_location PG_LSN NOT NULL,
|
||||
last_wal_standby_location PG_LSN,
|
||||
replication_lag BIGINT NOT NULL,
|
||||
apply_lag BIGINT NOT NULL
|
||||
)
|
||||
$repmgr_func$;
|
||||
ELSE
|
||||
EXECUTE $repmgr_func$
|
||||
CREATE TABLE repmgr.monitoring_history (
|
||||
primary_node_id INTEGER NOT NULL,
|
||||
standby_node_id INTEGER NOT NULL,
|
||||
last_monitor_time TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||
last_apply_time TIMESTAMP WITH TIME ZONE,
|
||||
last_wal_primary_location TEXT NOT NULL,
|
||||
last_wal_standby_location TEXT,
|
||||
replication_lag BIGINT NOT NULL,
|
||||
apply_lag BIGINT NOT NULL
|
||||
)
|
||||
$repmgr_func$;
|
||||
END IF;
|
||||
END$repmgr$;
|
||||
|
||||
|
||||
|
||||
CREATE INDEX idx_monitoring_history_time
|
||||
ON repmgr.monitoring_history (last_monitor_time, standby_node_id);
|
||||
|
||||
CREATE VIEW repmgr.show_nodes AS
|
||||
SELECT n.node_id,
|
||||
n.node_name,
|
||||
n.active,
|
||||
n.upstream_node_id,
|
||||
un.node_name AS upstream_node_name,
|
||||
n.type,
|
||||
n.priority,
|
||||
n.conninfo
|
||||
FROM repmgr.nodes n
|
||||
LEFT JOIN repmgr.nodes un
|
||||
ON un.node_id = n.upstream_node_id;
|
||||
|
||||
|
||||
/* XXX update upgrade scripts! */
|
||||
CREATE TABLE repmgr.voting_term (
|
||||
term INT NOT NULL
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX voting_term_restrict
|
||||
ON repmgr.voting_term ((TRUE));
|
||||
|
||||
CREATE RULE voting_term_delete AS
|
||||
ON DELETE TO repmgr.voting_term
|
||||
DO INSTEAD NOTHING;
|
||||
|
||||
|
||||
/* ================= */
|
||||
/* repmgrd functions */
|
||||
/* ================= */
|
||||
|
||||
/* monitoring functions */
|
||||
|
||||
CREATE FUNCTION set_local_node_id(INT)
|
||||
RETURNS VOID
|
||||
AS 'MODULE_PATHNAME', 'set_local_node_id'
|
||||
LANGUAGE C STRICT;
|
||||
|
||||
CREATE FUNCTION get_local_node_id()
|
||||
RETURNS INT
|
||||
AS 'MODULE_PATHNAME', 'get_local_node_id'
|
||||
LANGUAGE C STRICT;
|
||||
|
||||
CREATE FUNCTION standby_set_last_updated()
|
||||
RETURNS TIMESTAMP WITH TIME ZONE
|
||||
AS 'MODULE_PATHNAME', 'standby_set_last_updated'
|
||||
LANGUAGE C STRICT;
|
||||
|
||||
CREATE FUNCTION standby_get_last_updated()
|
||||
RETURNS TIMESTAMP WITH TIME ZONE
|
||||
AS 'MODULE_PATHNAME', 'standby_get_last_updated'
|
||||
LANGUAGE C STRICT;
|
||||
|
||||
/* failover functions */
|
||||
|
||||
CREATE FUNCTION notify_follow_primary(INT)
|
||||
RETURNS VOID
|
||||
AS 'MODULE_PATHNAME', 'notify_follow_primary'
|
||||
LANGUAGE C STRICT;
|
||||
|
||||
CREATE FUNCTION get_new_primary()
|
||||
RETURNS INT
|
||||
AS 'MODULE_PATHNAME', 'get_new_primary'
|
||||
LANGUAGE C STRICT;
|
||||
|
||||
CREATE FUNCTION reset_voting_status()
|
||||
RETURNS VOID
|
||||
AS 'MODULE_PATHNAME', 'reset_voting_status'
|
||||
LANGUAGE C STRICT;
|
||||
|
||||
CREATE FUNCTION am_bdr_failover_handler(INT)
|
||||
RETURNS BOOL
|
||||
AS 'MODULE_PATHNAME', 'am_bdr_failover_handler'
|
||||
LANGUAGE C STRICT;
|
||||
|
||||
CREATE FUNCTION unset_bdr_failover_handler()
|
||||
RETURNS VOID
|
||||
AS 'MODULE_PATHNAME', 'unset_bdr_failover_handler'
|
||||
LANGUAGE C STRICT;
|
||||
|
||||
|
||||
CREATE VIEW repmgr.replication_status AS
|
||||
SELECT m.primary_node_id, m.standby_node_id, n.node_name AS standby_name,
|
||||
n.type AS node_type, n.active, last_monitor_time,
|
||||
CASE WHEN n.type='standby' THEN m.last_wal_primary_location ELSE NULL END AS last_wal_primary_location,
|
||||
m.last_wal_standby_location,
|
||||
CASE WHEN n.type='standby' THEN pg_catalog.pg_size_pretty(m.replication_lag) ELSE NULL END AS replication_lag,
|
||||
CASE WHEN n.type='standby' THEN
|
||||
CASE WHEN replication_lag > 0 THEN age(now(), m.last_apply_time) ELSE '0'::INTERVAL END
|
||||
ELSE NULL
|
||||
END AS replication_time_lag,
|
||||
CASE WHEN n.type='standby' THEN pg_catalog.pg_size_pretty(m.apply_lag) ELSE NULL END AS apply_lag,
|
||||
AGE(NOW(), CASE WHEN pg_catalog.pg_is_in_recovery() THEN repmgr.standby_get_last_updated() ELSE m.last_monitor_time END) AS communication_time_lag
|
||||
FROM repmgr.monitoring_history m
|
||||
JOIN repmgr.nodes n ON m.standby_node_id = n.node_id
|
||||
WHERE (m.standby_node_id, m.last_monitor_time) IN (
|
||||
SELECT m1.standby_node_id, MAX(m1.last_monitor_time)
|
||||
FROM repmgr.monitoring_history m1 GROUP BY 1
|
||||
);
|
||||
|
||||
@@ -83,10 +83,9 @@ do_bdr_register(void)
|
||||
exit(ERR_BAD_CONFIG);
|
||||
}
|
||||
|
||||
/* BDR 2 implementation is for 2 nodes only */
|
||||
if (get_bdr_version_num() < 3 && bdr_nodes.node_count > 2)
|
||||
if (bdr_nodes.node_count > 2)
|
||||
{
|
||||
log_error(_("repmgr can only support BDR 2.x clusters with 2 nodes"));
|
||||
log_error(_("repmgr can only support BDR clusters with 2 nodes"));
|
||||
log_detail(_("this BDR cluster has %i nodes"), bdr_nodes.node_count);
|
||||
PQfinish(conn);
|
||||
pfree(dbname);
|
||||
@@ -177,7 +176,6 @@ do_bdr_register(void)
|
||||
|
||||
if (bdr_node_has_repmgr_set(conn, config_file_options.node_name) == false)
|
||||
{
|
||||
log_debug("bdr_node_has_repmgr_set() = false");
|
||||
bdr_node_set_repmgr_set(conn, config_file_options.node_name);
|
||||
}
|
||||
|
||||
@@ -203,7 +201,6 @@ do_bdr_register(void)
|
||||
if (bdr_nodes.node_count == 0)
|
||||
{
|
||||
log_error(_("unable to retrieve any BDR node records"));
|
||||
log_detail("%s", PQerrorMessage(conn));
|
||||
PQfinish(conn);
|
||||
exit(ERR_BAD_CONFIG);
|
||||
}
|
||||
@@ -255,35 +252,7 @@ do_bdr_register(void)
|
||||
}
|
||||
|
||||
/* Add the repmgr extension tables to a replication set */
|
||||
|
||||
if (get_bdr_version_num() < 3)
|
||||
{
|
||||
add_extension_tables_to_bdr_replication_set(conn);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* this is the only table we need to replicate */
|
||||
char *replication_set = get_default_bdr_replication_set(conn);
|
||||
|
||||
/*
|
||||
* this probably won't happen, but we need to be sure we're using
|
||||
* the replication set metadata correctly...
|
||||
*/
|
||||
if (conn == NULL)
|
||||
{
|
||||
log_error(_("unable to retrieve default BDR replication set"));
|
||||
log_hint(_("see preceding messages"));
|
||||
log_debug("check query in get_default_bdr_replication_set()");
|
||||
exit(ERR_BAD_CONFIG);
|
||||
}
|
||||
|
||||
if (is_table_in_bdr_replication_set(conn, "nodes", replication_set) == false)
|
||||
{
|
||||
add_table_to_bdr_replication_set(conn, "nodes", replication_set);
|
||||
}
|
||||
|
||||
pfree(replication_set);
|
||||
}
|
||||
add_extension_tables_to_bdr_replication_set(conn);
|
||||
|
||||
initPQExpBuffer(&event_details);
|
||||
|
||||
|
||||
@@ -83,7 +83,6 @@ do_cluster_show(void)
|
||||
int i = 0;
|
||||
ItemList warnings = {NULL, NULL};
|
||||
bool success = false;
|
||||
bool error_found = false;
|
||||
|
||||
/* Connect to local database to obtain cluster connection data */
|
||||
log_verbose(LOG_INFO, _("connecting to database"));
|
||||
@@ -219,7 +218,6 @@ do_cluster_show(void)
|
||||
else
|
||||
{
|
||||
appendPQExpBuffer(&details, "- failed");
|
||||
error_found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -283,7 +281,6 @@ do_cluster_show(void)
|
||||
else
|
||||
{
|
||||
appendPQExpBuffer(&details, "- failed");
|
||||
error_found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -295,27 +292,17 @@ do_cluster_show(void)
|
||||
if (cell->node_info->node_status == NODE_STATUS_UP)
|
||||
{
|
||||
if (cell->node_info->active == true)
|
||||
{
|
||||
appendPQExpBuffer(&details, "* running");
|
||||
}
|
||||
else
|
||||
{
|
||||
appendPQExpBuffer(&details, "! running");
|
||||
error_found = true;
|
||||
}
|
||||
}
|
||||
/* node is unreachable */
|
||||
else
|
||||
{
|
||||
if (cell->node_info->active == true)
|
||||
{
|
||||
appendPQExpBuffer(&details, "? unreachable");
|
||||
}
|
||||
else
|
||||
{
|
||||
appendPQExpBuffer(&details, "- failed");
|
||||
error_found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -323,7 +310,6 @@ do_cluster_show(void)
|
||||
{
|
||||
/* this should never happen */
|
||||
appendPQExpBuffer(&details, "? unknown node type");
|
||||
error_found = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -428,6 +414,7 @@ do_cluster_show(void)
|
||||
PQfinish(conn);
|
||||
|
||||
/* emit any warnings */
|
||||
|
||||
if (warnings.head != NULL && runtime_options.terse == false && runtime_options.output_mode != OM_CSV)
|
||||
{
|
||||
ItemListCell *cell = NULL;
|
||||
@@ -438,20 +425,6 @@ do_cluster_show(void)
|
||||
printf(_(" - %s\n"), cell->string);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If warnings were noted, even if they're not displayed (e.g. in --csv node),
|
||||
* that means something's not right so we need to emit a non-zero exit code.
|
||||
*/
|
||||
if (warnings.head != NULL)
|
||||
{
|
||||
error_found = true;
|
||||
}
|
||||
|
||||
if (error_found == true)
|
||||
{
|
||||
exit(ERR_NODE_STATUS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -463,7 +436,6 @@ do_cluster_show(void)
|
||||
* --all
|
||||
* --node-[id|name]
|
||||
* --event
|
||||
* --csv
|
||||
*/
|
||||
|
||||
void
|
||||
@@ -508,12 +480,8 @@ do_cluster_event(void)
|
||||
strncpy(headers_event[EV_TIMESTAMP].title, _("Timestamp"), MAXLEN);
|
||||
strncpy(headers_event[EV_DETAILS].title, _("Details"), MAXLEN);
|
||||
|
||||
/*
|
||||
* If --terse or --csv provided, simply omit the "Details" column.
|
||||
* In --csv mode we'd need to quote/escape the contents "Details" column,
|
||||
* which is doable but which will remain a TODO for now.
|
||||
*/
|
||||
if (runtime_options.terse == true || runtime_options.output_mode == OM_CSV)
|
||||
/* if --terse provided, simply omit the "Details" column */
|
||||
if (runtime_options.terse == true)
|
||||
column_count --;
|
||||
|
||||
for (i = 0; i < column_count; i++)
|
||||
@@ -536,64 +504,47 @@ do_cluster_event(void)
|
||||
|
||||
}
|
||||
|
||||
if (runtime_options.output_mode == OM_TEXT)
|
||||
for (i = 0; i < column_count; i++)
|
||||
{
|
||||
for (i = 0; i < column_count; i++)
|
||||
{
|
||||
if (i == 0)
|
||||
printf(" ");
|
||||
else
|
||||
printf(" | ");
|
||||
if (i == 0)
|
||||
printf(" ");
|
||||
else
|
||||
printf(" | ");
|
||||
|
||||
printf("%-*s",
|
||||
headers_event[i].max_length,
|
||||
headers_event[i].title);
|
||||
}
|
||||
printf("\n");
|
||||
printf("-");
|
||||
for (i = 0; i < column_count; i++)
|
||||
{
|
||||
int j;
|
||||
|
||||
for (j = 0; j < headers_event[i].max_length; j++)
|
||||
printf("-");
|
||||
|
||||
if (i < (column_count - 1))
|
||||
printf("-+-");
|
||||
else
|
||||
printf("-");
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
printf("%-*s",
|
||||
headers_event[i].max_length,
|
||||
headers_event[i].title);
|
||||
}
|
||||
printf("\n");
|
||||
printf("-");
|
||||
for (i = 0; i < column_count; i++)
|
||||
{
|
||||
int j;
|
||||
|
||||
for (j = 0; j < headers_event[i].max_length; j++)
|
||||
printf("-");
|
||||
|
||||
if (i < (column_count - 1))
|
||||
printf("-+-");
|
||||
else
|
||||
printf("-");
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
for (i = 0; i < PQntuples(res); i++)
|
||||
{
|
||||
int j;
|
||||
|
||||
if (runtime_options.output_mode == OM_CSV)
|
||||
printf(" ");
|
||||
for (j = 0; j < column_count; j++)
|
||||
{
|
||||
for (j = 0; j < column_count; j++)
|
||||
{
|
||||
printf("%s", PQgetvalue(res, i, j));
|
||||
if ((j + 1) < column_count)
|
||||
{
|
||||
printf(",");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf(" ");
|
||||
for (j = 0; j < column_count; j++)
|
||||
{
|
||||
printf("%-*s",
|
||||
headers_event[j].max_length,
|
||||
PQgetvalue(res, i, j));
|
||||
printf("%-*s",
|
||||
headers_event[j].max_length,
|
||||
PQgetvalue(res, i, j));
|
||||
|
||||
if (j < (column_count - 1))
|
||||
printf(" | ");
|
||||
}
|
||||
if (j < (column_count - 1))
|
||||
printf(" | ");
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
@@ -603,8 +554,7 @@ do_cluster_event(void)
|
||||
|
||||
PQfinish(conn);
|
||||
|
||||
if (runtime_options.output_mode == OM_TEXT)
|
||||
puts("");
|
||||
puts("");
|
||||
}
|
||||
|
||||
|
||||
@@ -619,8 +569,6 @@ do_cluster_crosscheck(void)
|
||||
|
||||
t_node_status_cube **cube;
|
||||
|
||||
bool error_found = false;
|
||||
|
||||
n = build_cluster_crosscheck(&cube, &name_length);
|
||||
if (runtime_options.output_mode == OM_CSV)
|
||||
{
|
||||
@@ -700,11 +648,9 @@ do_cluster_crosscheck(void)
|
||||
{
|
||||
case -2:
|
||||
c = '?';
|
||||
error_found = true;
|
||||
break;
|
||||
case -1:
|
||||
c = 'x';
|
||||
error_found = true;
|
||||
break;
|
||||
case 0:
|
||||
c = '*';
|
||||
@@ -743,11 +689,6 @@ do_cluster_crosscheck(void)
|
||||
|
||||
free(cube);
|
||||
}
|
||||
|
||||
if (error_found == true)
|
||||
{
|
||||
exit(ERR_NODE_STATUS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -763,8 +704,6 @@ do_cluster_matrix()
|
||||
|
||||
t_node_matrix_rec **matrix_rec_list;
|
||||
|
||||
bool error_found = false;
|
||||
|
||||
n = build_cluster_matrix(&matrix_rec_list, &name_length);
|
||||
|
||||
if (runtime_options.output_mode == OM_CSV)
|
||||
@@ -803,11 +742,9 @@ do_cluster_matrix()
|
||||
{
|
||||
case -2:
|
||||
c = '?';
|
||||
error_found = true;
|
||||
break;
|
||||
case -1:
|
||||
c = 'x';
|
||||
error_found = true;
|
||||
break;
|
||||
case 0:
|
||||
c = '*';
|
||||
@@ -833,11 +770,6 @@ do_cluster_matrix()
|
||||
}
|
||||
|
||||
free(matrix_rec_list);
|
||||
|
||||
if (error_found == true)
|
||||
{
|
||||
exit(ERR_NODE_STATUS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1332,7 +1264,6 @@ do_cluster_cleanup(void)
|
||||
PGconn *conn = NULL;
|
||||
PGconn *primary_conn = NULL;
|
||||
int entries_to_delete = 0;
|
||||
PQExpBufferData event_details;
|
||||
|
||||
conn = establish_db_connection(config_file_options.conninfo, true);
|
||||
|
||||
@@ -1346,13 +1277,7 @@ do_cluster_cleanup(void)
|
||||
|
||||
entries_to_delete = get_number_of_monitoring_records_to_delete(primary_conn, runtime_options.keep_history);
|
||||
|
||||
if (entries_to_delete < 0)
|
||||
{
|
||||
log_error(_("unable to query number of monitoring records to clean up"));
|
||||
PQfinish(primary_conn);
|
||||
exit(ERR_DB_QUERY);
|
||||
}
|
||||
else if (entries_to_delete == 0)
|
||||
if (entries_to_delete == 0)
|
||||
{
|
||||
log_info(_("no monitoring records to delete"));
|
||||
PQfinish(primary_conn);
|
||||
@@ -1362,23 +1287,10 @@ do_cluster_cleanup(void)
|
||||
log_debug("at least %i monitoring records for deletion",
|
||||
entries_to_delete);
|
||||
|
||||
initPQExpBuffer(&event_details);
|
||||
|
||||
if (delete_monitoring_records(primary_conn, runtime_options.keep_history) == false)
|
||||
{
|
||||
appendPQExpBuffer(&event_details,
|
||||
_("unable to delete monitoring records"));
|
||||
|
||||
log_error("%s", event_details.data);
|
||||
log_error(_("unable to delete monitoring records"));
|
||||
log_detail("%s", PQerrorMessage(primary_conn));
|
||||
|
||||
create_event_notification(primary_conn,
|
||||
&config_file_options,
|
||||
config_file_options.node_id,
|
||||
"cluster_cleanup",
|
||||
false,
|
||||
event_details.data);
|
||||
|
||||
PQfinish(primary_conn);
|
||||
exit(ERR_DB_QUERY);
|
||||
}
|
||||
@@ -1390,22 +1302,7 @@ do_cluster_cleanup(void)
|
||||
log_detail("%s", PQerrorMessage(primary_conn));
|
||||
}
|
||||
|
||||
appendPQExpBuffer(&event_details,
|
||||
_("monitoring records deleted"));
|
||||
|
||||
if (runtime_options.keep_history > 0)
|
||||
appendPQExpBuffer(&event_details,
|
||||
_("; records newer than %i day(s) retained"),
|
||||
runtime_options.keep_history);
|
||||
|
||||
create_event_notification(primary_conn,
|
||||
&config_file_options,
|
||||
config_file_options.node_id,
|
||||
"cluster_cleanup",
|
||||
true,
|
||||
event_details.data);
|
||||
|
||||
termPQExpBuffer(&event_details);
|
||||
PQfinish(primary_conn);
|
||||
|
||||
if (runtime_options.keep_history > 0)
|
||||
@@ -1432,7 +1329,6 @@ do_cluster_help(void)
|
||||
printf(_(" %s [OPTIONS] cluster matrix\n"), progname());
|
||||
printf(_(" %s [OPTIONS] cluster crosscheck\n"), progname());
|
||||
printf(_(" %s [OPTIONS] cluster event\n"), progname());
|
||||
printf(_(" %s [OPTIONS] cluster cleanup\n"), progname());
|
||||
puts("");
|
||||
|
||||
printf(_("CLUSTER SHOW\n"));
|
||||
@@ -1472,7 +1368,6 @@ do_cluster_help(void)
|
||||
printf(_(" --event filter specific event\n"));
|
||||
printf(_(" --node-id restrict entries to node with this ID\n"));
|
||||
printf(_(" --node-name restrict entries to node with this name\n"));
|
||||
printf(_(" --csv emit output as CSV\n"));
|
||||
puts("");
|
||||
|
||||
printf(_("CLUSTER CLEANUP\n"));
|
||||
|
||||
1372
repmgr-action-node.c
1372
repmgr-action-node.c
File diff suppressed because it is too large
Load Diff
@@ -64,10 +64,12 @@ do_primary_register(void)
|
||||
PQfinish(conn);
|
||||
exit(ERR_BAD_CONFIG);
|
||||
}
|
||||
|
||||
log_error(_("unable to determine server's recovery type"));
|
||||
PQfinish(conn);
|
||||
exit(ERR_DB_CONN);
|
||||
else
|
||||
{
|
||||
log_error(_("connection to node lost"));
|
||||
PQfinish(conn);
|
||||
exit(ERR_DB_CONN);
|
||||
}
|
||||
}
|
||||
|
||||
log_verbose(LOG_INFO, _("server is not in recovery"));
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -137,7 +137,7 @@ do_witness_register(void)
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: sanity check witness node is not part of main cluster; we could
|
||||
* TODO:sanity check witness node is not part of main cluster; we could
|
||||
* add a random application_name to the respective connections,
|
||||
* and do a simple check of pg_stat_activity
|
||||
*/
|
||||
@@ -193,26 +193,8 @@ do_witness_register(void)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that an active node with the same node_name doesn't exist already
|
||||
*/
|
||||
|
||||
record_status = get_node_record_by_name(primary_conn,
|
||||
config_file_options.node_name,
|
||||
&node_record);
|
||||
|
||||
|
||||
if (record_status == RECORD_FOUND)
|
||||
{
|
||||
if (node_record.active == true && node_record.node_id != config_file_options.node_id)
|
||||
{
|
||||
log_error(_("node %i exists already with node_name \"%s\""),
|
||||
node_record.node_id,
|
||||
config_file_options.node_name);
|
||||
PQfinish(primary_conn);
|
||||
exit(ERR_BAD_CONFIG);
|
||||
}
|
||||
}
|
||||
// XXX check other node with same name does not exist
|
||||
|
||||
/*
|
||||
* if repmgr.nodes contains entries, delete if -F/--force provided,
|
||||
@@ -243,7 +225,6 @@ do_witness_register(void)
|
||||
PQfinish(witness_conn);
|
||||
exit(SUCCESS);
|
||||
}
|
||||
|
||||
/* create record on primary */
|
||||
|
||||
/*
|
||||
@@ -310,59 +291,55 @@ do_witness_register(void)
|
||||
void
|
||||
do_witness_unregister(void)
|
||||
{
|
||||
PGconn *local_conn = NULL;
|
||||
PGconn *witness_conn = NULL;
|
||||
PGconn *primary_conn = NULL;
|
||||
t_node_info node_record = T_NODE_INFO_INITIALIZER;
|
||||
RecordStatus record_status = RECORD_NOT_FOUND;
|
||||
bool node_record_deleted = false;
|
||||
bool local_node_available = true;
|
||||
int witness_node_id = UNKNOWN_NODE_ID;
|
||||
bool witness_available = true;
|
||||
|
||||
if (runtime_options.node_id != UNKNOWN_NODE_ID)
|
||||
{
|
||||
/* user has specified the witness node id */
|
||||
witness_node_id = runtime_options.node_id;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* assume witness node is local node */
|
||||
witness_node_id = config_file_options.node_id;
|
||||
}
|
||||
|
||||
log_info(_("connecting to node \"%s\" (ID: %i)"),
|
||||
log_info(_("connecting to witness node \"%s\" (ID: %i)"),
|
||||
config_file_options.node_name,
|
||||
config_file_options.node_id);
|
||||
|
||||
local_conn = establish_db_connection_quiet(config_file_options.conninfo);
|
||||
witness_conn = establish_db_connection_quiet(config_file_options.conninfo);
|
||||
|
||||
if (PQstatus(local_conn) != CONNECTION_OK)
|
||||
if (PQstatus(witness_conn) != CONNECTION_OK)
|
||||
{
|
||||
if (!runtime_options.force)
|
||||
{
|
||||
log_error(_("unable to connect to node \"%s\" (ID: %i)"),
|
||||
log_error(_("unable to connect to witness node \"%s\" (ID: %i)"),
|
||||
config_file_options.node_name,
|
||||
config_file_options.node_id);
|
||||
log_detail("%s", PQerrorMessage(local_conn));
|
||||
log_detail("%s", PQerrorMessage(witness_conn));
|
||||
log_hint(_("provide -F/--force to remove the witness record if the server is not running"));
|
||||
exit(ERR_BAD_CONFIG);
|
||||
}
|
||||
|
||||
log_notice(_("unable to connect to witness node \"%s\" (ID: %i), removing node record on cluster primary only"),
|
||||
config_file_options.node_name,
|
||||
config_file_options.node_id);
|
||||
local_node_available = false;
|
||||
witness_available = false;
|
||||
}
|
||||
|
||||
if (local_node_available == true)
|
||||
if (witness_available == true)
|
||||
{
|
||||
primary_conn = get_primary_connection_quiet(local_conn, NULL, NULL);
|
||||
primary_conn = get_primary_connection_quiet(witness_conn, NULL, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Assume user has provided connection details for the primary server
|
||||
* Extract the repmgr user and database names from the conninfo string
|
||||
* provided in repmgr.conf
|
||||
*/
|
||||
get_conninfo_value(config_file_options.conninfo, "user", repmgr_user);
|
||||
get_conninfo_value(config_file_options.conninfo, "dbname", repmgr_db);
|
||||
|
||||
param_set_ine(&source_conninfo, "user", repmgr_user);
|
||||
param_set_ine(&source_conninfo, "dbname", repmgr_db);
|
||||
|
||||
primary_conn = establish_db_connection_by_params(&source_conninfo, false);
|
||||
|
||||
}
|
||||
|
||||
if (PQstatus(primary_conn) != CONNECTION_OK)
|
||||
@@ -370,26 +347,26 @@ do_witness_unregister(void)
|
||||
log_error(_("unable to connect to primary"));
|
||||
log_detail("%s", PQerrorMessage(primary_conn));
|
||||
|
||||
if (local_node_available == true)
|
||||
if (witness_available == true)
|
||||
{
|
||||
PQfinish(local_conn);
|
||||
PQfinish(witness_conn);
|
||||
}
|
||||
else if (runtime_options.connection_param_provided == false)
|
||||
else
|
||||
{
|
||||
log_hint(_("provide connection details for the primary server"));
|
||||
log_hint(_("provide connection details to primary server"));
|
||||
}
|
||||
exit(ERR_BAD_CONFIG);
|
||||
}
|
||||
|
||||
/* Check node exists and is really a witness */
|
||||
record_status = get_node_record(primary_conn, witness_node_id, &node_record);
|
||||
record_status = get_node_record(primary_conn, config_file_options.node_id, &node_record);
|
||||
|
||||
if (record_status != RECORD_FOUND)
|
||||
{
|
||||
log_error(_("no record found for node %i"), witness_node_id);
|
||||
log_error(_("no record found for node %i"), config_file_options.node_id);
|
||||
|
||||
if (local_node_available == true)
|
||||
PQfinish(local_conn);
|
||||
if (witness_available == true)
|
||||
PQfinish(witness_conn);
|
||||
PQfinish(primary_conn);
|
||||
|
||||
exit(ERR_BAD_CONFIG);
|
||||
@@ -397,17 +374,11 @@ do_witness_unregister(void)
|
||||
|
||||
if (node_record.type != WITNESS)
|
||||
{
|
||||
/*
|
||||
* The node (either explicitly provided with --node-id, or the local node)
|
||||
* is not a witness.
|
||||
*
|
||||
* TODO: scan node list and print hint about identity of known witness servers.
|
||||
*/
|
||||
log_error(_("node %i is not a witness node"), config_file_options.node_id);
|
||||
log_detail(_("node %i is a %s node"), config_file_options.node_id, get_node_type_string(node_record.type));
|
||||
|
||||
if (local_node_available == true)
|
||||
PQfinish(local_conn);
|
||||
if (witness_available == true)
|
||||
PQfinish(witness_conn);
|
||||
PQfinish(primary_conn);
|
||||
|
||||
exit(ERR_BAD_CONFIG);
|
||||
@@ -416,43 +387,49 @@ do_witness_unregister(void)
|
||||
if (runtime_options.dry_run == true)
|
||||
{
|
||||
log_info(_("prerequisites for unregistering the witness node are met"));
|
||||
if (local_node_available == true)
|
||||
PQfinish(local_conn);
|
||||
if (witness_available == true)
|
||||
PQfinish(witness_conn);
|
||||
PQfinish(primary_conn);
|
||||
|
||||
exit(SUCCESS);
|
||||
}
|
||||
|
||||
log_info(_("unregistering witness node %i"), witness_node_id);
|
||||
log_info(_("unregistering witness node %i"), config_file_options.node_id);
|
||||
node_record_deleted = delete_node_record(primary_conn,
|
||||
witness_node_id);
|
||||
config_file_options.node_id);
|
||||
|
||||
if (node_record_deleted == false)
|
||||
{
|
||||
PQfinish(primary_conn);
|
||||
PQfinish(witness_conn);
|
||||
exit(ERR_BAD_CONFIG);
|
||||
}
|
||||
|
||||
if (local_node_available == true)
|
||||
PQfinish(local_conn);
|
||||
PQfinish(local_conn);
|
||||
/* sync records from primary */
|
||||
if (witness_available == true && witness_copy_node_records(primary_conn, witness_conn) == false)
|
||||
{
|
||||
log_error(_("unable to copy repmgr node records from primary"));
|
||||
PQfinish(primary_conn);
|
||||
PQfinish(witness_conn);
|
||||
exit(ERR_BAD_CONFIG);
|
||||
}
|
||||
|
||||
/* Log the event */
|
||||
create_event_record(primary_conn,
|
||||
&config_file_options,
|
||||
witness_node_id,
|
||||
config_file_options.node_id,
|
||||
"witness_unregister",
|
||||
true,
|
||||
NULL);
|
||||
|
||||
PQfinish(primary_conn);
|
||||
|
||||
if (local_node_available == true)
|
||||
PQfinish(local_conn);
|
||||
if (witness_available == true)
|
||||
PQfinish(witness_conn);
|
||||
|
||||
log_info(_("witness unregistration complete"));
|
||||
log_detail(_("witness node with ID %i successfully unregistered"),
|
||||
witness_node_id);
|
||||
log_detail(_("witness node with id %i (conninfo: %s) successfully unregistered"),
|
||||
config_file_options.node_id, config_file_options.conninfo);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -472,19 +449,16 @@ void do_witness_help(void)
|
||||
puts("");
|
||||
printf(_(" Requires provision of connection information for the primary\n"));
|
||||
puts("");
|
||||
printf(_(" --dry-run check prerequisites but don't make any changes\n"));
|
||||
printf(_(" -F, --force overwrite an existing node record\n"));
|
||||
printf(_(" --dry-run check prerequisites but don't make any changes\n"));
|
||||
printf(_(" -F, --force overwrite an existing node record\n"));
|
||||
puts("");
|
||||
|
||||
printf(_("WITNESS UNREGISTER\n"));
|
||||
puts("");
|
||||
printf(_(" \"witness register\" unregisters a witness node.\n"));
|
||||
puts("");
|
||||
printf(_(" --dry-run check prerequisites but don't make any changes\n"));
|
||||
printf(_(" -F, --force unregister when witness node not running\n"));
|
||||
printf(_(" --node-id node ID of the witness node (provide if executing on\n"));
|
||||
printf(_(" another node)\n"));
|
||||
|
||||
printf(_(" --dry-run check prerequisites but don't make any changes\n"));
|
||||
printf(_(" -F, --force unregister when witness node not running\n"));
|
||||
puts("");
|
||||
|
||||
return;
|
||||
|
||||
@@ -47,7 +47,6 @@ typedef struct
|
||||
/* logging options */
|
||||
char log_level[MAXLEN]; /* overrides setting in repmgr.conf */
|
||||
bool log_to_file;
|
||||
bool quiet;
|
||||
bool terse;
|
||||
bool verbose;
|
||||
|
||||
@@ -107,7 +106,6 @@ typedef struct
|
||||
bool replication_lag;
|
||||
bool role;
|
||||
bool slots;
|
||||
bool missing_slots;
|
||||
bool has_passfile;
|
||||
bool replication_connection;
|
||||
|
||||
@@ -139,7 +137,7 @@ typedef struct
|
||||
/* general configuration options */ \
|
||||
"", false, false, "", false, false, \
|
||||
/* logging options */ \
|
||||
"", false, false, false, false, \
|
||||
"", false, false, false, \
|
||||
/* output options */ \
|
||||
false, false, false, \
|
||||
/* database connection options */ \
|
||||
@@ -154,13 +152,13 @@ typedef struct
|
||||
/* "standby clone"/"standby follow" options */ \
|
||||
NO_UPSTREAM_NODE, \
|
||||
/* "standby register" options */ \
|
||||
false, -1, DEFAULT_WAIT_START, \
|
||||
false, 0, DEFAULT_WAIT_START, \
|
||||
/* "standby switchover" options */ \
|
||||
false, false, "", false, \
|
||||
/* "node status" options */ \
|
||||
false, \
|
||||
/* "node check" options */ \
|
||||
false, false, false, false, false, false, false, false, \
|
||||
false, false, false, false, false, false, false, \
|
||||
/* "node join" options */ \
|
||||
"", \
|
||||
/* "node service" options */ \
|
||||
@@ -237,6 +235,5 @@ extern void get_node_config_directory(char *config_dir_buf);
|
||||
extern void get_node_data_directory(char *data_dir_buf);
|
||||
extern void init_node_record(t_node_info *node_record);
|
||||
extern bool can_use_pg_rewind(PGconn *conn, const char *data_directory, PQExpBufferData *reason);
|
||||
extern void drop_replication_slot_if_exists(PGconn *conn, int node_id, char *slot_name);
|
||||
|
||||
#endif /* _REPMGR_CLIENT_GLOBAL_H_ */
|
||||
|
||||
140
repmgr-client.c
140
repmgr-client.c
@@ -98,7 +98,7 @@ main(int argc, char **argv)
|
||||
{
|
||||
t_conninfo_param_list default_conninfo = T_CONNINFO_PARAM_LIST_INITIALIZER;
|
||||
|
||||
int optindex = 0;
|
||||
int optindex;
|
||||
int c;
|
||||
|
||||
char *repmgr_command = NULL;
|
||||
@@ -108,7 +108,6 @@ main(int argc, char **argv)
|
||||
char *dummy_action = "";
|
||||
|
||||
bool help_option = false;
|
||||
bool option_error_found = false;
|
||||
|
||||
set_progname(argv[0]);
|
||||
|
||||
@@ -179,10 +178,7 @@ main(int argc, char **argv)
|
||||
strncpy(runtime_options.username, pw->pw_name, MAXLEN);
|
||||
}
|
||||
|
||||
/* Make getopt emitting errors */
|
||||
opterr = 1;
|
||||
|
||||
while ((c = getopt_long(argc, argv, "?Vb:f:FwWd:h:p:U:R:S:D:ck:L:qtvC:", long_options,
|
||||
while ((c = getopt_long(argc, argv, "?Vb:f:FwWd:h:p:U:R:S:D:ck:L:tvC:", long_options,
|
||||
&optindex)) != -1)
|
||||
{
|
||||
/*
|
||||
@@ -200,7 +196,13 @@ main(int argc, char **argv)
|
||||
case OPT_HELP: /* --help */
|
||||
help_option = true;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
/* Actual help option given */
|
||||
if (strcmp(argv[optind - 1], "-?") == 0)
|
||||
{
|
||||
help_option = true;
|
||||
}
|
||||
break;
|
||||
case 'V':
|
||||
|
||||
/*
|
||||
@@ -471,10 +473,6 @@ main(int argc, char **argv)
|
||||
runtime_options.slots = true;
|
||||
break;
|
||||
|
||||
case OPT_MISSING_SLOTS:
|
||||
runtime_options.missing_slots = true;
|
||||
break;
|
||||
|
||||
case OPT_HAS_PASSFILE:
|
||||
runtime_options.has_passfile = true;
|
||||
break;
|
||||
@@ -574,12 +572,6 @@ main(int argc, char **argv)
|
||||
logger_output_mode = OM_DAEMON;
|
||||
break;
|
||||
|
||||
|
||||
/* --quiet */
|
||||
case 'q':
|
||||
runtime_options.quiet = true;
|
||||
break;
|
||||
|
||||
/* --terse */
|
||||
case 't':
|
||||
runtime_options.terse = true;
|
||||
@@ -635,29 +627,14 @@ main(int argc, char **argv)
|
||||
_("--recovery-min-apply-delay is now a configuration file parameter, \"recovery_min_apply_delay\""));
|
||||
break;
|
||||
|
||||
case ':': /* missing option argument */
|
||||
option_error_found = true;
|
||||
break;
|
||||
case '?':
|
||||
/* Actual help option given? */
|
||||
if (strcmp(argv[optind - 1], "-?") == 0)
|
||||
{
|
||||
help_option = true;
|
||||
break;
|
||||
}
|
||||
/* otherwise fall through to default */
|
||||
default: /* invalid option */
|
||||
option_error_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* If -d/--dbname appears to be a conninfo string, validate by attempting
|
||||
* to parse it (and if successful, store the parsed parameters)
|
||||
*/
|
||||
if (runtime_options.dbname[0])
|
||||
if (runtime_options.dbname)
|
||||
{
|
||||
if (strncmp(runtime_options.dbname, "postgresql://", 13) == 0 ||
|
||||
strncmp(runtime_options.dbname, "postgres://", 11) == 0 ||
|
||||
@@ -753,10 +730,9 @@ main(int argc, char **argv)
|
||||
if (cli_errors.head != NULL)
|
||||
{
|
||||
free_conninfo_params(&source_conninfo);
|
||||
exit_with_cli_errors(&cli_errors, NULL);
|
||||
exit_with_cli_errors(&cli_errors);
|
||||
}
|
||||
|
||||
|
||||
/*----------
|
||||
* Determine the node type and action; following are valid:
|
||||
*
|
||||
@@ -1003,30 +979,9 @@ main(int argc, char **argv)
|
||||
if (cli_errors.head != NULL)
|
||||
{
|
||||
free_conninfo_params(&source_conninfo);
|
||||
|
||||
exit_with_cli_errors(&cli_errors, valid_repmgr_command_found == true ? repmgr_command : NULL);
|
||||
exit_with_cli_errors(&cli_errors);
|
||||
}
|
||||
|
||||
/* no errors detected by repmgr, but getopt might have */
|
||||
if (option_error_found == true)
|
||||
{
|
||||
if (valid_repmgr_command_found == true)
|
||||
{
|
||||
printf(_("Try \"%s --help\" or \"%s %s --help\" for more information.\n"),
|
||||
progname(),
|
||||
progname(),
|
||||
repmgr_command);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf(_("Try \"repmgr --help\" for more information.\n"));
|
||||
}
|
||||
|
||||
free_conninfo_params(&source_conninfo);
|
||||
exit(ERR_BAD_CONFIG);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Print any warnings about inappropriate command line options, unless
|
||||
* -t/--terse set
|
||||
@@ -1055,6 +1010,7 @@ main(int argc, char **argv)
|
||||
runtime_options.output_mode = OM_OPTFORMAT;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Check for configuration file items which can be overriden by runtime
|
||||
* options
|
||||
@@ -1112,28 +1068,6 @@ main(int argc, char **argv)
|
||||
if (runtime_options.terse)
|
||||
logger_set_terse();
|
||||
|
||||
/*
|
||||
* If --dry-run specified, ensure log_level is at least LOG_INFO, regardless
|
||||
* of what's in the configuration file or -L/--log-level paremeter, otherwise
|
||||
* some or output might not be displayed.
|
||||
*/
|
||||
if (runtime_options.dry_run == true)
|
||||
{
|
||||
logger_set_min_level(LOG_INFO);
|
||||
}
|
||||
|
||||
/*
|
||||
* If -q/--quiet supplied, suppress any non-ERROR log output.
|
||||
* This overrides everything else; we'll leave it up to the user to deal with the
|
||||
* consequences of e.g. running --dry-run together with -q/--quiet.
|
||||
*/
|
||||
if (runtime_options.quiet == true)
|
||||
{
|
||||
logger_set_level(LOG_ERROR);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Node configuration information is not needed for all actions, with
|
||||
* STANDBY CLONE being the main exception.
|
||||
@@ -1519,7 +1453,6 @@ check_cli_parameters(const int action)
|
||||
{
|
||||
case PRIMARY_UNREGISTER:
|
||||
case STANDBY_UNREGISTER:
|
||||
case WITNESS_UNREGISTER:
|
||||
case CLUSTER_EVENT:
|
||||
case CLUSTER_MATRIX:
|
||||
case CLUSTER_CROSSCHECK:
|
||||
@@ -1560,7 +1493,6 @@ check_cli_parameters(const int action)
|
||||
case STANDBY_CLONE:
|
||||
case STANDBY_REGISTER:
|
||||
case STANDBY_FOLLOW:
|
||||
case BDR_REGISTER:
|
||||
break;
|
||||
default:
|
||||
item_list_append_format(&cli_warnings,
|
||||
@@ -1903,7 +1835,7 @@ do_help(void)
|
||||
printf(_(" %s [OPTIONS] standby {register|unregister|clone|promote|follow|switchover}\n"), progname());
|
||||
printf(_(" %s [OPTIONS] bdr {register|unregister}\n"), progname());
|
||||
printf(_(" %s [OPTIONS] node {status|check|rejoin|service}\n"), progname());
|
||||
printf(_(" %s [OPTIONS] cluster {show|event|matrix|crosscheck|cleanup}\n"), progname());
|
||||
printf(_(" %s [OPTIONS] cluster {show|event|matrix|crosscheck}\n"), progname());
|
||||
printf(_(" %s [OPTIONS] witness {register|unregister}\n"), progname());
|
||||
|
||||
puts("");
|
||||
@@ -1952,7 +1884,6 @@ do_help(void)
|
||||
printf(_(" --dry-run show what would happen for action, but don't execute it\n"));
|
||||
printf(_(" -L, --log-level set log level (overrides configuration file; default: NOTICE)\n"));
|
||||
printf(_(" --log-to-file log to file (or logging facility) defined in repmgr.conf\n"));
|
||||
printf(_(" -q, --quiet suppress all log output apart from errors\n"));
|
||||
printf(_(" -t, --terse don't display detail, hints and other non-critical output\n"));
|
||||
printf(_(" -v, --verbose display additional log output (useful for debugging)\n"));
|
||||
|
||||
@@ -2978,46 +2909,3 @@ can_use_pg_rewind(PGconn *conn, const char *data_directory, PQExpBufferData *rea
|
||||
|
||||
return can_use;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
drop_replication_slot_if_exists(PGconn *conn, int node_id, char *slot_name)
|
||||
{
|
||||
t_replication_slot slot_info = T_REPLICATION_SLOT_INITIALIZER;
|
||||
RecordStatus record_status = get_slot_record(conn, slot_name, &slot_info);
|
||||
|
||||
log_verbose(LOG_DEBUG, "attempting to delete slot \"%s\" on node %i",
|
||||
slot_name, node_id);
|
||||
|
||||
if (record_status != RECORD_FOUND)
|
||||
{
|
||||
/* this is a good thing */
|
||||
log_verbose(LOG_INFO,
|
||||
_("slot \"%s\" does not exist on node %i, nothing to remove"),
|
||||
slot_name, node_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (slot_info.active == false)
|
||||
{
|
||||
if (drop_replication_slot(conn, slot_name) == true)
|
||||
{
|
||||
log_notice(_("replication slot \"%s\" deleted on node %i"), slot_name, node_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error(_("unable to delete replication slot \"%s\" on node %i"), slot_name, node_id);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* if active replication slot exists, call Houston as we have a
|
||||
* problem
|
||||
*/
|
||||
else
|
||||
{
|
||||
log_warning(_("replication slot \"%s\" is still active on node %i"), slot_name, node_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -87,7 +87,6 @@
|
||||
#define OPT_REMOTE_NODE_ID 1038
|
||||
#define OPT_RECOVERY_CONF_ONLY 1039
|
||||
#define OPT_NO_WAIT 1040
|
||||
#define OPT_MISSING_SLOTS 1041
|
||||
|
||||
/* deprecated since 3.3 */
|
||||
#define OPT_DATA_DIR 999
|
||||
@@ -126,7 +125,6 @@ static struct option long_options[] =
|
||||
/* logging options */
|
||||
{"log-level", required_argument, NULL, 'L'},
|
||||
{"log-to-file", no_argument, NULL, OPT_LOG_TO_FILE},
|
||||
{"quiet", no_argument, NULL, 'q'},
|
||||
{"terse", no_argument, NULL, 't'},
|
||||
{"verbose", no_argument, NULL, 'v'},
|
||||
|
||||
@@ -166,7 +164,6 @@ static struct option long_options[] =
|
||||
{"replication-lag", no_argument, NULL, OPT_REPLICATION_LAG},
|
||||
{"role", no_argument, NULL, OPT_ROLE},
|
||||
{"slots", no_argument, NULL, OPT_SLOTS},
|
||||
{"missing-slots", no_argument, NULL, OPT_MISSING_SLOTS},
|
||||
{"has-passfile", no_argument, NULL, OPT_HAS_PASSFILE},
|
||||
{"replication-connection", no_argument, NULL, OPT_REPL_CONN},
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@
|
||||
#log_facility=STDERR # Logging facility: possible values are STDERR, or for
|
||||
# syslog integration, one of LOCAL0, LOCAL1, ..., LOCAL7, USER
|
||||
|
||||
#log_file='' # STDERR can be redirected to an arbitrary file
|
||||
#log_file='' # stderr can be redirected to an arbitrary file:
|
||||
#log_status_interval=300 # interval (in seconds) for repmgrd to log a status message
|
||||
|
||||
|
||||
@@ -143,11 +143,6 @@
|
||||
# Debian/Ubuntu users: you will probably need to
|
||||
# set this to the directory where `pg_ctl` is located,
|
||||
# e.g. /usr/lib/postgresql/9.6/bin/
|
||||
#
|
||||
# *NOTE* "pg_bindir" is only used when repmgr directly
|
||||
# executes PostgreSQL binaries; any user-defined scripts
|
||||
# *must* be specified with the full path
|
||||
#
|
||||
#use_primary_conninfo_password=false # explicitly set "password" in recovery.conf's
|
||||
# "primary_conninfo" parameter using the value contained
|
||||
# in the environment variable PGPASSWORD
|
||||
@@ -188,11 +183,11 @@ ssh_options='-q -o ConnectTimeout=10' # Options to append to "ssh"
|
||||
# parameter can be provided multiple times.
|
||||
|
||||
#restore_command='' # This will be placed in the recovery.conf file generated
|
||||
# by repmgr.
|
||||
# by repmgr.
|
||||
|
||||
#archive_cleanup_command='' # This will be placed in the recovery.conf file generated
|
||||
# by repmgr. Note we recommend using Barman for managing
|
||||
# WAL archives (see: https://www.pgbarman.org )
|
||||
# by repmgr. Note we recommend using Barman for managing
|
||||
# WAL archives (see: https://www.pgbarman.org )
|
||||
|
||||
#recovery_min_apply_delay= # If provided, "recovery_min_apply_delay" in recovery.conf
|
||||
# will be set to this value (PostgreSQL 9.4 and later).
|
||||
@@ -212,40 +207,16 @@ ssh_options='-q -o ConnectTimeout=10' # Options to append to "ssh"
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# "standby follow" settings
|
||||
# Standby follow settings
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
# These settings apply when instructing a standby to follow the new primary
|
||||
# ("repmgr standby follow").
|
||||
|
||||
#primary_follow_timeout=60 # The max length of time (in seconds) to wait
|
||||
#primary_follow_timeout=60 # The length of time (in seconds) to wait
|
||||
# for the new primary to become available
|
||||
#standby_follow_timeout=15 # The max length of time (in seconds) to wait
|
||||
# for the standby to connect to the primary
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# "standby switchover" settings
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
# These settings apply when switching roles between a primary and a standby
|
||||
# ("repmgr standby switchover").
|
||||
|
||||
#standby_reconnect_timeout=60 # The max length of time (in seconds) to wait
|
||||
# for the demoted standby to reconnect to the promoted
|
||||
# primary (note: this value should be equal to or greater
|
||||
# than that set for "node_rejoin_timeout")
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# "node rejoin" settings
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
# These settings apply when reintegrating a node into a replication cluster
|
||||
# with "repmgrd_node_rejoin"
|
||||
|
||||
#node_rejoin_timeout=60 # The maximum length of time (in seconds) to wait for
|
||||
# the node to reconnect to the replication cluster
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Barman options
|
||||
#------------------------------------------------------------------------------
|
||||
@@ -263,11 +234,6 @@ ssh_options='-q -o ConnectTimeout=10' # Options to append to "ssh"
|
||||
# These settings are only applied when repmgrd is running. Values shown
|
||||
# are defaults.
|
||||
|
||||
#repmgrd_pid_file= # Path of PID file to use for repmgrd; if not set, a PID file will
|
||||
# be generated in a temporary directory specified by the environment
|
||||
# variable $TMPDIR, or if not set, in "/tmp". This value can be overridden
|
||||
# by the command line option "-p/--pid-file"; the command line option
|
||||
# "--no-pid-file" will force PID file creation to be skipped.
|
||||
#failover=manual # one of 'automatic', 'manual'.
|
||||
# determines what action to take in the event of upstream failure
|
||||
#
|
||||
@@ -277,7 +243,7 @@ ssh_options='-q -o ConnectTimeout=10' # Options to append to "ssh"
|
||||
# manual attention to reattach it to replication
|
||||
# (does not apply to BDR mode)
|
||||
|
||||
#priority=100 # indicate a preferred priority for promoting nodes;
|
||||
#priority=100 # indicate a preferred priorty for promoting nodes;
|
||||
# a value of zero prevents the node being promoted to primary
|
||||
# (default: 100)
|
||||
|
||||
@@ -285,11 +251,11 @@ ssh_options='-q -o ConnectTimeout=10' # Options to append to "ssh"
|
||||
# primary (or other upstream node)
|
||||
#reconnect_interval=10 # Interval between attempts to reconnect to an unreachable
|
||||
# primary (or other upstream node)
|
||||
#promote_command= # command repmgrd executes when promoting a new primary; use something like:
|
||||
#promote_command= # command to execute when promoting a new primary; use something like:
|
||||
#
|
||||
# repmgr standby promote -f /etc/repmgr.conf
|
||||
#
|
||||
#follow_command= # command repmgrd executes when instructing a standby to follow a new primary;
|
||||
#follow_command= # command to execute when instructing a standby to follow a new primary;
|
||||
# use something like:
|
||||
#
|
||||
# repmgr standby follow -f /etc/repmgr.conf -W --upstream-node-id=%n
|
||||
@@ -297,9 +263,8 @@ ssh_options='-q -o ConnectTimeout=10' # Options to append to "ssh"
|
||||
#primary_notification_timeout=60 # Interval (in seconds) which repmgrd on a standby
|
||||
# will wait for a notification from the new primary,
|
||||
# before falling back to degraded monitoring
|
||||
#repmgrd_standby_startup_timeout=60 # Interval (in seconds) which repmgrd on a standby will wait
|
||||
# for the the local node to restart and become ready to accept connections after
|
||||
# executing "follow_command" (defaults to the value set in "standby_reconnect_timeout")
|
||||
#standby_reconnect_timeout=60 # Interval (in seconds) which repmgrd on a standby will wait
|
||||
# to reconnect to the local node after executing "follow_command"
|
||||
|
||||
#monitoring_history=no # Whether to write monitoring data to the "montoring_history" table
|
||||
#monitor_interval_secs=2 # Interval (in seconds) at which to write monitoring data
|
||||
@@ -337,17 +302,17 @@ ssh_options='-q -o ConnectTimeout=10' # Options to append to "ssh"
|
||||
#
|
||||
# Debian/Ubuntu users: use "sudo pg_ctlcluster" to execute service control commands.
|
||||
#
|
||||
# For more details, see: https://repmgr.org/docs/4.1/configuration-service-commands.html
|
||||
# For more details, see: https://repmgr.org/docs/4.0/configuration-service-commands.html
|
||||
|
||||
#service_start_command = ''
|
||||
#service_stop_command = ''
|
||||
#service_restart_command = ''
|
||||
#service_reload_command = ''
|
||||
#service_promote_command = '' # This parameter is intended for systems which provide a
|
||||
# package-level promote command, such as Debian's
|
||||
# "pg_ctlcluster". *IMPORTANT*: it is *not* a substitute
|
||||
# for "promote_command"; do not use "repmgr standby promote"
|
||||
# (or a script which executes "repmgr standby promote") here.
|
||||
#service_promote_command = '' # Note: this overrides any value contained in the setting
|
||||
# "promote_command". This is intended for systems which
|
||||
# provide a package-level promote command, such as Debian's
|
||||
# "pg_ctlcluster"
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Status check thresholds
|
||||
@@ -381,7 +346,7 @@ ssh_options='-q -o ConnectTimeout=10' # Options to append to "ssh"
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
#bdr_local_monitoring_only=false # Only monitor the local node; no checks will be
|
||||
# performed on the other node
|
||||
# performed on the other node
|
||||
#bdr_recovery_timeout # If a BDR node was offline and has become available
|
||||
# maximum length of time in seconds to wait for the
|
||||
# node to reconnect to the cluster
|
||||
# maximum length of time in seconds to wait for the
|
||||
# node to reconnect to the cluster
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# repmgr extension
|
||||
comment = 'Replication manager for PostgreSQL'
|
||||
default_version = '4.1'
|
||||
default_version = '4.0'
|
||||
module_pathname = '$libdir/repmgr'
|
||||
relocatable = false
|
||||
schema = repmgr
|
||||
|
||||
6
repmgr.h
6
repmgr.h
@@ -49,8 +49,6 @@
|
||||
#define REPLICATION_TYPE_BDR 2
|
||||
|
||||
#define UNKNOWN_SERVER_VERSION_NUM -1
|
||||
#define UNKNOWN_BDR_VERSION_NUM -1
|
||||
|
||||
#define UNKNOWN_TIMELINE_ID -1
|
||||
#define UNKNOWN_SYSTEM_IDENTIFIER 0
|
||||
|
||||
@@ -60,8 +58,6 @@
|
||||
|
||||
#define VOTING_TERM_NOT_SET -1
|
||||
|
||||
#define BDR2_REPLICATION_SET_NAME "repmgr"
|
||||
|
||||
/*
|
||||
* various default values - ensure repmgr.conf.sample is update
|
||||
* if any of these are changed
|
||||
@@ -74,7 +70,6 @@
|
||||
#define DEFAULT_ASYNC_QUERY_TIMEOUT 60 /* seconds */
|
||||
#define DEFAULT_PRIMARY_NOTIFICATION_TIMEOUT 60 /* seconds */
|
||||
#define DEFAULT_PRIMARY_FOLLOW_TIMEOUT 60 /* seconds */
|
||||
#define DEFAULT_STANDBY_FOLLOW_TIMEOUT 30 /* seconds */
|
||||
#define DEFAULT_BDR_RECOVERY_TIMEOUT 30 /* seconds */
|
||||
#define DEFAULT_ARCHIVE_READY_WARNING 16 /* WAL files */
|
||||
#define DEFAULT_ARCHIVE_READY_CRITICAL 128 /* WAL files */
|
||||
@@ -85,7 +80,6 @@
|
||||
#define DEFAULT_PROMOTE_CHECK_TIMEOUT 60 /* seconds */
|
||||
#define DEFAULT_PROMOTE_CHECK_INTERVAL 1 /* seconds */
|
||||
#define DEFAULT_STANDBY_RECONNECT_TIMEOUT 60 /* seconds */
|
||||
#define DEFAULT_NODE_REJOIN_TIMEOUT 60 /* seconds */
|
||||
|
||||
#ifndef RECOVERY_COMMAND_FILE
|
||||
#define RECOVERY_COMMAND_FILE "recovery.conf"
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
#define REPMGR_VERSION_DATE ""
|
||||
#define REPMGR_VERSION "4.1.1"
|
||||
#define REPMGR_VERSION "4.0.5"
|
||||
|
||||
|
||||
@@ -214,8 +214,7 @@ monitor_bdr(void)
|
||||
|
||||
log_warning(_("unable to connect to node %s (ID %i)"),
|
||||
cell->node_info->node_name, cell->node_info->node_id);
|
||||
//cell->node_info->conn = try_reconnect(cell->node_info);
|
||||
try_reconnect(&cell->node_info->conn, cell->node_info);
|
||||
cell->node_info->conn = try_reconnect(cell->node_info);
|
||||
|
||||
/* node has recovered - log and continue */
|
||||
if (cell->node_info->node_status == NODE_STATUS_UP)
|
||||
@@ -294,7 +293,7 @@ loop:
|
||||
/*
|
||||
* if we can reload, then could need to change local_conn
|
||||
*/
|
||||
if (reload_config(&config_file_options, BDR))
|
||||
if (reload_config(&config_file_options))
|
||||
{
|
||||
PQfinish(local_conn);
|
||||
local_conn = establish_db_connection(config_file_options.conninfo, true);
|
||||
@@ -304,12 +303,11 @@ loop:
|
||||
got_SIGHUP = false;
|
||||
}
|
||||
|
||||
/* XXX this looks like it will never be called */
|
||||
if (got_SIGHUP)
|
||||
{
|
||||
log_debug("SIGHUP received");
|
||||
|
||||
if (reload_config(&config_file_options, BDR))
|
||||
if (reload_config(&config_file_options))
|
||||
{
|
||||
PQfinish(local_conn);
|
||||
local_conn = establish_db_connection(config_file_options.conninfo, true);
|
||||
|
||||
@@ -58,9 +58,7 @@ static FailoverState failover_state = FAILOVER_STATE_UNKNOWN;
|
||||
|
||||
static int primary_node_id = UNKNOWN_NODE_ID;
|
||||
static t_node_info upstream_node_info = T_NODE_INFO_INITIALIZER;
|
||||
static NodeInfoList sibling_nodes = T_NODE_INFO_LIST_INITIALIZER;
|
||||
|
||||
static instr_time last_monitoring_update;
|
||||
static NodeInfoList standby_nodes = T_NODE_INFO_LIST_INITIALIZER;
|
||||
|
||||
|
||||
static ElectionResult do_election(void);
|
||||
@@ -83,8 +81,6 @@ static bool do_witness_failover(void);
|
||||
|
||||
static void update_monitoring_history(void);
|
||||
|
||||
static void handle_sighup(PGconn **conn, t_server_type server_type);
|
||||
|
||||
static const char * format_failover_state(FailoverState failover_state);
|
||||
|
||||
|
||||
@@ -166,8 +162,8 @@ do_physical_node_check(void)
|
||||
if (config_file_options.failover == FAILOVER_AUTOMATIC)
|
||||
{
|
||||
/*
|
||||
* Check that "promote_command" and "follow_command" are defined, otherwise repmgrd
|
||||
* won't be able to perform any useful action in a failover situation.
|
||||
* check that promote/follow commands are defined, otherwise repmgrd
|
||||
* won't be able to perform any useful action
|
||||
*/
|
||||
|
||||
bool required_param_missing = false;
|
||||
@@ -179,24 +175,14 @@ do_physical_node_check(void)
|
||||
if (config_file_options.service_promote_command[0] != '\0')
|
||||
{
|
||||
/*
|
||||
* "service_promote_command" is *not* a substitute for "promote_command";
|
||||
* it is intended for use in those systems (e.g. Debian) where there's a service
|
||||
* level promote command (e.g. pg_ctlcluster).
|
||||
*
|
||||
* "promote_command" should either execute "repmgr standby promote" directly, or
|
||||
* a script which executes "repmgr standby promote". This is essential, as the
|
||||
* repmgr metadata is updated by "repmgr standby promote".
|
||||
*
|
||||
* "service_promote_command", if set, will be executed by "repmgr standby promote",
|
||||
* but never by repmgrd.
|
||||
*
|
||||
* if repmgrd executes "service_promote_command" directly,
|
||||
* repmgr metadata won't get updated
|
||||
*/
|
||||
log_hint(_("\"service_promote_command\" is set, but can only be executed by \"repmgr standby promote\""));
|
||||
}
|
||||
|
||||
required_param_missing = true;
|
||||
}
|
||||
|
||||
if (config_file_options.follow_command[0] == '\0')
|
||||
{
|
||||
log_error(_("\"follow_command\" must be defined in the configuration file"));
|
||||
@@ -288,6 +274,8 @@ monitor_streaming_primary(void)
|
||||
|
||||
local_node_info.node_status = NODE_STATUS_UNKNOWN;
|
||||
|
||||
close_connection(&local_conn);
|
||||
|
||||
/*
|
||||
* as we're monitoring the primary, no point in trying to
|
||||
* write the event to the database
|
||||
@@ -303,7 +291,7 @@ monitor_streaming_primary(void)
|
||||
|
||||
termPQExpBuffer(&event_details);
|
||||
|
||||
try_reconnect(&local_conn, &local_node_info);
|
||||
local_conn = try_reconnect(&local_node_info);
|
||||
|
||||
if (local_node_info.node_status == NODE_STATUS_UP)
|
||||
{
|
||||
@@ -547,7 +535,26 @@ loop:
|
||||
|
||||
if (got_SIGHUP)
|
||||
{
|
||||
handle_sighup(&local_conn, PRIMARY);
|
||||
log_debug("SIGHUP received");
|
||||
|
||||
if (reload_config(&config_file_options))
|
||||
{
|
||||
close_connection(&local_conn);
|
||||
local_conn = establish_db_connection(config_file_options.conninfo, true);
|
||||
|
||||
if (*config_file_options.log_file)
|
||||
{
|
||||
FILE *fd;
|
||||
|
||||
fd = freopen(config_file_options.log_file, "a", stderr);
|
||||
if (fd == NULL)
|
||||
{
|
||||
fprintf(stderr, "error reopening stderr to \"%s\": %s",
|
||||
config_file_options.log_file, strerror(errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
got_SIGHUP = false;
|
||||
}
|
||||
|
||||
log_verbose(LOG_DEBUG, "sleeping %i seconds (parameter \"monitor_interval_secs\")",
|
||||
@@ -565,11 +572,9 @@ monitor_streaming_standby(void)
|
||||
instr_time log_status_interval_start;
|
||||
PQExpBufferData event_details;
|
||||
|
||||
log_debug("monitor_streaming_standby()");
|
||||
|
||||
reset_node_voting_status();
|
||||
|
||||
INSTR_TIME_SET_ZERO(last_monitoring_update);
|
||||
log_debug("monitor_streaming_standby()");
|
||||
|
||||
/*
|
||||
* If no upstream node id is specified in the metadata, we'll try and
|
||||
@@ -718,9 +723,10 @@ monitor_streaming_standby(void)
|
||||
_("unable to connect to upstream node \"%s\" (node ID: %i)"),
|
||||
upstream_node_info.node_name, upstream_node_info.node_id);
|
||||
|
||||
/* XXX possible pre-action event */
|
||||
/* */
|
||||
if (upstream_node_info.type == STANDBY)
|
||||
{
|
||||
/* XXX possible pre-action event */
|
||||
create_event_record(primary_conn,
|
||||
&config_file_options,
|
||||
config_file_options.node_id,
|
||||
@@ -742,6 +748,8 @@ monitor_streaming_standby(void)
|
||||
log_warning("%s", event_details.data);
|
||||
termPQExpBuffer(&event_details);
|
||||
|
||||
close_connection(&upstream_conn);
|
||||
|
||||
/*
|
||||
* if local node is unreachable, make a last-minute attempt to reconnect
|
||||
* before continuing with the failover process
|
||||
@@ -752,18 +760,13 @@ monitor_streaming_standby(void)
|
||||
check_connection(&local_node_info, &local_conn);
|
||||
}
|
||||
|
||||
try_reconnect(&upstream_conn, &upstream_node_info);
|
||||
upstream_conn = try_reconnect(&upstream_node_info);
|
||||
|
||||
/* Node has recovered - log and continue */
|
||||
if (upstream_node_info.node_status == NODE_STATUS_UP)
|
||||
{
|
||||
int upstream_node_unreachable_elapsed = calculate_elapsed(upstream_node_unreachable_start);
|
||||
|
||||
if (upstream_node_info.type == PRIMARY)
|
||||
{
|
||||
primary_conn = upstream_conn;
|
||||
}
|
||||
|
||||
initPQExpBuffer(&event_details);
|
||||
|
||||
appendPQExpBuffer(&event_details,
|
||||
@@ -771,7 +774,7 @@ monitor_streaming_standby(void)
|
||||
upstream_node_unreachable_elapsed);
|
||||
log_notice("%s", event_details.data);
|
||||
|
||||
create_event_notification(primary_conn,
|
||||
create_event_notification(upstream_conn,
|
||||
&config_file_options,
|
||||
config_file_options.node_id,
|
||||
"repmgrd_upstream_reconnect",
|
||||
@@ -813,29 +816,6 @@ monitor_streaming_standby(void)
|
||||
{
|
||||
int degraded_monitoring_elapsed = calculate_elapsed(degraded_monitoring_start);
|
||||
|
||||
if (config_file_options.degraded_monitoring_timeout > 0
|
||||
&& degraded_monitoring_elapsed > config_file_options.degraded_monitoring_timeout)
|
||||
{
|
||||
initPQExpBuffer(&event_details);
|
||||
|
||||
appendPQExpBuffer(&event_details,
|
||||
_("degraded monitoring timeout (%i seconds) exceeded, terminating"),
|
||||
degraded_monitoring_elapsed);
|
||||
|
||||
log_notice("%s", event_details.data);
|
||||
|
||||
create_event_notification(NULL,
|
||||
&config_file_options,
|
||||
config_file_options.node_id,
|
||||
"repmgrd_shutdown",
|
||||
true,
|
||||
event_details.data);
|
||||
|
||||
termPQExpBuffer(&event_details);
|
||||
terminate(ERR_MONITORING_TIMEOUT);
|
||||
}
|
||||
|
||||
|
||||
log_debug("monitoring node %i in degraded state for %i seconds",
|
||||
upstream_node_info.node_id,
|
||||
degraded_monitoring_elapsed);
|
||||
@@ -938,8 +918,8 @@ monitor_streaming_standby(void)
|
||||
get_active_sibling_node_records(local_conn,
|
||||
local_node_info.node_id,
|
||||
former_upstream_node_id,
|
||||
&sibling_nodes);
|
||||
notify_followers(&sibling_nodes, local_node_info.node_id);
|
||||
&standby_nodes);
|
||||
notify_followers(&standby_nodes, local_node_info.node_id);
|
||||
|
||||
/* this will restart monitoring in primary mode */
|
||||
monitoring_state = MS_NORMAL;
|
||||
@@ -978,12 +958,12 @@ monitor_streaming_standby(void)
|
||||
get_active_sibling_node_records(local_conn,
|
||||
local_node_info.node_id,
|
||||
local_node_info.upstream_node_id,
|
||||
&sibling_nodes);
|
||||
&standby_nodes);
|
||||
|
||||
if (sibling_nodes.node_count > 0)
|
||||
if (standby_nodes.node_count > 0)
|
||||
{
|
||||
log_debug("scanning %i node records to detect new primary...", sibling_nodes.node_count);
|
||||
for (cell = sibling_nodes.head; cell; cell = cell->next)
|
||||
log_debug("scanning %i node records to detect new primary...", standby_nodes.node_count);
|
||||
for (cell = standby_nodes.head; cell; cell = cell->next)
|
||||
{
|
||||
/* skip local node check, we did that above */
|
||||
if (cell->node_info->node_id == local_node_info.node_id)
|
||||
@@ -1013,7 +993,7 @@ monitor_streaming_standby(void)
|
||||
follow_new_primary(follow_node_id);
|
||||
}
|
||||
}
|
||||
clear_node_info_list(&sibling_nodes);
|
||||
clear_node_info_list(&standby_nodes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1041,7 +1021,8 @@ loop:
|
||||
|
||||
if (config_file_options.failover == FAILOVER_MANUAL)
|
||||
{
|
||||
appendPQExpBuffer(&monitoring_summary,
|
||||
appendPQExpBuffer(
|
||||
&monitoring_summary,
|
||||
_(" (automatic failover disabled)"));
|
||||
}
|
||||
|
||||
@@ -1051,18 +1032,6 @@ loop:
|
||||
{
|
||||
log_detail(_("waiting for upstream or another primary to reappear"));
|
||||
}
|
||||
else if (config_file_options.monitoring_history == true)
|
||||
{
|
||||
if (INSTR_TIME_IS_ZERO(last_monitoring_update))
|
||||
{
|
||||
log_detail(_("no monitoring statistics have been written yet"));
|
||||
}
|
||||
else
|
||||
{
|
||||
log_detail(_("last monitoring statistics update was %i seconds ago"),
|
||||
calculate_elapsed(last_monitoring_update));
|
||||
}
|
||||
}
|
||||
|
||||
INSTR_TIME_SET_CURRENT(log_status_interval_start);
|
||||
}
|
||||
@@ -1074,16 +1043,7 @@ loop:
|
||||
}
|
||||
else
|
||||
{
|
||||
if (config_file_options.monitoring_history == true)
|
||||
{
|
||||
log_verbose(LOG_WARNING, _("monitoring_history requested but primary connection not available"));
|
||||
}
|
||||
|
||||
/*
|
||||
* if monitoring not in use, we'll need to ensure the local connection
|
||||
* handle isn't stale
|
||||
*/
|
||||
(void) connection_ping(local_conn);
|
||||
connection_ping(local_conn);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1172,7 +1132,26 @@ loop:
|
||||
|
||||
if (got_SIGHUP)
|
||||
{
|
||||
handle_sighup(&local_conn, STANDBY);
|
||||
log_debug("SIGHUP received");
|
||||
|
||||
if (reload_config(&config_file_options))
|
||||
{
|
||||
close_connection(&local_conn);
|
||||
local_conn = establish_db_connection(config_file_options.conninfo, true);
|
||||
|
||||
if (*config_file_options.log_file)
|
||||
{
|
||||
FILE *fd;
|
||||
|
||||
fd = freopen(config_file_options.log_file, "a", stderr);
|
||||
if (fd == NULL)
|
||||
{
|
||||
fprintf(stderr, "error reopening stderr to \"%s\": %s",
|
||||
config_file_options.log_file, strerror(errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
got_SIGHUP = false;
|
||||
}
|
||||
|
||||
log_verbose(LOG_DEBUG, "sleeping %i seconds (parameter \"monitor_interval_secs\")",
|
||||
@@ -1192,18 +1171,36 @@ monitor_streaming_witness(void)
|
||||
PQExpBufferData event_details;
|
||||
RecordStatus record_status;
|
||||
|
||||
int primary_node_id = UNKNOWN_NODE_ID;
|
||||
|
||||
reset_node_voting_status();
|
||||
|
||||
log_debug("monitor_streaming_witness()");
|
||||
|
||||
/*
|
||||
* At this point we can't trust the local copy of "repmgr.nodes", as
|
||||
* it may not have been updated. We'll scan the cluster for the current
|
||||
* primary and refresh the copy from that before proceeding further.
|
||||
*/
|
||||
primary_conn = get_primary_connection_quiet(local_conn, &primary_node_id, NULL);
|
||||
if (get_primary_node_record(local_conn, &upstream_node_info) == false)
|
||||
{
|
||||
PQExpBufferData event_details;
|
||||
|
||||
initPQExpBuffer(&event_details);
|
||||
|
||||
appendPQExpBuffer(&event_details,
|
||||
_("unable to retrieve record for primary node"));
|
||||
|
||||
log_error("%s", event_details.data);
|
||||
log_hint(_("execute \"repmgr witness register --force\" to update the witness node "));
|
||||
close_connection(&local_conn);
|
||||
|
||||
create_event_notification(NULL,
|
||||
&config_file_options,
|
||||
config_file_options.node_id,
|
||||
"repmgrd_shutdown",
|
||||
false,
|
||||
event_details.data);
|
||||
|
||||
termPQExpBuffer(&event_details);
|
||||
|
||||
terminate(ERR_BAD_CONFIG);
|
||||
}
|
||||
|
||||
primary_conn = establish_db_connection(upstream_node_info.conninfo, false);
|
||||
|
||||
/*
|
||||
* Primary node must be running at repmgrd startup.
|
||||
@@ -1228,7 +1225,7 @@ monitor_streaming_witness(void)
|
||||
* refresh upstream node record from primary, so it's as up-to-date
|
||||
* as possible
|
||||
*/
|
||||
record_status = get_node_record(primary_conn, primary_node_id, &upstream_node_info);
|
||||
record_status = get_node_record(primary_conn, upstream_node_info.node_id, &upstream_node_info);
|
||||
|
||||
/*
|
||||
* This is unlikely to happen; if it does emit a warning for diagnostic
|
||||
@@ -1300,7 +1297,8 @@ monitor_streaming_witness(void)
|
||||
true,
|
||||
event_details.data);
|
||||
|
||||
try_reconnect(&primary_conn, &upstream_node_info);
|
||||
close_connection(&primary_conn);
|
||||
primary_conn = try_reconnect(&upstream_node_info);
|
||||
|
||||
/* Node has recovered - log and continue */
|
||||
if (upstream_node_info.node_status == NODE_STATUS_UP)
|
||||
@@ -1314,7 +1312,7 @@ monitor_streaming_witness(void)
|
||||
upstream_node_unreachable_elapsed);
|
||||
log_notice("%s", event_details.data);
|
||||
|
||||
create_event_notification(primary_conn,
|
||||
create_event_notification(upstream_conn,
|
||||
&config_file_options,
|
||||
config_file_options.node_id,
|
||||
"repmgrd_upstream_reconnect",
|
||||
@@ -1397,12 +1395,12 @@ monitor_streaming_witness(void)
|
||||
get_active_sibling_node_records(local_conn,
|
||||
local_node_info.node_id,
|
||||
local_node_info.upstream_node_id,
|
||||
&sibling_nodes);
|
||||
&standby_nodes);
|
||||
|
||||
if (sibling_nodes.node_count > 0)
|
||||
if (standby_nodes.node_count > 0)
|
||||
{
|
||||
log_debug("scanning %i node records to detect new primary...", sibling_nodes.node_count);
|
||||
for (cell = sibling_nodes.head; cell; cell = cell->next)
|
||||
log_debug("scanning %i node records to detect new primary...", standby_nodes.node_count);
|
||||
for (cell = standby_nodes.head; cell; cell = cell->next)
|
||||
{
|
||||
/* skip local node check, we did that above */
|
||||
if (cell->node_info->node_id == local_node_info.node_id)
|
||||
@@ -1432,7 +1430,7 @@ monitor_streaming_witness(void)
|
||||
witness_follow_new_primary(follow_node_id);
|
||||
}
|
||||
}
|
||||
clear_node_info_list(&sibling_nodes);
|
||||
clear_node_info_list(&standby_nodes);
|
||||
}
|
||||
}
|
||||
loop:
|
||||
@@ -1482,7 +1480,26 @@ loop:
|
||||
|
||||
if (got_SIGHUP)
|
||||
{
|
||||
handle_sighup(&local_conn, WITNESS);
|
||||
log_debug("SIGHUP received");
|
||||
|
||||
if (reload_config(&config_file_options))
|
||||
{
|
||||
close_connection(&local_conn);
|
||||
local_conn = establish_db_connection(config_file_options.conninfo, true);
|
||||
|
||||
if (*config_file_options.log_file)
|
||||
{
|
||||
FILE *fd;
|
||||
|
||||
fd = freopen(config_file_options.log_file, "a", stderr);
|
||||
if (fd == NULL)
|
||||
{
|
||||
fprintf(stderr, "error reopening stderr to \"%s\": %s",
|
||||
config_file_options.log_file, strerror(errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
got_SIGHUP = false;
|
||||
}
|
||||
|
||||
log_verbose(LOG_DEBUG, "sleeping %i seconds (parameter \"monitor_interval_secs\")",
|
||||
@@ -1499,15 +1516,8 @@ loop:
|
||||
static bool
|
||||
do_primary_failover(void)
|
||||
{
|
||||
ElectionResult election_result;
|
||||
|
||||
/*
|
||||
* Double-check status of the local connection
|
||||
*/
|
||||
check_connection(&local_node_info, &local_conn);
|
||||
|
||||
/* attempt to initiate voting process */
|
||||
election_result = do_election();
|
||||
ElectionResult election_result = do_election();
|
||||
|
||||
/* TODO add pre-event notification here */
|
||||
failover_state = FAILOVER_STATE_UNKNOWN;
|
||||
@@ -1521,7 +1531,7 @@ do_primary_failover(void)
|
||||
}
|
||||
else if (election_result == ELECTION_WON)
|
||||
{
|
||||
if (sibling_nodes.node_count > 0)
|
||||
if (standby_nodes.node_count > 0)
|
||||
{
|
||||
log_notice("this node is the winner, will now promote itself and inform other nodes");
|
||||
}
|
||||
@@ -1566,7 +1576,7 @@ do_primary_failover(void)
|
||||
get_active_sibling_node_records(local_conn,
|
||||
local_node_info.node_id,
|
||||
upstream_node_info.node_id,
|
||||
&sibling_nodes);
|
||||
&standby_nodes);
|
||||
|
||||
}
|
||||
else if (config_file_options.failover == FAILOVER_MANUAL)
|
||||
@@ -1628,10 +1638,10 @@ do_primary_failover(void)
|
||||
{
|
||||
case FAILOVER_STATE_PROMOTED:
|
||||
/* notify former siblings that they should now follow this node */
|
||||
notify_followers(&sibling_nodes, local_node_info.node_id);
|
||||
notify_followers(&standby_nodes, local_node_info.node_id);
|
||||
|
||||
/* we no longer care about our former siblings */
|
||||
clear_node_info_list(&sibling_nodes);
|
||||
clear_node_info_list(&standby_nodes);
|
||||
|
||||
/* pass control back down to start_monitoring() */
|
||||
log_info(_("switching to primary monitoring mode"));
|
||||
@@ -1645,10 +1655,10 @@ do_primary_failover(void)
|
||||
* notify siblings that they should resume following the original
|
||||
* primary
|
||||
*/
|
||||
notify_followers(&sibling_nodes, upstream_node_info.node_id);
|
||||
notify_followers(&standby_nodes, upstream_node_info.node_id);
|
||||
|
||||
/* we no longer care about our former siblings */
|
||||
clear_node_info_list(&sibling_nodes);
|
||||
clear_node_info_list(&standby_nodes);
|
||||
|
||||
/* pass control back down to start_monitoring() */
|
||||
log_info(_("resuming standby monitoring mode"));
|
||||
@@ -1728,21 +1738,12 @@ update_monitoring_history(void)
|
||||
long long unsigned int replication_lag_bytes = 0;
|
||||
|
||||
/* both local and primary connections must be available */
|
||||
if (PQstatus(primary_conn) != CONNECTION_OK)
|
||||
{
|
||||
log_warning(_("primary connection is not available, unable to update monitoring history"));
|
||||
if (PQstatus(primary_conn) != CONNECTION_OK || PQstatus(local_conn) != CONNECTION_OK)
|
||||
return;
|
||||
}
|
||||
|
||||
if (PQstatus(local_conn) != CONNECTION_OK)
|
||||
{
|
||||
log_warning(_("local connection is not available, unable to update monitoring history"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (get_replication_info(local_conn, &replication_info) == false)
|
||||
{
|
||||
log_warning(_("unable to retrieve replication status information, unable to update monitoring history"));
|
||||
log_warning(_("unable to retrieve replication status information"));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1794,7 +1795,8 @@ update_monitoring_history(void)
|
||||
replication_lag_bytes = 0;
|
||||
}
|
||||
|
||||
add_monitoring_record(primary_conn,
|
||||
add_monitoring_record(
|
||||
primary_conn,
|
||||
local_conn,
|
||||
primary_node_id,
|
||||
local_node_info.node_id,
|
||||
@@ -1804,8 +1806,6 @@ update_monitoring_history(void)
|
||||
replication_info.last_xact_replay_timestamp,
|
||||
replication_lag_bytes,
|
||||
apply_lag_bytes);
|
||||
|
||||
INSTR_TIME_SET_CURRENT(last_monitoring_update);
|
||||
}
|
||||
|
||||
|
||||
@@ -1830,7 +1830,7 @@ do_upstream_standby_failover(void)
|
||||
t_node_info primary_node_info = T_NODE_INFO_INITIALIZER;
|
||||
RecordStatus record_status = RECORD_NOT_FOUND;
|
||||
RecoveryType primary_type = RECTYPE_UNKNOWN;
|
||||
int i, standby_follow_result;
|
||||
int i, r;
|
||||
char parsed_follow_command[MAXPGPATH] = "";
|
||||
|
||||
close_connection(&upstream_conn);
|
||||
@@ -1864,18 +1864,9 @@ do_upstream_standby_failover(void)
|
||||
|
||||
if (primary_type != RECTYPE_PRIMARY)
|
||||
{
|
||||
if (primary_type == RECTYPE_STANDBY)
|
||||
{
|
||||
log_error(_("last known primary \"%s\" (ID: %i) is in recovery, not following"),
|
||||
primary_node_info.node_name,
|
||||
primary_node_info.node_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
log_error(_("unable to determine status of last known primary \"%s\" (ID: %i), not following"),
|
||||
primary_node_info.node_name,
|
||||
primary_node_info.node_id);
|
||||
}
|
||||
log_error(_("last known primary\"%s\" (ID: %i) is in recovery, not following"),
|
||||
primary_node_info.node_name,
|
||||
primary_node_info.node_id);
|
||||
|
||||
close_connection(&primary_conn);
|
||||
monitoring_state = MS_DEGRADED;
|
||||
@@ -1886,6 +1877,8 @@ do_upstream_standby_failover(void)
|
||||
/* Close the connection to this server */
|
||||
close_connection(&local_conn);
|
||||
|
||||
initPQExpBuffer(&event_details);
|
||||
|
||||
log_debug(_("standby follow command is:\n \"%s\""),
|
||||
config_file_options.follow_command);
|
||||
|
||||
@@ -1895,12 +1888,10 @@ do_upstream_standby_failover(void)
|
||||
*/
|
||||
parse_follow_command(parsed_follow_command, config_file_options.follow_command, primary_node_info.node_id);
|
||||
|
||||
standby_follow_result = system(parsed_follow_command);
|
||||
r = system(parsed_follow_command);
|
||||
|
||||
if (standby_follow_result != 0)
|
||||
if (r != 0)
|
||||
{
|
||||
initPQExpBuffer(&event_details);
|
||||
|
||||
appendPQExpBuffer(&event_details,
|
||||
_("unable to execute follow command:\n %s"),
|
||||
config_file_options.follow_command);
|
||||
@@ -1911,7 +1902,8 @@ do_upstream_standby_failover(void)
|
||||
* It may not possible to write to the event notification table but we
|
||||
* should be able to generate an external notification if required.
|
||||
*/
|
||||
create_event_notification(primary_conn,
|
||||
create_event_notification(
|
||||
primary_conn,
|
||||
&config_file_options,
|
||||
local_node_info.node_id,
|
||||
"repmgrd_failover_follow",
|
||||
@@ -1924,22 +1916,18 @@ do_upstream_standby_failover(void)
|
||||
/*
|
||||
* It's possible that the standby is still starting up after the "follow_command"
|
||||
* completes, so poll for a while until we get a connection.
|
||||
*
|
||||
* NOTE: we've previously closed the local connection, so even if the follow command
|
||||
* failed for whatever reason and the local node remained up, we can re-open
|
||||
* the local connection.
|
||||
*/
|
||||
|
||||
for (i = 0; i < config_file_options.repmgrd_standby_startup_timeout; i++)
|
||||
for (i = 0; i < config_file_options.standby_reconnect_timeout; i++)
|
||||
{
|
||||
local_conn = establish_db_connection(local_node_info.conninfo, false);
|
||||
|
||||
if (PQstatus(local_conn) == CONNECTION_OK)
|
||||
break;
|
||||
|
||||
log_debug("sleeping 1 second; %i of %i (\"repmgrd_standby_startup_timeout\") attempts to reconnect to local node",
|
||||
log_debug("sleeping 1 second; %i of %i attempts to reconnect to local node",
|
||||
i + 1,
|
||||
config_file_options.repmgrd_standby_startup_timeout);
|
||||
config_file_options.standby_reconnect_timeout);
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
@@ -1953,47 +1941,28 @@ do_upstream_standby_failover(void)
|
||||
/* refresh shared memory settings which will have been zapped by the restart */
|
||||
repmgrd_set_local_node_id(local_conn, config_file_options.node_id);
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
|
||||
if (standby_follow_result != 0)
|
||||
if (update_node_record_set_upstream(primary_conn,
|
||||
local_node_info.node_id,
|
||||
primary_node_info.node_id) == false)
|
||||
{
|
||||
monitoring_state = MS_DEGRADED;
|
||||
INSTR_TIME_SET_CURRENT(degraded_monitoring_start);
|
||||
appendPQExpBuffer(&event_details,
|
||||
_("unable to set node %i's new upstream ID to %i"),
|
||||
local_node_info.node_id,
|
||||
primary_node_info.node_id);
|
||||
|
||||
return FAILOVER_STATE_FOLLOW_FAIL;
|
||||
}
|
||||
log_error("%s", event_details.data);
|
||||
|
||||
/*
|
||||
* update upstream_node_id to primary node (but only if follow command
|
||||
* was successful)
|
||||
*/
|
||||
create_event_notification(
|
||||
NULL,
|
||||
&config_file_options,
|
||||
local_node_info.node_id,
|
||||
"repmgrd_failover_follow",
|
||||
false,
|
||||
event_details.data);
|
||||
|
||||
{
|
||||
if (update_node_record_set_upstream(primary_conn,
|
||||
local_node_info.node_id,
|
||||
primary_node_info.node_id) == false)
|
||||
{
|
||||
initPQExpBuffer(&event_details);
|
||||
appendPQExpBuffer(&event_details,
|
||||
_("unable to set node %i's new upstream ID to %i"),
|
||||
local_node_info.node_id,
|
||||
primary_node_info.node_id);
|
||||
termPQExpBuffer(&event_details);
|
||||
|
||||
log_error("%s", event_details.data);
|
||||
|
||||
create_event_notification(NULL,
|
||||
&config_file_options,
|
||||
local_node_info.node_id,
|
||||
"repmgrd_failover_follow",
|
||||
false,
|
||||
event_details.data);
|
||||
|
||||
termPQExpBuffer(&event_details);
|
||||
|
||||
terminate(ERR_BAD_CONFIG);
|
||||
}
|
||||
terminate(ERR_BAD_CONFIG);
|
||||
}
|
||||
|
||||
/* refresh own internal node record */
|
||||
@@ -2009,8 +1978,6 @@ do_upstream_standby_failover(void)
|
||||
local_node_info.upstream_node_id = primary_node_info.node_id;
|
||||
}
|
||||
|
||||
initPQExpBuffer(&event_details);
|
||||
|
||||
appendPQExpBuffer(&event_details,
|
||||
_("node %i is now following primary node %i"),
|
||||
local_node_info.node_id,
|
||||
@@ -2018,7 +1985,8 @@ do_upstream_standby_failover(void)
|
||||
|
||||
log_notice("%s", event_details.data);
|
||||
|
||||
create_event_notification(primary_conn,
|
||||
create_event_notification(
|
||||
primary_conn,
|
||||
&config_file_options,
|
||||
local_node_info.node_id,
|
||||
"repmgrd_failover_follow",
|
||||
@@ -2065,10 +2033,10 @@ promote_self(void)
|
||||
return FAILOVER_STATE_PROMOTION_FAILED;
|
||||
}
|
||||
|
||||
/* the presence of this command has been established already */
|
||||
/* the presence of either of this command has been established already */
|
||||
promote_command = config_file_options.promote_command;
|
||||
|
||||
log_info(_("promote_command is:\n \"%s\""),
|
||||
log_debug("promote command is:\n \"%s\"",
|
||||
promote_command);
|
||||
|
||||
if (log_type == REPMGR_STDERR && *config_file_options.log_file)
|
||||
@@ -2400,7 +2368,7 @@ follow_new_primary(int new_primary_id)
|
||||
* completes, so poll for a while until we get a connection.
|
||||
*/
|
||||
|
||||
for (i = 0; i < config_file_options.repmgrd_standby_startup_timeout; i++)
|
||||
for (i = 0; i < config_file_options.standby_reconnect_timeout; i++)
|
||||
{
|
||||
local_conn = establish_db_connection(local_node_info.conninfo, false);
|
||||
|
||||
@@ -2409,7 +2377,7 @@ follow_new_primary(int new_primary_id)
|
||||
|
||||
log_debug("sleeping 1 second; %i of %i attempts to reconnect to local node",
|
||||
i + 1,
|
||||
config_file_options.repmgrd_standby_startup_timeout);
|
||||
config_file_options.standby_reconnect_timeout);
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
@@ -2475,26 +2443,20 @@ witness_follow_new_primary(int new_primary_id)
|
||||
{
|
||||
RecoveryType primary_recovery_type = get_recovery_type(upstream_conn);
|
||||
|
||||
switch (primary_recovery_type)
|
||||
if (primary_recovery_type == RECTYPE_PRIMARY)
|
||||
{
|
||||
case RECTYPE_PRIMARY:
|
||||
new_primary_ok = true;
|
||||
break;
|
||||
case RECTYPE_STANDBY:
|
||||
new_primary_ok = false;
|
||||
log_warning(_("new primary is not in recovery"));
|
||||
break;
|
||||
case RECTYPE_UNKNOWN:
|
||||
new_primary_ok = false;
|
||||
log_warning(_("unable to determine status of new primary"));
|
||||
break;
|
||||
new_primary_ok = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_primary_ok = false;
|
||||
log_warning(_("new primary is not in recovery"));
|
||||
close_connection(&upstream_conn);
|
||||
}
|
||||
}
|
||||
|
||||
if (new_primary_ok == false)
|
||||
{
|
||||
close_connection(&upstream_conn);
|
||||
|
||||
return FAILOVER_STATE_FOLLOW_FAIL;
|
||||
}
|
||||
|
||||
@@ -2581,7 +2543,6 @@ do_election(void)
|
||||
|
||||
/* we're visible */
|
||||
int visible_nodes = 1;
|
||||
int total_nodes = 0;
|
||||
|
||||
NodeInfoListCell *cell = NULL;
|
||||
|
||||
@@ -2632,16 +2593,14 @@ do_election(void)
|
||||
get_active_sibling_node_records(local_conn,
|
||||
local_node_info.node_id,
|
||||
upstream_node_info.node_id,
|
||||
&sibling_nodes);
|
||||
|
||||
total_nodes = sibling_nodes.node_count + 1;
|
||||
&standby_nodes);
|
||||
|
||||
log_debug("do_election(): primary location is %s", upstream_node_info.location);
|
||||
|
||||
local_node_info.last_wal_receive_lsn = InvalidXLogRecPtr;
|
||||
|
||||
/* fast path if no other standbys (or witness) exists - normally win by default */
|
||||
if (sibling_nodes.node_count == 0)
|
||||
if (standby_nodes.node_count == 0)
|
||||
{
|
||||
if (strncmp(upstream_node_info.location, local_node_info.location, MAXLEN) == 0)
|
||||
{
|
||||
@@ -2669,7 +2628,7 @@ do_election(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
/* standby nodes found - check if we're in the primary location before checking theirs */
|
||||
/* standby nodes found - check if we're in the primary location befor checking theirs */
|
||||
if (strncmp(upstream_node_info.location, local_node_info.location, MAXLEN) == 0)
|
||||
{
|
||||
primary_location_seen = true;
|
||||
@@ -2684,7 +2643,7 @@ do_election(void)
|
||||
/* pointer to "winning" node, initially self */
|
||||
candidate_node = &local_node_info;
|
||||
|
||||
for (cell = sibling_nodes.head; cell; cell = cell->next)
|
||||
for (cell = standby_nodes.head; cell; cell = cell->next)
|
||||
{
|
||||
/* assume the worst case */
|
||||
cell->node_info->node_status = NODE_STATUS_UNKNOWN;
|
||||
@@ -2739,7 +2698,7 @@ do_election(void)
|
||||
candidate_node = cell->node_info;
|
||||
}
|
||||
/* LSN is same - tiebreak on priority, then node_id */
|
||||
else if (cell->node_info->last_wal_receive_lsn == candidate_node->last_wal_receive_lsn)
|
||||
else if(cell->node_info->last_wal_receive_lsn == candidate_node->last_wal_receive_lsn)
|
||||
{
|
||||
log_verbose(LOG_DEBUG, "node %i has same LSN as current candidate %i",
|
||||
cell->node_info->node_id,
|
||||
@@ -2791,9 +2750,9 @@ do_election(void)
|
||||
|
||||
log_debug("visible nodes: %i; total nodes: %i",
|
||||
visible_nodes,
|
||||
total_nodes);
|
||||
standby_nodes.node_count);
|
||||
|
||||
if (visible_nodes <= (total_nodes / 2.0))
|
||||
if (visible_nodes <= (standby_nodes.node_count / 2.0))
|
||||
{
|
||||
log_notice(_("unable to reach a qualified majority of nodes"));
|
||||
log_detail(_("node will enter degraded monitoring state waiting for reconnect"));
|
||||
@@ -2980,30 +2939,3 @@ format_failover_state(FailoverState failover_state)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
handle_sighup(PGconn **conn, t_server_type server_type)
|
||||
{
|
||||
log_debug("SIGHUP received");
|
||||
|
||||
if (reload_config(&config_file_options, server_type))
|
||||
{
|
||||
PQfinish(*conn);
|
||||
*conn = establish_db_connection(config_file_options.conninfo, true);
|
||||
}
|
||||
|
||||
if (*config_file_options.log_file)
|
||||
{
|
||||
FILE *fd;
|
||||
|
||||
log_debug("reopening %s", config_file_options.log_file);
|
||||
|
||||
fd = freopen(config_file_options.log_file, "a", stderr);
|
||||
if (fd == NULL)
|
||||
{
|
||||
fprintf(stderr, "error reopening stderr to \"%s\": %s",
|
||||
config_file_options.log_file, strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
got_SIGHUP = false;
|
||||
}
|
||||
|
||||
153
repmgrd.c
153
repmgrd.c
@@ -35,10 +35,8 @@
|
||||
|
||||
static char *config_file = NULL;
|
||||
static bool verbose = false;
|
||||
static char pid_file[MAXPGPATH];
|
||||
static bool daemonize = true;
|
||||
static bool show_pid_file = false;
|
||||
static bool no_pid_file = false;
|
||||
static char *pid_file = NULL;
|
||||
static bool daemonize = false;
|
||||
|
||||
t_configuration_options config_file_options = T_CONFIGURATION_OPTIONS_INITIALIZER;
|
||||
|
||||
@@ -101,10 +99,8 @@ main(int argc, char **argv)
|
||||
{"config-file", required_argument, NULL, 'f'},
|
||||
|
||||
/* daemon options */
|
||||
{"daemonize", optional_argument, NULL, 'd'},
|
||||
{"daemonize", no_argument, NULL, 'd'},
|
||||
{"pid-file", required_argument, NULL, 'p'},
|
||||
{"show-pid-file", no_argument, NULL, 's'},
|
||||
{"no-pid-file", no_argument, NULL, OPT_NO_PID_FILE},
|
||||
|
||||
/* logging options */
|
||||
{"log-level", required_argument, NULL, 'L'},
|
||||
@@ -117,6 +113,8 @@ main(int argc, char **argv)
|
||||
|
||||
set_progname(argv[0]);
|
||||
|
||||
srand(time(NULL));
|
||||
|
||||
/* Disallow running as root */
|
||||
if (geteuid() == 0)
|
||||
{
|
||||
@@ -130,10 +128,6 @@ main(int argc, char **argv)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
srand(time(NULL));
|
||||
|
||||
memset(pid_file, 0, MAXPGPATH);
|
||||
|
||||
while ((c = getopt_long(argc, argv, "?Vf:L:vdp:m", long_options, &optindex)) != -1)
|
||||
{
|
||||
switch (c)
|
||||
@@ -175,22 +169,11 @@ main(int argc, char **argv)
|
||||
/* daemon options */
|
||||
|
||||
case 'd':
|
||||
if (optarg != NULL)
|
||||
{
|
||||
daemonize = parse_bool(optarg, "-d/--daemonize", &cli_errors);
|
||||
}
|
||||
daemonize = true;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
strncpy(pid_file, optarg, MAXPGPATH);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
show_pid_file = true;
|
||||
break;
|
||||
|
||||
case OPT_NO_PID_FILE:
|
||||
no_pid_file = true;
|
||||
pid_file = optarg;
|
||||
break;
|
||||
|
||||
/* logging options */
|
||||
@@ -237,7 +220,7 @@ main(int argc, char **argv)
|
||||
/* Exit here already if errors in command line options found */
|
||||
if (cli_errors.head != NULL)
|
||||
{
|
||||
exit_with_cli_errors(&cli_errors, NULL);
|
||||
exit_with_cli_errors(&cli_errors);
|
||||
}
|
||||
|
||||
startup_event_logged = false;
|
||||
@@ -256,58 +239,6 @@ main(int argc, char **argv)
|
||||
*/
|
||||
load_config(config_file, verbose, false, &config_file_options, argv[0]);
|
||||
|
||||
/* Determine pid file location, unless --no-pid-file supplied */
|
||||
|
||||
if (no_pid_file == false)
|
||||
{
|
||||
if (config_file_options.repmgrd_pid_file[0] != '\0')
|
||||
{
|
||||
if (pid_file[0] != '\0')
|
||||
{
|
||||
log_warning(_("\"repmgrd_pid_file\" will be overridden by --pid-file"));
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy(pid_file, config_file_options.repmgrd_pid_file, MAXPGPATH);
|
||||
}
|
||||
}
|
||||
|
||||
/* no pid file provided - determine location */
|
||||
if (pid_file[0] == '\0')
|
||||
{
|
||||
/* packagers: if feasible, patch PID file path into "package_pid_file" */
|
||||
char package_pid_file[MAXPGPATH] = "";
|
||||
|
||||
if (package_pid_file[0] != '\0')
|
||||
{
|
||||
maxpath_snprintf(pid_file, "%s", package_pid_file);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *tmpdir = getenv("TMPDIR");
|
||||
|
||||
if (!tmpdir)
|
||||
tmpdir = "/tmp";
|
||||
|
||||
maxpath_snprintf(pid_file, "%s/repmgrd.pid", tmpdir);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* --no-pid-file supplied - overwrite any value provided with --pid-file ... */
|
||||
memset(pid_file, 0, MAXPGPATH);
|
||||
}
|
||||
|
||||
|
||||
/* If --show-pid-file supplied, output the location (if set) and exit */
|
||||
|
||||
if (show_pid_file == true)
|
||||
{
|
||||
printf("%s\n", pid_file);
|
||||
exit(SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
/* Some configuration file items can be overriden by command line options */
|
||||
|
||||
@@ -320,6 +251,8 @@ main(int argc, char **argv)
|
||||
strncpy(config_file_options.log_level, cli_log_level, MAXLEN);
|
||||
}
|
||||
|
||||
log_notice(_("repmgrd (repmgr %s) starting up"), REPMGR_VERSION);
|
||||
|
||||
/*
|
||||
* -m/--monitoring-history, if provided, will override repmgr.conf's
|
||||
* monitoring_history; this is for backwards compatibility as it's
|
||||
@@ -347,8 +280,6 @@ main(int argc, char **argv)
|
||||
|
||||
logger_init(&config_file_options, progname());
|
||||
|
||||
log_notice(_("repmgrd (%s %s) starting up"), progname(), REPMGR_VERSION);
|
||||
|
||||
if (verbose)
|
||||
logger_set_verbose();
|
||||
|
||||
@@ -483,7 +414,7 @@ main(int argc, char **argv)
|
||||
daemonize_process();
|
||||
}
|
||||
|
||||
if (pid_file[0] != '\0')
|
||||
if (pid_file != NULL)
|
||||
{
|
||||
check_and_create_pid_file(pid_file);
|
||||
}
|
||||
@@ -738,8 +669,6 @@ show_help(void)
|
||||
{
|
||||
printf(_("%s: replication management daemon for PostgreSQL\n"), progname());
|
||||
puts("");
|
||||
printf(_("%s monitors a cluster of servers and optionally performs failover.\n"), progname());
|
||||
puts("");
|
||||
|
||||
printf(_("Usage:\n"));
|
||||
printf(_(" %s [OPTIONS]\n"), progname());
|
||||
@@ -759,21 +688,19 @@ show_help(void)
|
||||
|
||||
puts("");
|
||||
|
||||
printf(_("Daemon configuration options:\n"));
|
||||
printf(_(" -d, --daemonize[=true/false]\n"));
|
||||
printf(_(" detach process from foreground (default: true)\n"));
|
||||
printf(_(" -p, --pid-file=PATH use the specified PID file\n"));
|
||||
printf(_(" -s, --show-pid-file show PID file which would be used by the current configuration\n"));
|
||||
printf(_(" --no-pid-file don't write a PID file\n"));
|
||||
printf(_("General configuration options:\n"));
|
||||
printf(_(" -d, --daemonize detach process from foreground\n"));
|
||||
printf(_(" -p, --pid-file=PATH write a PID file\n"));
|
||||
puts("");
|
||||
|
||||
printf(_("%s monitors a cluster of servers and optionally performs failover.\n"), progname());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
try_reconnect(PGconn **conn, t_node_info *node_info)
|
||||
PGconn *
|
||||
try_reconnect(t_node_info *node_info)
|
||||
{
|
||||
PGconn *our_conn;
|
||||
PGconn *conn;
|
||||
t_conninfo_param_list conninfo_params = T_CONNINFO_PARAM_LIST_INITIALIZER;
|
||||
|
||||
int i;
|
||||
@@ -782,6 +709,7 @@ try_reconnect(PGconn **conn, t_node_info *node_info)
|
||||
|
||||
initialize_conninfo_params(&conninfo_params, false);
|
||||
|
||||
|
||||
/* we assume by now the conninfo string is parseable */
|
||||
(void) parse_conninfo_string(node_info->conninfo, &conninfo_params, NULL, false);
|
||||
|
||||
@@ -804,47 +732,18 @@ try_reconnect(PGconn **conn, t_node_info *node_info)
|
||||
* degraded monitoring? - make that configurable
|
||||
*/
|
||||
|
||||
our_conn = establish_db_connection_by_params(&conninfo_params, false);
|
||||
conn = establish_db_connection_by_params(&conninfo_params, false);
|
||||
|
||||
if (PQstatus(our_conn) == CONNECTION_OK)
|
||||
if (PQstatus(conn) == CONNECTION_OK)
|
||||
{
|
||||
free_conninfo_params(&conninfo_params);
|
||||
|
||||
log_info(_("connection to node %i succeeded"), node_info->node_id);
|
||||
|
||||
if (PQstatus(*conn) == CONNECTION_BAD)
|
||||
{
|
||||
log_verbose(LOG_INFO, "original connection handle returned CONNECTION_BAD, using new connection");
|
||||
close_connection(conn);
|
||||
*conn = our_conn;
|
||||
}
|
||||
else
|
||||
{
|
||||
ExecStatusType ping_result;
|
||||
|
||||
ping_result = connection_ping(*conn);
|
||||
|
||||
if (ping_result != PGRES_TUPLES_OK)
|
||||
{
|
||||
log_info("original connnection no longer available, using new connection");
|
||||
close_connection(conn);
|
||||
*conn = our_conn;
|
||||
}
|
||||
else
|
||||
{
|
||||
log_info(_("original connection is still available"));
|
||||
|
||||
PQfinish(our_conn);
|
||||
}
|
||||
}
|
||||
|
||||
node_info->node_status = NODE_STATUS_UP;
|
||||
|
||||
return;
|
||||
return conn;
|
||||
}
|
||||
|
||||
close_connection(&our_conn);
|
||||
log_notice(_("unable to reconnect to node %i"), node_info->node_id);
|
||||
close_connection(&conn);
|
||||
log_notice(_("unable to reconnect to node"));
|
||||
}
|
||||
|
||||
if (i + 1 < max_attempts)
|
||||
@@ -863,7 +762,7 @@ try_reconnect(PGconn **conn, t_node_info *node_info)
|
||||
|
||||
free_conninfo_params(&conninfo_params);
|
||||
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -903,7 +802,7 @@ terminate(int retval)
|
||||
{
|
||||
logger_shutdown();
|
||||
|
||||
if (pid_file[0] != '\0')
|
||||
if (pid_file)
|
||||
{
|
||||
unlink(pid_file);
|
||||
}
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
#include <time.h>
|
||||
#include "portability/instr_time.h"
|
||||
|
||||
#define OPT_NO_PID_FILE 1000
|
||||
|
||||
extern volatile sig_atomic_t got_SIGHUP;
|
||||
extern MonitoringState monitoring_state;
|
||||
extern instr_time degraded_monitoring_start;
|
||||
@@ -21,13 +19,11 @@ extern t_node_info local_node_info;
|
||||
extern PGconn *local_conn;
|
||||
extern bool startup_event_logged;
|
||||
|
||||
void try_reconnect(PGconn **conn, t_node_info *node_info);
|
||||
PGconn *try_reconnect(t_node_info *node_info);
|
||||
|
||||
int calculate_elapsed(instr_time start_time);
|
||||
const char *print_monitoring_state(MonitoringState monitoring_state);
|
||||
|
||||
void update_registration(PGconn *conn);
|
||||
void terminate(int retval);
|
||||
|
||||
|
||||
#endif /* _REPMGRD_H_ */
|
||||
|
||||
Reference in New Issue
Block a user