mirror of
https://github.com/EnterpriseDB/repmgr.git
synced 2026-03-23 15:16:29 +00:00
Compare commits
237 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
4
FAQ.md
4
FAQ.md
@@ -1,7 +1,9 @@
|
|||||||
FAQ - Frequently Asked Questions about repmgr
|
FAQ - Frequently Asked Questions about repmgr
|
||||||
=============================================
|
=============================================
|
||||||
|
|
||||||
The repmgr 4 FAQ is located here: [repmgr FAQ (Frequently Asked Questions)](https://repmgr.org/docs/4.0/appendix-faq.html "repmgr FAQ")
|
The repmgr 4 FAQ is located here:
|
||||||
|
|
||||||
|
https://repmgr.org/docs/appendix-faq.html
|
||||||
|
|
||||||
The repmgr 3.x FAQ can be found here:
|
The repmgr 3.x FAQ can be found here:
|
||||||
|
|
||||||
|
|||||||
102
HISTORY
102
HISTORY
@@ -1,104 +1,4 @@
|
|||||||
4.2.0 2018-??-??
|
4.0.4 2018-03-08
|
||||||
repmgr: add parameter "shutdown_check_timeout" for use by "standby switchover";
|
|
||||||
GitHub #504 (Ian)
|
|
||||||
repmgr: add "--node-id" option to "repmgr cluster cleanup"; GitHub #493 (Ian)
|
|
||||||
repmgr: report unreachable nodes when running "repmgr cluster (matrix|crosscheck);
|
|
||||||
GitHub #246 (Ian)
|
|
||||||
repmgr: add configuration file parameter "repmgr_bindir"; GitHub #246 (Ian)
|
|
||||||
repmgr: fix "Missing replication slots" label in "node check"; GitHub #507 (Ian)
|
|
||||||
repmgrd: fix parsing of -d/--daemonize option (Ian)
|
|
||||||
repmgrd: support "pausing" of repmgrd (Ian)
|
|
||||||
|
|
||||||
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)
|
|
||||||
repmgr: add configuration parameter "config_directory"; GitHub #424 (Ian)
|
|
||||||
repmgr: add "dbname=replication" to all replication connection strings;
|
|
||||||
GitHub #421 (Ian)
|
|
||||||
repmgr: add sanity check if --upstream-node-id not supplied when executing
|
|
||||||
"standby register"; GitHub #395 (Ian)
|
|
||||||
repmgr: enable provision of "archive_cleanup_command" in recovery.conf;
|
|
||||||
GitHub #416 (Ian)
|
|
||||||
repmgr: actively check for node to rejoin cluster; GitHub #415 (Ian)
|
|
||||||
repmgr: enable pg_rewind to be used with PostgreSQL 9.3/9.4; GitHub #413 (Ian)
|
|
||||||
repmgr: fix minimum accepted value for "degraded_monitoring_timeout";
|
|
||||||
GitHub #411 (Ian)
|
|
||||||
repmgr: fix superuser password handling; GitHub #400 (Ian)
|
|
||||||
repmgr: fix parsing of "archive_ready_critical" configuration file
|
|
||||||
parameter; GitHub #426 (Ian)
|
|
||||||
repmgr: fix display of conninfo parsing error messages (Ian)
|
|
||||||
repmgr: fix "repmgr cluster crosscheck" output; GitHub #389 (Ian)
|
|
||||||
repmgrd: prevent standby connection handle from going stale (Ian)
|
|
||||||
repmgrd: fix memory leaks in witness code; GitHub #402 (AndrzejNowicki, Martín)
|
|
||||||
repmgrd: handle "pg_ctl promote" timeout; GitHub #425 (Ian)
|
|
||||||
repmgrd: handle failover situation with only two nodes in the primary
|
|
||||||
location, and at least one node in another location; GitHub #407 (Ian)
|
|
||||||
repmgrd: set "connect_timeout=2" when pinging a server (Ian)
|
|
||||||
|
|
||||||
4.0.4 2018-03-09
|
|
||||||
repmgr: add "standby clone --recovery-conf-only" option; GitHub #382 (Ian)
|
repmgr: add "standby clone --recovery-conf-only" option; GitHub #382 (Ian)
|
||||||
repmgr: make "standby promote" timeout values configurable; GitHub #387 (Ian)
|
repmgr: make "standby promote" timeout values configurable; GitHub #387 (Ian)
|
||||||
repmgr: improve replication slot warnings generated by "node status";
|
repmgr: improve replication slot warnings generated by "node status";
|
||||||
|
|||||||
16
Makefile.in
16
Makefile.in
@@ -11,11 +11,7 @@ EXTENSION = repmgr
|
|||||||
|
|
||||||
DATA = \
|
DATA = \
|
||||||
repmgr--unpackaged--4.0.sql \
|
repmgr--unpackaged--4.0.sql \
|
||||||
repmgr--4.0.sql \
|
repmgr--4.0.sql
|
||||||
repmgr--4.0--4.1.sql \
|
|
||||||
repmgr--4.1.sql \
|
|
||||||
repmgr--4.1--4.2.sql \
|
|
||||||
repmgr--4.2.sql
|
|
||||||
|
|
||||||
REGRESS = repmgr_extension
|
REGRESS = repmgr_extension
|
||||||
|
|
||||||
@@ -30,24 +26,19 @@ all: \
|
|||||||
PG_CPPFLAGS = -std=gnu89 -I$(includedir_internal) -I$(libpq_srcdir) -Wall -Wmissing-prototypes -Wmissing-declarations $(EXTRA_CFLAGS)
|
PG_CPPFLAGS = -std=gnu89 -I$(includedir_internal) -I$(libpq_srcdir) -Wall -Wmissing-prototypes -Wmissing-declarations $(EXTRA_CFLAGS)
|
||||||
SHLIB_LINK = $(libpq)
|
SHLIB_LINK = $(libpq)
|
||||||
|
|
||||||
|
HEADERS = $(wildcard *.h)
|
||||||
|
|
||||||
OBJS = \
|
OBJS = \
|
||||||
repmgr.o
|
repmgr.o
|
||||||
|
|
||||||
include Makefile.global
|
include Makefile.global
|
||||||
|
|
||||||
ifeq ($(vpath_build),yes)
|
|
||||||
HEADERS = $(wildcard *.h)
|
|
||||||
else
|
|
||||||
HEADERS_built = $(wildcard *.h)
|
|
||||||
endif
|
|
||||||
|
|
||||||
$(info Building against PostgreSQL $(MAJORVERSION))
|
$(info Building against PostgreSQL $(MAJORVERSION))
|
||||||
|
|
||||||
REPMGR_CLIENT_OBJS = repmgr-client.o \
|
REPMGR_CLIENT_OBJS = repmgr-client.o \
|
||||||
repmgr-action-primary.o repmgr-action-standby.o repmgr-action-witness.o \
|
repmgr-action-primary.o repmgr-action-standby.o repmgr-action-witness.o \
|
||||||
repmgr-action-bdr.o repmgr-action-cluster.o repmgr-action-node.o repmgr-action-daemon.o \
|
repmgr-action-bdr.o repmgr-action-cluster.o repmgr-action-node.o \
|
||||||
configfile.o log.o strutil.o controldata.o dirutil.o compat.o dbutils.o
|
configfile.o log.o strutil.o controldata.o dirutil.o compat.o dbutils.o
|
||||||
REPMGRD_OBJS = repmgrd.o repmgrd-physical.o repmgrd-bdr.o configfile.o log.o dbutils.o strutil.o controldata.o compat.o
|
REPMGRD_OBJS = repmgrd.o repmgrd-physical.o repmgrd-bdr.o configfile.o log.o dbutils.o strutil.o controldata.o compat.o
|
||||||
DATE=$(shell date "+%Y-%m-%d")
|
DATE=$(shell date "+%Y-%m-%d")
|
||||||
@@ -91,7 +82,6 @@ additional-clean:
|
|||||||
rm -f repmgr-action-bdr.o
|
rm -f repmgr-action-bdr.o
|
||||||
rm -f repmgr-action-node.o
|
rm -f repmgr-action-node.o
|
||||||
rm -f repmgr-action-cluster.o
|
rm -f repmgr-action-cluster.o
|
||||||
rm -f repmgr-action-daemon.o
|
|
||||||
rm -f repmgrd.o
|
rm -f repmgrd.o
|
||||||
rm -f repmgrd-physical.o
|
rm -f repmgrd-physical.o
|
||||||
rm -f repmgrd-bdr.o
|
rm -f repmgrd-bdr.o
|
||||||
|
|||||||
20
TODO.md
20
TODO.md
@@ -1,20 +0,0 @@
|
|||||||
TODO
|
|
||||||
====
|
|
||||||
|
|
||||||
This file contains a list of improvements which are desireable and/or have
|
|
||||||
been requested, and which we aim to address/implement when time and resources
|
|
||||||
permit.
|
|
||||||
|
|
||||||
It is *not* a roadmap and there's no guarantee of any item being implemented
|
|
||||||
within any given timeframe.
|
|
||||||
|
|
||||||
|
|
||||||
Enable suspension of repmgrd failover
|
|
||||||
-------------------------------------
|
|
||||||
|
|
||||||
When performing maintenance, e.g. a switchover, it's necessary to stop all
|
|
||||||
repmgrd nodes to prevent unintended failover; this is obviously inconvenient.
|
|
||||||
We'll need to implement some way of notifying each repmgrd to suspend automatic
|
|
||||||
failover until further notice.
|
|
||||||
|
|
||||||
Requested in GitHub #410 ( https://github.com/2ndQuadrant/repmgr/issues/410 )
|
|
||||||
170
configfile.c
170
configfile.c
@@ -28,8 +28,10 @@ char config_file_path[MAXPGPATH] = "";
|
|||||||
static bool config_file_provided = false;
|
static bool config_file_provided = false;
|
||||||
bool config_file_found = 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 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_line(char *buf, char *name, char *value);
|
||||||
static void parse_event_notifications_list(t_configuration_options *options, const char *arg);
|
static void parse_event_notifications_list(t_configuration_options *options, const char *arg);
|
||||||
@@ -88,7 +90,8 @@ load_config(const char *config_file, bool verbose, bool terse, t_configuration_o
|
|||||||
|
|
||||||
if (pwd != NULL)
|
if (pwd != NULL)
|
||||||
{
|
{
|
||||||
appendPQExpBufferStr(&fullpath, pwd);
|
appendPQExpBuffer(&fullpath,
|
||||||
|
"%s", pwd);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -104,7 +107,9 @@ load_config(const char *config_file, bool verbose, bool terse, t_configuration_o
|
|||||||
exit(ERR_BAD_CONFIG);
|
exit(ERR_BAD_CONFIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
appendPQExpBufferStr(&fullpath, cwd);
|
appendPQExpBuffer(&fullpath,
|
||||||
|
"%s",
|
||||||
|
cwd);
|
||||||
}
|
}
|
||||||
|
|
||||||
appendPQExpBuffer(&fullpath,
|
appendPQExpBuffer(&fullpath,
|
||||||
@@ -236,7 +241,7 @@ end_search:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
void
|
||||||
parse_config(t_configuration_options *options, bool terse)
|
parse_config(t_configuration_options *options, bool terse)
|
||||||
{
|
{
|
||||||
/* Collate configuration file errors here for friendlier reporting */
|
/* Collate configuration file errors here for friendlier reporting */
|
||||||
@@ -283,9 +288,7 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *
|
|||||||
memset(options->node_name, 0, sizeof(options->node_name));
|
memset(options->node_name, 0, sizeof(options->node_name));
|
||||||
memset(options->conninfo, 0, sizeof(options->conninfo));
|
memset(options->conninfo, 0, sizeof(options->conninfo));
|
||||||
memset(options->data_directory, 0, sizeof(options->data_directory));
|
memset(options->data_directory, 0, sizeof(options->data_directory));
|
||||||
memset(options->config_directory, 0, sizeof(options->data_directory));
|
|
||||||
memset(options->pg_bindir, 0, sizeof(options->pg_bindir));
|
memset(options->pg_bindir, 0, sizeof(options->pg_bindir));
|
||||||
memset(options->repmgr_bindir, 0, sizeof(options->repmgr_bindir));
|
|
||||||
options->replication_type = REPLICATION_TYPE_PHYSICAL;
|
options->replication_type = REPLICATION_TYPE_PHYSICAL;
|
||||||
|
|
||||||
/*-------------
|
/*-------------
|
||||||
@@ -311,31 +314,16 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *
|
|||||||
options->tablespace_mapping.tail = NULL;
|
options->tablespace_mapping.tail = NULL;
|
||||||
memset(options->recovery_min_apply_delay, 0, sizeof(options->recovery_min_apply_delay));
|
memset(options->recovery_min_apply_delay, 0, sizeof(options->recovery_min_apply_delay));
|
||||||
options->recovery_min_apply_delay_provided = false;
|
options->recovery_min_apply_delay_provided = false;
|
||||||
memset(options->archive_cleanup_command, 0, sizeof(options->archive_cleanup_command));
|
|
||||||
options->use_primary_conninfo_password = false;
|
options->use_primary_conninfo_password = false;
|
||||||
memset(options->passfile, 0, sizeof(options->passfile));
|
memset(options->passfile, 0, sizeof(options->passfile));
|
||||||
|
|
||||||
/*-------------------------
|
/*-----------------------
|
||||||
* standby promote settings
|
* standby promote settings
|
||||||
*-------------------------
|
*------------------------
|
||||||
*/
|
*/
|
||||||
options->promote_check_timeout = DEFAULT_PROMOTE_CHECK_TIMEOUT;
|
options->promote_check_timeout = DEFAULT_PROMOTE_CHECK_TIMEOUT;
|
||||||
options->promote_check_interval = DEFAULT_PROMOTE_CHECK_INTERVAL;
|
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->shutdown_check_timeout = DEFAULT_SHUTDOWN_CHECK_TIMEOUT;
|
|
||||||
options->standby_reconnect_timeout = DEFAULT_STANDBY_RECONNECT_TIMEOUT;
|
|
||||||
|
|
||||||
/*-----------------
|
/*-----------------
|
||||||
* repmgrd settings
|
* repmgrd settings
|
||||||
*-----------------
|
*-----------------
|
||||||
@@ -355,8 +343,8 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *
|
|||||||
options->degraded_monitoring_timeout = -1;
|
options->degraded_monitoring_timeout = -1;
|
||||||
options->async_query_timeout = DEFAULT_ASYNC_QUERY_TIMEOUT;
|
options->async_query_timeout = DEFAULT_ASYNC_QUERY_TIMEOUT;
|
||||||
options->primary_notification_timeout = DEFAULT_PRIMARY_NOTIFICATION_TIMEOUT;
|
options->primary_notification_timeout = DEFAULT_PRIMARY_NOTIFICATION_TIMEOUT;
|
||||||
options->repmgrd_standby_startup_timeout = -1; /* defaults to "standby_reconnect_timeout" if not set */
|
options->primary_follow_timeout = DEFAULT_PRIMARY_FOLLOW_TIMEOUT;
|
||||||
memset(options->repmgrd_pid_file, 0, sizeof(options->repmgrd_pid_file));
|
options->standby_reconnect_timeout = DEFAULT_STANDBY_RECONNECT_TIMEOUT;
|
||||||
|
|
||||||
/*-------------
|
/*-------------
|
||||||
* witness settings
|
* witness settings
|
||||||
@@ -475,9 +463,6 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *
|
|||||||
strncpy(options->conninfo, value, MAXLEN);
|
strncpy(options->conninfo, value, MAXLEN);
|
||||||
else if (strcmp(name, "data_directory") == 0)
|
else if (strcmp(name, "data_directory") == 0)
|
||||||
strncpy(options->data_directory, value, MAXPGPATH);
|
strncpy(options->data_directory, value, MAXPGPATH);
|
||||||
else if (strcmp(name, "config_directory") == 0)
|
|
||||||
strncpy(options->config_directory, value, MAXPGPATH);
|
|
||||||
|
|
||||||
else if (strcmp(name, "replication_user") == 0)
|
else if (strcmp(name, "replication_user") == 0)
|
||||||
{
|
{
|
||||||
if (strlen(value) < NAMEDATALEN)
|
if (strlen(value) < NAMEDATALEN)
|
||||||
@@ -488,8 +473,6 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *
|
|||||||
}
|
}
|
||||||
else if (strcmp(name, "pg_bindir") == 0)
|
else if (strcmp(name, "pg_bindir") == 0)
|
||||||
strncpy(options->pg_bindir, value, MAXPGPATH);
|
strncpy(options->pg_bindir, value, MAXPGPATH);
|
||||||
else if (strcmp(name, "repmgr_bindir") == 0)
|
|
||||||
strncpy(options->repmgr_bindir, value, MAXPGPATH);
|
|
||||||
|
|
||||||
else if (strcmp(name, "replication_type") == 0)
|
else if (strcmp(name, "replication_type") == 0)
|
||||||
{
|
{
|
||||||
@@ -525,8 +508,6 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *
|
|||||||
parse_time_unit_parameter(name, value, options->recovery_min_apply_delay, error_list);
|
parse_time_unit_parameter(name, value, options->recovery_min_apply_delay, error_list);
|
||||||
options->recovery_min_apply_delay_provided = true;
|
options->recovery_min_apply_delay_provided = true;
|
||||||
}
|
}
|
||||||
else if (strcmp(name, "archive_cleanup_command") == 0)
|
|
||||||
strncpy(options->archive_cleanup_command, value, MAXLEN);
|
|
||||||
else if (strcmp(name, "use_primary_conninfo_password") == 0)
|
else if (strcmp(name, "use_primary_conninfo_password") == 0)
|
||||||
options->use_primary_conninfo_password = parse_bool(value, name, error_list);
|
options->use_primary_conninfo_password = parse_bool(value, name, error_list);
|
||||||
else if (strcmp(name, "passfile") == 0)
|
else if (strcmp(name, "passfile") == 0)
|
||||||
@@ -539,26 +520,10 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *
|
|||||||
else if (strcmp(name, "promote_check_interval") == 0)
|
else if (strcmp(name, "promote_check_interval") == 0)
|
||||||
options->promote_check_interval = repmgr_atoi(value, name, error_list, 1);
|
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, "shutdown_check_timeout") == 0)
|
|
||||||
options->shutdown_check_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);
|
|
||||||
|
|
||||||
/* 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 */
|
/* node check settings */
|
||||||
else if (strcmp(name, "archive_ready_warning") == 0)
|
else if (strcmp(name, "archive_ready_warning") == 0)
|
||||||
options->archive_ready_warning = repmgr_atoi(value, name, error_list, 1);
|
options->archive_ready_warning = repmgr_atoi(value, name, error_list, 1);
|
||||||
else if (strcmp(name, "archive_ready_critical") == 0)
|
else if (strcmp(name, "archive_ready_critcial") == 0)
|
||||||
options->archive_ready_critical = repmgr_atoi(value, name, error_list, 1);
|
options->archive_ready_critical = repmgr_atoi(value, name, error_list, 1);
|
||||||
else if (strcmp(name, "replication_lag_warning") == 0)
|
else if (strcmp(name, "replication_lag_warning") == 0)
|
||||||
options->replication_lag_warning = repmgr_atoi(value, name, error_list, 1);
|
options->replication_lag_warning = repmgr_atoi(value, name, error_list, 1);
|
||||||
@@ -599,15 +564,15 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *
|
|||||||
else if (strcmp(name, "monitoring_history") == 0)
|
else if (strcmp(name, "monitoring_history") == 0)
|
||||||
options->monitoring_history = parse_bool(value, name, error_list);
|
options->monitoring_history = parse_bool(value, name, error_list);
|
||||||
else if (strcmp(name, "degraded_monitoring_timeout") == 0)
|
else if (strcmp(name, "degraded_monitoring_timeout") == 0)
|
||||||
options->degraded_monitoring_timeout = repmgr_atoi(value, name, error_list, -1);
|
options->degraded_monitoring_timeout = repmgr_atoi(value, name, error_list, 1);
|
||||||
else if (strcmp(name, "async_query_timeout") == 0)
|
else if (strcmp(name, "async_query_timeout") == 0)
|
||||||
options->async_query_timeout = repmgr_atoi(value, name, error_list, 0);
|
options->async_query_timeout = repmgr_atoi(value, name, error_list, 0);
|
||||||
else if (strcmp(name, "primary_notification_timeout") == 0)
|
else if (strcmp(name, "primary_notification_timeout") == 0)
|
||||||
options->primary_notification_timeout = repmgr_atoi(value, name, error_list, 0);
|
options->primary_notification_timeout = repmgr_atoi(value, name, error_list, 0);
|
||||||
else if (strcmp(name, "repmgrd_standby_startup_timeout") == 0)
|
else if (strcmp(name, "primary_follow_timeout") == 0)
|
||||||
options->repmgrd_standby_startup_timeout = repmgr_atoi(value, name, error_list, 0);
|
options->primary_follow_timeout = repmgr_atoi(value, name, error_list, 0);
|
||||||
else if (strcmp(name, "repmgrd_pid_file") == 0)
|
else if (strcmp(name, "standby_reconnect_timeout") == 0)
|
||||||
strncpy(options->repmgrd_pid_file, value, MAXPGPATH);
|
options->standby_reconnect_timeout = repmgr_atoi(value, name, error_list, 0);
|
||||||
|
|
||||||
/* witness settings */
|
/* witness settings */
|
||||||
else if (strcmp(name, "witness_sync_interval") == 0)
|
else if (strcmp(name, "witness_sync_interval") == 0)
|
||||||
@@ -789,17 +754,6 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *
|
|||||||
PQconninfoFree(conninfo_options);
|
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 */
|
/* add warning about changed "barman_" parameter meanings */
|
||||||
if ((options->barman_host[0] == '\0' && options->barman_server[0] != '\0') ||
|
if ((options->barman_host[0] == '\0' && options->barman_server[0] != '\0') ||
|
||||||
(options->barman_host[0] != '\0' && options->barman_server[0] == '\0'))
|
(options->barman_host[0] != '\0' && options->barman_server[0] == '\0'))
|
||||||
@@ -824,12 +778,6 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList *
|
|||||||
item_list_append(error_list,
|
item_list_append(error_list,
|
||||||
_("\replication_lag_critical\" must be greater than \"replication_lag_warning\""));
|
_("\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\""));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -994,11 +942,12 @@ parse_time_unit_parameter(const char *name, const char *value, char *dest, ItemL
|
|||||||
char *ptr = NULL;
|
char *ptr = NULL;
|
||||||
int targ = strtol(value, &ptr, 10);
|
int targ = strtol(value, &ptr, 10);
|
||||||
|
|
||||||
if (targ < 0)
|
if (targ < 1)
|
||||||
{
|
{
|
||||||
if (errors != NULL)
|
if (errors != NULL)
|
||||||
{
|
{
|
||||||
item_list_append_format(errors,
|
item_list_append_format(
|
||||||
|
errors,
|
||||||
_("invalid value provided for \"%s\""),
|
_("invalid value provided for \"%s\""),
|
||||||
name);
|
name);
|
||||||
}
|
}
|
||||||
@@ -1052,16 +1001,13 @@ parse_time_unit_parameter(const char *name, const char *value, char *dest, ItemL
|
|||||||
* - promote_delay
|
* - promote_delay
|
||||||
* - reconnect_attempts
|
* - reconnect_attempts
|
||||||
* - reconnect_interval
|
* - reconnect_interval
|
||||||
* - repmgrd_standby_startup_timeout
|
|
||||||
* - retry_promote_interval_secs
|
* - retry_promote_interval_secs
|
||||||
*
|
*
|
||||||
* non-changeable options (repmgrd references these from the "repmgr.nodes"
|
* non-changeable options
|
||||||
* table, not the configuration file)
|
|
||||||
*
|
*
|
||||||
* - node_id
|
* - node_id
|
||||||
* - node_name
|
* - node_name
|
||||||
* - data_directory
|
* - data_directory
|
||||||
* - location
|
|
||||||
* - priority
|
* - priority
|
||||||
* - replication_type
|
* - replication_type
|
||||||
*
|
*
|
||||||
@@ -1070,7 +1016,7 @@ parse_time_unit_parameter(const char *name, const char *value, char *dest, ItemL
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
reload_config(t_configuration_options *orig_options, t_server_type server_type)
|
reload_config(t_configuration_options *orig_options)
|
||||||
{
|
{
|
||||||
PGconn *conn;
|
PGconn *conn;
|
||||||
t_configuration_options new_options = T_CONFIGURATION_OPTIONS_INITIALIZER;
|
t_configuration_options new_options = T_CONFIGURATION_OPTIONS_INITIALIZER;
|
||||||
@@ -1080,50 +1026,17 @@ reload_config(t_configuration_options *orig_options, t_server_type server_type)
|
|||||||
static ItemList config_errors = {NULL, NULL};
|
static ItemList config_errors = {NULL, NULL};
|
||||||
static ItemList config_warnings = {NULL, NULL};
|
static ItemList config_warnings = {NULL, NULL};
|
||||||
|
|
||||||
PQExpBufferData errors;
|
|
||||||
|
|
||||||
log_info(_("reloading configuration file"));
|
log_info(_("reloading configuration file"));
|
||||||
|
|
||||||
_parse_config(&new_options, &config_errors, &config_warnings);
|
_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)
|
if (config_errors.head != NULL)
|
||||||
{
|
{
|
||||||
ItemListCell *cell = NULL;
|
/* XXX dump errors to log */
|
||||||
|
|
||||||
log_warning(_("unable to parse new configuration, retaining current configuration"));
|
log_warning(_("unable to parse new configuration, retaining current configuration"));
|
||||||
|
|
||||||
initPQExpBuffer(&errors);
|
|
||||||
|
|
||||||
appendPQExpBufferStr(&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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* The following options cannot be changed */
|
/* The following options cannot be changed */
|
||||||
|
|
||||||
if (new_options.node_id != orig_options->node_id)
|
if (new_options.node_id != orig_options->node_id)
|
||||||
@@ -1277,7 +1190,7 @@ reload_config(t_configuration_options *orig_options, t_server_type server_type)
|
|||||||
config_changed = true;
|
config_changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* promote_delay (for testing use only; not documented */
|
/* promote_delay */
|
||||||
if (orig_options->promote_delay != new_options.promote_delay)
|
if (orig_options->promote_delay != new_options.promote_delay)
|
||||||
{
|
{
|
||||||
orig_options->promote_delay = new_options.promote_delay;
|
orig_options->promote_delay = new_options.promote_delay;
|
||||||
@@ -1304,15 +1217,6 @@ reload_config(t_configuration_options *orig_options, t_server_type server_type)
|
|||||||
config_changed = true;
|
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
|
* Handle changes to logging configuration
|
||||||
*/
|
*/
|
||||||
@@ -1405,23 +1309,13 @@ exit_with_config_file_errors(ItemList *config_errors, ItemList *config_warnings,
|
|||||||
|
|
||||||
|
|
||||||
void
|
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"));
|
fprintf(stderr, _("The following command line errors were encountered:\n"));
|
||||||
|
|
||||||
print_item_list(error_list);
|
print_item_list(error_list);
|
||||||
|
|
||||||
if (repmgr_command != NULL)
|
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname());
|
||||||
{
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
|
|
||||||
exit(ERR_BAD_CONFIG);
|
exit(ERR_BAD_CONFIG);
|
||||||
}
|
}
|
||||||
@@ -1526,14 +1420,11 @@ repmgr_atoi(const char *value, const char *config_item, ItemList *error_list, in
|
|||||||
*
|
*
|
||||||
* https://www.postgresql.org/docs/current/static/config-setting.html
|
* 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)
|
parse_bool(const char *s, const char *config_item, ItemList *error_list)
|
||||||
{
|
{
|
||||||
PQExpBufferData errors;
|
PQExpBufferData errors;
|
||||||
|
|
||||||
if (s == NULL)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (strcasecmp(s, "0") == 0)
|
if (strcasecmp(s, "0") == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -1815,9 +1706,6 @@ free_parsed_argv(char ***argv_array)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
parse_pg_basebackup_options(const char *pg_basebackup_options, t_basebackup_options *backup_options, int server_version_num, ItemList *error_list)
|
parse_pg_basebackup_options(const char *pg_basebackup_options, t_basebackup_options *backup_options, int server_version_num, ItemList *error_list)
|
||||||
{
|
{
|
||||||
|
|||||||
45
configfile.h
45
configfile.h
@@ -73,9 +73,7 @@ typedef struct
|
|||||||
char conninfo[MAXLEN];
|
char conninfo[MAXLEN];
|
||||||
char replication_user[NAMEDATALEN];
|
char replication_user[NAMEDATALEN];
|
||||||
char data_directory[MAXPGPATH];
|
char data_directory[MAXPGPATH];
|
||||||
char config_directory[MAXPGPATH];
|
|
||||||
char pg_bindir[MAXPGPATH];
|
char pg_bindir[MAXPGPATH];
|
||||||
char repmgr_bindir[MAXPGPATH];
|
|
||||||
int replication_type;
|
int replication_type;
|
||||||
|
|
||||||
/* log settings */
|
/* log settings */
|
||||||
@@ -91,7 +89,6 @@ typedef struct
|
|||||||
TablespaceList tablespace_mapping;
|
TablespaceList tablespace_mapping;
|
||||||
char recovery_min_apply_delay[MAXLEN];
|
char recovery_min_apply_delay[MAXLEN];
|
||||||
bool recovery_min_apply_delay_provided;
|
bool recovery_min_apply_delay_provided;
|
||||||
char archive_cleanup_command[MAXLEN];
|
|
||||||
bool use_primary_conninfo_password;
|
bool use_primary_conninfo_password;
|
||||||
char passfile[MAXPGPATH];
|
char passfile[MAXPGPATH];
|
||||||
|
|
||||||
@@ -99,17 +96,6 @@ typedef struct
|
|||||||
int promote_check_timeout;
|
int promote_check_timeout;
|
||||||
int promote_check_interval;
|
int promote_check_interval;
|
||||||
|
|
||||||
/* standby follow settings */
|
|
||||||
int primary_follow_timeout;
|
|
||||||
int standby_follow_timeout;
|
|
||||||
|
|
||||||
/* standby switchover settings */
|
|
||||||
int shutdown_check_timeout;
|
|
||||||
int standby_reconnect_timeout;
|
|
||||||
|
|
||||||
/* node rejoin settings */
|
|
||||||
int node_rejoin_timeout;
|
|
||||||
|
|
||||||
/* node check settings */
|
/* node check settings */
|
||||||
int archive_ready_warning;
|
int archive_ready_warning;
|
||||||
int archive_ready_critical;
|
int archive_ready_critical;
|
||||||
@@ -132,8 +118,8 @@ typedef struct
|
|||||||
int degraded_monitoring_timeout;
|
int degraded_monitoring_timeout;
|
||||||
int async_query_timeout;
|
int async_query_timeout;
|
||||||
int primary_notification_timeout;
|
int primary_notification_timeout;
|
||||||
int repmgrd_standby_startup_timeout;
|
int primary_follow_timeout;
|
||||||
char repmgrd_pid_file[MAXPGPATH];
|
int standby_reconnect_timeout;
|
||||||
|
|
||||||
/* BDR settings */
|
/* BDR settings */
|
||||||
bool bdr_local_monitoring_only;
|
bool bdr_local_monitoring_only;
|
||||||
@@ -172,21 +158,13 @@ typedef struct
|
|||||||
|
|
||||||
#define T_CONFIGURATION_OPTIONS_INITIALIZER { \
|
#define T_CONFIGURATION_OPTIONS_INITIALIZER { \
|
||||||
/* node information */ \
|
/* node information */ \
|
||||||
UNKNOWN_NODE_ID, "", "", "", "", "", "", "", REPLICATION_TYPE_PHYSICAL, \
|
UNKNOWN_NODE_ID, "", "", "", "", "", REPLICATION_TYPE_PHYSICAL, \
|
||||||
/* log settings */ \
|
/* log settings */ \
|
||||||
"", "", "", DEFAULT_LOG_STATUS_INTERVAL, \
|
"", "", "", DEFAULT_LOG_STATUS_INTERVAL, \
|
||||||
/* standby clone settings */ \
|
/* standby action settings */ \
|
||||||
false, "", "", { NULL, NULL }, "", false, "", false, "", \
|
false, "", "", { NULL, NULL }, "", false, false, "", \
|
||||||
/* standby promote settings */ \
|
/* standby promote settings */ \
|
||||||
DEFAULT_PROMOTE_CHECK_TIMEOUT, DEFAULT_PROMOTE_CHECK_INTERVAL, \
|
DEFAULT_PROMOTE_CHECK_TIMEOUT, DEFAULT_PROMOTE_CHECK_INTERVAL, \
|
||||||
/* standby follow settings */ \
|
|
||||||
DEFAULT_PRIMARY_FOLLOW_TIMEOUT, \
|
|
||||||
DEFAULT_STANDBY_FOLLOW_TIMEOUT, \
|
|
||||||
/* standby switchover settings */ \
|
|
||||||
DEFAULT_SHUTDOWN_CHECK_TIMEOUT, \
|
|
||||||
DEFAULT_STANDBY_RECONNECT_TIMEOUT, \
|
|
||||||
/* node rejoin settings */ \
|
|
||||||
DEFAULT_NODE_REJOIN_TIMEOUT, \
|
|
||||||
/* node check settings */ \
|
/* node check settings */ \
|
||||||
DEFAULT_ARCHIVE_READY_WARNING, DEFAULT_ARCHIVE_READY_CRITICAL, \
|
DEFAULT_ARCHIVE_READY_WARNING, DEFAULT_ARCHIVE_READY_CRITICAL, \
|
||||||
DEFAULT_REPLICATION_LAG_WARNING, DEFAULT_REPLICATION_LAG_CRITICAL, \
|
DEFAULT_REPLICATION_LAG_WARNING, DEFAULT_REPLICATION_LAG_CRITICAL, \
|
||||||
@@ -200,7 +178,8 @@ typedef struct
|
|||||||
false, -1, \
|
false, -1, \
|
||||||
DEFAULT_ASYNC_QUERY_TIMEOUT, \
|
DEFAULT_ASYNC_QUERY_TIMEOUT, \
|
||||||
DEFAULT_PRIMARY_NOTIFICATION_TIMEOUT, \
|
DEFAULT_PRIMARY_NOTIFICATION_TIMEOUT, \
|
||||||
-1, "", \
|
DEFAULT_PRIMARY_FOLLOW_TIMEOUT, \
|
||||||
|
DEFAULT_STANDBY_RECONNECT_TIMEOUT, \
|
||||||
/* BDR settings */ \
|
/* BDR settings */ \
|
||||||
false, DEFAULT_BDR_RECOVERY_TIMEOUT, \
|
false, DEFAULT_BDR_RECOVERY_TIMEOUT, \
|
||||||
/* service settings */ \
|
/* service settings */ \
|
||||||
@@ -276,20 +255,16 @@ typedef struct
|
|||||||
"", "", "", "" \
|
"", "", "", "" \
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "dbutils.h"
|
|
||||||
|
|
||||||
void set_progname(const char *argv0);
|
void set_progname(const char *argv0);
|
||||||
const char *progname(void);
|
const char *progname(void);
|
||||||
|
|
||||||
void load_config(const char *config_file, bool verbose, bool terse, t_configuration_options *options, char *argv0);
|
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_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,
|
int repmgr_atoi(const char *s,
|
||||||
const char *config_item,
|
const char *config_item,
|
||||||
ItemList *error_list,
|
ItemList *error_list,
|
||||||
@@ -305,7 +280,7 @@ void free_parsed_argv(char ***argv_array);
|
|||||||
|
|
||||||
|
|
||||||
/* called by repmgr-client and repmgrd */
|
/* 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);
|
void print_item_list(ItemList *item_list);
|
||||||
|
|
||||||
#endif /* _REPMGR_CONFIGFILE_H_ */
|
#endif /* _REPMGR_CONFIGFILE_H_ */
|
||||||
|
|||||||
18
configure
vendored
18
configure
vendored
@@ -1,6 +1,6 @@
|
|||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
# Guess values for system-dependent variables and create Makefiles.
|
# Guess values for system-dependent variables and create Makefiles.
|
||||||
# Generated by GNU Autoconf 2.69 for repmgr 4.2.
|
# Generated by GNU Autoconf 2.69 for repmgr 4.0.4.
|
||||||
#
|
#
|
||||||
# Report bugs to <pgsql-bugs@postgresql.org>.
|
# Report bugs to <pgsql-bugs@postgresql.org>.
|
||||||
#
|
#
|
||||||
@@ -582,8 +582,8 @@ MAKEFLAGS=
|
|||||||
# Identity of this package.
|
# Identity of this package.
|
||||||
PACKAGE_NAME='repmgr'
|
PACKAGE_NAME='repmgr'
|
||||||
PACKAGE_TARNAME='repmgr'
|
PACKAGE_TARNAME='repmgr'
|
||||||
PACKAGE_VERSION='4.2'
|
PACKAGE_VERSION='4.0.4'
|
||||||
PACKAGE_STRING='repmgr 4.2'
|
PACKAGE_STRING='repmgr 4.0.4'
|
||||||
PACKAGE_BUGREPORT='pgsql-bugs@postgresql.org'
|
PACKAGE_BUGREPORT='pgsql-bugs@postgresql.org'
|
||||||
PACKAGE_URL='https://2ndquadrant.com/en/resources/repmgr/'
|
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.
|
# 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.
|
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||||
cat <<_ACEOF
|
cat <<_ACEOF
|
||||||
\`configure' configures repmgr 4.2 to adapt to many kinds of systems.
|
\`configure' configures repmgr 4.0.4 to adapt to many kinds of systems.
|
||||||
|
|
||||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||||
|
|
||||||
@@ -1239,7 +1239,7 @@ fi
|
|||||||
|
|
||||||
if test -n "$ac_init_help"; then
|
if test -n "$ac_init_help"; then
|
||||||
case $ac_init_help in
|
case $ac_init_help in
|
||||||
short | recursive ) echo "Configuration of repmgr 4.2:";;
|
short | recursive ) echo "Configuration of repmgr 4.0.4:";;
|
||||||
esac
|
esac
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
|
|
||||||
@@ -1313,7 +1313,7 @@ fi
|
|||||||
test -n "$ac_init_help" && exit $ac_status
|
test -n "$ac_init_help" && exit $ac_status
|
||||||
if $ac_init_version; then
|
if $ac_init_version; then
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
repmgr configure 4.2
|
repmgr configure 4.0.4
|
||||||
generated by GNU Autoconf 2.69
|
generated by GNU Autoconf 2.69
|
||||||
|
|
||||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||||
@@ -1332,7 +1332,7 @@ cat >config.log <<_ACEOF
|
|||||||
This file contains any messages produced by compilers while
|
This file contains any messages produced by compilers while
|
||||||
running configure, to aid debugging if configure makes a mistake.
|
running configure, to aid debugging if configure makes a mistake.
|
||||||
|
|
||||||
It was created by repmgr $as_me 4.2, which was
|
It was created by repmgr $as_me 4.0.4, which was
|
||||||
generated by GNU Autoconf 2.69. Invocation command line was
|
generated by GNU Autoconf 2.69. Invocation command line was
|
||||||
|
|
||||||
$ $0 $@
|
$ $0 $@
|
||||||
@@ -2359,7 +2359,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
|||||||
# report actual input values of CONFIG_FILES etc. instead of their
|
# report actual input values of CONFIG_FILES etc. instead of their
|
||||||
# values after options handling.
|
# values after options handling.
|
||||||
ac_log="
|
ac_log="
|
||||||
This file was extended by repmgr $as_me 4.2, which was
|
This file was extended by repmgr $as_me 4.0.4, which was
|
||||||
generated by GNU Autoconf 2.69. Invocation command line was
|
generated by GNU Autoconf 2.69. Invocation command line was
|
||||||
|
|
||||||
CONFIG_FILES = $CONFIG_FILES
|
CONFIG_FILES = $CONFIG_FILES
|
||||||
@@ -2422,7 +2422,7 @@ _ACEOF
|
|||||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||||
ac_cs_version="\\
|
ac_cs_version="\\
|
||||||
repmgr config.status 4.2
|
repmgr config.status 4.0.4
|
||||||
configured by $0, generated by GNU Autoconf 2.69,
|
configured by $0, generated by GNU Autoconf 2.69,
|
||||||
with options \\"\$ac_cs_config\\"
|
with options \\"\$ac_cs_config\\"
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
AC_INIT([repmgr], [4.2], [pgsql-bugs@postgresql.org], [repmgr], [https://2ndquadrant.com/en/resources/repmgr/])
|
AC_INIT([repmgr], [4.0.4], [pgsql-bugs@postgresql.org], [repmgr], [https://2ndquadrant.com/en/resources/repmgr/])
|
||||||
|
|
||||||
AC_COPYRIGHT([Copyright (c) 2010-2018, 2ndQuadrant Ltd.])
|
AC_COPYRIGHT([Copyright (c) 2010-2018, 2ndQuadrant Ltd.])
|
||||||
|
|
||||||
|
|||||||
157
controldata.c
157
controldata.c
@@ -37,8 +37,13 @@ get_system_identifier(const char *data_directory)
|
|||||||
uint64 system_identifier = UNKNOWN_SYSTEM_IDENTIFIER;
|
uint64 system_identifier = UNKNOWN_SYSTEM_IDENTIFIER;
|
||||||
|
|
||||||
control_file_info = get_controlfile(data_directory);
|
control_file_info = get_controlfile(data_directory);
|
||||||
system_identifier = control_file_info->system_identifier;
|
|
||||||
|
|
||||||
|
if (control_file_info->control_file_processed == true)
|
||||||
|
system_identifier = control_file_info->control_file->system_identifier;
|
||||||
|
else
|
||||||
|
system_identifier = UNKNOWN_SYSTEM_IDENTIFIER;
|
||||||
|
|
||||||
|
pfree(control_file_info->control_file);
|
||||||
pfree(control_file_info);
|
pfree(control_file_info);
|
||||||
|
|
||||||
return system_identifier;
|
return system_identifier;
|
||||||
@@ -52,8 +57,13 @@ get_db_state(const char *data_directory)
|
|||||||
|
|
||||||
control_file_info = get_controlfile(data_directory);
|
control_file_info = get_controlfile(data_directory);
|
||||||
|
|
||||||
state = control_file_info->state;
|
if (control_file_info->control_file_processed == true)
|
||||||
|
state = control_file_info->control_file->state;
|
||||||
|
else
|
||||||
|
/* if we were unable to parse the control file, assume DB is shut down */
|
||||||
|
state = DB_SHUTDOWNED;
|
||||||
|
|
||||||
|
pfree(control_file_info->control_file);
|
||||||
pfree(control_file_info);
|
pfree(control_file_info);
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
@@ -68,8 +78,12 @@ get_latest_checkpoint_location(const char *data_directory)
|
|||||||
|
|
||||||
control_file_info = get_controlfile(data_directory);
|
control_file_info = get_controlfile(data_directory);
|
||||||
|
|
||||||
checkPoint = control_file_info->checkPoint;
|
if (control_file_info->control_file_processed == false)
|
||||||
|
return InvalidXLogRecPtr;
|
||||||
|
|
||||||
|
checkPoint = control_file_info->control_file->checkPoint;
|
||||||
|
|
||||||
|
pfree(control_file_info->control_file);
|
||||||
pfree(control_file_info);
|
pfree(control_file_info);
|
||||||
|
|
||||||
return checkPoint;
|
return checkPoint;
|
||||||
@@ -84,8 +98,16 @@ get_data_checksum_version(const char *data_directory)
|
|||||||
|
|
||||||
control_file_info = get_controlfile(data_directory);
|
control_file_info = get_controlfile(data_directory);
|
||||||
|
|
||||||
data_checksum_version = (int) control_file_info->data_checksum_version;
|
if (control_file_info->control_file_processed == false)
|
||||||
|
{
|
||||||
|
data_checksum_version = -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
data_checksum_version = (int) control_file_info->control_file->data_checksum_version;
|
||||||
|
}
|
||||||
|
|
||||||
|
pfree(control_file_info->control_file);
|
||||||
pfree(control_file_info);
|
pfree(control_file_info);
|
||||||
|
|
||||||
return data_checksum_version;
|
return data_checksum_version;
|
||||||
@@ -117,109 +139,33 @@ describe_db_state(DBState state)
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We maintain our own version of get_controlfile() as we need cross-version
|
* we maintain our own version of get_controlfile() as we need cross-version
|
||||||
* compatibility, and also don't care if the file isn't readable.
|
* compatibility, and also don't care if the file isn't readable.
|
||||||
*/
|
*/
|
||||||
static ControlFileInfo *
|
static ControlFileInfo *
|
||||||
get_controlfile(const char *DataDir)
|
get_controlfile(const char *DataDir)
|
||||||
{
|
{
|
||||||
ControlFileInfo *control_file_info;
|
ControlFileInfo *control_file_info;
|
||||||
FILE *fp = NULL;
|
int fd;
|
||||||
int fd, ret, version_num;
|
|
||||||
char PgVersionPath[MAXPGPATH] = "";
|
|
||||||
char ControlFilePath[MAXPGPATH] = "";
|
char ControlFilePath[MAXPGPATH] = "";
|
||||||
char file_version_string[64] = "";
|
|
||||||
long file_major, file_minor;
|
|
||||||
char *endptr = NULL;
|
|
||||||
void *ControlFileDataPtr = NULL;
|
|
||||||
int expected_size = 0;
|
|
||||||
|
|
||||||
control_file_info = palloc0(sizeof(ControlFileInfo));
|
control_file_info = palloc0(sizeof(ControlFileInfo));
|
||||||
|
|
||||||
/* set default values */
|
|
||||||
control_file_info->control_file_processed = false;
|
control_file_info->control_file_processed = false;
|
||||||
control_file_info->system_identifier = UNKNOWN_SYSTEM_IDENTIFIER;
|
control_file_info->control_file = palloc0(sizeof(ControlFileData));
|
||||||
control_file_info->state = DB_SHUTDOWNED;
|
|
||||||
control_file_info->checkPoint = InvalidXLogRecPtr;
|
|
||||||
control_file_info->data_checksum_version = -1;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Read PG_VERSION, as we'll need to determine which struct to read
|
|
||||||
* the control file contents into
|
|
||||||
*/
|
|
||||||
snprintf(PgVersionPath, MAXPGPATH, "%s/PG_VERSION", DataDir);
|
|
||||||
|
|
||||||
fp = fopen(PgVersionPath, "r");
|
|
||||||
|
|
||||||
if (fp == NULL)
|
|
||||||
{
|
|
||||||
log_warning(_("could not open file \"%s\" for reading"),
|
|
||||||
PgVersionPath);
|
|
||||||
log_detail("%s", strerror(errno));
|
|
||||||
return control_file_info;
|
|
||||||
}
|
|
||||||
|
|
||||||
file_version_string[0] = '\0';
|
|
||||||
|
|
||||||
ret = fscanf(fp, "%63s", file_version_string);
|
|
||||||
fclose(fp);
|
|
||||||
|
|
||||||
if (ret != 1 || endptr == file_version_string)
|
|
||||||
{
|
|
||||||
log_warning(_("unable to determine major version number from PG_VERSION"));
|
|
||||||
|
|
||||||
return control_file_info;
|
|
||||||
}
|
|
||||||
|
|
||||||
file_major = strtol(file_version_string, &endptr, 10);
|
|
||||||
file_minor = 0;
|
|
||||||
|
|
||||||
if (*endptr == '.')
|
|
||||||
file_minor = strtol(endptr + 1, NULL, 10);
|
|
||||||
|
|
||||||
version_num = ((int) file_major * 10000) + ((int) file_minor * 100);
|
|
||||||
|
|
||||||
if (version_num < 90300)
|
|
||||||
{
|
|
||||||
log_warning(_("Data directory appears to be initialised for %s"), file_version_string);
|
|
||||||
return control_file_info;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
snprintf(ControlFilePath, MAXPGPATH, "%s/global/pg_control", DataDir);
|
snprintf(ControlFilePath, MAXPGPATH, "%s/global/pg_control", DataDir);
|
||||||
|
|
||||||
if ((fd = open(ControlFilePath, O_RDONLY | PG_BINARY, 0)) == -1)
|
if ((fd = open(ControlFilePath, O_RDONLY | PG_BINARY, 0)) == -1)
|
||||||
{
|
{
|
||||||
log_warning(_("could not open file \"%s\" for reading"),
|
log_debug("could not open file \"%s\" for reading: %s",
|
||||||
ControlFilePath);
|
ControlFilePath, strerror(errno));
|
||||||
log_detail("%s", strerror(errno));
|
|
||||||
return control_file_info;
|
return control_file_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (read(fd, control_file_info->control_file, sizeof(ControlFileData)) != sizeof(ControlFileData))
|
||||||
if (version_num >= 90500)
|
|
||||||
{
|
{
|
||||||
expected_size = sizeof(ControlFileData95);
|
log_debug("could not read file \"%s\": %s",
|
||||||
ControlFileDataPtr = palloc0(expected_size);
|
ControlFilePath, strerror(errno));
|
||||||
}
|
|
||||||
else if (version_num >= 90400)
|
|
||||||
{
|
|
||||||
expected_size = sizeof(ControlFileData94);
|
|
||||||
ControlFileDataPtr = palloc0(expected_size);
|
|
||||||
}
|
|
||||||
else if (version_num >= 90300)
|
|
||||||
{
|
|
||||||
expected_size = sizeof(ControlFileData93);
|
|
||||||
ControlFileDataPtr = palloc0(expected_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (read(fd, ControlFileDataPtr, expected_size) != expected_size)
|
|
||||||
{
|
|
||||||
log_warning(_("could not read file \"%s\""),
|
|
||||||
ControlFilePath);
|
|
||||||
log_detail("%s", strerror(errno));
|
|
||||||
|
|
||||||
return control_file_info;
|
return control_file_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,41 +173,6 @@ get_controlfile(const char *DataDir)
|
|||||||
|
|
||||||
control_file_info->control_file_processed = true;
|
control_file_info->control_file_processed = true;
|
||||||
|
|
||||||
if (version_num >= 110000)
|
|
||||||
{
|
|
||||||
ControlFileData11 *ptr = (struct ControlFileData11 *)ControlFileDataPtr;
|
|
||||||
control_file_info->system_identifier = ptr->system_identifier;
|
|
||||||
control_file_info->state = ptr->state;
|
|
||||||
control_file_info->checkPoint = ptr->checkPoint;
|
|
||||||
control_file_info->data_checksum_version = ptr->data_checksum_version;
|
|
||||||
}
|
|
||||||
else if (version_num >= 90500)
|
|
||||||
{
|
|
||||||
ControlFileData95 *ptr = (struct ControlFileData95 *)ControlFileDataPtr;
|
|
||||||
control_file_info->system_identifier = ptr->system_identifier;
|
|
||||||
control_file_info->state = ptr->state;
|
|
||||||
control_file_info->checkPoint = ptr->checkPoint;
|
|
||||||
control_file_info->data_checksum_version = ptr->data_checksum_version;
|
|
||||||
}
|
|
||||||
else if (version_num >= 90400)
|
|
||||||
{
|
|
||||||
ControlFileData94 *ptr = (struct ControlFileData94 *)ControlFileDataPtr;
|
|
||||||
control_file_info->system_identifier = ptr->system_identifier;
|
|
||||||
control_file_info->state = ptr->state;
|
|
||||||
control_file_info->checkPoint = ptr->checkPoint;
|
|
||||||
control_file_info->data_checksum_version = ptr->data_checksum_version;
|
|
||||||
}
|
|
||||||
else if (version_num >= 90300)
|
|
||||||
{
|
|
||||||
ControlFileData93 *ptr = (struct ControlFileData93 *)ControlFileDataPtr;
|
|
||||||
control_file_info->system_identifier = ptr->system_identifier;
|
|
||||||
control_file_info->state = ptr->state;
|
|
||||||
control_file_info->checkPoint = ptr->checkPoint;
|
|
||||||
control_file_info->data_checksum_version = ptr->data_checksum_version;
|
|
||||||
}
|
|
||||||
|
|
||||||
pfree(ControlFileDataPtr);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We don't check the CRC here as we're potentially checking a pg_control
|
* We don't check the CRC here as we're potentially checking a pg_control
|
||||||
* file from a different PostgreSQL version to the one repmgr was compiled
|
* file from a different PostgreSQL version to the one repmgr was compiled
|
||||||
|
|||||||
316
controldata.h
316
controldata.h
@@ -12,326 +12,12 @@
|
|||||||
#include "postgres_fe.h"
|
#include "postgres_fe.h"
|
||||||
#include "catalog/pg_control.h"
|
#include "catalog/pg_control.h"
|
||||||
|
|
||||||
/*
|
|
||||||
* A simplified representation of pg_control containing only those fields
|
|
||||||
* required by repmgr.
|
|
||||||
*/
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
bool control_file_processed;
|
bool control_file_processed;
|
||||||
uint64 system_identifier;
|
ControlFileData *control_file;
|
||||||
DBState state;
|
|
||||||
XLogRecPtr checkPoint;
|
|
||||||
uint32 data_checksum_version;
|
|
||||||
} ControlFileInfo;
|
} ControlFileInfo;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Same for 9.3, 9.4 */
|
|
||||||
typedef struct CheckPoint93
|
|
||||||
{
|
|
||||||
XLogRecPtr redo; /* next RecPtr available when we began to
|
|
||||||
* create CheckPoint (i.e. REDO start point) */
|
|
||||||
TimeLineID ThisTimeLineID; /* current TLI */
|
|
||||||
TimeLineID PrevTimeLineID; /* previous TLI, if this record begins a new
|
|
||||||
* timeline (equals ThisTimeLineID otherwise) */
|
|
||||||
bool fullPageWrites; /* current full_page_writes */
|
|
||||||
uint32 nextXidEpoch; /* higher-order bits of nextXid */
|
|
||||||
TransactionId nextXid; /* next free XID */
|
|
||||||
Oid nextOid; /* next free OID */
|
|
||||||
MultiXactId nextMulti; /* next free MultiXactId */
|
|
||||||
MultiXactOffset nextMultiOffset; /* next free MultiXact offset */
|
|
||||||
TransactionId oldestXid; /* cluster-wide minimum datfrozenxid */
|
|
||||||
Oid oldestXidDB; /* database with minimum datfrozenxid */
|
|
||||||
MultiXactId oldestMulti; /* cluster-wide minimum datminmxid */
|
|
||||||
Oid oldestMultiDB; /* database with minimum datminmxid */
|
|
||||||
pg_time_t time; /* time stamp of checkpoint */
|
|
||||||
|
|
||||||
TransactionId oldestActiveXid;
|
|
||||||
} CheckPoint93;
|
|
||||||
|
|
||||||
|
|
||||||
/* Same for 9.5, 9.6, 10, HEAD */
|
|
||||||
typedef struct CheckPoint95
|
|
||||||
{
|
|
||||||
XLogRecPtr redo; /* next RecPtr available when we began to
|
|
||||||
* create CheckPoint (i.e. REDO start point) */
|
|
||||||
TimeLineID ThisTimeLineID; /* current TLI */
|
|
||||||
TimeLineID PrevTimeLineID; /* previous TLI, if this record begins a new
|
|
||||||
* timeline (equals ThisTimeLineID otherwise) */
|
|
||||||
bool fullPageWrites; /* current full_page_writes */
|
|
||||||
uint32 nextXidEpoch; /* higher-order bits of nextXid */
|
|
||||||
TransactionId nextXid; /* next free XID */
|
|
||||||
Oid nextOid; /* next free OID */
|
|
||||||
MultiXactId nextMulti; /* next free MultiXactId */
|
|
||||||
MultiXactOffset nextMultiOffset; /* next free MultiXact offset */
|
|
||||||
TransactionId oldestXid; /* cluster-wide minimum datfrozenxid */
|
|
||||||
Oid oldestXidDB; /* database with minimum datfrozenxid */
|
|
||||||
MultiXactId oldestMulti; /* cluster-wide minimum datminmxid */
|
|
||||||
Oid oldestMultiDB; /* database with minimum datminmxid */
|
|
||||||
pg_time_t time; /* time stamp of checkpoint */
|
|
||||||
TransactionId oldestCommitTsXid; /* oldest Xid with valid commit
|
|
||||||
* timestamp */
|
|
||||||
TransactionId newestCommitTsXid; /* newest Xid with valid commit
|
|
||||||
* timestamp */
|
|
||||||
|
|
||||||
TransactionId oldestActiveXid;
|
|
||||||
} CheckPoint95;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct ControlFileData93
|
|
||||||
{
|
|
||||||
uint64 system_identifier;
|
|
||||||
|
|
||||||
uint32 pg_control_version; /* PG_CONTROL_VERSION */
|
|
||||||
uint32 catalog_version_no; /* see catversion.h */
|
|
||||||
|
|
||||||
DBState state; /* see enum above */
|
|
||||||
pg_time_t time; /* time stamp of last pg_control update */
|
|
||||||
XLogRecPtr checkPoint; /* last check point record ptr */
|
|
||||||
XLogRecPtr prevCheckPoint; /* previous check point record ptr */
|
|
||||||
|
|
||||||
CheckPoint93 checkPointCopy; /* copy of last check point record */
|
|
||||||
|
|
||||||
XLogRecPtr unloggedLSN; /* current fake LSN value, for unlogged rels */
|
|
||||||
|
|
||||||
XLogRecPtr minRecoveryPoint;
|
|
||||||
TimeLineID minRecoveryPointTLI;
|
|
||||||
XLogRecPtr backupStartPoint;
|
|
||||||
XLogRecPtr backupEndPoint;
|
|
||||||
bool backupEndRequired;
|
|
||||||
|
|
||||||
int wal_level;
|
|
||||||
int MaxConnections;
|
|
||||||
int max_prepared_xacts;
|
|
||||||
int max_locks_per_xact;
|
|
||||||
|
|
||||||
uint32 maxAlign; /* alignment requirement for tuples */
|
|
||||||
double floatFormat; /* constant 1234567.0 */
|
|
||||||
|
|
||||||
uint32 blcksz; /* data block size for this DB */
|
|
||||||
uint32 relseg_size; /* blocks per segment of large relation */
|
|
||||||
|
|
||||||
uint32 xlog_blcksz; /* block size within WAL files */
|
|
||||||
uint32 xlog_seg_size; /* size of each WAL segment */
|
|
||||||
|
|
||||||
uint32 nameDataLen; /* catalog name field width */
|
|
||||||
uint32 indexMaxKeys; /* max number of columns in an index */
|
|
||||||
|
|
||||||
uint32 toast_max_chunk_size; /* chunk size in TOAST tables */
|
|
||||||
|
|
||||||
/* flag indicating internal format of timestamp, interval, time */
|
|
||||||
bool enableIntTimes; /* int64 storage enabled? */
|
|
||||||
|
|
||||||
/* flags indicating pass-by-value status of various types */
|
|
||||||
bool float4ByVal; /* float4 pass-by-value? */
|
|
||||||
bool float8ByVal; /* float8, int8, etc pass-by-value? */
|
|
||||||
|
|
||||||
/* Are data pages protected by checksums? Zero if no checksum version */
|
|
||||||
uint32 data_checksum_version;
|
|
||||||
|
|
||||||
} ControlFileData93;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Following fields added since 9.3:
|
|
||||||
*
|
|
||||||
* int max_worker_processes;
|
|
||||||
* int max_prepared_xacts;
|
|
||||||
* int max_locks_per_xact;
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
typedef struct ControlFileData94
|
|
||||||
{
|
|
||||||
uint64 system_identifier;
|
|
||||||
|
|
||||||
uint32 pg_control_version; /* PG_CONTROL_VERSION */
|
|
||||||
uint32 catalog_version_no; /* see catversion.h */
|
|
||||||
|
|
||||||
DBState state; /* see enum above */
|
|
||||||
pg_time_t time; /* time stamp of last pg_control update */
|
|
||||||
XLogRecPtr checkPoint; /* last check point record ptr */
|
|
||||||
XLogRecPtr prevCheckPoint; /* previous check point record ptr */
|
|
||||||
|
|
||||||
CheckPoint93 checkPointCopy; /* copy of last check point record */
|
|
||||||
|
|
||||||
XLogRecPtr unloggedLSN; /* current fake LSN value, for unlogged rels */
|
|
||||||
|
|
||||||
XLogRecPtr minRecoveryPoint;
|
|
||||||
TimeLineID minRecoveryPointTLI;
|
|
||||||
XLogRecPtr backupStartPoint;
|
|
||||||
XLogRecPtr backupEndPoint;
|
|
||||||
bool backupEndRequired;
|
|
||||||
|
|
||||||
int wal_level;
|
|
||||||
bool wal_log_hints;
|
|
||||||
int MaxConnections;
|
|
||||||
int max_worker_processes;
|
|
||||||
int max_prepared_xacts;
|
|
||||||
int max_locks_per_xact;
|
|
||||||
|
|
||||||
uint32 maxAlign; /* alignment requirement for tuples */
|
|
||||||
double floatFormat; /* constant 1234567.0 */
|
|
||||||
|
|
||||||
uint32 blcksz; /* data block size for this DB */
|
|
||||||
uint32 relseg_size; /* blocks per segment of large relation */
|
|
||||||
|
|
||||||
uint32 xlog_blcksz; /* block size within WAL files */
|
|
||||||
uint32 xlog_seg_size; /* size of each WAL segment */
|
|
||||||
|
|
||||||
uint32 nameDataLen; /* catalog name field width */
|
|
||||||
uint32 indexMaxKeys; /* max number of columns in an index */
|
|
||||||
|
|
||||||
uint32 toast_max_chunk_size; /* chunk size in TOAST tables */
|
|
||||||
uint32 loblksize; /* chunk size in pg_largeobject */
|
|
||||||
|
|
||||||
bool enableIntTimes; /* int64 storage enabled? */
|
|
||||||
|
|
||||||
bool float4ByVal; /* float4 pass-by-value? */
|
|
||||||
bool float8ByVal; /* float8, int8, etc pass-by-value? */
|
|
||||||
|
|
||||||
/* Are data pages protected by checksums? Zero if no checksum version */
|
|
||||||
uint32 data_checksum_version;
|
|
||||||
|
|
||||||
} ControlFileData94;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Following field added since 9.4:
|
|
||||||
*
|
|
||||||
* bool track_commit_timestamp;
|
|
||||||
*
|
|
||||||
* Unchanged in 9.6
|
|
||||||
*
|
|
||||||
* In 10, following field appended *after* "data_checksum_version":
|
|
||||||
*
|
|
||||||
* char mock_authentication_nonce[MOCK_AUTH_NONCE_LEN];
|
|
||||||
*
|
|
||||||
* (but we don't care about that)
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct ControlFileData95
|
|
||||||
{
|
|
||||||
uint64 system_identifier;
|
|
||||||
|
|
||||||
uint32 pg_control_version; /* PG_CONTROL_VERSION */
|
|
||||||
uint32 catalog_version_no; /* see catversion.h */
|
|
||||||
|
|
||||||
DBState state; /* see enum above */
|
|
||||||
pg_time_t time; /* time stamp of last pg_control update */
|
|
||||||
XLogRecPtr checkPoint; /* last check point record ptr */
|
|
||||||
XLogRecPtr prevCheckPoint; /* previous check point record ptr */
|
|
||||||
|
|
||||||
CheckPoint95 checkPointCopy; /* copy of last check point record */
|
|
||||||
|
|
||||||
XLogRecPtr unloggedLSN; /* current fake LSN value, for unlogged rels */
|
|
||||||
|
|
||||||
XLogRecPtr minRecoveryPoint;
|
|
||||||
TimeLineID minRecoveryPointTLI;
|
|
||||||
XLogRecPtr backupStartPoint;
|
|
||||||
XLogRecPtr backupEndPoint;
|
|
||||||
bool backupEndRequired;
|
|
||||||
|
|
||||||
int wal_level;
|
|
||||||
bool wal_log_hints;
|
|
||||||
int MaxConnections;
|
|
||||||
int max_worker_processes;
|
|
||||||
int max_prepared_xacts;
|
|
||||||
int max_locks_per_xact;
|
|
||||||
bool track_commit_timestamp;
|
|
||||||
|
|
||||||
uint32 maxAlign; /* alignment requirement for tuples */
|
|
||||||
double floatFormat; /* constant 1234567.0 */
|
|
||||||
|
|
||||||
uint32 blcksz; /* data block size for this DB */
|
|
||||||
uint32 relseg_size; /* blocks per segment of large relation */
|
|
||||||
|
|
||||||
uint32 xlog_blcksz; /* block size within WAL files */
|
|
||||||
uint32 xlog_seg_size; /* size of each WAL segment */
|
|
||||||
|
|
||||||
uint32 nameDataLen; /* catalog name field width */
|
|
||||||
uint32 indexMaxKeys; /* max number of columns in an index */
|
|
||||||
|
|
||||||
uint32 toast_max_chunk_size; /* chunk size in TOAST tables */
|
|
||||||
uint32 loblksize; /* chunk size in pg_largeobject */
|
|
||||||
|
|
||||||
bool enableIntTimes; /* int64 storage enabled? */
|
|
||||||
|
|
||||||
bool float4ByVal; /* float4 pass-by-value? */
|
|
||||||
bool float8ByVal; /* float8, int8, etc pass-by-value? */
|
|
||||||
|
|
||||||
uint32 data_checksum_version;
|
|
||||||
|
|
||||||
} ControlFileData95;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Following field removed in 11:
|
|
||||||
*
|
|
||||||
* XLogRecPtr prevCheckPoint;
|
|
||||||
*
|
|
||||||
* In 10, following field appended *after* "data_checksum_version":
|
|
||||||
*
|
|
||||||
* char mock_authentication_nonce[MOCK_AUTH_NONCE_LEN];
|
|
||||||
*
|
|
||||||
* (but we don't care about that)
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef struct ControlFileData11
|
|
||||||
{
|
|
||||||
uint64 system_identifier;
|
|
||||||
|
|
||||||
uint32 pg_control_version; /* PG_CONTROL_VERSION */
|
|
||||||
uint32 catalog_version_no; /* see catversion.h */
|
|
||||||
|
|
||||||
DBState state; /* see enum above */
|
|
||||||
pg_time_t time; /* time stamp of last pg_control update */
|
|
||||||
XLogRecPtr checkPoint; /* last check point record ptr */
|
|
||||||
|
|
||||||
CheckPoint95 checkPointCopy; /* copy of last check point record */
|
|
||||||
|
|
||||||
XLogRecPtr unloggedLSN; /* current fake LSN value, for unlogged rels */
|
|
||||||
|
|
||||||
XLogRecPtr minRecoveryPoint;
|
|
||||||
TimeLineID minRecoveryPointTLI;
|
|
||||||
XLogRecPtr backupStartPoint;
|
|
||||||
XLogRecPtr backupEndPoint;
|
|
||||||
bool backupEndRequired;
|
|
||||||
|
|
||||||
int wal_level;
|
|
||||||
bool wal_log_hints;
|
|
||||||
int MaxConnections;
|
|
||||||
int max_worker_processes;
|
|
||||||
int max_prepared_xacts;
|
|
||||||
int max_locks_per_xact;
|
|
||||||
bool track_commit_timestamp;
|
|
||||||
|
|
||||||
uint32 maxAlign; /* alignment requirement for tuples */
|
|
||||||
double floatFormat; /* constant 1234567.0 */
|
|
||||||
|
|
||||||
uint32 blcksz; /* data block size for this DB */
|
|
||||||
uint32 relseg_size; /* blocks per segment of large relation */
|
|
||||||
|
|
||||||
uint32 xlog_blcksz; /* block size within WAL files */
|
|
||||||
uint32 xlog_seg_size; /* size of each WAL segment */
|
|
||||||
|
|
||||||
uint32 nameDataLen; /* catalog name field width */
|
|
||||||
uint32 indexMaxKeys; /* max number of columns in an index */
|
|
||||||
|
|
||||||
uint32 toast_max_chunk_size; /* chunk size in TOAST tables */
|
|
||||||
uint32 loblksize; /* chunk size in pg_largeobject */
|
|
||||||
|
|
||||||
bool enableIntTimes; /* int64 storage enabled? */
|
|
||||||
|
|
||||||
bool float4ByVal; /* float4 pass-by-value? */
|
|
||||||
bool float8ByVal; /* float8, int8, etc pass-by-value? */
|
|
||||||
|
|
||||||
uint32 data_checksum_version;
|
|
||||||
|
|
||||||
} ControlFileData11;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
extern DBState get_db_state(const char *data_directory);
|
extern DBState get_db_state(const char *data_directory);
|
||||||
extern const char *describe_db_state(DBState state);
|
extern const char *describe_db_state(DBState state);
|
||||||
extern int get_data_checksum_version(const char *data_directory);
|
extern int get_data_checksum_version(const char *data_directory);
|
||||||
|
|||||||
61
dbutils.h
61
dbutils.h
@@ -29,9 +29,7 @@
|
|||||||
#include "voting.h"
|
#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 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 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 BDR3_NODES_COLUMNS "ns.node_id, 0, 0, ns.node_name, ns.interface_connstr, ns.peer_state_name"
|
|
||||||
|
|
||||||
|
|
||||||
#define ERRBUFF_SIZE 512
|
#define ERRBUFF_SIZE 512
|
||||||
|
|
||||||
@@ -96,14 +94,6 @@ typedef enum
|
|||||||
SLOT_ACTIVE
|
SLOT_ACTIVE
|
||||||
} ReplSlotStatus;
|
} ReplSlotStatus;
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
BACKUP_STATE_UNKNOWN = -1,
|
|
||||||
BACKUP_STATE_IN_BACKUP,
|
|
||||||
BACKUP_STATE_NO_BACKUP
|
|
||||||
} BackupState;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Struct to store node information
|
* Struct to store node information
|
||||||
*/
|
*/
|
||||||
@@ -247,14 +237,18 @@ typedef struct s_bdr_node_info
|
|||||||
char node_sysid[MAXLEN];
|
char node_sysid[MAXLEN];
|
||||||
uint32 node_timeline;
|
uint32 node_timeline;
|
||||||
uint32 node_dboid;
|
uint32 node_dboid;
|
||||||
|
char node_status;
|
||||||
char node_name[MAXLEN];
|
char node_name[MAXLEN];
|
||||||
char node_local_dsn[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;
|
} t_bdr_node_info;
|
||||||
|
|
||||||
#define T_BDR_NODE_INFO_INITIALIZER { \
|
#define T_BDR_NODE_INFO_INITIALIZER { \
|
||||||
"", InvalidOid, InvalidOid, \
|
"", InvalidOid, InvalidOid, \
|
||||||
"", "", "" \
|
'?', "", "", "", \
|
||||||
|
false, -1 \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -327,21 +321,6 @@ typedef struct
|
|||||||
UNKNOWN_TIMELINE_ID, \
|
UNKNOWN_TIMELINE_ID, \
|
||||||
InvalidXLogRecPtr \
|
InvalidXLogRecPtr \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
typedef struct RepmgrdInfo {
|
|
||||||
int node_id;
|
|
||||||
int pid;
|
|
||||||
char pid_text[MAXLEN];
|
|
||||||
char pid_file[MAXLEN];
|
|
||||||
bool pg_running;
|
|
||||||
char pg_running_text[MAXLEN];
|
|
||||||
bool running;
|
|
||||||
char repmgrd_running[MAXLEN];
|
|
||||||
bool paused;
|
|
||||||
} RepmgrdInfo;
|
|
||||||
|
|
||||||
|
|
||||||
/* global variables */
|
/* global variables */
|
||||||
|
|
||||||
extern int server_version_num;
|
extern int server_version_num;
|
||||||
@@ -374,11 +353,10 @@ PGconn *get_primary_connection(PGconn *standby_conn, int *primary_id, char *p
|
|||||||
PGconn *get_primary_connection_quiet(PGconn *standby_conn, int *primary_id, char *primary_conninfo_out);
|
PGconn *get_primary_connection_quiet(PGconn *standby_conn, int *primary_id, char *primary_conninfo_out);
|
||||||
|
|
||||||
bool is_superuser_connection(PGconn *conn, t_connection_user *userinfo);
|
bool is_superuser_connection(PGconn *conn, t_connection_user *userinfo);
|
||||||
void close_connection(PGconn **conn);
|
|
||||||
|
|
||||||
/* conninfo manipulation functions */
|
/* conninfo manipulation functions */
|
||||||
bool get_conninfo_value(const char *conninfo, const char *keyword, char *output);
|
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 initialize_conninfo_params(t_conninfo_param_list *param_list, bool set_defaults);
|
||||||
void free_conninfo_params(t_conninfo_param_list *param_list);
|
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);
|
void copy_conninfo_params(t_conninfo_param_list *dest_list, t_conninfo_param_list *source_list);
|
||||||
@@ -386,11 +364,10 @@ void conn_to_param_list(PGconn *conn, t_conninfo_param_list *param_list);
|
|||||||
void param_set(t_conninfo_param_list *param_list, const char *param, const char *value);
|
void param_set(t_conninfo_param_list *param_list, const char *param, const char *value);
|
||||||
void param_set_ine(t_conninfo_param_list *param_list, const char *param, const char *value);
|
void param_set_ine(t_conninfo_param_list *param_list, const char *param, const char *value);
|
||||||
char *param_get(t_conninfo_param_list *param_list, const char *param);
|
char *param_get(t_conninfo_param_list *param_list, const char *param);
|
||||||
bool parse_conninfo_string(const char *conninfo_str, t_conninfo_param_list *param_list, char **errmsg, bool ignore_local_params);
|
bool parse_conninfo_string(const char *conninfo_str, t_conninfo_param_list *param_list, char *errmsg, bool ignore_local_params);
|
||||||
char *param_list_to_string(t_conninfo_param_list *param_list);
|
char *param_list_to_string(t_conninfo_param_list *param_list);
|
||||||
bool has_passfile(void);
|
bool has_passfile(void);
|
||||||
|
|
||||||
|
|
||||||
/* transaction functions */
|
/* transaction functions */
|
||||||
bool begin_transaction(PGconn *conn);
|
bool begin_transaction(PGconn *conn);
|
||||||
bool commit_transaction(PGconn *conn);
|
bool commit_transaction(PGconn *conn);
|
||||||
@@ -409,16 +386,11 @@ bool get_cluster_size(PGconn *conn, char *size);
|
|||||||
int get_server_version(PGconn *conn, char *server_version);
|
int get_server_version(PGconn *conn, char *server_version);
|
||||||
RecoveryType get_recovery_type(PGconn *conn);
|
RecoveryType get_recovery_type(PGconn *conn);
|
||||||
int get_primary_node_id(PGconn *conn);
|
int get_primary_node_id(PGconn *conn);
|
||||||
|
bool can_use_pg_rewind(PGconn *conn, const char *data_directory, PQExpBufferData *reason);
|
||||||
int get_ready_archive_files(PGconn *conn, const char *data_directory);
|
int get_ready_archive_files(PGconn *conn, const char *data_directory);
|
||||||
bool identify_system(PGconn *repl_conn, t_system_identification *identification);
|
bool identify_system(PGconn *repl_conn, t_system_identification *identification);
|
||||||
bool repmgrd_set_local_node_id(PGconn *conn, int local_node_id);
|
bool repmgrd_set_local_node_id(PGconn *conn, int local_node_id);
|
||||||
int repmgrd_get_local_node_id(PGconn *conn);
|
int repmgrd_get_local_node_id(PGconn *conn);
|
||||||
BackupState server_in_exclusive_backup_mode(PGconn *conn);
|
|
||||||
void repmgrd_set_pid(PGconn *conn, pid_t repmgrd_pid, const char *pidfile);
|
|
||||||
pid_t repmgrd_get_pid(PGconn *conn);
|
|
||||||
bool repmgrd_is_running(PGconn *conn);
|
|
||||||
bool repmgrd_is_paused(PGconn *conn);
|
|
||||||
bool repmgrd_pause(PGconn *conn, bool pause);
|
|
||||||
|
|
||||||
/* extension functions */
|
/* extension functions */
|
||||||
ExtensionStatus get_repmgr_extension_status(PGconn *conn);
|
ExtensionStatus get_repmgr_extension_status(PGconn *conn);
|
||||||
@@ -441,7 +413,7 @@ t_node_info *get_node_record_pointer(PGconn *conn, int node_id);
|
|||||||
bool get_local_node_record(PGconn *conn, int node_id, t_node_info *node_info);
|
bool get_local_node_record(PGconn *conn, int node_id, t_node_info *node_info);
|
||||||
bool get_primary_node_record(PGconn *conn, t_node_info *node_info);
|
bool get_primary_node_record(PGconn *conn, t_node_info *node_info);
|
||||||
|
|
||||||
bool get_all_node_records(PGconn *conn, NodeInfoList *node_list);
|
void get_all_node_records(PGconn *conn, NodeInfoList *node_list);
|
||||||
void get_downstream_node_records(PGconn *conn, int node_id, NodeInfoList *nodes);
|
void get_downstream_node_records(PGconn *conn, int node_id, NodeInfoList *nodes);
|
||||||
void get_active_sibling_node_records(PGconn *conn, int node_id, int upstream_node_id, NodeInfoList *node_list);
|
void get_active_sibling_node_records(PGconn *conn, int node_id, int upstream_node_id, NodeInfoList *node_list);
|
||||||
void get_node_records_by_priority(PGconn *conn, NodeInfoList *node_list);
|
void get_node_records_by_priority(PGconn *conn, NodeInfoList *node_list);
|
||||||
@@ -482,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 create_replication_slot(PGconn *conn, char *slot_name, int server_version_num, PQExpBufferData *error_msg);
|
||||||
bool drop_replication_slot(PGconn *conn, char *slot_name);
|
bool drop_replication_slot(PGconn *conn, char *slot_name);
|
||||||
RecordStatus get_slot_record(PGconn *conn, char *slot_name, t_replication_slot *record);
|
RecordStatus get_slot_record(PGconn *conn, char *slot_name, t_replication_slot *record);
|
||||||
int get_free_replication_slot_count(PGconn *conn);
|
int get_free_replication_slots(PGconn *conn);
|
||||||
int get_inactive_replication_slots(PGconn *conn, KeyValueList *list);
|
|
||||||
|
|
||||||
/* tablespace functions */
|
/* tablespace functions */
|
||||||
bool get_tablespace_name_by_location(PGconn *conn, const char *location, char *name);
|
bool get_tablespace_name_by_location(PGconn *conn, const char *location, char *name);
|
||||||
@@ -494,8 +465,6 @@ int wait_connection_availability(PGconn *conn, long long timeout);
|
|||||||
|
|
||||||
/* node availability functions */
|
/* node availability functions */
|
||||||
bool is_server_available(const char *conninfo);
|
bool is_server_available(const char *conninfo);
|
||||||
bool is_server_available_params(t_conninfo_param_list *param_list);
|
|
||||||
ExecStatusType connection_ping(PGconn *conn);
|
|
||||||
|
|
||||||
/* monitoring functions */
|
/* monitoring functions */
|
||||||
void
|
void
|
||||||
@@ -511,8 +480,8 @@ add_monitoring_record(PGconn *primary_conn,
|
|||||||
long long unsigned int apply_lag_bytes
|
long long unsigned int apply_lag_bytes
|
||||||
);
|
);
|
||||||
|
|
||||||
int get_number_of_monitoring_records_to_delete(PGconn *primary_conn, int keep_history, int node_id);
|
int get_number_of_monitoring_records_to_delete(PGconn *primary_conn, int keep_history);
|
||||||
bool delete_monitoring_records(PGconn *primary_conn, int keep_history, int node_id);
|
bool delete_monitoring_records(PGconn *primary_conn, int keep_history);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -534,14 +503,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);
|
bool is_downstream_node_attached(PGconn *conn, char *node_name);
|
||||||
|
|
||||||
/* BDR functions */
|
/* BDR functions */
|
||||||
int get_bdr_version_num(void);
|
|
||||||
void get_all_bdr_node_records(PGconn *conn, BdrNodeInfoList *node_list);
|
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);
|
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(PGconn *conn, PQExpBufferData *output);
|
||||||
bool is_bdr_db_quiet(PGconn *conn);
|
bool is_bdr_db_quiet(PGconn *conn);
|
||||||
bool is_active_bdr_node(PGconn *conn, const char *node_name);
|
bool is_active_bdr_node(PGconn *conn, const char *node_name);
|
||||||
bool is_bdr_repmgr(PGconn *conn);
|
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 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);
|
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);
|
void add_extension_tables_to_bdr_replication_set(PGconn *conn);
|
||||||
|
|||||||
@@ -24,9 +24,8 @@
|
|||||||
series will no longer be actively maintained.
|
series will no longer be actively maintained.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
&repmgr; 2.x supports PostgreSQL 9.0 ~ 9.3. While it is compatible
|
repmgr 2.x supports PostgreSQL 9.0 ~ 9.3. While it is compatible
|
||||||
with PostgreSQL 9.3, we recommend using repmgr 4.x. &repmgr; 2.x is
|
with PostgreSQL 9.3, we recommend using repmgr 4.x.
|
||||||
no longer maintained.
|
|
||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
|
|
||||||
@@ -36,7 +35,7 @@
|
|||||||
Replication slots, introduced in PostgreSQL 9.4, ensure that the
|
Replication slots, introduced in PostgreSQL 9.4, ensure that the
|
||||||
primary server will retain WAL files until they have been consumed
|
primary server will retain WAL files until they have been consumed
|
||||||
by all standby servers. This makes WAL file management much easier,
|
by all standby servers. This makes WAL file management much easier,
|
||||||
and if used &repmgr; will no longer insist on a fixed minimum number
|
and if used `repmgr` will no longer insist on a fixed minimum number
|
||||||
(default: 5000) of WAL files being retained.
|
(default: 5000) of WAL files being retained.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
@@ -87,35 +86,12 @@
|
|||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
To minimize downtime during major upgrades, for more recent PostgreSQL
|
To minimize downtime during major upgrades, for more recent PostgreSQL
|
||||||
versions (PostgreSQL 9.4 and later),
|
versions <ulink url="https://www.2ndquadrant.com/en/resources/pglogical/">pglogical</ulink>
|
||||||
<ulink url="https://www.2ndquadrant.com/en/resources/pglogical/">pglogical</ulink>
|
|
||||||
can be used to set up a parallel cluster using the newer PostgreSQL version,
|
can be used to set up a parallel cluster using the newer PostgreSQL version,
|
||||||
which can be kept in sync with the existing production cluster until the
|
which can be kept in sync with the existing production cluster until the
|
||||||
new cluster is ready to be put into production.
|
new cluster is ready to be put into production.
|
||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
|
|
||||||
<sect2 id="faq-libdir-repmgr-error">
|
|
||||||
<title>What does this error mean: <literal>ERROR: could not access file "$libdir/repmgr"</literal>?</title>
|
|
||||||
<para>
|
|
||||||
It means the &repmgr; extension code is not installed in the
|
|
||||||
PostgreSQL application directory. This typically happens when using PostgreSQL
|
|
||||||
packages provided by a third-party vendor, which often have different
|
|
||||||
filesystem layouts.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Either use PostgreSQL packages provided by the community or 2ndQuadrant; if this
|
|
||||||
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>
|
||||||
|
|
||||||
<sect1 id="faq-repmgr" xreflabel="repmgr">
|
<sect1 id="faq-repmgr" xreflabel="repmgr">
|
||||||
@@ -129,7 +105,6 @@
|
|||||||
standby to have been cloned using &repmgr;.
|
standby to have been cloned using &repmgr;.
|
||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
|
|
||||||
<sect2 id="faq-repmgr-clone-other-source" >
|
<sect2 id="faq-repmgr-clone-other-source" >
|
||||||
<title>Can I use a standby not cloned by &repmgr; as a &repmgr; node?</title>
|
<title>Can I use a standby not cloned by &repmgr; as a &repmgr; node?</title>
|
||||||
|
|
||||||
@@ -143,13 +118,6 @@
|
|||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
|
|
||||||
<sect2 id="faq-repmgr-recovery-conf" >
|
|
||||||
<title>What does &repmgr; write in <filename>recovery.conf</filename>, and what options can be set there?</title>
|
|
||||||
<para>
|
|
||||||
See section <link linkend="repmgr-standby-clone-recovery-conf">Customising recovery.conf</link>.
|
|
||||||
</para>
|
|
||||||
</sect2>
|
|
||||||
|
|
||||||
<sect2 id="faq-repmgr-failed-primary-standby" xreflabel="Reintegrate a failed primary as a standby">
|
<sect2 id="faq-repmgr-failed-primary-standby" xreflabel="Reintegrate a failed primary as a standby">
|
||||||
<title>How can a failed primary be re-added as a standby?</title>
|
<title>How can a failed primary be re-added as a standby?</title>
|
||||||
<para>
|
<para>
|
||||||
@@ -158,23 +126,19 @@
|
|||||||
needs to be re-registered as a standby.
|
needs to be re-registered as a standby.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
It's possible to use <command>pg_rewind</command> to re-synchronise the existing data
|
In PostgreSQL 9.5 and later, it's possible to use <command>pg_rewind</command>
|
||||||
directory, which will usually be much
|
to re-synchronise the existing data directory, which will usually be much
|
||||||
faster than re-cloning the server. However <command>pg_rewind</command> can only
|
faster than re-cloning the server. However <command>pg_rewind</command> can only
|
||||||
be used if PostgreSQL either has <varname>wal_log_hints</varname> enabled, or
|
be used if PostgreSQL either has <varname>wal_log_hints</varname> enabled, or
|
||||||
data checksums were enabled when the cluster was initialized.
|
data checksums were enabled when the cluster was initialized.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
|
||||||
Note that <command>pg_rewind</command> is available as part of the core PostgreSQL
|
|
||||||
distribution from PostgreSQL 9.5, and as a third-party utility for PostgreSQL 9.3 and 9.4.
|
|
||||||
</para>
|
|
||||||
<para>
|
<para>
|
||||||
&repmgr; provides the command <command>repmgr node rejoin</command> which can
|
&repmgr; provides the command <command>repmgr node rejoin</command> which can
|
||||||
optionally execute <command>pg_rewind</command>; see the <xref linkend="repmgr-node-rejoin">
|
optionally execute <command>pg_rewind</command>; see the <xref linkend="repmgr-node-rejoin">
|
||||||
documentation for details, in particular the section <xref linkend="repmgr-node-rejoin-pg-rewind">.
|
documentation for details.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
If <command>pg_rewind</command> cannot be used, then the data directory will need
|
If <command>pg_rewind</command> cannot be used, then the data directory will have
|
||||||
to be re-cloned from scratch.
|
to be re-cloned from scratch.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
@@ -247,22 +211,11 @@
|
|||||||
Under some circumstances event notifications can be generated for servers
|
Under some circumstances event notifications can be generated for servers
|
||||||
which have not yet been registered; it's also useful to retain a record
|
which have not yet been registered; it's also useful to retain a record
|
||||||
of events which includes servers removed from the replication cluster
|
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>
|
</para>
|
||||||
</sect2>
|
</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>
|
</sect1>
|
||||||
@@ -274,7 +227,7 @@
|
|||||||
<sect2 id="faq-repmgrd-prevent-promotion" xreflabel="Prevent standby from being promoted to primary">
|
<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>
|
<title>How can I prevent a node from ever being promoted to primary?</title>
|
||||||
<para>
|
<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>.
|
<command><link linkend="repmgr-standby-register">repmgr standby register --force</link></command>.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
@@ -322,36 +275,5 @@
|
|||||||
</para>
|
</para>
|
||||||
</sect2>
|
</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>
|
</sect1>
|
||||||
</appendix>
|
</appendix>
|
||||||
|
|||||||
@@ -1,126 +1,48 @@
|
|||||||
<appendix id="appendix-packages" xreflabel="Package details">
|
<appendix id="appendix-packages" xreflabel="Package details">
|
||||||
<indexterm>
|
<indexterm>
|
||||||
<primary>packages</primary>
|
<primary>packages</primary>
|
||||||
</indexterm>
|
</indexterm>
|
||||||
|
|
||||||
<title>&repmgr; package details</title>
|
<title>&repmgr; package details</title>
|
||||||
|
<para>
|
||||||
|
This section provides technical details about various &repmgr; binary
|
||||||
|
packages, such as location of the installed binaries and
|
||||||
|
configuration files.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<sect1 id="packages-centos" xreflabel="CentOS packages">
|
||||||
|
<title>CentOS, RHEL, Scientific Linux etc.</title>
|
||||||
<para>
|
<para>
|
||||||
This section provides technical details about various &repmgr; binary
|
Currently packages are provided for versions 6.x and 7.x of CentOS et al.
|
||||||
packages, such as location of the installed binaries and
|
|
||||||
configuration files.
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<sect1 id="packages-centos" xreflabel="CentOS packages">
|
<note>
|
||||||
<title>CentOS Packages</title>
|
|
||||||
|
|
||||||
<indexterm>
|
|
||||||
<primary>packages</primary>
|
|
||||||
<secondary>CentOS packages</secondary>
|
|
||||||
</indexterm>
|
|
||||||
|
|
||||||
<indexterm>
|
|
||||||
<primary>CentOS</primary>
|
|
||||||
<secondary>package information</secondary>
|
|
||||||
</indexterm>
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Currently, &repmgr; RPM packages are provided for versions 6.x and 7.x of CentOS. These should also
|
For PostgreSQL 9.6 and lower, the CentOS packages use a mixture of <literal>9.6</literal>
|
||||||
work on matching versions of Red Hat Enterprise Linux, Scientific Linux and Oracle Enterprise Linux;
|
and <literal>96</literal> in various places to designate the major version;
|
||||||
together with CentOS, these are the same RedHat-based distributions for which the main community project
|
from PostgreSQL 10, the first part of the version number (e.g. <literal>10</literal>) is
|
||||||
(PGDG) provides packages (see the <ulink url="https://yum.postgresql.org/">PostgreSQL RPM Building Project</ulink>
|
the major version, so there is more consistency in file/path/package naming.
|
||||||
page for details).
|
|
||||||
</para>
|
</para>
|
||||||
|
</note>
|
||||||
<para>
|
|
||||||
Note these &repmgr; RPM packages are not designed to work with SuSE/OpenSuSE.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<note>
|
|
||||||
<para>
|
|
||||||
&repmgr; packages are designed to be compatible with community-provided PostgreSQL packages.
|
|
||||||
They may not work with vendor-specific packages such as those provided by RedHat for RHEL
|
|
||||||
customers, as the filesystem layout may be different to the community RPMs.
|
|
||||||
Please contact your support vendor for assistance.
|
|
||||||
</para>
|
|
||||||
</note>
|
|
||||||
|
|
||||||
<sect2 id="packages-centos-repositories">
|
|
||||||
<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; release.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<table id="centos-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-REDHAT-2NDQ">https://repmgr.org/docs/4.1/installation-packages.html#INSTALLATION-PACKAGES-REDHAT-2NDQ</ulink></entry>
|
|
||||||
</row>
|
|
||||||
</tbody>
|
|
||||||
</tgroup>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<table id="centos-pgdg-repository">
|
|
||||||
<title>PostgreSQL community repository (PGDG)</title>
|
|
||||||
<tgroup cols="2">
|
|
||||||
<tbody>
|
|
||||||
<row>
|
|
||||||
<entry>Repository URL:</entry>
|
|
||||||
<entry><ulink url="https://yum.postgresql.org/repopackages.php">https://yum.postgresql.org/repopackages.php</ulink></entry>
|
|
||||||
</row>
|
|
||||||
<row>
|
|
||||||
<entry>Repository documentation:</entry>
|
|
||||||
<entry><ulink url="https://yum.postgresql.org/">https://yum.postgresql.org/</ulink></entry>
|
|
||||||
</row>
|
|
||||||
</tbody>
|
|
||||||
</tgroup>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
</sect2>
|
|
||||||
|
|
||||||
<sect2 id="packages-centos-details">
|
|
||||||
<title>CentOS package details</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
The two tables below list relevant information, paths, commands etc. for the &repmgr; packages on
|
|
||||||
CentOS 7 (with systemd) and CentOS 6 (no systemd). Substitute the appropriate PostgreSQL major
|
|
||||||
version number for your installation.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<note>
|
|
||||||
<para>
|
|
||||||
For PostgreSQL 9.6 and lower, the CentOS packages use a mixture of <literal>9.6</literal>
|
|
||||||
and <literal>96</literal> in various places to designate the major version; e.g. the
|
|
||||||
package name is <literal>repmgr96</literal>, but the binary directory is
|
|
||||||
<filename>/var/lib/pgsql/9.6/data</filename>.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
From PostgreSQL 10, the first part of the version number (e.g. <literal>10</literal>) is
|
|
||||||
the major version, so there is more consistency in file/path/package naming
|
|
||||||
(package <literal>repmgr10</literal>, binary directory <filename>/var/lib/pgsql/10/data</filename>).
|
|
||||||
</para>
|
|
||||||
</note>
|
|
||||||
|
|
||||||
|
|
||||||
<table id="centos-7-packages">
|
<table id="centos-7-packages">
|
||||||
<title>CentOS 7 packages</title>
|
<title>CentOS 7 packages</title>
|
||||||
|
|
||||||
<tgroup cols="2">
|
<tgroup cols="2">
|
||||||
<tbody>
|
<tbody>
|
||||||
|
<row>
|
||||||
|
<entry>Repository URL:</entry>
|
||||||
|
<entry><ulink url="https://yum.postgresql.org/repopackages.php">https://yum.postgresql.org/repopackages.php</ulink></entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>Repository documentation:</entry>
|
||||||
|
<entry><ulink url="https://yum.postgresql.org/">https://yum.postgresql.org/</ulink></entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
<entry>Package name example:</entry>
|
<entry>Package name example:</entry>
|
||||||
<entry><filename>repmgr10-4.0.4-1.rhel7.x86_64</filename></entry>
|
<entry><filename>repmgr10-4.0.0-1.rhel7.x86_64</filename></entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
@@ -130,7 +52,7 @@
|
|||||||
|
|
||||||
<row>
|
<row>
|
||||||
<entry>Installation command:</entry>
|
<entry>Installation command:</entry>
|
||||||
<entry><literal>yum install repmgr10</literal></entry>
|
<entry><literal>yum install -y repmgr10</literal></entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
@@ -139,7 +61,7 @@
|
|||||||
</row>
|
</row>
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
<entry>repmgr in default path:</entry>
|
<entry>In default path:</entry>
|
||||||
<entry>NO</entry>
|
<entry>NO</entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
@@ -148,14 +70,9 @@
|
|||||||
<entry><filename>/etc/repmgr/10/repmgr.conf</filename></entry>
|
<entry><filename>/etc/repmgr/10/repmgr.conf</filename></entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
<row>
|
|
||||||
<entry>Data directory:</entry>
|
|
||||||
<entry><filename>/var/lib/pgsql/10/data</filename></entry>
|
|
||||||
</row>
|
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
<entry>repmgrd service command:</entry>
|
<entry>repmgrd service command:</entry>
|
||||||
<entry><command>systemctl [start|stop|restart|reload] repmgr10</command></entry>
|
<entry><literal>service repmgr10</literal></entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
@@ -165,7 +82,7 @@
|
|||||||
|
|
||||||
<row>
|
<row>
|
||||||
<entry>repmgrd log file location:</entry>
|
<entry>repmgrd log file location:</entry>
|
||||||
<entry>(not specified by package; set in <filename>repmgr.conf</filename>)</entry>
|
<entry>(not specified)</entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
</tbody>
|
</tbody>
|
||||||
@@ -177,20 +94,29 @@
|
|||||||
|
|
||||||
<tgroup cols="2">
|
<tgroup cols="2">
|
||||||
<tbody>
|
<tbody>
|
||||||
|
<row>
|
||||||
|
<entry>Repository URL:</entry>
|
||||||
|
<entry><ulink url="https://yum.postgresql.org/repopackages.php">https://yum.postgresql.org/repopackages.php</ulink></entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
|
<row>
|
||||||
|
<entry>Repository documentation:</entry>
|
||||||
|
<entry><ulink url="https://yum.postgresql.org/">https://yum.postgresql.org/</ulink></entry>
|
||||||
|
</row>
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
<entry>Package name example:</entry>
|
<entry>Package name example:</entry>
|
||||||
<entry><filename>repmgr96-4.0.4-1.rhel6.x86_64</filename></entry>
|
<entry><filename>repmgr96-4.0.0-1.rhel6.x86_64</filename></entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
<entry>Metapackage:</entry>
|
<entry>Metapackage:</entry>
|
||||||
<entry>(none)</entry>
|
<entry>NO</entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
<entry>Installation command:</entry>
|
<entry>Installation command:</entry>
|
||||||
<entry><literal>yum install repmgr96</literal></entry>
|
<entry><literal>yum install -y repmgr96</literal></entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
@@ -199,7 +125,7 @@
|
|||||||
</row>
|
</row>
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
<entry>repmgr in default path:</entry>
|
<entry>In default path:</entry>
|
||||||
<entry>NO</entry>
|
<entry>NO</entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
@@ -208,14 +134,9 @@
|
|||||||
<entry><filename>/etc/repmgr/9.6/repmgr.conf</filename></entry>
|
<entry><filename>/etc/repmgr/9.6/repmgr.conf</filename></entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
<row>
|
|
||||||
<entry>Data directory:</entry>
|
|
||||||
<entry><filename>/var/lib/pgsql/9.6/data</filename></entry>
|
|
||||||
</row>
|
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
<entry>repmgrd service command:</entry>
|
<entry>repmgrd service command:</entry>
|
||||||
<entry><literal>service [start|stop|restart|reload] repmgr-9.6</literal></entry>
|
<entry>service repmgr-9.6</entry>
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
@@ -232,331 +153,6 @@
|
|||||||
</tgroup>
|
</tgroup>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
</sect2>
|
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<sect1 id="packages-debian-ubuntu" xreflabel="Debian/Ubuntu packages">
|
|
||||||
<title>Debian/Ubuntu Packages</title>
|
|
||||||
<indexterm>
|
|
||||||
<primary>packages</primary>
|
|
||||||
<secondary>Debian/Ubuntu packages</secondary>
|
|
||||||
</indexterm>
|
|
||||||
|
|
||||||
<indexterm>
|
|
||||||
<primary>Debian/Ubuntu</primary>
|
|
||||||
<secondary>package information</secondary>
|
|
||||||
</indexterm>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
&repmgr; <literal>.deb</literal> packages are provided via the
|
|
||||||
PostgreSQL Community APT repository, and are available for each community-supported
|
|
||||||
PostgreSQL version, currently supported Debian releases, and currently supported
|
|
||||||
Ubuntu LTS releases.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<sect2 id="packages-apt-repository">
|
|
||||||
<title>APT repository</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
&repmgr; packages are available from the PostgreSQL Community APT repository,
|
|
||||||
which is updated immediately after each &repmgr; release.
|
|
||||||
</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">
|
|
||||||
<tbody>
|
|
||||||
<row>
|
|
||||||
<entry>Repository URL:</entry>
|
|
||||||
<entry><ulink url="http://apt.postgresql.org/">http://apt.postgresql.org/</ulink></entry>
|
|
||||||
</row>
|
|
||||||
<row>
|
|
||||||
<entry>Repository documentation:</entry>
|
|
||||||
<entry><ulink url="https://wiki.postgresql.org/wiki/Apt)">https://wiki.postgresql.org/wiki/Apt)</ulink></entry>
|
|
||||||
</row>
|
|
||||||
</tbody>
|
|
||||||
</tgroup>
|
|
||||||
</table>
|
|
||||||
</sect2>
|
|
||||||
|
|
||||||
<sect2 id="packages-debian-details">
|
|
||||||
<title>Debian/Ubuntu package details</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
The table below lists relevant information, paths, commands etc. for the &repmgr; packages on
|
|
||||||
Debian 9.x ("Stretch"). Substitute the appropriate PostgreSQL major
|
|
||||||
version number for your installation.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
See also <xref linkend="repmgrd-configuration-debian-ubuntu"> for some specifics related
|
|
||||||
to configuring the <application>repmgrd</application> daemon.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<table id="debian-9-packages">
|
|
||||||
<title>Debian 9.x packages</title>
|
|
||||||
|
|
||||||
<tgroup cols="2">
|
|
||||||
<tbody>
|
|
||||||
|
|
||||||
<row>
|
|
||||||
<entry>Package name example:</entry>
|
|
||||||
<entry><filename>postgresql-10-repmgr</filename></entry>
|
|
||||||
</row>
|
|
||||||
|
|
||||||
<row>
|
|
||||||
<entry>Metapackage:</entry>
|
|
||||||
<entry><filename>repmgr-common</filename></entry>
|
|
||||||
</row>
|
|
||||||
|
|
||||||
<row>
|
|
||||||
<entry>Installation command:</entry>
|
|
||||||
<entry><literal>apt-get install postgresql-10-repmgr</literal></entry>
|
|
||||||
</row>
|
|
||||||
|
|
||||||
<row>
|
|
||||||
<entry>Binary location:</entry>
|
|
||||||
<entry><filename>/usr/lib/postgresql/10/bin</filename></entry>
|
|
||||||
</row>
|
|
||||||
|
|
||||||
<row>
|
|
||||||
<entry>repmgr in default path:</entry>
|
|
||||||
<entry>Yes (via wrapper script <filename>/usr/bin/repmgr</filename>)</entry>
|
|
||||||
</row>
|
|
||||||
|
|
||||||
<row>
|
|
||||||
<entry>Configuration file location:</entry>
|
|
||||||
<entry>(not set by package)</entry>
|
|
||||||
</row>
|
|
||||||
|
|
||||||
<row>
|
|
||||||
<entry>Data directory:</entry>
|
|
||||||
<entry><filename>/var/lib/postgresql/10/main</filename></entry>
|
|
||||||
</row>
|
|
||||||
|
|
||||||
<row>
|
|
||||||
<entry>PostgreSQL service command:</entry>
|
|
||||||
<entry><command>systemctl [start|stop|restart|reload] postgresql@10-main</command></entry>
|
|
||||||
|
|
||||||
</row>
|
|
||||||
|
|
||||||
<row>
|
|
||||||
<entry>repmgrd service command:</entry>
|
|
||||||
<entry><command>systemctl [start|stop|restart|reload] repmgrd</command></entry>
|
|
||||||
</row>
|
|
||||||
|
|
||||||
<row>
|
|
||||||
<entry>repmgrd service file location:</entry>
|
|
||||||
<entry><filename>/etc/init.d/repmgrd</filename> (defaults in: <filename>/etc/defaults/repmgrd</filename>)</entry>
|
|
||||||
</row>
|
|
||||||
|
|
||||||
<row>
|
|
||||||
<entry>repmgrd log file location:</entry>
|
|
||||||
<entry>(not specified by package; set in <filename>repmgr.conf</filename>)</entry>
|
|
||||||
</row>
|
|
||||||
|
|
||||||
</tbody>
|
|
||||||
</tgroup>
|
|
||||||
</table>
|
|
||||||
<note>
|
|
||||||
<para>
|
|
||||||
Instead of using the <application>systemd</application> service command directly,
|
|
||||||
it's recommended to execute <command>pg_ctlcluster</command> (as <literal>root</literal>,
|
|
||||||
either directly or via <command>sudo</command>), e.g.:
|
|
||||||
<programlisting>
|
|
||||||
<command>pg_ctlcluster 10 main [start|stop|restart|reload]</command></programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
For pre-<application>systemd</application> systems, <command>pg_ctlcluster</command>
|
|
||||||
can be executed directly by the <literal>postgres</literal> user.
|
|
||||||
</para>
|
|
||||||
</note>
|
|
||||||
</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>
|
</appendix>
|
||||||
|
|||||||
@@ -15,763 +15,9 @@
|
|||||||
See also: <xref linkend="upgrading-repmgr">
|
See also: <xref linkend="upgrading-repmgr">
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<sect1 id="release-4.2">
|
|
||||||
<title>Release 4.2</title>
|
|
||||||
<para><emphasis>???, 2018</emphasis></para>
|
|
||||||
<para>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<sect2>
|
|
||||||
<title>Configuration file changes</title>
|
|
||||||
<para>
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
New parameter <varname>shutdown_check_timeout</varname> (default: 60 seconds) added;
|
|
||||||
this provides an explicit timeout for
|
|
||||||
<command><link linkend="repmgr-standby-switchover">repmgr standby switchover</link></command>
|
|
||||||
to check that the demotion candidate (current primary) has shut down. Previously, the parameters
|
|
||||||
<literal>reconnect_attempts</literal> and <literal>reconnect_interval</literal>
|
|
||||||
were used to calculate a timeout, but these are actually
|
|
||||||
intended for primary failure detection. (GitHub #504).
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
New parameter <varname>repmgr_bindir</varname> added, to facilitate remote invocation of repmgr
|
|
||||||
when the repmgr binary is located somewhere other than the PostgreSQL binary directory, as it
|
|
||||||
cannot be assumed all package maintainers will install &repmgr; there.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
This parameter is optional; if not set (the default), &repmgr; will fall back
|
|
||||||
to <option>pg_bindir</option> (if set).
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
(GitHub #246).
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
</sect2>
|
|
||||||
|
|
||||||
<sect2>
|
|
||||||
<title>repmgr enhancements</title>
|
|
||||||
<para>
|
|
||||||
<itemizedlist>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<command><link linkend="repmgr-cluster-cleanup">repmgr cluster cleanup</link></command>
|
|
||||||
now accepts the <option>--node-id</option> option to delete records for only one
|
|
||||||
node. (GitHub #493).
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
When running
|
|
||||||
<command><link linkend="repmgr-cluster-matrix">repmgr cluster matrix</link></command> and
|
|
||||||
<command><link linkend="repmgr-cluster-crosscheck">repmgr cluster crosscheck</link></command>,
|
|
||||||
&repmgr; will report nodes unreachable via SSH, and emit return code <literal>ERR_BAD_SSH</literal>.
|
|
||||||
(GitHub #246).
|
|
||||||
</para>
|
|
||||||
<note>
|
|
||||||
<para>
|
|
||||||
Users relying on
|
|
||||||
<command><link linkend="repmgr-cluster-crosscheck">repmgr cluster crosscheck</link></command>
|
|
||||||
to return a non-zero return code as a way of detecting connectivity errors should be aware
|
|
||||||
that <literal>ERR_BAD_SSH</literal> will be returned if there is an SSH connection error
|
|
||||||
from the node where the command is executed, even if the command is able to establish
|
|
||||||
that PostgreSQL connectivity is fine. Therefore the exact return code should be checked
|
|
||||||
to determine what kind of connectivity error has been detected.
|
|
||||||
</para>
|
|
||||||
</note>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
</sect2>
|
|
||||||
|
|
||||||
|
|
||||||
<sect2>
|
|
||||||
<title>repmgrd enhancements</title>
|
|
||||||
<para>
|
|
||||||
<itemizedlist>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<application>repmgrd</application> can now be "paused", i.e. instructed
|
|
||||||
not to take any action such as a failover, even if the prerequisites for such an
|
|
||||||
action are detected.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
This removes the need to stop <application>repmgrd</application> on all nodes when
|
|
||||||
performing a planned operation such as a switchover.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
For further details, see <link linkend="repmgrd-pausing">Pausing repmgrd</link>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
</sect2>
|
|
||||||
|
|
||||||
<sect2>
|
|
||||||
<title>Bug fixes</title>
|
|
||||||
<para>
|
|
||||||
<itemizedlist>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
&repmgr;: fix "Missing replication slots" label in
|
|
||||||
<command><link linkend="repmgr-node-check">repmgr node check</link></command>. (GitHub #507)
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<application>repmgrd</application>: fix parsing of <option>-d/--daemonize</option> option.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
</sect2>
|
|
||||||
</sect1>
|
|
||||||
|
|
||||||
<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-switchover">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>
|
|
||||||
<para>
|
|
||||||
&repmgr; 4.0.5 contains a number of usability enhancements related to
|
|
||||||
<application>pg_rewind</application> usage, <filename>recovery.conf</filename>
|
|
||||||
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>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Various documentation improvements, with particular emphasis on
|
|
||||||
the importance of setting appropriate <link linkend="configuration-file-service-commands">service commands</link>
|
|
||||||
instead of relying on <application>pg_ctl</application>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Poll demoted primary after restart as a standby during a switchover operation (GitHub #408).
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Add configuration parameter <option>config_directory</option> (GitHub #424).
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Add sanity check if <option>--upstream-node-id</option> not supplied when executing
|
|
||||||
<xref linkend="repmgr-standby-register"> (GitHub #395).
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Enable <link linkend="repmgr-node-rejoin-pg-rewind">pg_rewind</link> to be used with
|
|
||||||
PostgreSQL 9.3/9.4 (GitHub #413).
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
When generating replication connection strings, set <literal>dbname=replication</literal>
|
|
||||||
if appropriate (GitHub #421).
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Enable provision of <option>archive_cleanup_command</option> in <filename>recovery.conf</filename>
|
|
||||||
(GitHub #416).
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Actively check for node to <link linkend="repmgr-node-rejoin">rejoin</link> cluster (GitHub #415).
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<application>repmgrd</application>: set <literal>connect_timeout=2</literal> (if not explicitly set)
|
|
||||||
when pinging a server.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
</sect2>
|
|
||||||
|
|
||||||
<sect2>
|
|
||||||
<title>Bug fixes</title>
|
|
||||||
<para>
|
|
||||||
|
|
||||||
<itemizedlist>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Fix display of conninfo parsing error messages.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Fix minimum accepted value for <varname>degraded_monitoring_timeout</varname> (GitHub #411).
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Fix superuser password handling (GitHub #400)
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Fix parsing of <varname>archive_ready_critical</varname> configuration file parameter (GitHub #426).
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Fix <command><link linkend="repmgr-cluster-crosscheck">repmgr cluster crosscheck</link></command>
|
|
||||||
output (GitHub #389)
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Fix memory leaks in witness code (GitHub #402).
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<application>repmgrd</application>: handle <command>pg_ctl promote</command> timeout (GitHub #425).
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<application>repmgrd</application>: handle failover situation with only two nodes in the primary
|
|
||||||
location, and at least one node in another location (GitHub #407).
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<application>repmgrd</application>: prevent standby connection handle from going stale.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
</sect2>
|
|
||||||
|
|
||||||
</sect1>
|
|
||||||
|
|
||||||
|
|
||||||
<sect1 id="release-4.0.4">
|
<sect1 id="release-4.0.4">
|
||||||
<title>Release 4.0.4</title>
|
<title>Release 4.0.4</title>
|
||||||
<para><emphasis>Fri Mar 9, 2018</emphasis></para>
|
<para><emphasis>Thu Mar 8, 2018</emphasis></para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
&repmgr; 4.0.4 contains some bug fixes and and a number of
|
&repmgr; 4.0.4 contains some bug fixes and and a number of
|
||||||
@@ -784,15 +30,6 @@
|
|||||||
for more details.
|
for more details.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<note>
|
|
||||||
<para>
|
|
||||||
It is not possible to perform a switchover where the demotion candidate is
|
|
||||||
running &repmgr; 4.0.2 or lower; all nodes should be upgraded to the latest version (4.0.4).
|
|
||||||
This is due to additional checks introduced in 4.0.3 which require the presence of
|
|
||||||
4.0.3 or later versions on all nodes.
|
|
||||||
</para>
|
|
||||||
</note>
|
|
||||||
|
|
||||||
<sect2>
|
<sect2>
|
||||||
<title>Usability enhancements</title>
|
<title>Usability enhancements</title>
|
||||||
|
|
||||||
@@ -907,14 +144,6 @@
|
|||||||
This release can be installed as a simple package upgrade from repmgr 4.0 ~ 4.0.2;
|
This release can be installed as a simple package upgrade from repmgr 4.0 ~ 4.0.2;
|
||||||
repmgrd (if running) should be restarted.
|
repmgrd (if running) should be restarted.
|
||||||
</para>
|
</para>
|
||||||
<note>
|
|
||||||
<para>
|
|
||||||
It is not possible to perform a switchover where the demotion candidate is
|
|
||||||
running &repmgr; 4.0.2 or lower; all nodes should be upgraded to 4.0.3. This is due
|
|
||||||
to additional checks introduced in 4.0.3 which require the presence of
|
|
||||||
4.0.3 or later versions on all nodes.
|
|
||||||
</para>
|
|
||||||
</note>
|
|
||||||
<sect2>
|
<sect2>
|
||||||
<title>Usability enhancements</title>
|
<title>Usability enhancements</title>
|
||||||
|
|
||||||
|
|||||||
@@ -5,14 +5,14 @@
|
|||||||
<title>repmgr source code signing key</title>
|
<title>repmgr source code signing key</title>
|
||||||
<para>
|
<para>
|
||||||
The signing key ID used for <application>repmgr</application> source code bundles is:
|
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>.
|
<literal>0x297F1DCC</literal></ulink>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
To download the <application>repmgr</application> source key to your computer:
|
To download the <application>repmgr</application> source key to your computer:
|
||||||
<programlisting>
|
<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
|
gpg --fingerprint 0x297F1DCC
|
||||||
</programlisting>
|
</programlisting>
|
||||||
then verify that the fingerprint is the expected value:
|
then verify that the fingerprint is the expected value:
|
||||||
@@ -33,5 +33,34 @@
|
|||||||
|
|
||||||
</sect1>
|
</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>
|
</appendix>
|
||||||
|
|||||||
@@ -51,7 +51,7 @@
|
|||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<sect2 id="cloning-from-barman-prerequisites">
|
<sect2 id="cloning-from-barman-prerequisites" xreflabel="Prerequisites for cloning from Barman">
|
||||||
<title>Prerequisites for cloning from Barman</title>
|
<title>Prerequisites for cloning from Barman</title>
|
||||||
<para>
|
<para>
|
||||||
In order to enable Barman support for <command>repmgr standby clone</command>, following
|
In order to enable Barman support for <command>repmgr standby clone</command>, following
|
||||||
@@ -352,13 +352,11 @@
|
|||||||
provide additional parameters for <command>pg_basebackup</command> to customise the
|
provide additional parameters for <command>pg_basebackup</command> to customise the
|
||||||
cloning process.
|
cloning process.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
By default, <command>pg_basebackup</command> performs a checkpoint before beginning the backup
|
By default, <command>pg_basebackup</command> performs a checkpoint before beginning the backup
|
||||||
process. However, a normal checkpoint may take some time to complete;
|
process. However, a normal checkpoint may take some time to complete;
|
||||||
a fast checkpoint can be forced with <command><link linkend="repmgr-standby-clone">repmgr standby clone</link></command>'s
|
a fast checkpoint can be forced with the <literal>-c/--fast-checkpoint</literal> option.
|
||||||
<literal>-c/--fast-checkpoint</literal> option.
|
However this may impact performance of the server being cloned from (typically the primary)
|
||||||
Note that this may impact performance of the server being cloned from (typically the primary)
|
|
||||||
so should be used with care.
|
so should be used with care.
|
||||||
</para>
|
</para>
|
||||||
<tip>
|
<tip>
|
||||||
@@ -372,18 +370,6 @@
|
|||||||
Other options can be passed to <command>pg_basebackup</command> by including them
|
Other options can be passed to <command>pg_basebackup</command> by including them
|
||||||
in the <filename>repmgr.conf</filename> setting <varname>pg_basebackup_options</varname>.
|
in the <filename>repmgr.conf</filename> setting <varname>pg_basebackup_options</varname>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
|
||||||
Not that by default, &repmgr; executes <command>pg_basebackup</command> with <option>-X/--wal-method</option>
|
|
||||||
(PostgreSQL 9.6 and earlier: <option>-X/--xlog-method</option>) set to <literal>stream</literal>.
|
|
||||||
From PostgreSQL 9.6, if replication slots are in use, it will also create a replication slot before
|
|
||||||
running the base backup, and execute <command>pg_basebackup</command> with the
|
|
||||||
<option>-S/--slot</option> option set to the name of the previously created replication slot.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
These parameters can set by the user in <varname>pg_basebackup_options</varname>, in which case they
|
|
||||||
will override the &repmgr; default values. However normally there's no reason to do this.
|
|
||||||
</para>
|
|
||||||
<para>
|
<para>
|
||||||
If using a separate directory to store WAL files, provide the option <literal>--waldir</literal>
|
If using a separate directory to store WAL files, provide the option <literal>--waldir</literal>
|
||||||
(<literal>--xlogdir</literal> in PostgreSQL 9.6 and earlier) with the absolute path to the
|
(<literal>--xlogdir</literal> in PostgreSQL 9.6 and earlier) with the absolute path to the
|
||||||
@@ -398,16 +384,11 @@
|
|||||||
|
|
||||||
<sect2 id="cloning-advanced-managing-passwords" xreflabel="Managing passwords">
|
<sect2 id="cloning-advanced-managing-passwords" xreflabel="Managing passwords">
|
||||||
<title>Managing passwords</title>
|
<title>Managing passwords</title>
|
||||||
<indexterm>
|
|
||||||
<primary>cloning</primary>
|
|
||||||
<secondary>using passwords</secondary>
|
|
||||||
</indexterm>
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
If replication connections to a standby's upstream server are password-protected,
|
If replication connections to a standby's upstream server are password-protected,
|
||||||
the standby must be able to provide the password so it can begin streaming replication.
|
the standby must be able to provide the password so it can begin streaming
|
||||||
|
replication.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The recommended way to do this is to store the password in the <literal>postgres</literal> system
|
The recommended way to do this is to store the password in the <literal>postgres</literal> system
|
||||||
user's <filename>~/.pgpass</filename> file. It's also possible to store the password in the
|
user's <filename>~/.pgpass</filename> file. It's also possible to store the password in the
|
||||||
@@ -415,17 +396,6 @@
|
|||||||
security reasons. For more details see the
|
security reasons. For more details see the
|
||||||
<ulink url="https://www.postgresql.org/docs/current/static/libpq-pgpass.html">PostgreSQL password file documentation</ulink>.
|
<ulink url="https://www.postgresql.org/docs/current/static/libpq-pgpass.html">PostgreSQL password file documentation</ulink>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<note>
|
|
||||||
<para>
|
|
||||||
If using a <filename>pgpass</filename> file, an entry for the replication user (by default the
|
|
||||||
user who connects to the <literal>repmgr</literal> database) <emphasis>must</emphasis>
|
|
||||||
be provided, with database name set to <literal>replication</literal>, e.g.:
|
|
||||||
<programlisting>
|
|
||||||
node1:5432:replication:repmgr:12345</programlisting>
|
|
||||||
</para>
|
|
||||||
</note>
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
If, for whatever reason, you wish to include the password in <filename>recovery.conf</filename>,
|
If, for whatever reason, you wish to include the password in <filename>recovery.conf</filename>,
|
||||||
set <varname>use_primary_conninfo_password</varname> to <literal>true</literal> in
|
set <varname>use_primary_conninfo_password</varname> to <literal>true</literal> in
|
||||||
@@ -437,7 +407,8 @@
|
|||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
It is of course also possible to include the password value in the <varname>conninfo</varname>
|
It is of course also possible to include the password value in the <varname>conninfo</varname>
|
||||||
string for each node, but this is obviously a security risk and should be avoided.
|
string for each node, but this is obviously a security risk and should be
|
||||||
|
avoided.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
From PostgreSQL 9.6, <application>libpq</application> supports the <varname>passfile</varname>
|
From PostgreSQL 9.6, <application>libpq</application> supports the <varname>passfile</varname>
|
||||||
|
|||||||
@@ -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,130 +0,0 @@
|
|||||||
<sect1 id="configuration-file-service-commands" xreflabel="service command settings">
|
|
||||||
<indexterm>
|
|
||||||
<primary>repmgr.conf</primary>
|
|
||||||
<secondary>service command settings</secondary>
|
|
||||||
</indexterm>
|
|
||||||
<indexterm>
|
|
||||||
<primary>service command settings</primary>
|
|
||||||
<secondary>configuration in repmgr.conf</secondary>
|
|
||||||
</indexterm>
|
|
||||||
<title>Service command settings</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
In some circumstances, &repmgr; (and <application>repmgrd</application>) need to
|
|
||||||
be able to stop, start or restart PostgreSQL. &repmgr; commands which need to do this
|
|
||||||
include <link linkend="repmgr-standby-follow"><command>repmgr standby follow</command></link>,
|
|
||||||
<link linkend="repmgr-standby-switchover"><command>repmgr standby switchover</command></link> and
|
|
||||||
<link linkend="repmgr-node-rejoin"><command>repmgr node rejoin</command></link>.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
By default, &repmgr; will use PostgreSQL's <command>pg_ctl</command> utility to control the PostgreSQL
|
|
||||||
server. However this can lead to various problems, particularly when PostgreSQL has been
|
|
||||||
installed from packages, and especially so if <application>systemd</application> is in use.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
|
|
||||||
<note>
|
|
||||||
<para>
|
|
||||||
If using <application>systemd</application>, ensure you have <varname>RemoveIPC</varname> set to <literal>off</literal>.
|
|
||||||
See the <ulink url="https://wiki.postgresql.org/wiki/Systemd">systemd</ulink>
|
|
||||||
entry in the <ulink url="https://wiki.postgresql.org/wiki/Main_Page">PostgreSQL wiki</ulink> for details.
|
|
||||||
</para>
|
|
||||||
</note>
|
|
||||||
|
|
||||||
|
|
||||||
<para>
|
|
||||||
With this in mind, we recommend to <emphasis>always</emphasis> configure &repmgr; to use the
|
|
||||||
available system service commands.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
To do this, specify the appropriate command for each action
|
|
||||||
in <filename>repmgr.conf</filename> using the following configuration
|
|
||||||
parameters:
|
|
||||||
<programlisting>
|
|
||||||
service_start_command
|
|
||||||
service_stop_command
|
|
||||||
service_restart_command
|
|
||||||
service_reload_command</programlisting>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<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>.
|
|
||||||
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">.
|
|
||||||
</para>
|
|
||||||
</note>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
To confirm which command &repmgr; will execute for each action, use
|
|
||||||
<command>repmgr node service --list --action=...</command>, e.g.:
|
|
||||||
<programlisting>
|
|
||||||
repmgr -f /etc/repmgr.conf node service --list --action=stop
|
|
||||||
repmgr -f /etc/repmgr.conf node service --list --action=start
|
|
||||||
repmgr -f /etc/repmgr.conf node service --list --action=restart
|
|
||||||
repmgr -f /etc/repmgr.conf node service --list --action=reload</programlisting>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
These commands will be executed by the system user which &repmgr; runs as (usually <literal>postgres</literal>)
|
|
||||||
and will probably require passwordless sudo access to be able to execute the command.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
For example, using <application>systemd</application> on CentOS 7, the service commands can be
|
|
||||||
set as follows:
|
|
||||||
<programlisting>
|
|
||||||
service_start_command = 'sudo systemctl start postgresql-9.6'
|
|
||||||
service_stop_command = 'sudo systemctl stop postgresql-9.6'
|
|
||||||
service_restart_command = 'sudo systemctl restart postgresql-9.6'
|
|
||||||
service_reload_command = 'sudo systemctl reload postgresql-9.6'</programlisting>
|
|
||||||
and <filename>/etc/sudoers</filename> should be set as follows:
|
|
||||||
<programlisting>
|
|
||||||
Defaults:postgres !requiretty
|
|
||||||
postgres ALL = NOPASSWD: /usr/bin/systemctl stop postgresql-9.6, \
|
|
||||||
/usr/bin/systemctl start postgresql-9.6, \
|
|
||||||
/usr/bin/systemctl restart postgresql-9.6, \
|
|
||||||
/usr/bin/systemctl reload postgresql-9.6</programlisting>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<important>
|
|
||||||
<indexterm>
|
|
||||||
<primary>pg_ctlcluster</primary>
|
|
||||||
<secondary>service command settings</secondary>
|
|
||||||
</indexterm>
|
|
||||||
<para>
|
|
||||||
Debian/Ubuntu users: instead of calling <command>sudo systemctl</command> directly, use
|
|
||||||
<command>sudo pg_ctlcluster</command>, e.g.:
|
|
||||||
<programlisting>
|
|
||||||
service_start_command = 'sudo pg_ctlcluster 9.6 main start'
|
|
||||||
service_stop_command = 'sudo pg_ctlcluster 9.6 main stop'
|
|
||||||
service_restart_command = 'sudo pg_ctlcluster 9.6 main restart'
|
|
||||||
service_reload_command = 'sudo pg_ctlcluster 9.6 main reload'</programlisting>
|
|
||||||
and set <filename>/etc/sudoers</filename> accordingly.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
While <command>pg_ctlcluster</command> will work when executed as user <literal>postgres</literal>,
|
|
||||||
it's strongly recommended to use <command>sudo pg_ctlcluster</command> on <application>systemd</application>
|
|
||||||
systems, to ensure <application>systemd</application> has a correct picture of
|
|
||||||
the PostgreSQL application state.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
</important>
|
|
||||||
|
|
||||||
</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>
|
<indexterm>
|
||||||
<primary>repmgr.conf</primary>
|
<primary>repmgr.conf</primary>
|
||||||
<secondary>required settings</secondary>
|
<secondary>settings</secondary>
|
||||||
</indexterm>
|
</indexterm>
|
||||||
|
|
||||||
<title>Required configuration file settings</title>
|
<title>Configuration file settings</title>
|
||||||
<para>
|
<para>
|
||||||
Each <filename>repmgr.conf</filename> file must contain the following parameters:
|
Each <filename>repmgr.conf</filename> file must contain the following parameters:
|
||||||
</para>
|
</para>
|
||||||
@@ -92,10 +92,7 @@
|
|||||||
|
|
||||||
<para>
|
<para>
|
||||||
For a full list of annotated configuration items, see the file
|
For a full list of annotated configuration items, see the file
|
||||||
<ulink url="https://raw.githubusercontent.com/2ndQuadrant/repmgr/master/repmgr.conf.sample">repmgr.conf.sample</ulink>.
|
<ulink url="https://raw.githubusercontent.com/2ndQuadrant/repmgr/master/repmgr.conf.sample">repmgr.conf.sample</>.
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
For <application>repmgrd</application>-specific settings, see <xref linkend="repmgrd-configuration">.
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<note>
|
<note>
|
||||||
@@ -2,17 +2,15 @@
|
|||||||
<title>repmgr configuration</title>
|
<title>repmgr configuration</title>
|
||||||
|
|
||||||
&configuration-file;
|
&configuration-file;
|
||||||
&configuration-file-required-settings;
|
&configuration-file-settings;
|
||||||
&configuration-file-log-settings;
|
|
||||||
&configuration-file-service-commands;
|
|
||||||
|
|
||||||
<sect1 id="configuration-permissions" xreflabel="Database user permissions">
|
<sect1 id="configuration-permissions" xreflabel="User permissions">
|
||||||
<indexterm>
|
<indexterm>
|
||||||
<primary>configuration</primary>
|
<primary>configuration</primary>
|
||||||
<secondary>database user permissions</secondary>
|
<secondary>user permissions</secondary>
|
||||||
</indexterm>
|
</indexterm>
|
||||||
|
|
||||||
<title>repmgr database user permissions</title>
|
<title>repmgr user permissions</title>
|
||||||
<para>
|
<para>
|
||||||
&repmgr; will create an extension database containing objects
|
&repmgr; will create an extension database containing objects
|
||||||
for administering &repmgr; metadata. The user defined in the <varname>conninfo</varname>
|
for administering &repmgr; metadata. The user defined in the <varname>conninfo</varname>
|
||||||
|
|||||||
@@ -16,22 +16,15 @@
|
|||||||
<para>
|
<para>
|
||||||
A typical use case for a witness server is a two-node streaming replication
|
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).
|
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,
|
By creating a witness server in the same location as the primary, if the primary
|
||||||
if the primary becomes unavailable it's possible for the standby to decide whether
|
becomes unavailable it's possible for the standby to decide whether it can
|
||||||
it can promote itself without risking a "split brain" scenario: if it can't see either the
|
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
|
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,
|
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,
|
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
|
and it can therefore promote itself (and ideally take action to fence the
|
||||||
former primary).
|
former primary).
|
||||||
</para>
|
</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>
|
<para>
|
||||||
For more complex replication scenarios,e.g. with multiple datacentres, it may
|
For more complex replication scenarios,e.g. with multiple datacentres, it may
|
||||||
be preferable to use location-based failover, which ensures that only nodes
|
be preferable to use location-based failover, which ensures that only nodes
|
||||||
|
|||||||
@@ -147,104 +147,34 @@
|
|||||||
<para>
|
<para>
|
||||||
By default, all notification types will be passed to the designated script;
|
By default, all notification types will be passed to the designated script;
|
||||||
the notification types can be filtered to explicitly named ones using the
|
the notification types can be filtered to explicitly named ones using the
|
||||||
<varname>event_notifications</varname> parameter.
|
<varname>event_notifications</varname> parameter:
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Events generated by the &repmgr; command:
|
|
||||||
|
|
||||||
<itemizedlist spacing="compact" mark="bullet">
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<simpara><literal><link linkend="repmgr-primary-register-events">cluster_created</link></literal></simpara>
|
<simpara><literal>primary_register</literal></simpara>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<simpara><literal><link linkend="repmgr-primary-register-events">primary_register</link></literal></simpara>
|
<simpara><literal>primary_unregister</literal></simpara>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<simpara><literal><link linkend="repmgr-primary-unregister-events">primary_unregister</link></literal></simpara>
|
<simpara><literal>standby_register</literal></simpara>
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara><literal><link linkend="repmgr-standby-clone-events">standby_clone</link></literal></simpara>
|
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<simpara><literal><link linkend="repmgr-standby-register-events">standby_register</link></literal></simpara>
|
<simpara><literal>standby_register_sync</literal></simpara>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<simpara><literal><link linkend="repmgr-standby-register-events">standby_register_sync</link></literal></simpara>
|
<simpara><literal>standby_unregister</literal></simpara>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<simpara><literal><link linkend="repmgr-standby-unregister-events">standby_unregister</link></literal></simpara>
|
<simpara><literal>standby_clone</literal></simpara>
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara><literal><link linkend="repmgr-standby-promote-events">standby_promote</link></literal></simpara>
|
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<simpara><literal><link linkend="repmgr-standby-follow-events">standby_follow</link></literal></simpara>
|
<simpara><literal>standby_promote</literal></simpara>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<simpara><literal><link linkend="repmgr-standby-switchover-events">standby_switchover</link></literal></simpara>
|
<simpara><literal>standby_follow</literal></simpara>
|
||||||
</listitem>
|
</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>
|
<listitem>
|
||||||
<simpara><literal>standby_disconnect_manual</literal></simpara>
|
<simpara><literal>standby_disconnect_manual</literal></simpara>
|
||||||
</listitem>
|
</listitem>
|
||||||
@@ -254,13 +184,39 @@
|
|||||||
<listitem>
|
<listitem>
|
||||||
<simpara><literal>standby_recovery</literal></simpara>
|
<simpara><literal>standby_recovery</literal></simpara>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
<listitem>
|
||||||
</itemizedlist>
|
<simpara><literal>witness_register</literal></simpara>
|
||||||
</para>
|
</listitem>
|
||||||
|
<listitem>
|
||||||
<para>
|
<simpara><literal>witness_unregister</literal></simpara>
|
||||||
Events generated by <application>repmgrd</application> (BDR mode):
|
</listitem>
|
||||||
<itemizedlist spacing="compact" mark="bullet">
|
<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_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>
|
<listitem>
|
||||||
<simpara><literal>bdr_failover</literal></simpara>
|
<simpara><literal>bdr_failover</literal></simpara>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
|||||||
@@ -38,9 +38,7 @@
|
|||||||
<!ENTITY quickstart SYSTEM "quickstart.sgml">
|
<!ENTITY quickstart SYSTEM "quickstart.sgml">
|
||||||
<!ENTITY configuration SYSTEM "configuration.sgml">
|
<!ENTITY configuration SYSTEM "configuration.sgml">
|
||||||
<!ENTITY configuration-file SYSTEM "configuration-file.sgml">
|
<!ENTITY configuration-file SYSTEM "configuration-file.sgml">
|
||||||
<!ENTITY configuration-file-required-settings SYSTEM "configuration-file-required-settings.sgml">
|
<!ENTITY configuration-file-settings SYSTEM "configuration-file-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 cloning-standbys SYSTEM "cloning-standbys.sgml">
|
<!ENTITY cloning-standbys SYSTEM "cloning-standbys.sgml">
|
||||||
<!ENTITY promoting-standby SYSTEM "promoting-standby.sgml">
|
<!ENTITY promoting-standby SYSTEM "promoting-standby.sgml">
|
||||||
<!ENTITY follow-new-primary SYSTEM "follow-new-primary.sgml">
|
<!ENTITY follow-new-primary SYSTEM "follow-new-primary.sgml">
|
||||||
@@ -58,7 +56,6 @@
|
|||||||
<!ENTITY repmgrd-cascading-replication SYSTEM "repmgrd-cascading-replication.sgml">
|
<!ENTITY repmgrd-cascading-replication SYSTEM "repmgrd-cascading-replication.sgml">
|
||||||
<!ENTITY repmgrd-network-split SYSTEM "repmgrd-network-split.sgml">
|
<!ENTITY repmgrd-network-split SYSTEM "repmgrd-network-split.sgml">
|
||||||
<!ENTITY repmgrd-witness-server SYSTEM "repmgrd-witness-server.sgml">
|
<!ENTITY repmgrd-witness-server SYSTEM "repmgrd-witness-server.sgml">
|
||||||
<!ENTITY repmgrd-pausing SYSTEM "repmgrd-pausing.sgml">
|
|
||||||
<!ENTITY repmgrd-bdr SYSTEM "repmgrd-bdr.sgml">
|
<!ENTITY repmgrd-bdr SYSTEM "repmgrd-bdr.sgml">
|
||||||
|
|
||||||
<!ENTITY repmgr-primary-register SYSTEM "repmgr-primary-register.sgml">
|
<!ENTITY repmgr-primary-register SYSTEM "repmgr-primary-register.sgml">
|
||||||
@@ -79,9 +76,6 @@
|
|||||||
<!ENTITY repmgr-cluster-crosscheck SYSTEM "repmgr-cluster-crosscheck.sgml">
|
<!ENTITY repmgr-cluster-crosscheck SYSTEM "repmgr-cluster-crosscheck.sgml">
|
||||||
<!ENTITY repmgr-cluster-event SYSTEM "repmgr-cluster-event.sgml">
|
<!ENTITY repmgr-cluster-event SYSTEM "repmgr-cluster-event.sgml">
|
||||||
<!ENTITY repmgr-cluster-cleanup SYSTEM "repmgr-cluster-cleanup.sgml">
|
<!ENTITY repmgr-cluster-cleanup SYSTEM "repmgr-cluster-cleanup.sgml">
|
||||||
<!ENTITY repmgr-daemon-status SYSTEM "repmgr-daemon-status.sgml">
|
|
||||||
<!ENTITY repmgr-daemon-pause SYSTEM "repmgr-daemon-pause.sgml">
|
|
||||||
<!ENTITY repmgr-daemon-unpause SYSTEM "repmgr-daemon-unpause.sgml">
|
|
||||||
|
|
||||||
<!ENTITY appendix-release-notes SYSTEM "appendix-release-notes.sgml">
|
<!ENTITY appendix-release-notes SYSTEM "appendix-release-notes.sgml">
|
||||||
<!ENTITY appendix-faq SYSTEM "appendix-faq.sgml">
|
<!ENTITY appendix-faq SYSTEM "appendix-faq.sgml">
|
||||||
|
|||||||
@@ -5,95 +5,83 @@
|
|||||||
system.
|
system.
|
||||||
</para>
|
</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>
|
<indexterm>
|
||||||
<primary>installation</primary>
|
<primary>installation</primary>
|
||||||
<secondary>on Red Hat/CentOS/Fedora etc.</secondary>
|
<secondary>on Redhat/CentOS/Fedora etc.</secondary>
|
||||||
</indexterm>
|
</indexterm>
|
||||||
|
|
||||||
<title>RedHat/CentOS/Fedora</title>
|
<title>RedHat/Fedora/CentOS</title>
|
||||||
<para>
|
<para>
|
||||||
&repmgr; RPM packages for RedHat/CentOS variants and Fedora are available from the
|
RPM packages for &repmgr; are available via Yum through
|
||||||
<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
|
|
||||||
the PostgreSQL Global Development Group RPM repository
|
the PostgreSQL Global Development Group RPM repository
|
||||||
(<ulink url="https://yum.postgresql.org/">http://yum.postgresql.org/</ulink>).
|
(<ulink url="https://yum.postgresql.org/">http://yum.postgresql.org/</ulink>).
|
||||||
Follow the instructions for your distribution (RedHat, CentOS,
|
Follow the instructions for your distribution (RedHat, CentOS,
|
||||||
Fedora, etc.) and architecture as detailed there. Note that it can take some days
|
Fedora, etc.) and architecture as detailed there.
|
||||||
for new &repmgr; packages to become available via the this repository.
|
|
||||||
</para>
|
</para>
|
||||||
<note>
|
|
||||||
<para>
|
|
||||||
&repmgr; packages are designed to be compatible with the community-provided PostgreSQL packages.
|
|
||||||
They may not work with vendor-specific packages such as those provided by RedHat for RHEL
|
|
||||||
customers, as the filesystem layout may be different to the community RPMs.
|
|
||||||
Please contact your support vendor for assistance.
|
|
||||||
</para>
|
|
||||||
</note>
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
For more information on the package contents, including details of installation
|
<ulink url="https://2ndquadrant.com">2ndQuadrant</ulink> also provides its
|
||||||
paths and relevant <link linkend="configuration-file-service-commands">service commands</link>,
|
own RPM packages which are made available
|
||||||
see the appendix section <xref linkend="packages-centos">.
|
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>
|
</para>
|
||||||
|
|
||||||
|
|
||||||
<sect3 id="installation-packages-redhat-2ndq">
|
<sect3 id="installation-packages-redhat-2ndq">
|
||||||
<title>2ndQuadrant public RPM yum repository</title>
|
<title>2ndQuadrant repmgr yum repository</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Beginning with <ulink url="https://repmgr.org/docs/4.1/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://2ndquadrant.com/">2ndQuadrant</ulink> provides a dedicated <literal>yum</literal>
|
||||||
<ulink url="https://dl.2ndquadrant.com/">public repository</ulink> for 2ndQuadrant software,
|
repository for &repmgr; releases. This repository complements the main
|
||||||
including &repmgr;. We recommend using this for all future &repmgr; releases.
|
<ulink url="https://yum.postgresql.org/repopackages.php">PGDG community repository</ulink>,
|
||||||
</para>
|
but enables repmgr users to access the latest &repmgr; packages before they are
|
||||||
<para>
|
available via the PGDG repository, which can take several days to be updated following
|
||||||
General instructions for using this repository can be found on its
|
a fresh &repmgr; release.
|
||||||
<ulink url="https://dl.2ndquadrant.com/">homepage</ulink>. Specific instructions
|
</para>
|
||||||
for installing &repmgr; follow below.
|
|
||||||
</para>
|
|
||||||
<para>
|
<para>
|
||||||
<emphasis>Installation</emphasis>
|
<emphasis>Installation</emphasis>
|
||||||
|
|
||||||
<itemizedlist>
|
<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>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Install the repository definition for your distribution and PostgreSQL version
|
Import the repository public key (optional but recommended):
|
||||||
(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>):
|
|
||||||
<programlisting>
|
<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>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
@@ -103,13 +91,13 @@ $ yum install repmgr10</programlisting>
|
|||||||
<emphasis>Compatibility with PGDG Repositories</emphasis>
|
<emphasis>Compatibility with PGDG Repositories</emphasis>
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
The 2ndQuadrant &repmgr; yum repository packages use the same definitions and file system layout as the
|
The 2ndQuadrant &repmgr; yum repository uses exactly the same package definitions as the
|
||||||
main PGDG repository.
|
main PGDG repository and is effectively a selective mirror for &repmgr; packages only.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Normally <application>yum</application> will prioritize the repository with the most recent &repmgr; version.
|
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
|
Once the PGDG repository has been updated, it doesn't matter which repository
|
||||||
the packages are installed from.
|
the packages are installed from.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
To ensure the 2ndQuadrant repository is always prioritised, install <literal>yum-plugin-priorities</literal>
|
To ensure the 2ndQuadrant repository is always prioritised, install <literal>yum-plugin-priorities</literal>
|
||||||
@@ -123,23 +111,30 @@ $ yum install repmgr10</programlisting>
|
|||||||
To install a specific package version, execute <command>yum --showduplicates list</command>
|
To install a specific package version, execute <command>yum --showduplicates list</command>
|
||||||
for the package in question:
|
for the package in question:
|
||||||
<programlisting>
|
<programlisting>
|
||||||
[root@localhost ~]# yum --showduplicates list repmgr10
|
[root@localhost ~]# yum --showduplicates list repmgr96
|
||||||
Loaded plugins: fastestmirror
|
Loaded plugins: fastestmirror
|
||||||
Loading mirror speeds from cached hostfile
|
Loading mirror speeds from cached hostfile
|
||||||
* base: ftp.iij.ad.jp
|
* base: ftp.iij.ad.jp
|
||||||
* extras: ftp.iij.ad.jp
|
* extras: ftp.iij.ad.jp
|
||||||
* updates: ftp.iij.ad.jp
|
* updates: ftp.iij.ad.jp
|
||||||
Available Packages
|
Available Packages
|
||||||
repmgr10.x86_64 4.0.3-1.rhel7 pgdg10
|
repmgr96.x86_64 3.2-1.el6 2ndquadrant-repmgr
|
||||||
repmgr10.x86_64 4.0.4-1.rhel7 pgdg10
|
repmgr96.x86_64 3.2.1-1.el6 2ndquadrant-repmgr
|
||||||
repmgr10.x86_64 4.0.5-1.el7 2ndquadrant-repo-10</programlisting>
|
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.:
|
then append the appropriate version number to the package name with a hyphen, e.g.:
|
||||||
<programlisting>
|
<programlisting>
|
||||||
[root@localhost ~]# yum install repmgr10-4.0.3-1.rhel7</programlisting>
|
[root@localhost ~]# yum install repmgr96-3.3.2-1.el6</programlisting>
|
||||||
</para>
|
</para>
|
||||||
</sect3>
|
</sect3>
|
||||||
</sect2>
|
</sect2>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<sect2 id="installation-packages-debian" xreflabel="Installing from packages on Debian or Ubuntu">
|
<sect2 id="installation-packages-debian" xreflabel="Installing from packages on Debian or Ubuntu">
|
||||||
|
|
||||||
<indexterm>
|
<indexterm>
|
||||||
@@ -153,76 +148,6 @@ $ yum install repmgr10</programlisting>
|
|||||||
Instructions can be found in the APT section of the PostgreSQL Wiki
|
Instructions can be found in the APT section of the PostgreSQL Wiki
|
||||||
(<ulink url="https://wiki.postgresql.org/wiki/Apt">https://wiki.postgresql.org/wiki/Apt</ulink>).
|
(<ulink url="https://wiki.postgresql.org/wiki/Apt">https://wiki.postgresql.org/wiki/Apt</ulink>).
|
||||||
</para>
|
</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>,
|
|
||||||
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>
|
</sect2>
|
||||||
|
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
A dedicated system user for &repmgr; is <emphasis>not</emphasis> required; as many &repmgr; and
|
A dedicated system user for &repmgr; is *not* required; as many &repmgr; and
|
||||||
<application>repmgrd</application> actions require direct access to the PostgreSQL data directory,
|
<application>repmgrd</application> actions require direct access to the PostgreSQL data directory,
|
||||||
these commands should be executed by the <literal>postgres</literal> user.
|
these commands should be executed by the <literal>postgres</literal> user.
|
||||||
</para>
|
</para>
|
||||||
@@ -61,13 +61,6 @@
|
|||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<tip>
|
|
||||||
<simpara>
|
|
||||||
Consider setting <varname>ConnectTimeout</varname> to a low value in your SSH configuration.
|
|
||||||
This will make it faster to detect any SSH connection errors.
|
|
||||||
</simpara>
|
|
||||||
</tip>
|
|
||||||
|
|
||||||
<tip>
|
<tip>
|
||||||
<simpara>
|
<simpara>
|
||||||
We recommend using a session multiplexer utility such as <command>screen</command> or
|
We recommend using a session multiplexer utility such as <command>screen</command> or
|
||||||
|
|||||||
@@ -12,8 +12,8 @@
|
|||||||
To install &repmgr; the prerequisites for compiling
|
To install &repmgr; the prerequisites for compiling
|
||||||
&postgres; must be installed. These are described in &postgres;'s
|
&postgres; must be installed. These are described in &postgres;'s
|
||||||
documentation
|
documentation
|
||||||
on <ulink url="https://www.postgresql.org/docs/current/static/install-requirements.html">build requirements</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/static/docguide-toolsets.html">build requirements for documentation</ulink>.
|
and <ulink url="https://www.postgresql.org/docs/current/docguide-toolsets.html">build requirements for documentation</ulink>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@@ -80,7 +80,7 @@
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<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>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
|
|||||||
@@ -2,8 +2,7 @@
|
|||||||
<title>repmgr overview</title>
|
<title>repmgr overview</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
This chapter provides a high-level overview of &repmgr;'s components and
|
This chapter provides a high-level overview of repmgr's components and functionality.
|
||||||
functionality.
|
|
||||||
</para>
|
</para>
|
||||||
<sect1 id="repmgr-concepts" xreflabel="Concepts">
|
<sect1 id="repmgr-concepts" xreflabel="Concepts">
|
||||||
|
|
||||||
|
|||||||
@@ -234,45 +234,17 @@
|
|||||||
<para>
|
<para>
|
||||||
<filename>repmgr.conf</filename> should not be stored inside the PostgreSQL data directory,
|
<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
|
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>.
|
for further details about <filename>repmgr.conf</filename>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<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>
|
|
||||||
|
|
||||||
<tip>
|
<tip>
|
||||||
<simpara>
|
<simpara>
|
||||||
For Debian-based distributions we recommend explictly setting
|
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>.
|
not in the standard path are located. For PostgreSQL 9.6 this would be <filename>/usr/lib/postgresql/9.6/bin/</filename>.
|
||||||
</simpara>
|
</simpara>
|
||||||
</tip>
|
</tip>
|
||||||
|
|
||||||
<tip>
|
|
||||||
<simpara>
|
|
||||||
If your distribution places the &repmgr; binaries in a location other than the
|
|
||||||
PostgreSQL installation directory, specify this with <option>repmgr_bindir</option>
|
|
||||||
to enable &repmgr; to perform operations (e.g.
|
|
||||||
<command><link linkend="repmgr-cluster-crosscheck">repmgr cluster crosscheck</link></command>)
|
|
||||||
on other nodes.
|
|
||||||
</simpara>
|
|
||||||
</tip>
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
See the file
|
See the file
|
||||||
<ulink url="https://raw.githubusercontent.com/2ndQuadrant/repmgr/master/repmgr.conf.sample">repmgr.conf.sample</>
|
<ulink url="https://raw.githubusercontent.com/2ndQuadrant/repmgr/master/repmgr.conf.sample">repmgr.conf.sample</>
|
||||||
|
|||||||
@@ -15,14 +15,9 @@
|
|||||||
<title>Description</title>
|
<title>Description</title>
|
||||||
<para>
|
<para>
|
||||||
Purges monitoring history from the <literal>repmgr.monitoring_history</literal> table to
|
Purges monitoring history from the <literal>repmgr.monitoring_history</literal> table to
|
||||||
prevent excessive table growth.
|
prevent excessive table growth. Use the <literal>-k/--keep-history</literal> to specify the
|
||||||
</para>
|
number of days of monitoring history to retain. This command can be used
|
||||||
<para>
|
manually or as a cronjob.
|
||||||
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.
|
|
||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
@@ -43,35 +38,4 @@
|
|||||||
<filename>repmgr.conf</filename>.
|
<filename>repmgr.conf</filename>.
|
||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</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>Options</title>
|
|
||||||
<variablelist>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><option>--node-id</option></term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Only delete monitoring records for the specified node.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
</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>
|
</refentry>
|
||||||
|
|||||||
@@ -38,59 +38,5 @@
|
|||||||
and therefore determine the state of outbound connections from that node.
|
and therefore determine the state of outbound connections from that node.
|
||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</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_BAD_SSH (12)</option></term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
One or more nodes could not be accessed via SSH.
|
|
||||||
</para>
|
|
||||||
<note>
|
|
||||||
<simpara>
|
|
||||||
This only applies to nodes unreachable from the node where
|
|
||||||
this command is executed.
|
|
||||||
</simpara>
|
|
||||||
<simpara>
|
|
||||||
It's also possible that the crosscheck establishes that
|
|
||||||
connections between PostgreSQL on all nodes are functioning,
|
|
||||||
even if SSH access between some nodes is not possible.
|
|
||||||
</simpara>
|
|
||||||
</note>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><option>ERR_NODE_STATUS (25)</option></term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
PostgreSQL on one or more nodes could not be reached.
|
|
||||||
</para>
|
|
||||||
<note>
|
|
||||||
<simpara>
|
|
||||||
This error code overrides <option>ERR_BAD_SSH</option>.
|
|
||||||
</simpara>
|
|
||||||
</note>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
</variablelist>
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
</refentry>
|
</refentry>
|
||||||
|
|
||||||
|
|||||||
@@ -49,22 +49,6 @@
|
|||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</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>
|
<refsect1>
|
||||||
<title>Example</title>
|
<title>Example</title>
|
||||||
<para>
|
<para>
|
||||||
|
|||||||
@@ -97,49 +97,5 @@
|
|||||||
useful result.
|
useful result.
|
||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</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_BAD_SSH (12)</option></term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
One or more nodes could not be accessed via SSH.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><option>ERR_NODE_STATUS (25)</option></term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
PostgreSQL on one or more nodes could not be reached.
|
|
||||||
</para>
|
|
||||||
<note>
|
|
||||||
<simpara>
|
|
||||||
This error code overrides <option>ERR_BAD_SSH</option>.
|
|
||||||
</simpara>
|
|
||||||
</note>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
</variablelist>
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
</refentry>
|
</refentry>
|
||||||
|
|
||||||
|
|||||||
@@ -81,91 +81,35 @@
|
|||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
<title>Options</title>
|
<title>Options</title>
|
||||||
|
<para>
|
||||||
<variablelist>
|
<command>repmgr cluster show</command> accepts an optional parameter <literal>--csv</literal>, which
|
||||||
|
outputs the replication cluster's status in a simple CSV format, suitable for
|
||||||
<varlistentry>
|
parsing by scripts:
|
||||||
<term><option>--csv</option></term>
|
<programlisting>
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<command>repmgr cluster show</command> accepts an optional parameter <literal>--csv</literal>, which
|
|
||||||
outputs the replication cluster's status in a simple CSV format, suitable for
|
|
||||||
parsing by scripts, e.g.:
|
|
||||||
<programlisting>
|
|
||||||
$ repmgr -f /etc/repmgr.conf cluster show --csv
|
$ repmgr -f /etc/repmgr.conf cluster show --csv
|
||||||
1,-1,-1
|
1,-1,-1
|
||||||
2,0,0
|
2,0,0
|
||||||
3,0,1</programlisting>
|
3,0,1</programlisting>
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The columns have following meanings:
|
|
||||||
<itemizedlist spacing="compact" mark="bullet">
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
node ID
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
availability (0 = available, -1 = unavailable)
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
recovery state (0 = not in recovery, 1 = in recovery, -1 = unknown)
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><option>--verbose</option></term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Display the full text of any database connection error messages
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
</variablelist>
|
|
||||||
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>Exit codes</title>
|
|
||||||
<para>
|
|
||||||
Following exit codes can be emitted by <command>repmgr cluster show</command>:
|
|
||||||
</para>
|
</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>
|
<para>
|
||||||
<xref linkend="repmgr-node-status">, <xref linkend="repmgr-node-check">, <xref linkend="repmgr-daemon-status">
|
The columns have following meanings:
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
node ID
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
availability (0 = available, -1 = unavailable)
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
recovery state (0 = not in recovery, 1 = in recovery, -1 = unknown)
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
|||||||
@@ -1,109 +0,0 @@
|
|||||||
<refentry id="repmgr-daemon-pause">
|
|
||||||
<indexterm>
|
|
||||||
<primary>repmgr daemon pause</primary>
|
|
||||||
</indexterm>
|
|
||||||
|
|
||||||
<refmeta>
|
|
||||||
<refentrytitle>repmgr daemon pause</refentrytitle>
|
|
||||||
</refmeta>
|
|
||||||
|
|
||||||
<refnamediv>
|
|
||||||
<refname>repmgr daemon pause</refname>
|
|
||||||
<refpurpose>Instruct all <application>repmgrd</application> instances in the replication cluster to pause failover operations</refpurpose>
|
|
||||||
</refnamediv>
|
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>Description</title>
|
|
||||||
<para>
|
|
||||||
This command can be run on any active node in the replication cluster to instruct all
|
|
||||||
running <application>repmgrd</application> instances to "pause" themselves, i.e. take no
|
|
||||||
action (such as promoting themselves or following a new primary) if a failover event is detected.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
This functionality is useful for performing maintenance operations, such as switchovers
|
|
||||||
or upgrades, which might otherwise trigger a failover if <application>repmgrd</application>
|
|
||||||
is running normally.
|
|
||||||
</para>
|
|
||||||
<note>
|
|
||||||
<para>
|
|
||||||
It's important to wait a few seconds after restarting PostgreSQL on any node before running
|
|
||||||
<command>repmgr daemon pause</command>, as the <application>repmgrd</application> instance
|
|
||||||
on the restarted node will take a second or two before it has updated its status.
|
|
||||||
</para>
|
|
||||||
</note>
|
|
||||||
<para>
|
|
||||||
<xref linkend="repmgr-daemon-unpause"> will instruct all previously paused <application>repmgrd</application>
|
|
||||||
instances to resume normal failover operation.
|
|
||||||
</para>
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>Execution</title>
|
|
||||||
<para>
|
|
||||||
<command>repmgr daemon pause</command> can be executed on any active node in the
|
|
||||||
replication cluster. A valid <filename>repmgr.conf</filename> file is required.
|
|
||||||
It will have no effect on previously paused nodes.
|
|
||||||
</para>
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>Example</title>
|
|
||||||
<para>
|
|
||||||
<programlisting>
|
|
||||||
$ repmgr -f /etc/repmgr.conf daemon pause
|
|
||||||
NOTICE: node 1 (node1) paused
|
|
||||||
NOTICE: node 2 (node2) paused
|
|
||||||
NOTICE: node 3 (node3) paused</programlisting>
|
|
||||||
</para>
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>Options</title>
|
|
||||||
<variablelist>
|
|
||||||
<varlistentry>
|
|
||||||
<term><option>--dry-run</option></term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Check if nodes are reachable but don't pause <application>repmgrd</application>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>Exit codes</title>
|
|
||||||
<para>
|
|
||||||
Following exit codes can be emitted by <command>repmgr daemon unpause</command>:
|
|
||||||
</para>
|
|
||||||
<variablelist>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><option>SUCCESS (0)</option></term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<application>repmgrd</application> could be paused on all nodes.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><option>ERR_REPMGRD_PAUSE (26)</option></term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<application>repmgrd</application> could not be paused on one or mode nodes.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
</variablelist>
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>See also</title>
|
|
||||||
<para>
|
|
||||||
<xref linkend="repmgr-daemon-unpause">, <xref linkend="repmgr-daemon-status">
|
|
||||||
</para>
|
|
||||||
</refsect1>
|
|
||||||
</refentry>
|
|
||||||
|
|
||||||
@@ -1,165 +0,0 @@
|
|||||||
<refentry id="repmgr-daemon-status">
|
|
||||||
<indexterm>
|
|
||||||
<primary>repmgr daemon status</primary>
|
|
||||||
</indexterm>
|
|
||||||
|
|
||||||
<refmeta>
|
|
||||||
<refentrytitle>repmgr daemon status</refentrytitle>
|
|
||||||
</refmeta>
|
|
||||||
|
|
||||||
<refnamediv>
|
|
||||||
<refname>repmgr daemon status</refname>
|
|
||||||
<refpurpose>display information about the status of <application>repmgrd</application> on each node in the cluster</refpurpose>
|
|
||||||
</refnamediv>
|
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>Description</title>
|
|
||||||
<para>
|
|
||||||
This command provides an overview over all active nodes in the cluster and the state
|
|
||||||
of each node's <application>repmgrd</application> instance. It can be used to check
|
|
||||||
the result of <xref linkend="repmgr-daemon-pause"> and <xref linkend="repmgr-daemon-unpause">
|
|
||||||
operations.
|
|
||||||
</para>
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>Execution</title>
|
|
||||||
<para>
|
|
||||||
<command>repmgr daemon status</command> can be executed on any active node in the
|
|
||||||
replication cluster. A valid <filename>repmgr.conf</filename> file is required.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<note>
|
|
||||||
<para>
|
|
||||||
After restarting PostgreSQL on any node, the <application>repmgrd</application> instance
|
|
||||||
will take a second or two before it is able to update its status. Until then,
|
|
||||||
<application>repmgrd</application> will be shown as not running.
|
|
||||||
</para>
|
|
||||||
</note>
|
|
||||||
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>Examples</title>
|
|
||||||
<para>
|
|
||||||
<application>repmgrd</application> running normally on all nodes:
|
|
||||||
<programlisting>$ repmgr -f /etc/repmgr.conf daemon status
|
|
||||||
ID | Name | Role | Status | repmgrd | PID | Paused?
|
|
||||||
----+-------+---------+---------+---------+------+---------
|
|
||||||
1 | node1 | primary | running | running | 7851 | no
|
|
||||||
2 | node2 | standby | running | running | 7889 | no
|
|
||||||
3 | node3 | standby | running | running | 7918 | no</programlisting>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
<application>repmgrd</application> paused on all nodes (using <xref linkend="repmgr-daemon-pause">):
|
|
||||||
<programlisting>$ repmgr -f /etc/repmgr.conf daemon status
|
|
||||||
ID | Name | Role | Status | repmgrd | PID | Paused?
|
|
||||||
----+-------+---------+---------+---------+------+---------
|
|
||||||
1 | node1 | primary | running | running | 7851 | yes
|
|
||||||
2 | node2 | standby | running | running | 7889 | yes
|
|
||||||
3 | node3 | standby | running | running | 7918 | yes</programlisting>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
<application>repmgrd</application> not running on one node:
|
|
||||||
<programlisting>$ repmgr -f /etc/repmgr.conf daemon status
|
|
||||||
ID | Name | Role | Status | repmgrd | PID | Paused?
|
|
||||||
----+-------+---------+---------+-------------+------+---------
|
|
||||||
1 | node1 | primary | running | running | 7851 | yes
|
|
||||||
2 | node2 | standby | running | not running | n/a | n/a
|
|
||||||
3 | node3 | standby | running | running | 7918 | yes</programlisting>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>Options</title>
|
|
||||||
|
|
||||||
<variablelist>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><option>--csv</option></term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<command>repmgr daemon status</command> accepts an optional parameter <literal>--csv</literal>, which
|
|
||||||
outputs the replication cluster's status in a simple CSV format, suitable for
|
|
||||||
parsing by scripts, e.g.:
|
|
||||||
<programlisting>
|
|
||||||
$ repmgr -f /etc/repmgr.conf daemon status --csv
|
|
||||||
1,node1,primary,1,1,10204,1
|
|
||||||
2,node2,standby,1,0,-1,1
|
|
||||||
3,node3,standby,1,1,10225,1</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The columns have following meanings:
|
|
||||||
<itemizedlist spacing="compact" mark="bullet">
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
node ID
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
node name
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
node type (primary or standby)
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
PostgreSQL server running
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<application>repmgrd</application> running (1 = running, 0 = not running)
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<application>repmgrd</application> PID (-1 if not running)
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<application>repmgrd</application> paused (1 = paused, 0 = not paused)
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><option>--verbose</option></term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Display the full text of any database connection error messages
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
</variablelist>
|
|
||||||
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>See also</title>
|
|
||||||
<para>
|
|
||||||
<xref linkend="repmgr-daemon-pause">, <xref linkend="repmgr-daemon-unpause">, <xref linkend="repmgr-cluster-show">
|
|
||||||
</para>
|
|
||||||
</refsect1>
|
|
||||||
</refentry>
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
<refentry id="repmgr-daemon-unpause">
|
|
||||||
<indexterm>
|
|
||||||
<primary>repmgr daemon unpause</primary>
|
|
||||||
</indexterm>
|
|
||||||
|
|
||||||
<refmeta>
|
|
||||||
<refentrytitle>repmgr daemon unpause</refentrytitle>
|
|
||||||
</refmeta>
|
|
||||||
|
|
||||||
<refnamediv>
|
|
||||||
<refname>repmgr daemon unpause</refname>
|
|
||||||
<refpurpose>Instruct all <application>repmgrd</application> instances in the replication cluster to resume failover operations</refpurpose>
|
|
||||||
</refnamediv>
|
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>Description</title>
|
|
||||||
<para>
|
|
||||||
This command can be run on any active node in the replication cluster to instruct all
|
|
||||||
running <application>repmgrd</application> instances to "unpause"
|
|
||||||
(following a previous execution of <xref linkend="repmgr-daemon-pause">)
|
|
||||||
and resume normal failover/monitoring operation.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<note>
|
|
||||||
<para>
|
|
||||||
It's important to wait a few seconds after restarting PostgreSQL on any node before running
|
|
||||||
<command>repmgr daemon pause</command>, as the <application>repmgrd</application> instance
|
|
||||||
on the restarted node will take a second or two before it has updated its status.
|
|
||||||
</para>
|
|
||||||
</note>
|
|
||||||
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>Execution</title>
|
|
||||||
<para>
|
|
||||||
<command>repmgr daemon unpause</command> can be executed on any active node in the
|
|
||||||
replication cluster. A valid <filename>repmgr.conf</filename> file is required.
|
|
||||||
It will have no effect on nodes which are not already paused.
|
|
||||||
</para>
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>Example</title>
|
|
||||||
<para>
|
|
||||||
<programlisting>
|
|
||||||
$ repmgr -f /etc/repmgr.conf daemon unpause
|
|
||||||
NOTICE: node 1 (node1) unpaused
|
|
||||||
NOTICE: node 2 (node2) unpaused
|
|
||||||
NOTICE: node 3 (node3) unpaused</programlisting>
|
|
||||||
</para>
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>Options</title>
|
|
||||||
<variablelist>
|
|
||||||
<varlistentry>
|
|
||||||
<term><option>--dry-run</option></term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Check if nodes are reachable but don't unpause <application>repmgrd</application>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>Exit codes</title>
|
|
||||||
<para>
|
|
||||||
Following exit codes can be emitted by <command>repmgr daemon unpause</command>:
|
|
||||||
</para>
|
|
||||||
<variablelist>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><option>SUCCESS (0)</option></term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<application>repmgrd</application> could be unpaused on all nodes.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><option>ERR_REPMGRD_PAUSE (26)</option></term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<application>repmgrd</application> could not be unpaused on one or mode nodes.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
</variablelist>
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>See also</title>
|
|
||||||
<para>
|
|
||||||
<xref linkend="repmgr-daemon-pause">, <xref linkend="repmgr-daemon-status">
|
|
||||||
</para>
|
|
||||||
</refsect1>
|
|
||||||
</refentry>
|
|
||||||
|
|
||||||
@@ -30,8 +30,7 @@
|
|||||||
Replication lag: OK (N/A - node is primary)
|
Replication lag: OK (N/A - node is primary)
|
||||||
WAL archiving: OK (0 pending files)
|
WAL archiving: OK (0 pending files)
|
||||||
Downstream servers: OK (2 of 2 downstream nodes attached)
|
Downstream servers: OK (2 of 2 downstream nodes attached)
|
||||||
Replication slots: OK (node has no replication slots)
|
Replication slots: OK (node has no replication slots)</programlisting>
|
||||||
Missing replication slots: OK (node has no missing replication slots)</programlisting>
|
|
||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
<refsect1>
|
<refsect1>
|
||||||
@@ -62,9 +61,7 @@
|
|||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<simpara>
|
<simpara>
|
||||||
<literal>--archive-ready</literal>: checks for WAL files which have not yet been archived,
|
<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.
|
|
||||||
</simpara>
|
</simpara>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
|
||||||
@@ -80,110 +77,11 @@
|
|||||||
</simpara>
|
</simpara>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<literal>--missing-slots</literal>: checks there are no missing replication slots
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</para>
|
</para>
|
||||||
|
<para>
|
||||||
|
Individual checks can also be output in a Nagios-compatible format by additionally
|
||||||
|
providing the option <literal>--nagios</literal>.
|
||||||
|
</para>
|
||||||
</refsect1>
|
</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>
|
</refentry>
|
||||||
|
|||||||
@@ -28,10 +28,6 @@
|
|||||||
If the node is running and needs to be attached to the current primary, use
|
If the node is running and needs to be attached to the current primary, use
|
||||||
<xref linkend="repmgr-standby-follow">.
|
<xref linkend="repmgr-standby-follow">.
|
||||||
</para>
|
</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>
|
</tip>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
@@ -50,95 +46,6 @@
|
|||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
|
|
||||||
<title>Options</title>
|
|
||||||
<variablelist>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><option>--dry-run</option></term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Check prerequisites but don't actually execute the rejoin.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><option>--force-rewind[=/path/to/pg_rewind]</option></term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Execute <application>pg_rewind</application>.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
It is only necessary to provide the <application>pg_rewind</application> path
|
|
||||||
if using PostgreSQL 9.3 or 9.4, and <application>pg_rewind</application>
|
|
||||||
is not installed in the PostgreSQL <filename>bin</filename> directory.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><option>--config-files</option></term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
comma-separated list of configuration files to retain after
|
|
||||||
executing <application>pg_rewind</application>.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Currently <application>pg_rewind</application> will overwrite
|
|
||||||
the local node's configuration files with the files from the source node,
|
|
||||||
so it's advisable to use this option to ensure they are kept.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><option>--config-archive-dir</option></term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Directory to temporarily store configuration files specified with
|
|
||||||
<option>--config-files</option>; default: <filename>/tmp</filename>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><option>-W/--no-wait</option></term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Don't wait for the node to rejoin cluster.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
If this option is supplied, &repmgr; will restart the node but
|
|
||||||
not wait for it to connect to the primary.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
</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>
|
<title>Event notifications</title>
|
||||||
<para>
|
<para>
|
||||||
A <literal>node_rejoin</literal> <link linkend="event-notifications">event notification</link> will be generated.
|
A <literal>node_rejoin</literal> <link linkend="event-notifications">event notification</link> will be generated.
|
||||||
@@ -170,18 +77,11 @@
|
|||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1 id="repmgr-node-rejoin-pg-rewind" xreflabel="Using pg_rewind">
|
<refsect1 id="repmgr-node-rejoin-pg-rewind" xreflabel="Using pg_rewind">
|
||||||
|
|
||||||
<indexterm>
|
|
||||||
<primary>pg_rewind</primary>
|
|
||||||
<secondary>using with "repmgr node rejoin"</secondary>
|
|
||||||
</indexterm>
|
|
||||||
|
|
||||||
<title>Using <command>pg_rewind</command></title>
|
<title>Using <command>pg_rewind</command></title>
|
||||||
<para>
|
<para>
|
||||||
<command>repmgr node rejoin</command> can optionally use <command>pg_rewind</command> to re-integrate a
|
<command>repmgr node rejoin</command> can optionally use <command>pg_rewind</command> to re-integrate a
|
||||||
node which has diverged from the rest of the cluster, typically a failed primary.
|
node which has diverged from the rest of the cluster, typically a failed primary.
|
||||||
<command>pg_rewind</command> is available in PostgreSQL 9.5 and later as part of the core distribution,
|
<command>pg_rewind</command> is available in PostgreSQL 9.5 and later.
|
||||||
and can be installed from external sources for PostgreSQL 9.3 and 9.4.
|
|
||||||
</para>
|
</para>
|
||||||
<note>
|
<note>
|
||||||
<para>
|
<para>
|
||||||
@@ -193,7 +93,7 @@
|
|||||||
</note>
|
</note>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
To have <command>repmgr node rejoin</command> use <command>pg_rewind</command>,
|
To have <command>repmgr node rejoin</command> use <command>pg_rewind</command> if required,
|
||||||
pass the command line option <literal>--force-rewind</literal>, which will tell &repmgr;
|
pass the command line option <literal>--force-rewind</literal>, which will tell &repmgr;
|
||||||
to execute <command>pg_rewind</command> to ensure the node can be rejoined successfully.
|
to execute <command>pg_rewind</command> to ensure the node can be rejoined successfully.
|
||||||
</para>
|
</para>
|
||||||
@@ -226,15 +126,6 @@
|
|||||||
INFO: pg_rewind would now be executed
|
INFO: pg_rewind would now be executed
|
||||||
DETAIL: pg_rewind command is:
|
DETAIL: pg_rewind command is:
|
||||||
pg_rewind -D '/var/lib/postgresql/data' --source-server='host=node1 dbname=repmgr user=repmgr'</programlisting>
|
pg_rewind -D '/var/lib/postgresql/data' --source-server='host=node1 dbname=repmgr user=repmgr'</programlisting>
|
||||||
|
|
||||||
<note>
|
|
||||||
<para>
|
|
||||||
If <option>--force-rewind</option> is used with the <option>--dry-run</option> option,
|
|
||||||
this checks the prerequisites for using <application>pg_rewind</application>, but cannot
|
|
||||||
predict the outcome of actually executing <application>pg_rewind</application>.
|
|
||||||
</para>
|
|
||||||
</note>
|
|
||||||
|
|
||||||
<programlisting>
|
<programlisting>
|
||||||
$ repmgr node rejoin -f /etc/repmgr.conf -d 'host=node1 dbname=repmgr user=repmgr' \
|
$ repmgr node rejoin -f /etc/repmgr.conf -d 'host=node1 dbname=repmgr user=repmgr' \
|
||||||
--force-rewind --config-files=postgresql.local.conf,postgresql.conf --verbose
|
--force-rewind --config-files=postgresql.local.conf,postgresql.conf --verbose
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
<title>Example</title>
|
<title>Example</title>
|
||||||
<para>
|
<para>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
$ repmgr -f /etc/repmgr.conf node status
|
$ repmgr -f /etc/repmgr.comf node status
|
||||||
Node "node1":
|
Node "node1":
|
||||||
PostgreSQL version: 10beta1
|
PostgreSQL version: 10beta1
|
||||||
Total data size: 30 MB
|
Total data size: 30 MB
|
||||||
@@ -38,54 +38,10 @@
|
|||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</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>
|
<refsect1>
|
||||||
<title>See also</title>
|
<title>See also</title>
|
||||||
<para>
|
<para>
|
||||||
See <xref linkend="repmgr-node-check"> to diagnose issues and <xref linkend="repmgr-cluster-show">
|
See <xref linkend="repmgr-node-check"> to diagnose issues.
|
||||||
for an overview of all nodes in the cluster.
|
|
||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
</refentry>
|
</refentry>
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
<title>Description</title>
|
<title>Description</title>
|
||||||
<para>
|
<para>
|
||||||
<command>repmgr primary register</command> registers a primary node in a
|
<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
|
installing the &repmgr; extension. This command needs to be executed before any
|
||||||
standby nodes are registered.
|
standby nodes are registered.
|
||||||
</para>
|
</para>
|
||||||
@@ -63,7 +63,7 @@
|
|||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>-F</option>, <option>--force</option></term>
|
<term><option>-F</option><option>--force</option></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Overwrite an existing node record
|
Overwrite an existing node record
|
||||||
@@ -75,18 +75,10 @@
|
|||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
|
||||||
<refsect1 id="repmgr-primary-register-events">
|
<refsect1>
|
||||||
<title>Event notifications</title>
|
<title>Event notifications</title>
|
||||||
<para>
|
<para>
|
||||||
Following <link linkend="event-notifications">event notifications</link> will be generated:
|
A <literal>primary_register</literal> <link linkend="event-notifications">event notification</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>
|
|
||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
|||||||
@@ -64,7 +64,7 @@
|
|||||||
|
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1 id="repmgr-primary-unregister-events">
|
<refsect1>
|
||||||
<title>Event notifications</title>
|
<title>Event notifications</title>
|
||||||
<para>
|
<para>
|
||||||
A <literal>primary_unregister</literal> <link linkend="event-notifications">event notification</link> will be generated.
|
A <literal>primary_unregister</literal> <link linkend="event-notifications">event notification</link> will be generated.
|
||||||
|
|||||||
@@ -25,11 +25,9 @@
|
|||||||
<note>
|
<note>
|
||||||
<simpara>
|
<simpara>
|
||||||
<command>repmgr standby clone</command> does not start the standby, and after cloning
|
<command>repmgr standby clone</command> does not start the standby, and after cloning
|
||||||
a standby, the command <command>repmgr standby register</command> must be executed to
|
<command>repmgr standby register</command> must be executed to notify &repmgr; of its presence.
|
||||||
notify &repmgr; of its existence.
|
|
||||||
</simpara>
|
</simpara>
|
||||||
</note>
|
</note>
|
||||||
|
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
|
||||||
@@ -49,7 +47,7 @@
|
|||||||
not be copied by default. &repmgr; can copy these files, either to the same
|
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
|
location on the standby server (provided appropriate directory and file permissions
|
||||||
are available), or into the standby's data directory. This requires passwordless
|
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
|
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>
|
the same path as on the upstream server. Note that the user executing <command>repmgr</command>
|
||||||
must have write access to those directories.
|
must have write access to those directories.
|
||||||
@@ -59,96 +57,15 @@
|
|||||||
<literal>--copy-external-config-files=pgdata</literal>, but note that
|
<literal>--copy-external-config-files=pgdata</literal>, but note that
|
||||||
any include directives in the copied files may need to be updated.
|
any include directives in the copied files may need to be updated.
|
||||||
</para>
|
</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>
|
<tip>
|
||||||
<simpara>
|
<simpara>
|
||||||
For reliable configuration file management we recommend using a
|
For reliable configuration file management we recommend using a
|
||||||
configuration management tool such as Ansible, Chef, Puppet or Salt.
|
configuration management tool such as Ansible, Chef, Puppet or Salt.
|
||||||
</simpara>
|
</simpara>
|
||||||
</tip>
|
</tip>
|
||||||
|
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1 id="repmgr-standby-clone-recovery-conf">
|
<refsect1 id="repmgr-standby-clone-wal-management" xreflabel="Managing WAL during the cloning process">
|
||||||
<indexterm>
|
|
||||||
<primary>recovery.conf</primary>
|
|
||||||
<secondary>customising with "repmgr standby clone"</secondary>
|
|
||||||
</indexterm>
|
|
||||||
|
|
||||||
<title>Customising recovery.conf</title>
|
|
||||||
<para>
|
|
||||||
By default, &repmgr; will create a minimal <filename>recovery.conf</filename>
|
|
||||||
containing following parameters:
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<itemizedlist spacing="compact" mark="bullet">
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara><varname>standby_mode</varname> (always <literal>'on'</literal>)</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara><varname>recovery_target_timeline</varname> (always <literal>'latest'</literal>)</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara><varname>primary_conninfo</varname></simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara><varname>primary_slot_name</varname> (if replication slots in use)</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
</itemizedlist>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
The following additional parameters can be specified in <filename>repmgr.conf</filename>
|
|
||||||
for inclusion in <filename>recovery.conf</filename>:
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<itemizedlist spacing="compact" mark="bullet">
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara><varname>restore_command</varname></simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara><varname>archive_cleanup_command</varname></simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara><varname>recovery_min_apply_delay</varname></simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
</itemizedlist>
|
|
||||||
|
|
||||||
<note>
|
|
||||||
<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
|
|
||||||
WAL files, see <xref linkend="cloning-from-barman">.
|
|
||||||
</para>
|
|
||||||
</note>
|
|
||||||
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
<refsect1 id="repmgr-standby-clone-wal-management">
|
|
||||||
<title>Managing WAL during the cloning process</title>
|
<title>Managing WAL during the cloning process</title>
|
||||||
<para>
|
<para>
|
||||||
When initially cloning a standby, you will need to ensure
|
When initially cloning a standby, you will need to ensure
|
||||||
@@ -185,22 +102,15 @@
|
|||||||
|
|
||||||
|
|
||||||
<refsect1 id="repmgr-standby-create-recovery-conf">
|
<refsect1 id="repmgr-standby-create-recovery-conf">
|
||||||
|
|
||||||
<indexterm>
|
|
||||||
<primary>recovery.conf</primary>
|
|
||||||
<secondary>generating for a standby cloned by another method</secondary>
|
|
||||||
</indexterm>
|
|
||||||
|
|
||||||
<title>Using a standby cloned by another method</title>
|
<title>Using a standby cloned by another method</title>
|
||||||
<para>
|
<para>
|
||||||
&repmgr; supports standbys cloned by another method (e.g. using <application>barman</application>'s
|
&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>
|
||||||
<para>
|
<para>
|
||||||
To integrate the standby as a &repmgr; node, ensure the <filename>repmgr.conf</filename>
|
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
|
file is created for the node, then execute the command
|
||||||
<command><link linkend="repmgr-standby-register">repmgr standby register</link></command>.
|
<command>repmgr standby clone --recovery-conf-only</command>.
|
||||||
Then execute the command <command>repmgr standby clone --recovery-conf-only</command>.
|
|
||||||
This will create the <filename>recovery.conf</filename> file needed to attach
|
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
|
the node to its upstream, and will also create a replication slot on the
|
||||||
upstream node if required.
|
upstream node if required.
|
||||||
@@ -215,13 +125,6 @@
|
|||||||
to check the prerequisites for creating the <filename>recovery.conf</filename> file,
|
to check the prerequisites for creating the <filename>recovery.conf</filename> file,
|
||||||
and display the contents of the file without actually creating it.
|
and display the contents of the file without actually creating it.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<note>
|
|
||||||
<para>
|
|
||||||
<option>--recovery-conf-only</option> was introduced in &repmgr; <link linkend="release-4.0.4">4.0.4</link>.
|
|
||||||
</para>
|
|
||||||
</note>
|
|
||||||
|
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
@@ -230,15 +133,6 @@
|
|||||||
|
|
||||||
<variablelist>
|
<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>
|
<varlistentry>
|
||||||
<term><option>--dry-run</option></term>
|
<term><option>--dry-run</option></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
@@ -257,7 +151,7 @@
|
|||||||
<term><option>-c, --fast-checkpoint</option></term>
|
<term><option>-c, --fast-checkpoint</option></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Force fast checkpoint (not effective when cloning from Barman).
|
force fast checkpoint (not effective when cloning from Barman
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@@ -266,7 +160,7 @@
|
|||||||
<term><option>--copy-external-config-files[={samepath|pgdata}]</option></term>
|
<term><option>--copy-external-config-files[={samepath|pgdata}]</option></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Copy configuration files located outside the data directory on the source
|
copy configuration files located outside the data directory on the source
|
||||||
node to the same path on the standby (default) or to the
|
node to the same path on the standby (default) or to the
|
||||||
PostgreSQL data directory.
|
PostgreSQL data directory.
|
||||||
</para>
|
</para>
|
||||||
@@ -277,7 +171,7 @@
|
|||||||
<term><option>--no-upstream-connection</option></term>
|
<term><option>--no-upstream-connection</option></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
When using Barman, do not connect to upstream node.
|
when using Barman, do not connect to upstream node
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@@ -286,7 +180,7 @@
|
|||||||
<term><option>-R, --remote-user=USERNAME</option></term>
|
<term><option>-R, --remote-user=USERNAME</option></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Remote system username for SSH operations (default: current local system username).
|
remote system username for SSH operations (default: current local system username)
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@@ -295,7 +189,7 @@
|
|||||||
<term><option> --recovery-conf-only</option></term>
|
<term><option> --recovery-conf-only</option></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Create <filename>recovery.conf</filename> file for a previously cloned instance. &repmgr 4.0.4 and later.
|
create <filename>recovery.conf</filename> file for a previously cloned instance
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@@ -304,7 +198,7 @@
|
|||||||
<term><option>--replication-user</option></term>
|
<term><option>--replication-user</option></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
User to make replication connections with (optional, not usually required).
|
user to make replication connections with (optional, not usually required)
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@@ -313,8 +207,8 @@
|
|||||||
<term><option>--superuser</option></term>
|
<term><option>--superuser</option></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
If the &repmgr; user is not a superuser, the name of a valid superuser must
|
if the &repmgr; user is not a superuser, the name of a valid superuser must
|
||||||
be provided with this option.
|
be provided with this option
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@@ -325,7 +219,7 @@
|
|||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
<literal>primary_conninfo</literal> value to write in recovery.conf
|
<literal>primary_conninfo</literal> value to write in recovery.conf
|
||||||
when the intended upstream server does not yet exist.
|
when the intended upstream server does not yet exist
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@@ -342,7 +236,7 @@
|
|||||||
<term><option>--without-barman </option></term>
|
<term><option>--without-barman </option></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Do not use Barman even if configured.
|
do not use Barman even if configured
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@@ -350,18 +244,12 @@
|
|||||||
</variablelist>
|
</variablelist>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1 id="repmgr-standby-clone-events">
|
<refsect1>
|
||||||
<title>Event notifications</title>
|
<title>Event notifications</title>
|
||||||
<para>
|
<para>
|
||||||
A <literal>standby_clone</literal> <link linkend="event-notifications">event notification</link> will be generated.
|
A <literal>standby_clone</literal> <link linkend="event-notifications">event notification</link> will be generated.
|
||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>See also</title>
|
|
||||||
<para>
|
|
||||||
See <xref linkend="cloning-standbys"> for details about various aspects of cloning.
|
|
||||||
</para>
|
|
||||||
</refsect1>
|
|
||||||
</refentry>
|
</refentry>
|
||||||
|
|
||||||
|
|||||||
@@ -26,18 +26,10 @@
|
|||||||
running. It can only be used to attach an active standby to the current primary node
|
running. It can only be used to attach an active standby to the current primary node
|
||||||
(and not to another standby).
|
(and not to another standby).
|
||||||
</para>
|
</para>
|
||||||
<tip>
|
<para>
|
||||||
<para>
|
To re-add an inactive node to the replication cluster, see
|
||||||
To re-add an inactive node to the replication cluster, use
|
<xref linkend="repmgr-node-rejoin">
|
||||||
<xref linkend="repmgr-node-rejoin">.
|
</para>
|
||||||
</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>
|
|
||||||
|
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
@@ -79,7 +71,7 @@
|
|||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>-w</option></term>
|
<term><option>-W</option></term>
|
||||||
<term><option>--wait</option></term>
|
<term><option>--wait</option></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
@@ -94,13 +86,13 @@
|
|||||||
</variablelist>
|
</variablelist>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1 id="repmgr-standby-follow-events">
|
<refsect1>
|
||||||
<title>Event notifications</title>
|
<title>Event notifications</title>
|
||||||
<para>
|
<para>
|
||||||
A <literal>standby_follow</literal> <link linkend="event-notifications">event notification</link> will be generated.
|
A <literal>standby_follow</literal> <link linkend="event-notifications">event notification</link> will be generated.
|
||||||
</para>
|
</para>
|
||||||
<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
|
being followed, <literal>%c</literal> with its <literal>conninfo</literal> string, and
|
||||||
<literal>%a</literal> with its node name.
|
<literal>%a</literal> with its node name.
|
||||||
</para>
|
</para>
|
||||||
|
|||||||
@@ -32,7 +32,6 @@
|
|||||||
check the promotion every <varname>promote_check_interval</varname> seconds (default: 1 second).
|
check the promotion every <varname>promote_check_interval</varname> seconds (default: 1 second).
|
||||||
Both values can be defined in <filename>repmgr.conf</filename>.
|
Both values can be defined in <filename>repmgr.conf</filename>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
@@ -50,7 +49,7 @@
|
|||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
|
||||||
<refsect1 id="repmgr-standby-promote-events">
|
<refsect1>
|
||||||
<title>Event notifications</title>
|
<title>Event notifications</title>
|
||||||
<para>
|
<para>
|
||||||
A <literal>standby_promote</literal> <link linkend="event-notifications">event notification</link> will be generated.
|
A <literal>standby_promote</literal> <link linkend="event-notifications">event notification</link> will be generated.
|
||||||
|
|||||||
@@ -159,7 +159,7 @@
|
|||||||
</variablelist>
|
</variablelist>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1 id="repmgr-standby-register-events">
|
<refsect1>
|
||||||
<title>Event notifications</title>
|
<title>Event notifications</title>
|
||||||
<para>
|
<para>
|
||||||
A <literal>standby_register</literal> <link linkend="event-notifications">event notification</link>
|
A <literal>standby_register</literal> <link linkend="event-notifications">event notification</link>
|
||||||
@@ -173,7 +173,7 @@
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<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
|
primary node, <literal>%c</literal> with its <literal>conninfo</literal> string, and
|
||||||
<literal>%a</literal> with its node name.
|
<literal>%a</literal> with its node name.
|
||||||
</para>
|
</para>
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
<refpurpose>promote a standby to primary and demote the existing primary to a standby</refpurpose>
|
<refpurpose>promote a standby to primary and demote the existing primary to a standby</refpurpose>
|
||||||
</refnamediv>
|
</refnamediv>
|
||||||
|
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
<title>Description</title>
|
<title>Description</title>
|
||||||
|
|
||||||
@@ -35,29 +34,7 @@
|
|||||||
&repmgr; will attempt to check for potential issues but cannot guarantee
|
&repmgr; will attempt to check for potential issues but cannot guarantee
|
||||||
a successful switchover.
|
a successful switchover.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
|
||||||
&repmgr; will refuse to perform the switchover if an exclusive backup is running on
|
|
||||||
the current primary.
|
|
||||||
</para>
|
|
||||||
</note>
|
</note>
|
||||||
<para>
|
|
||||||
For more details on performing a switchover, including preparation and configuration,
|
|
||||||
see section <xref linkend="performing-switchover">.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<note>
|
|
||||||
<para>
|
|
||||||
From <link linkend="release-4.2">repmgr 4.2</link>, &repmgr; will instruct any running
|
|
||||||
<application>repmgrd</application> instances to pause operations while the switchover
|
|
||||||
is being carried out, to prevent <application>repmgrd</application> from
|
|
||||||
unintentionally promoting a node. For more details, see <xref linkend="repmgrd-pausing">.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Users of &repmgr; versions prior to 4.2 should ensure that <application>repmgrd</application>
|
|
||||||
is not running on any nodes while a switchover is being executed.
|
|
||||||
</para>
|
|
||||||
</note>
|
|
||||||
|
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
@@ -68,9 +45,8 @@
|
|||||||
<term><option>--always-promote</option></term>
|
<term><option>--always-promote</option></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Promote standby to primary, even if it is behind or has diverged
|
Promote standby to primary, even if it is behind original primary
|
||||||
from the original primary. The original primary will be shut down in any case,
|
(original primary will be shut down in any case).
|
||||||
and will need to be manually reintegrated into the replication cluster.
|
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@@ -108,14 +84,11 @@
|
|||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>--force-rewind[=/path/to/pg_rewind]</option></term>
|
<term><option>--force-rewind</option></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Use <application>pg_rewind</application> to reintegrate the old primary if necessary
|
Use <application>pg_rewind</application> to reintegrate the old primary if necessary
|
||||||
(and the prerequisites for using <application>pg_rewind</application> are met).
|
(PostgreSQL 9.5 and later).
|
||||||
If using PostgreSQL 9.3 or 9.4, and the <application>pg_rewind</application>
|
|
||||||
binary is not installed in the PostgreSQL <filename>bin</filename> directory,
|
|
||||||
provide its full path. For more details see also <xref linkend="switchover-pg-rewind">.
|
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@@ -130,21 +103,6 @@
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term><option>--repmgrd-no-pause</option></term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Don't pause <application>repmgrd</application> while executing a switchover.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
This option should not be used unless you take steps by other means
|
|
||||||
to ensure <application>repmgrd</application> is paused or not
|
|
||||||
running on all nodes.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>--siblings-follow</option></term>
|
<term><option>--siblings-follow</option></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
@@ -157,55 +115,6 @@
|
|||||||
|
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>Configuration file settings</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Note that following parameters in <filename>repmgr.conf</filename> are relevant to the
|
|
||||||
switchover operation:
|
|
||||||
<itemizedlist spacing="compact" mark="bullet">
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<literal>replication_lag_critical</literal>:
|
|
||||||
if replication lag (in seconds) on the standby exceeds this value, the
|
|
||||||
switchover will be aborted (unless the <literal>-F/--force</literal> option
|
|
||||||
is provided)
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<literal>shutdown_check_timeout</literal>: maximum number of seconds to wait for the
|
|
||||||
demotion candidate (current primary) to shut down, before aborting the switchover.
|
|
||||||
</simpara>
|
|
||||||
<simpara>
|
|
||||||
Note that this parameter is set on the node where <command>repmgr standby switchover</command>
|
|
||||||
is executed (promotion candidate); setting it on the demotion candidate (former primary) will
|
|
||||||
have no effect.
|
|
||||||
</simpara>
|
|
||||||
<note>
|
|
||||||
<para>
|
|
||||||
In versions prior to <link linkend="release-4.2">&repmgr; 4.2</link>, <command>repmgr standby switchover</command> would
|
|
||||||
use the values defined in <literal>reconnect_attempts</literal> and <literal>reconnect_interval</literal>
|
|
||||||
to determine the timeout for demotion candidate shutdown.
|
|
||||||
</para>
|
|
||||||
</note>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<literal>standby_reconnect_timeout</literal>:
|
|
||||||
maximum number of seconds to attempt to wait for the demotion candidate (former primary)
|
|
||||||
to reconnect to the promoted primary (default: 60 seconds)
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
<title>Execution</title>
|
<title>Execution</title>
|
||||||
|
|
||||||
@@ -213,12 +122,10 @@
|
|||||||
Execute with the <literal>--dry-run</literal> option to test the switchover as far as
|
Execute with the <literal>--dry-run</literal> option to test the switchover as far as
|
||||||
possible without actually changing the status of either node.
|
possible without actually changing the status of either node.
|
||||||
</para>
|
</para>
|
||||||
<important>
|
<para>
|
||||||
<para>
|
<application>repmgrd</application> should not be active on any nodes while a switchover is being
|
||||||
<application>repmgrd</application> must be shut down on all nodes while a switchover is being
|
executed. This restriction may be lifted in a later version.
|
||||||
executed. This restriction will be removed in a future &repmgr; version.
|
</para>
|
||||||
</para>
|
|
||||||
</important>
|
|
||||||
<para>
|
<para>
|
||||||
External database connections, e.g. from an application, should not be permitted while
|
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
|
the switchover is taking place. In particular, active transactions on the primary
|
||||||
@@ -226,7 +133,7 @@
|
|||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1 id="repmgr-standby-switchover-events">
|
<refsect1>
|
||||||
<title>Event notifications</title>
|
<title>Event notifications</title>
|
||||||
<para>
|
<para>
|
||||||
<literal>standby_switchover</literal> and <literal>standby_promote</literal>
|
<literal>standby_switchover</literal> and <literal>standby_promote</literal>
|
||||||
@@ -243,7 +150,7 @@
|
|||||||
<refsect1>
|
<refsect1>
|
||||||
<title>Exit codes</title>
|
<title>Exit codes</title>
|
||||||
<para>
|
<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>
|
</para>
|
||||||
<variablelist>
|
<variablelist>
|
||||||
|
|
||||||
@@ -271,7 +178,7 @@
|
|||||||
<para>
|
<para>
|
||||||
The switchover was executed but a problem was encountered.
|
The switchover was executed but a problem was encountered.
|
||||||
Typically this means the former primary could not be reattached
|
Typically this means the former primary could not be reattached
|
||||||
as a standby. Check preceding log messages for more information.
|
as a standby.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|||||||
@@ -59,7 +59,7 @@
|
|||||||
</variablelist>
|
</variablelist>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1 id="repmgr-standby-unregister-events">
|
<refsect1>
|
||||||
<title>Event notifications</title>
|
<title>Event notifications</title>
|
||||||
<para>
|
<para>
|
||||||
A <literal>standby_unregister</literal> <link linkend="event-notifications">event notification</link> will be generated.
|
A <literal>standby_unregister</literal> <link linkend="event-notifications">event notification</link> will be generated.
|
||||||
|
|||||||
@@ -50,7 +50,7 @@
|
|||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
|
||||||
<refsect1 id="repmgr-witness-register-events">
|
<refsect1>
|
||||||
<title>Event notifications</title>
|
<title>Event notifications</title>
|
||||||
<para>
|
<para>
|
||||||
A <literal>witness_register</literal> <link linkend="event-notifications">event notification</link> will be generated.
|
A <literal>witness_register</literal> <link linkend="event-notifications">event notification</link> will be generated.
|
||||||
|
|||||||
@@ -20,10 +20,7 @@
|
|||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
The node does not have to be running to be unregistered, however if this is the
|
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
|
case then connection information for the primary server must be provided.
|
||||||
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.
|
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Execute with the <literal>--dry-run</literal> option to check what would happen
|
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: connecting to witness node "node3" (ID: 3)
|
||||||
INFO: unregistering witness node 3
|
INFO: unregistering witness node 3
|
||||||
INFO: witness unregistration complete
|
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>
|
||||||
<para>
|
<para>
|
||||||
Unregistering a non-running witness node:
|
Unregistering a non-running witness node:
|
||||||
<programlisting>
|
<programlisting>
|
||||||
$ repmgr -f /etc/repmgr.conf witness unregister -h node1 -p 5501 -F
|
$ repmgr -f /etc/repmgr.conf witness unregister -h node1 -p 5501 -F
|
||||||
INFO: connecting to node "node3" (ID: 3)
|
INFO: connecting to witness node "node3" (ID: 3)
|
||||||
NOTICE: unable to connect to node "node3" (ID: 3), removing node record on cluster primary only
|
NOTICE: unable to connect to witness node "node3" (ID: 3), removing node record on cluster primary only
|
||||||
INFO: unregistering witness node 3
|
INFO: unregistering witness node 3
|
||||||
INFO: witness unregistration complete
|
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>
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
@@ -65,34 +62,8 @@
|
|||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
|
||||||
<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>
|
<title>Event notifications</title>
|
||||||
<para>
|
<para>
|
||||||
A <literal>witness_unregister</literal> <link linkend="event-notifications">event notification</link> will be generated.
|
A <literal>witness_unregister</literal> <link linkend="event-notifications">event notification</link> will be generated.
|
||||||
|
|||||||
@@ -86,7 +86,6 @@
|
|||||||
&repmgrd-cascading-replication;
|
&repmgrd-cascading-replication;
|
||||||
&repmgrd-network-split;
|
&repmgrd-network-split;
|
||||||
&repmgrd-witness-server;
|
&repmgrd-witness-server;
|
||||||
&repmgrd-pausing;
|
|
||||||
&repmgrd-degraded-monitoring;
|
&repmgrd-degraded-monitoring;
|
||||||
&repmgrd-monitoring;
|
&repmgrd-monitoring;
|
||||||
&repmgrd-bdr;
|
&repmgrd-bdr;
|
||||||
@@ -113,9 +112,6 @@
|
|||||||
&repmgr-cluster-crosscheck;
|
&repmgr-cluster-crosscheck;
|
||||||
&repmgr-cluster-event;
|
&repmgr-cluster-event;
|
||||||
&repmgr-cluster-cleanup;
|
&repmgr-cluster-cleanup;
|
||||||
&repmgr-daemon-status;
|
|
||||||
&repmgr-daemon-pause;
|
|
||||||
&repmgr-daemon-unpause;
|
|
||||||
</part>
|
</part>
|
||||||
|
|
||||||
&appendix-release-notes;
|
&appendix-release-notes;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
</para>
|
</para>
|
||||||
<note>
|
<note>
|
||||||
<simpara>
|
<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
|
a two-node scenario. Introducing additional nodes will create an inherent
|
||||||
risk of node desynchronisation if a node goes down without being cleanly
|
risk of node desynchronisation if a node goes down without being cleanly
|
||||||
removed from the cluster.
|
removed from the cluster.
|
||||||
@@ -99,16 +99,15 @@
|
|||||||
replication cluster. The database must be the BDR-enabled database.
|
replication cluster. The database must be the BDR-enabled database.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
If defined, the <varname>event_notifications</varname> parameter will restrict
|
If defined, the evenr <application>event_notifications</application> parameter
|
||||||
execution of the script defined in <varname>event_notification_command</varname>
|
will restrict execution of <varname>event_notification_command</varname>
|
||||||
to the specified event(s).
|
to the specified event(s).
|
||||||
</para>
|
</para>
|
||||||
<note>
|
<note>
|
||||||
<simpara>
|
<simpara>
|
||||||
<varname>event_notification_command</varname> is the script which does the actual "heavy lifting"
|
<varname>event_notification_command</varname> is the script which does the actual "heavy lifting"
|
||||||
of reconfiguring the proxy server/ connection pooler. It is fully
|
of reconfiguring the proxy server/ connection pooler. It is fully
|
||||||
user-definable; see section <xref linkend="bdr-event-notification-command"> for a reference
|
user-definable; a reference implementation is documented below.
|
||||||
implementation.
|
|
||||||
</simpara>
|
</simpara>
|
||||||
</note>
|
</note>
|
||||||
|
|
||||||
@@ -170,8 +169,8 @@
|
|||||||
</para>
|
</para>
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|
||||||
<sect1 id="bdr-event-notification-command" xreflabel="Defining the BDR failover "event_notification command"">
|
<sect1 id="bdr-event-notification-command" xreflabel="BDR failover event notification command">
|
||||||
<title>Defining the BDR failover "event_notification_command"</title>
|
<title>Defining the "event_notification_command"</title>
|
||||||
<para>
|
<para>
|
||||||
Key to "failover" execution is the <literal>event_notification_command</literal>,
|
Key to "failover" execution is the <literal>event_notification_command</literal>,
|
||||||
which is a user-definable script specified in <filename>repmpgr.conf</filename>
|
which is a user-definable script specified in <filename>repmpgr.conf</filename>
|
||||||
|
|||||||
@@ -1,499 +1,60 @@
|
|||||||
<chapter id="repmgrd-configuration">
|
<chapter id="repmgrd-configuration">
|
||||||
|
|
||||||
<indexterm>
|
<indexterm>
|
||||||
<primary>repmgrd</primary>
|
<primary>repmgrd</primary>
|
||||||
<secondary>configuration</secondary>
|
<secondary>configuration</secondary>
|
||||||
</indexterm>
|
</indexterm>
|
||||||
|
|
||||||
<title>repmgrd configuration</title>
|
<title>repmgrd configuration</title>
|
||||||
|
<para>
|
||||||
|
To use <application>repmgrd</application>, its associated function library must be
|
||||||
|
included in <filename>postgresql.conf</filename> with:
|
||||||
|
|
||||||
<para>
|
<programlisting>
|
||||||
<application>repmgrd</application> is a daemon which runs on each PostgreSQL node,
|
shared_preload_libraries = 'repmgr'</programlisting>
|
||||||
monitoring the local node, and (unless it's the primary node) the upstream server
|
</para>
|
||||||
(the primary server or with cascading replication, another standby) which it's
|
<para>
|
||||||
connected to.
|
Changing this setting requires a restart of PostgreSQL; for more details see
|
||||||
</para>
|
the <ulink url="https://www.postgresql.org/docs/current/static/runtime-config-client.html#GUC-SHARED-PRELOAD-LIBRARIES">PostgreSQL documentation</ulink>.
|
||||||
<para>
|
</para>
|
||||||
<application>repmgrd</application> can be configured to provide failover
|
<para>
|
||||||
capability in case the primary upstream node becomes unreachable, and/or
|
Additionally the following <application>repmgrd</application> options *must* be set in
|
||||||
provide monitoring data to the &repmgr; metadatabase.
|
<filename>repmgr.conf</filename> (adjust configuration file locations as appropriate):
|
||||||
</para>
|
<programlisting>
|
||||||
|
failover=automatic
|
||||||
<sect1 id="repmgrd-basic-configuration">
|
promote_command='repmgr standby promote -f /etc/repmgr.conf --log-to-file'
|
||||||
<title>repmgrd basic configuration</title>
|
follow_command='repmgr standby follow -f /etc/repmgr.conf --log-to-file --upstream-node-id=%n'</programlisting>
|
||||||
|
</para>
|
||||||
<para>
|
<para>
|
||||||
To use <application>repmgrd</application>, its associated function library <emphasis>must</emphasis> be
|
Note that the <literal>--log-to-file</literal> option will cause
|
||||||
included via <filename>postgresql.conf</filename> with:
|
output generated by the &repmgr; command, when executed by <application>repmgrd</application>,
|
||||||
|
to be logged to the same destination configured to receive log output for <application>repmgrd</application>.
|
||||||
<programlisting>
|
See <filename>repmgr.conf.sample</filename> for further <application>repmgrd</application>-specific settings.
|
||||||
shared_preload_libraries = 'repmgr'</programlisting>
|
</para>
|
||||||
</para>
|
<para>
|
||||||
<para>
|
When <varname>failover</varname> is set to <literal>automatic</literal>, upon detecting failure
|
||||||
Changing this setting requires a restart of PostgreSQL; for more details see
|
of the current primary, <application>repmgrd</application> will execute one of
|
||||||
the <ulink url="https://www.postgresql.org/docs/current/static/runtime-config-client.html#GUC-SHARED-PRELOAD-LIBRARIES">PostgreSQL documentation</ulink>.
|
<varname>promote_command</varname> or <varname>follow_command</varname>,
|
||||||
</para>
|
depending on whether the current server is to become the new primary, or
|
||||||
|
needs to follow another server which has become the new primary. Note that
|
||||||
|
these commands can be any valid shell script which results in one of these
|
||||||
<sect2 id="repmgrd-automatic-failover-configuration">
|
two actions happening, but if &repmgr;'s <command>standby follow</command> or
|
||||||
<title>automatic failover configuration</title>
|
<command>standby promote</command>
|
||||||
<para>
|
commands are not executed (either directly as shown here, or from a script which
|
||||||
If using automatic failover, the following <application>repmgrd</application> options *must* be set in
|
performs other actions), the &repmgr; metadata will not be updated and
|
||||||
<filename>repmgr.conf</filename> :
|
&repmgr; will no longer function reliably.
|
||||||
<programlisting>
|
</para>
|
||||||
failover=automatic
|
<para>
|
||||||
promote_command='/usr/bin/repmgr standby promote -f /etc/repmgr.conf --log-to-file'
|
The <varname>follow_command</varname> should provide the <literal>--upstream-node-id=%n</literal>
|
||||||
follow_command='/usr/bin/repmgr standby follow -f /etc/repmgr.conf --log-to-file --upstream-node-id=%n'</programlisting>
|
option to <command>repmgr standby follow</command>; the <literal>%n</literal> will be replaced by
|
||||||
</para>
|
<application>repmgrd</application> with the ID of the new primary node. If this is not provided, &repmgr;
|
||||||
<para>
|
will attempt to determine the new primary by itself, but if the
|
||||||
Adjust file paths as appropriate; alway specify the full path to the &repmgr; binary.
|
original primary comes back online after the new primary is promoted, there is a risk that
|
||||||
</para>
|
<command>repmgr standby follow</command> will result in the node continuing to follow
|
||||||
|
the original primary.
|
||||||
<note>
|
</para>
|
||||||
<para>
|
<sect1 id="repmgrd-connection-settings">
|
||||||
&repmgr; will not apply <option>pg_bindir</option> when executing <option>promote_command</option>
|
<title>repmgrd connection settings</title>
|
||||||
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>,
|
|
||||||
to be logged to the same destination configured to receive log output for <application>repmgrd</application>.
|
|
||||||
See <filename><ulink url="https://raw.githubusercontent.com/2ndQuadrant/repmgr/master/repmgr.conf.sample">repmgr.conf.sample</ulink></filename>
|
|
||||||
for further <application>repmgrd</application>-specific settings.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
When <varname>failover</varname> is set to <literal>automatic</literal>, upon detecting failure
|
|
||||||
of the current primary, <application>repmgrd</application> will execute one of:
|
|
||||||
</para>
|
|
||||||
<itemizedlist spacing="compact" mark="bullet">
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<varname>promote_command</varname> (if the current server is to become the new primary)
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<varname>follow_command</varname> (if the current server needs to follow another server which has
|
|
||||||
become the new primary)
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
<note>
|
|
||||||
<para>
|
|
||||||
These commands can be any valid shell script which results in one of these
|
|
||||||
two actions happening, but if &repmgr;'s <command>standby follow</command> or
|
|
||||||
<command>standby promote</command>
|
|
||||||
commands are not executed (either directly as shown here, or from a script which
|
|
||||||
performs other actions), the &repmgr; metadata will not be updated and
|
|
||||||
&repmgr; will no longer function reliably.
|
|
||||||
</para>
|
|
||||||
</note>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
The <varname>follow_command</varname> should provide the <literal>--upstream-node-id=%n</literal>
|
|
||||||
option to <command>repmgr standby follow</command>; the <literal>%n</literal> will be replaced by
|
|
||||||
<application>repmgrd</application> with the ID of the new primary node. If this is not provided, &repmgr;
|
|
||||||
will attempt to determine the new primary by itself, but if the
|
|
||||||
original primary comes back online after the new primary is promoted, there is a risk that
|
|
||||||
<command>repmgr standby follow</command> will result in the node continuing to follow
|
|
||||||
the original primary.
|
|
||||||
</para>
|
|
||||||
</sect2>
|
|
||||||
|
|
||||||
<sect2 id="repmgrd-service-configuration">
|
|
||||||
<indexterm>
|
|
||||||
<primary>repmgrd</primary>
|
|
||||||
<secondary>PostgreSQL service configuration</secondary>
|
|
||||||
</indexterm>
|
|
||||||
<title>PostgreSQL service configuration</title>
|
|
||||||
<para>
|
|
||||||
If using automatic failover, currently <application>repmgrd</application> will need to execute
|
|
||||||
<link linkend="repmgr-standby-follow"><command>repmgr standby follow</command></link>
|
|
||||||
to restart PostgreSQL on standbys to have them follow a new primary.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
To ensure this happens smoothly, it's essential to provide the appropriate system/service restart
|
|
||||||
command appropriate to your operating system via <varname>service_restart_command</varname>
|
|
||||||
in <filename>repmgr.conf</filename>. If you don't do this, <application>repmgrd</application>
|
|
||||||
will default to using <command>pg_ctl</command>, which can result in unexpected problems,
|
|
||||||
particularly on <application>systemd</application>-based systems.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
For more details, see <xref linkend="configuration-file-service-commands">.
|
|
||||||
</para>
|
|
||||||
</sect2>
|
|
||||||
|
|
||||||
<sect2 id="repmgrd-monitoring-configuration" xreflabel="repmgrd monitoring configuration">
|
|
||||||
<indexterm>
|
|
||||||
<primary>repmgrd</primary>
|
|
||||||
<secondary>monitoring configuration</secondary>
|
|
||||||
</indexterm>
|
|
||||||
<title>Monitoring configuration</title>
|
|
||||||
<para>
|
|
||||||
To enable monitoring, set:
|
|
||||||
<programlisting>
|
|
||||||
monitoring_history=yes</programlisting>
|
|
||||||
in <filename>repmgr.conf</filename>.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The default monitoring interval is 2 seconds; this value can be explicitly set using:
|
|
||||||
<programlisting>
|
|
||||||
monitor_interval_secs=<seconds></programlisting>
|
|
||||||
in <filename>repmgr.conf</filename>.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
For more details on monitoring, see <xref linkend="repmgrd-monitoring">.
|
|
||||||
</para>
|
|
||||||
</sect2>
|
|
||||||
|
|
||||||
<sect2 id="repmgrd-reloading-configuration"xreflabel="reloading repmgrd configuration">
|
|
||||||
<indexterm>
|
|
||||||
<primary>repmgrd</primary>
|
|
||||||
<secondary>applying configuration changes</secondary>
|
|
||||||
</indexterm>
|
|
||||||
<title>Applying configuration changes to repmgrd</title>
|
|
||||||
<para>
|
|
||||||
To apply configuration file changes to a running <application>repmgrd</application>
|
|
||||||
daemon, execute the operating system's <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>
|
|
||||||
<tip>
|
|
||||||
<para>
|
|
||||||
Check the <application>repmgrd</application> log to see what changes were
|
|
||||||
applied, or if any issues were encountered when reloading the configuration.
|
|
||||||
</para>
|
|
||||||
</tip>
|
|
||||||
<para>
|
|
||||||
Note that only the following subset of configuration file parameters can be changed on a
|
|
||||||
running <application>repmgrd</application> daemon:
|
|
||||||
</para>
|
|
||||||
<itemizedlist spacing="compact" mark="bullet">
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<varname>async_query_timeout</varname>
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<varname>bdr_local_monitoring_only</varname>
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<varname>bdr_recovery_timeout</varname>
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<varname>conninfo</varname>
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<varname>degraded_monitoring_timeout</varname>
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<varname>event_notification_command</varname>
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<varname>event_notifications</varname>
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<varname>failover</varname>
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<varname>follow_command</varname>
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<varname>log_facility</varname>
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<varname>log_file</varname>
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<varname>log_level</varname>
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<varname>log_status_interval</varname>
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<varname>monitor_interval_secs</varname>
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<varname>monitoring_history</varname>
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<varname>primary_notification_timeout</varname>
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<varname>promote_command</varname>
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<varname>reconnect_attempts</varname>
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<varname>reconnect_interval</varname>
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<varname>repmgrd_standby_startup_timeout</varname>
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
</itemizedlist>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
The following set of configuration file parameters must be updated via
|
|
||||||
<command><link linkend="repmgr-standby-register">repmgr standby register --force</link></command>,
|
|
||||||
as they require changes to the <literal>repmgr.nodes</literal> table so they are visible to
|
|
||||||
all nodes in the replication cluster:
|
|
||||||
</para>
|
|
||||||
<itemizedlist spacing="compact" mark="bullet">
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<varname>node_id</varname>
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<varname>node_name</varname>
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<varname>data_directory</varname>
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<varname>location</varname>
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<varname>priority</varname>
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
</itemizedlist>
|
|
||||||
|
|
||||||
<note>
|
|
||||||
<para>
|
|
||||||
After executing <command><link linkend="repmgr-standby-register">repmgr standby register --force</link></command>,
|
|
||||||
<application>repmgrd</application> <emphasis>must</emphasis> be restarted for the changes to take effect.
|
|
||||||
</para>
|
|
||||||
</note>
|
|
||||||
|
|
||||||
</sect2>
|
|
||||||
|
|
||||||
</sect1>
|
|
||||||
|
|
||||||
<sect1 id="repmgrd-daemon">
|
|
||||||
<indexterm>
|
|
||||||
<primary>repmgrd</primary>
|
|
||||||
<secondary>starting and stopping</secondary>
|
|
||||||
</indexterm>
|
|
||||||
<title>repmgrd daemon</title>
|
|
||||||
<para>
|
|
||||||
If installed from a package, the <application>repmgrd</application> can be started
|
|
||||||
via the operating system's service command, e.g. in <application>systemd</application>
|
|
||||||
using <command>systemctl</command>.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
See appendix <xref linkend="appendix-packages"> for details of service commands
|
|
||||||
for different distributions.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<application>repmgrd</application> can be started manually like this:
|
|
||||||
<programlisting>
|
|
||||||
repmgrd -f /etc/repmgr.conf --pid-file /tmp/repmgrd.pid</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>
|
|
||||||
|
|
||||||
<sect2 id="repmgrd-configuration-debian-ubuntu">
|
|
||||||
<indexterm>
|
|
||||||
<primary>repmgrd</primary>
|
|
||||||
<secondary>Debian/Ubuntu and daemon configuration</secondary>
|
|
||||||
</indexterm>
|
|
||||||
<indexterm>
|
|
||||||
<primary>Debian/Ubuntu</primary>
|
|
||||||
<secondary>repmgrd daemon configuration</secondary>
|
|
||||||
</indexterm>
|
|
||||||
|
|
||||||
<title>repmgrd daemon configuration on Debian/Ubuntu</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
If &repmgr; was installed from Debian/Ubuntu packages, additional configuration
|
|
||||||
is required before <application>repmgrd</application> is started as a daemon.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
This is done via the file <filename>/etc/default/repmgrd</filename>, which by default
|
|
||||||
looks like this:
|
|
||||||
<programlisting>
|
|
||||||
# default settings for repmgrd. This file is source by /bin/sh from
|
|
||||||
# /etc/init.d/repmgrd
|
|
||||||
|
|
||||||
# disable repmgrd by default so it won't get started upon installation
|
|
||||||
# valid values: yes/no
|
|
||||||
REPMGRD_ENABLED=no
|
|
||||||
|
|
||||||
# configuration file (required)
|
|
||||||
#REPMGRD_CONF="/path/to/repmgr.conf"
|
|
||||||
|
|
||||||
# additional options
|
|
||||||
REPMGRD_OPTS="--daemonize=false"
|
|
||||||
|
|
||||||
# user to run repmgrd as
|
|
||||||
#REPMGRD_USER=postgres
|
|
||||||
|
|
||||||
# repmgrd binary
|
|
||||||
#REPMGRD_BIN=/usr/bin/repmgrd
|
|
||||||
|
|
||||||
# pid file
|
|
||||||
#REPMGRD_PIDFILE=/var/run/repmgrd.pid</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Set <varname>REPMGRD_ENABLED</varname> to <literal>yes</literal>, and <varname>REPMGRD_CONF</varname>
|
|
||||||
to the <filename>repmgr.conf</filename> file you are using.
|
|
||||||
</para>
|
|
||||||
<tip>
|
|
||||||
<para>
|
|
||||||
See <xref linkend="packages-debian-ubuntu"> for details of the Debian/Ubuntu packages and
|
|
||||||
typical file locations (including <filename>repmgr.conf</filename>).
|
|
||||||
</para>
|
|
||||||
</tip>
|
|
||||||
<para>
|
|
||||||
From <application>repmgrd</application> 4.1, ensure <varname>REPMGRD_OPTS</varname> includes
|
|
||||||
<option>--daemonize=false</option>, as daemonization is handled by the service command.
|
|
||||||
We recommend setting <varname>repmgrd_pid_file</varname> in <filename>repmgr.conf</filename> to the
|
|
||||||
same value set in <varname>REPMGRD_PIDFILE</varname> to prevent another <application>repmgrd</application>
|
|
||||||
instance from being started manually.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
If using <application>systemd</application>, you may need to execute <command>systemctl daemon-reload</command>.
|
|
||||||
Also, if you attempted to start <application>repmgrd</application> using <command>systemctl start repmgrd</command>,
|
|
||||||
you'll need to execute <command>systemctl stop repmgrd</command>. Because that's how <application>systemd</application>
|
|
||||||
rolls.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
</sect2>
|
|
||||||
</sect1>
|
|
||||||
|
|
||||||
<sect1 id="repmgrd-connection-settings">
|
|
||||||
<title>repmgrd connection settings</title>
|
|
||||||
<para>
|
<para>
|
||||||
In addition to the &repmgr; configuration settings, parameters in the
|
In addition to the &repmgr; configuration settings, parameters in the
|
||||||
<varname>conninfo</varname> string influence how &repmgr; makes a network connection to
|
<varname>conninfo</varname> string influence how &repmgr; makes a network connection to
|
||||||
@@ -515,43 +76,25 @@ REPMGRD_OPTS="--daemonize=false"
|
|||||||
<ulink url="https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-PARAMKEYWORDS">PostgreSQL documentation</ulink>.
|
<ulink url="https://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-PARAMKEYWORDS">PostgreSQL documentation</ulink>.
|
||||||
</para>
|
</para>
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<sect1 id="repmgrd-log-rotation">
|
<sect1 id="repmgrd-log-rotation">
|
||||||
<indexterm>
|
|
||||||
<primary>log rotation</primary>
|
|
||||||
<secondary>repmgrd</secondary>
|
|
||||||
</indexterm>
|
|
||||||
|
|
||||||
<indexterm>
|
|
||||||
<primary>repmgrd</primary>
|
|
||||||
<secondary>log rotation</secondary>
|
|
||||||
</indexterm>
|
|
||||||
|
|
||||||
<title>repmgrd log rotation</title>
|
<title>repmgrd log rotation</title>
|
||||||
<para>
|
<para>
|
||||||
To ensure the current <application>repmgrd</application> logfile
|
To ensure the current <application>repmgrd</application> logfile does not grow
|
||||||
(specified in <filename>repmgr.conf</filename> with the parameter
|
indefinitely, configure your system's <command>logrotate</command> to
|
||||||
<option>log_file</option>) does not grow indefinitely, configure your
|
regularly rotate it.
|
||||||
system's <command>logrotate</command> to regularly rotate it.
|
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Sample configuration to rotate logfiles weekly with retention for
|
Sample configuration to rotate logfiles weekly with retention for
|
||||||
up to 52 weeks and rotation forced if a file grows beyond 100Mb:
|
up to 52 weeks and rotation forced if a file grows beyond 100Mb:
|
||||||
<programlisting>
|
<programlisting>
|
||||||
/var/log/repmgr/repmgrd.log {
|
/var/log/postgresql/repmgr-9.6.log {
|
||||||
missingok
|
missingok
|
||||||
compress
|
compress
|
||||||
rotate 52
|
rotate 52
|
||||||
maxsize 100M
|
maxsize 100M
|
||||||
weekly
|
weekly
|
||||||
create 0600 postgres postgres
|
create 0600 postgres postgres
|
||||||
postrotate
|
|
||||||
/usr/bin/killall -HUP repmgrd
|
|
||||||
endscript
|
|
||||||
}</programlisting>
|
}</programlisting>
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
</sect1>
|
</sect1>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<chapter id="repmgrd-degraded-monitoring" xreflabel="repmgrd degraded monitoring">
|
<chapter id="repmgrd-degraded-monitoring">
|
||||||
<indexterm>
|
<indexterm>
|
||||||
<primary>repmgrd</primary>
|
<primary>repmgrd</primary>
|
||||||
<secondary>degraded monitoring</secondary>
|
<secondary>degraded monitoring</secondary>
|
||||||
@@ -7,8 +7,8 @@
|
|||||||
<title>"degraded monitoring" mode</title>
|
<title>"degraded monitoring" mode</title>
|
||||||
<para>
|
<para>
|
||||||
In certain circumstances, <application>repmgrd</application> is not able to fulfill its primary mission
|
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"
|
of monitoring the nodes' upstream server. In these cases it enters "degraded
|
||||||
mode, where <application>repmgrd</application> remains active but is waiting for the situation
|
monitoring" mode, where <application>repmgrd</application> remains active but is waiting for the situation
|
||||||
to be resolved.
|
to be resolved.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
|
|||||||
@@ -1,12 +1,8 @@
|
|||||||
<chapter id="repmgrd-monitoring" xreflabel="Monitoring with repmgrd">
|
<chapter id="repmgrd-monitoring">
|
||||||
<indexterm>
|
<indexterm>
|
||||||
<primary>repmgrd</primary>
|
<primary>repmgrd</primary>
|
||||||
<secondary>monitoring</secondary>
|
<secondary>monitoring</secondary>
|
||||||
</indexterm>
|
</indexterm>
|
||||||
<indexterm>
|
|
||||||
<primary>monitoring</primary>
|
|
||||||
<secondary>with repmgrd</secondary>
|
|
||||||
</indexterm>
|
|
||||||
|
|
||||||
<title>Monitoring with repmgrd</title>
|
<title>Monitoring with repmgrd</title>
|
||||||
<para>
|
<para>
|
||||||
|
|||||||
@@ -40,8 +40,8 @@
|
|||||||
In a failover situation, <application>repmgrd</application> will check if any servers in the
|
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>
|
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
|
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>
|
other location (it will however enter <xref linkend="repmgrd-degraded-monitoring"> mode until
|
||||||
mode until a primary becomes visible).
|
a primary becomes visible).
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|||||||
@@ -1,169 +0,0 @@
|
|||||||
<chapter id="repmgrd-pausing" xreflabel="Pausing repmgrd">
|
|
||||||
|
|
||||||
<indexterm>
|
|
||||||
<primary>repmgrd</primary>
|
|
||||||
<secondary>pausing</secondary>
|
|
||||||
</indexterm>
|
|
||||||
|
|
||||||
<indexterm>
|
|
||||||
<primary>pausing repmgrd</primary>
|
|
||||||
</indexterm>
|
|
||||||
|
|
||||||
<title>Pausing repmgrd</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
In normal operation, <application>repmgrd</application> monitors the state of the
|
|
||||||
PostgreSQL node it is running on, and will take appropriate action if problems
|
|
||||||
are detected, e.g. (if so configured) promote the node to primary, if the existing
|
|
||||||
primary has been determined as failed.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
However, <application>repmgrd</application> is unable to distinguish between
|
|
||||||
planned outages (such as performing a <link linkend="performing-switchover">switchover</link>
|
|
||||||
or upgrading a server), and an actual server outage. In versions prior to &repmgr; 4.2
|
|
||||||
it was necessary to stop <application>repmgrd</application> on all nodes (or at least
|
|
||||||
on all nodes where <application>repmgrd</application> is
|
|
||||||
<link linkend="repmgrd-automatic-failover">configured for automatic failover</link>)
|
|
||||||
to prevent <application>repmgrd</application> from making changes to the
|
|
||||||
replication cluster.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
From <link linkend="release-4.2">&repmgr; 4.2</link>, <application>repmgrd</application>
|
|
||||||
can now be "paused", i.e. instructed not to take any action such as performing a failover.
|
|
||||||
This can be done from any node in the cluster, removing the need to stop/restart
|
|
||||||
each <application>repmgrd</application> individually.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<sect1 id="repmgrd-pausing-prerequisites">
|
|
||||||
<title>Prerequisites for pausing <application>repmgrd</application></title>
|
|
||||||
<para>
|
|
||||||
In order to be able to pause/unpause <application>repmgrd</application>, following
|
|
||||||
prerequisites must be met:
|
|
||||||
<itemizedlist spacing="compact" mark="bullet">
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara><link linkend="release-4.2">&repmgr; 4.2</link> or later must be installed on all nodes.</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>The same major &repmgr; version (e.g. 4.2) must be installed on all nodes (and preferably the same minor version).</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
PostgreSQL on all nodes must be accessible from the node where the
|
|
||||||
<literal>pause</literal>/<literal>unpause</literal> operation is executed, using the
|
|
||||||
<varname>conninfo</varname> string shown by <link linkend="repmgr-cluster-show"><command>repmgr cluster show</command></link>.
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
<note>
|
|
||||||
<para>
|
|
||||||
These conditions are required for normal &repmgr; operation in any case.
|
|
||||||
</para>
|
|
||||||
</note>
|
|
||||||
|
|
||||||
</sect1>
|
|
||||||
|
|
||||||
<sect1 id="repmgrd-pausing-execution">
|
|
||||||
<title>Pausing/unpausing <application>repmgrd</application></title>
|
|
||||||
<para>
|
|
||||||
To pause <application>repmgrd</application>, execute <link linkend="repmgr-daemon-pause"><command>repmgr daemon pause</command></link>, e.g.:
|
|
||||||
<programlisting>
|
|
||||||
$ repmgr -f /etc/repmgr.conf daemon pause
|
|
||||||
NOTICE: node 1 (node1) paused
|
|
||||||
NOTICE: node 2 (node2) paused
|
|
||||||
NOTICE: node 3 (node3) paused</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The state of <application>repmgrd</application> on each node can be checked with
|
|
||||||
<link linkend="repmgr-daemon-status"><command>repmgr daemon status</command></link>, e.g.:
|
|
||||||
<programlisting>$ repmgr -f /etc/repmgr.conf daemon status
|
|
||||||
ID | Name | Role | Status | repmgrd | PID | Paused?
|
|
||||||
----+-------+---------+---------+---------+------+---------
|
|
||||||
1 | node1 | primary | running | running | 7851 | yes
|
|
||||||
2 | node2 | standby | running | running | 7889 | yes
|
|
||||||
3 | node3 | standby | running | running | 7918 | yes</programlisting>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<note>
|
|
||||||
<para>
|
|
||||||
If executing a switchover with <link linkend="repmgr-standby-switchover"><command>repmgr standby switchover</command></link>,
|
|
||||||
&repmgr; will automatically pause/unpause <application>repmgrd</application> as part of the switchover process.
|
|
||||||
</para>
|
|
||||||
</note>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
If the primary (in this example, <literal>node1</literal>) is stopped, <application>repmgrd</application>
|
|
||||||
running on one of the standbys (here: <literal>node2</literal>) will react like this:
|
|
||||||
<programlisting>
|
|
||||||
[2018-09-20 12:22:21] [WARNING] unable to connect to upstream node "node1" (node ID: 1)
|
|
||||||
[2018-09-20 12:22:21] [INFO] checking state of node 1, 1 of 5 attempts
|
|
||||||
[2018-09-20 12:22:21] [INFO] sleeping 1 seconds until next reconnection attempt
|
|
||||||
...
|
|
||||||
[2018-09-20 12:22:24] [INFO] sleeping 1 seconds until next reconnection attempt
|
|
||||||
[2018-09-20 12:22:25] [INFO] checking state of node 1, 5 of 5 attempts
|
|
||||||
[2018-09-20 12:22:25] [WARNING] unable to reconnect to node 1 after 5 attempts
|
|
||||||
[2018-09-20 12:22:25] [NOTICE] node is paused
|
|
||||||
[2018-09-20 12:22:33] [INFO] node "node2" (node ID: 2) monitoring upstream node "node1" (node ID: 1) in degraded state
|
|
||||||
[2018-09-20 12:22:33] [DETAIL] repmgrd paused by administrator
|
|
||||||
[2018-09-20 12:22:33] [HINT] execute "repmgr daemon unpause" to resume normal failover mode</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
If the primary becomes available again (e.g. following a software upgrade), <application>repmgrd</application>
|
|
||||||
will automatically reconnect, e.g.:
|
|
||||||
<programlisting>
|
|
||||||
[2018-09-20 13:12:41] [NOTICE] reconnected to upstream node 1 after 8 seconds, resuming monitoring</programlisting>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
To unpause <application>repmgrd</application>, execute <link linkend="repmgr-daemon-unpause"><command>repmgr daemon unpause</command></link>, e.g.:
|
|
||||||
<programlisting>
|
|
||||||
$ repmgr -f /etc/repmgr.conf daemon pause
|
|
||||||
NOTICE: node 1 (node1) unpaused
|
|
||||||
NOTICE: node 2 (node2) unpaused
|
|
||||||
NOTICE: node 3 (node3) unpaused</programlisting>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<note>
|
|
||||||
<para>
|
|
||||||
If the previous primary is no longer accessible when <application>repmgrd</application>
|
|
||||||
is unpaused, no failover action will be taken. Instead, a new primary must be manually promoted using
|
|
||||||
<link linkend="repmgr-standby-promote"><command>repmgr standby promote</command></link>,
|
|
||||||
and any standbys attached to the new primary with
|
|
||||||
<link linkend="repmgr-standby-follow"><command>repmgr standby follow</command></link>.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
This is to prevent <link linkend="repmgr-daemon-unpause"><command>repmgr daemon unpause</command></link>
|
|
||||||
resulting in the automatic promotion of a new primary, which may be a problem particularly
|
|
||||||
in larger clusters, where <application>repmgrd</application> could select a different promotion
|
|
||||||
candidate to the one intended by the administrator.
|
|
||||||
</para>
|
|
||||||
</note>
|
|
||||||
|
|
||||||
<sect2 id="repmgrd-pausing-details">
|
|
||||||
<title>Details on the <application>repmgrd</application> pausing mechanism</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
The pause state of each node will be stored over a PostgreSQL restart.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
<link linkend="repmgr-daemon-pause"><command>repmgr daemon pause</command></link> and
|
|
||||||
<link linkend="repmgr-daemon-unpause"><command>repmgr daemon unpause</command></link> can be
|
|
||||||
executed even if <application>repmgrd</application> is not running; in this case,
|
|
||||||
<application>repmgrd</application> will start up in whichever pause state has been set.
|
|
||||||
</para>
|
|
||||||
<note>
|
|
||||||
<para>
|
|
||||||
<link linkend="repmgr-daemon-pause"><command>repmgr daemon pause</command></link> and
|
|
||||||
<link linkend="repmgr-daemon-unpause"><command>repmgr daemon unpause</command></link>
|
|
||||||
<emphasis>do not</emphasis> stop/start <application>repmgrd</application>.
|
|
||||||
</para>
|
|
||||||
</note>
|
|
||||||
</sect2>
|
|
||||||
</sect1>
|
|
||||||
</chapter>
|
|
||||||
|
|
||||||
@@ -19,10 +19,9 @@
|
|||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
<command>repmgr standby switchover</command> differs from other &repmgr;
|
<command>repmgr standby switchover</command> differs from other &repmgr;
|
||||||
actions in that it also performs actions on other servers (the demotion
|
actions in that it also performs actions on another server (the demotion
|
||||||
candidate, and optionally any other servers which are to follow the new primary),
|
candidate), which means passwordless SSH access is required to that server
|
||||||
which means passwordless SSH access is required to those servers from the one where
|
from the one where <command>repmgr standby switchover</command> is executed.
|
||||||
<command>repmgr standby switchover</command> is executed.
|
|
||||||
</para>
|
</para>
|
||||||
<note>
|
<note>
|
||||||
<simpara>
|
<simpara>
|
||||||
@@ -58,14 +57,7 @@
|
|||||||
|
|
||||||
<para>
|
<para>
|
||||||
As mentioned in the previous section, success of the switchover operation depends on
|
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.
|
&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>).
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@@ -75,21 +67,13 @@
|
|||||||
promotion candidate to all standbys attached to the demotion candidate.
|
promotion candidate to all standbys attached to the demotion candidate.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<note>
|
|
||||||
<simpara>
|
|
||||||
&repmgr; expects to find the &repmgr; binary in the same path on the remote
|
|
||||||
server as on the local server.
|
|
||||||
</simpara>
|
|
||||||
</note>
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Double-check which commands will be used to stop/start/restart the current
|
Double-check which commands will be used to stop/start/restart the current
|
||||||
primary; on the current primary execute:
|
primary; on the primary execute:
|
||||||
<programlisting>
|
<programlisting>
|
||||||
repmgr -f /etc/repmgr.conf node service --list --action=stop
|
repmgr -f /etc/repmgr.conf node service --list --action=stop
|
||||||
repmgr -f /etc/repmgr.conf node service --list --action=start
|
repmgr -f /etc/repmgr.conf node service --list --action=start
|
||||||
repmgr -f /etc/repmgr.conf node service --list --action=restart</programlisting>
|
repmgr -f /etc/repmgr.conf node service --list --action=restart</programlisting>
|
||||||
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@@ -108,11 +92,7 @@
|
|||||||
<para>
|
<para>
|
||||||
If the <option>service_*_command</option> options aren't defined, &repmgr; will
|
If the <option>service_*_command</option> options aren't defined, &repmgr; will
|
||||||
fall back to using <application>pg_ctl</application> to stop/start/restart
|
fall back to using <application>pg_ctl</application> to stop/start/restart
|
||||||
PostgreSQL, which may not work properly, particularly when executed on a remote
|
PostgreSQL, which may not work properly.
|
||||||
server.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
For more details, see <xref linkend="configuration-file-service-commands">.
|
|
||||||
</para>
|
</para>
|
||||||
</important>
|
</important>
|
||||||
|
|
||||||
@@ -130,20 +110,13 @@
|
|||||||
</note>
|
</note>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Check that access from applications is minimalized or preferably blocked
|
Check that access from applications is minimalized or preferably blocked
|
||||||
completely, so applications are not unexpectedly interrupted.
|
completely, so applications are not unexpectedly interrupted.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<note>
|
|
||||||
<para>
|
|
||||||
If an exclusive backup is running on the current primary, &repmgr; will not perform the
|
|
||||||
switchover.
|
|
||||||
</para>
|
|
||||||
</note>
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Check there is no significant replication lag on standbys attached to the
|
Check there is no significant replication lag on standbys attached to the
|
||||||
current primary.
|
current primary.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@@ -154,19 +127,10 @@
|
|||||||
manually with <command>repmgr node check --archive-ready</command>.
|
manually with <command>repmgr node check --archive-ready</command>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<note>
|
<para>
|
||||||
<para>
|
Ensure that <application>repmgrd</application> is *not* running anywhere to prevent it unintentionally
|
||||||
From <link linkend="release-4.2">repmgr 4.2</link>, &repmgr; will instruct any running
|
promoting a node.
|
||||||
<application>repmgrd</application> instances to pause operations while the switchover
|
</para>
|
||||||
is being carried out, to prevent <application>repmgrd</application> from
|
|
||||||
unintentionally promoting a node. For more details, see <xref linkend="repmgrd-pausing">.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Users of &repmgr; versions prior to 4.2 should ensure that <application>repmgrd</application>
|
|
||||||
is not running on any nodes while a switchover is being executed.
|
|
||||||
</para>
|
|
||||||
</note>
|
|
||||||
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Finally, consider executing <command>repmgr standby switchover</command> with the
|
Finally, consider executing <command>repmgr standby switchover</command> with the
|
||||||
@@ -199,60 +163,34 @@
|
|||||||
</para>
|
</para>
|
||||||
</important>
|
</important>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Note that following parameters in <filename>repmgr.conf</filename> are relevant to the
|
||||||
|
switchover operation:
|
||||||
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<literal>reconnect_attempts</literal>: number of times to check the original primary
|
||||||
|
for a clean shutdown after executing the shutdown command, before aborting
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<literal>reconnect_interval</literal>: interval (in seconds) to check the original
|
||||||
|
primary for a clean shutdown after executing the shutdown command (up to a maximum
|
||||||
|
of <literal>reconnect_attempts</literal> tries)
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<literal>replication_lag_critical</literal>:
|
||||||
|
if replication lag (in seconds) on the standby exceeds this value, the
|
||||||
|
switchover will be aborted (unless the <literal>-F/--force</literal> option
|
||||||
|
is provided)
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
<note>
|
</itemizedlist>
|
||||||
<simpara>
|
</para>
|
||||||
See <xref linkend="repmgr-standby-switchover"> for a full list of available
|
|
||||||
command line options and <filename>repmgr.conf</filename> settings relevant
|
|
||||||
to performing a switchover.
|
|
||||||
</simpara>
|
|
||||||
</note>
|
|
||||||
|
|
||||||
<sect2 id="switchover-pg-rewind" xreflabel="Switchover and pg_rewind">
|
|
||||||
<indexterm>
|
|
||||||
<primary>pg_rewind</primary>
|
|
||||||
<secondary>using with "repmgr standby switchover"</secondary>
|
|
||||||
</indexterm>
|
|
||||||
<title>Switchover and pg_rewind</title>
|
|
||||||
<para>
|
|
||||||
If the demotion candidate does not shut down smoothly or cleanly, there's a risk it
|
|
||||||
will have a slightly divergent timeline and will not be able to attach to the new
|
|
||||||
primary. To fix this situation without needing to reclone the old primary, it's
|
|
||||||
possible to use the <application>pg_rewind</application> utility, which will usually be
|
|
||||||
able to resync the two servers.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
To have &repmgr; execute <application>pg_rewind</application> if it detects this
|
|
||||||
situation after promoting the new primary, add the <option>--force-rewind</option>
|
|
||||||
option.
|
|
||||||
</para>
|
|
||||||
<note>
|
|
||||||
<simpara>
|
|
||||||
If &repmgr; detects a situation where it needs to execute <application>pg_rewind</application>,
|
|
||||||
it will execute a <literal>CHECKPOINT</literal> on the new primary before executing
|
|
||||||
<application>pg_rewind</application>.
|
|
||||||
</simpara>
|
|
||||||
</note>
|
|
||||||
<para>
|
|
||||||
For more details on <application>pg_rewind</application>, see:
|
|
||||||
<ulink url="https://www.postgresql.org/docs/current/static/app-pgrewind.html">https://www.postgresql.org/docs/current/static/app-pgrewind.html</ulink>.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<application>pg_rewind</application> has been part of the core PostgreSQL distribution since
|
|
||||||
version 9.5. Users of versions 9.3 and 9.4 will need to manually install it; the source code is available here:
|
|
||||||
<ulink url="https://github.com/vmware/pg_rewind">https://github.com/vmware/pg_rewind</ulink>.
|
|
||||||
If the <application>pg_rewind</application>
|
|
||||||
binary is not installed in the PostgreSQL <filename>bin</filename> directory, provide
|
|
||||||
its full path on the demotion candidate with <option>--force-rewind</option>.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Note that building the 9.3/9.4 version of <application>pg_rewind</application> requires the PostgreSQL
|
|
||||||
source code. Also, PostgreSQL 9.3 does not provide <varname>wal_log_hints</varname>,
|
|
||||||
meaning data checksums must have been enabled when the database was initialized.
|
|
||||||
</para>
|
|
||||||
</sect2>
|
|
||||||
|
|
||||||
|
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|
||||||
<sect1 id="switchover-execution" xreflabel="Executing the switchover command">
|
<sect1 id="switchover-execution" xreflabel="Executing the switchover command">
|
||||||
@@ -310,21 +248,7 @@
|
|||||||
2 | node2 | primary | * running | | default | host=node2 dbname=repmgr user=repmgr
|
2 | node2 | primary | * running | | default | host=node2 dbname=repmgr user=repmgr
|
||||||
</programlisting>
|
</programlisting>
|
||||||
</para>
|
</para>
|
||||||
<para>
|
|
||||||
If <application>repmgrd</application> is in use, it's worth double-checking that
|
|
||||||
all nodes are unpaused by executing <command><link linkend="repmgr-daemon-status">repmgr-daemon-status</link></command>.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<note>
|
|
||||||
<para>
|
|
||||||
Users of &repmgr; versions prior to 4.2 will need to manually restart <application>repmgrd</application>
|
|
||||||
on all nodes after the switchover is completed.
|
|
||||||
</para>
|
|
||||||
</note>
|
|
||||||
|
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|
||||||
|
|
||||||
<sect1 id="switchover-caveats" xreflabel="Caveats">
|
<sect1 id="switchover-caveats" xreflabel="Caveats">
|
||||||
<indexterm>
|
<indexterm>
|
||||||
<primary>switchover</primary>
|
<primary>switchover</primary>
|
||||||
@@ -350,76 +274,17 @@
|
|||||||
for details.
|
for details.
|
||||||
</simpara>
|
</simpara>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<simpara>
|
||||||
|
<application>repmgrd</application> should not be running with setting <varname>failover=automatic</varname>
|
||||||
|
in <filename>repmgr.conf</filename> when a switchover is carried out, otherwise the
|
||||||
|
<application>repmgrd</application> daemon may try and promote a standby by itself.
|
||||||
|
</simpara>
|
||||||
|
</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</para>
|
</para>
|
||||||
|
<para>
|
||||||
|
We hope to remove some of these restrictions in future versions of &repmgr;.
|
||||||
|
</para>
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|
||||||
<sect1 id="switchover-troubleshooting" xreflabel="Troubleshooting">
|
|
||||||
<indexterm>
|
|
||||||
<primary>switchover</primary>
|
|
||||||
<secondary>troubleshooting</secondary>
|
|
||||||
</indexterm>
|
|
||||||
<title>Troubleshooting switchover issues</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
As <link linkend="performing-switchover">emphasised previously</link>, performing a switchover
|
|
||||||
is a non-trivial operation and there are a number of potential issues which can occur.
|
|
||||||
While &repmgr; attempts to perform sanity checks, there's no guaranteed way of determining the success of
|
|
||||||
a switchover without actually carrying it out.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<sect2 id="switchover-troubleshooting-primary-shutdown">
|
|
||||||
<title>Demotion candidate (old primary) does not shut down</title>
|
|
||||||
<para>
|
|
||||||
&repmgr; may abort a switchover with a message like:
|
|
||||||
<programlisting>
|
|
||||||
ERROR: shutdown of the primary server could not be confirmed
|
|
||||||
HINT: check the primary server status before performing any further actions</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
This means the shutdown of the old primary has taken longer than &repmgr; expected,
|
|
||||||
and it has given up waiting.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
In this case, check the PostgreSQL log on the primary server to see what is going
|
|
||||||
on. It's entirely possible the shutdown process is just taking longer than the
|
|
||||||
timeout set by the configuration parameter <varname>shutdown_check_timeout</varname>
|
|
||||||
(default: 60 seconds), in which case you may need to adjust this parameter.
|
|
||||||
</para>
|
|
||||||
<note>
|
|
||||||
<para>
|
|
||||||
Note that <varname>shutdown_check_timeout</varname>is set on the node where
|
|
||||||
<command>repmgr standby switchover</command> is executed (promotion candidate); setting it on the
|
|
||||||
demotion candidate (former primary) will have no effect.
|
|
||||||
</para>
|
|
||||||
</note>
|
|
||||||
<para>
|
|
||||||
If the primary server has shut down cleanly, and no other node has been promoted,
|
|
||||||
it is safe to restart it, in which case the replication cluster will be restored
|
|
||||||
to its original configuration.
|
|
||||||
</para>
|
|
||||||
</sect2>
|
|
||||||
|
|
||||||
<sect2 id="switchover-troubleshooting-exclusive-backup">
|
|
||||||
<title>Switchover aborts with an "exclusive backup" error</title>
|
|
||||||
<para>
|
|
||||||
&repmgr; may abort a switchover with a message like:
|
|
||||||
<programlisting>
|
|
||||||
ERROR: unable to perform a switchover while primary server is in exclusive backup mode
|
|
||||||
HINT: stop backup before attempting the switchover</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
This means an exclusive backup is running on the current primary; interrupting this
|
|
||||||
will not only abort the backup, but potentially leave the primary with an ambiguous
|
|
||||||
backup state.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
To proceed, either wait until the backup has finished, or cancel it with the command
|
|
||||||
<command>SELECT pg_stop_backup()</command>. For more details see the PostgreSQL
|
|
||||||
documentation section
|
|
||||||
<ulink url="https://www.postgresql.org/docs/current/static/continuous-archiving.html#BACKUP-LOWLEVEL-BASE-BACKUP-EXCLUSIVE">Making an exclusive low level backup</ulink>.
|
|
||||||
</para>
|
|
||||||
</sect2>
|
|
||||||
</sect1>
|
|
||||||
|
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|||||||
@@ -7,9 +7,9 @@
|
|||||||
<title>Upgrading repmgr</title>
|
<title>Upgrading repmgr</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
&repmgr; is updated regularly with minor releases (e.g. 4.0.1 to 4.0.2)
|
&repmgr; is updated regularly with point releases (e.g. 4.0.1 to 4.0.2)
|
||||||
containing bugfixes and other minor improvements. Any substantial new
|
containing bugfixes and other minor improvements. Any substantial new
|
||||||
functionality will be included in a major release (e.g. 4.0 to 4.1).
|
functionality will be included in a feature release (e.g. 4.0.x to 4.1.x).
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<sect1 id="upgrading-repmgr-extension" xreflabel="Upgrading repmgr 4.x and later">
|
<sect1 id="upgrading-repmgr-extension" xreflabel="Upgrading repmgr 4.x and later">
|
||||||
@@ -19,201 +19,37 @@
|
|||||||
</indexterm>
|
</indexterm>
|
||||||
<title>Upgrading repmgr 4.x and later</title>
|
<title>Upgrading repmgr 4.x and later</title>
|
||||||
<para>
|
<para>
|
||||||
From version 4, &repmgr; consists of three elements:
|
&repmgr; 4.x is implemented as a PostgreSQL extension; normally the upgrade consists
|
||||||
<itemizedlist spacing="compact" mark="bullet">
|
of the two following steps:
|
||||||
|
<orderedlist>
|
||||||
<listitem>
|
<listitem>
|
||||||
<simpara>
|
<simpara>
|
||||||
the <application>repmgr</application> and <application>repmgrd</application> executables
|
Install the updated package (or compile the updated source)
|
||||||
</simpara>
|
</simpara>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
<listitem>
|
||||||
<listitem>
|
<simpara>
|
||||||
<simpara>
|
In the database where the &repmgr; extension is installed, execute
|
||||||
the objects for the &repmgr; PostgreSQL extension (SQL files for creating/updating
|
<command>ALTER EXTENSION repmgr UPDATE</command>.
|
||||||
repmgr metadata, and the extension control file)
|
</simpara>
|
||||||
</simpara>
|
</listitem>
|
||||||
</listitem>
|
</orderedlist>
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
the shared library module used by <application>repmgrd</application> which
|
|
||||||
is resident in the PostgreSQL backend
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
With <emphasis>minor releases</emphasis>, usually changes are only made to the <application>repmgr</application>
|
|
||||||
and <application>repmgrd</application> executables. In this case, the upgrade is quite straightforward,
|
|
||||||
and is simply a case of installing the new version, and restarting <application>repmgrd</application>
|
|
||||||
(if running).
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
For <emphasis>major releases</emphasis>, the &repmgr; PostgreSQL extension will need to be updated
|
Always check the <link linkend="appendix-release-notes">release notes</link> for every
|
||||||
to the latest version. Additionally, if the shared library module has been updated (this is sometimes,
|
release as they may contain upgrade instructions particular to individual versions.
|
||||||
but not always the case), PostgreSQL itself will need to be restarted on each node.
|
|
||||||
</para>
|
</para>
|
||||||
<important>
|
|
||||||
<para>
|
|
||||||
Always check the <link linkend="appendix-release-notes">release notes</link> for every
|
|
||||||
release as they may contain upgrade instructions particular to individual versions.
|
|
||||||
</para>
|
|
||||||
</important>
|
|
||||||
|
|
||||||
<sect2 id="upgrading-minor-version" xreflabel="Upgrading a minor version release">
|
<para>
|
||||||
<indexterm>
|
If the <application>repmgrd</application> daemon is in use, we recommend stopping it
|
||||||
<primary>upgrading</primary>
|
before upgrading &repmgr;.
|
||||||
<secondary>minor release</secondary>
|
</para>
|
||||||
</indexterm>
|
<para>
|
||||||
<title>Upgrading a minor version release</title>
|
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
|
||||||
<para>
|
release notes for details.
|
||||||
The process for installing minor version upgrades is quite straightforward:
|
</para>
|
||||||
|
|
||||||
<itemizedlist spacing="compact" mark="bullet">
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
install the new &repmgr; version
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
restart <application>repmgrd</application> on all nodes where it is running
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
</itemizedlist>
|
|
||||||
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<note>
|
|
||||||
<para>
|
|
||||||
Some packaging systems (e.g. <link linkend="packages-debian-ubuntu">Debian/Ubuntu</link>
|
|
||||||
may restart <application>repmgrd</application> as part of the package upgrade process.
|
|
||||||
</para>
|
|
||||||
</note>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Minor version upgrades can be performed in any order on the nodes in the replication
|
|
||||||
cluster.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
A PostgreSQL restart is <emphasis>not</emphasis> required for minor version upgrades.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<note>
|
|
||||||
<para>
|
|
||||||
The same &repmgr; "major version" (e.g. <literal>4.2</literal>) must be
|
|
||||||
installed on all nodes in the replication cluster. While it's possible to have differing
|
|
||||||
&repmgr; "minor versions" (e.g. <literal>4.2.1</literal>) on different nodes,
|
|
||||||
we strongly recommend updating all nodes to the latest minor version.
|
|
||||||
</para>
|
|
||||||
</note>
|
|
||||||
|
|
||||||
</sect2>
|
|
||||||
|
|
||||||
<sect2 id="upgrading-major-version" xreflabel="Upgrading a major version release">
|
|
||||||
<indexterm>
|
|
||||||
<primary>upgrading</primary>
|
|
||||||
<secondary>major release</secondary>
|
|
||||||
</indexterm>
|
|
||||||
<title>Upgrading a major version release</title>
|
|
||||||
<para>
|
|
||||||
"major version" upgrades need to be planned more carefully, as they may include
|
|
||||||
changes to the &repmgr; metadata (which need to be propagated from the primary to all
|
|
||||||
standbys) and/or changes to the shared object file used by <application>repmgrd</application>
|
|
||||||
(which require a PostgreSQL restart).
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
With this in mind,
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
<orderedlist>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
Stop <application>repmgrd</application> (if in use) on all nodes where it is running.
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
Disable the <application>repmgrd</application> service on all nodes where it is in use;
|
|
||||||
this is to prevent packages from prematurely restarting <application>repmgrd</application>.
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
Install the updated package (or compile the updated source) on all nodes.
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
If running a <literal>systemd</literal>-based Linux distribution, execute (as <literal>root</literal>,
|
|
||||||
or with appropriate <literal>sudo</literal> permissions):
|
|
||||||
<programlisting>
|
|
||||||
systemctl daemon-reload</programlisting>
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
If the &repmgr; shared library module has been updated (check the <link linkend="appendix-release-notes">release notes</link>!),
|
|
||||||
restart PostgreSQL, then <application>repmgrd</application> (if in use) on each node,
|
|
||||||
The order in which this is applied to individual nodes is not critical,
|
|
||||||
and it's also fine to restart PostgreSQL on all nodes first before starting <application>repmgrd</application>.
|
|
||||||
</simpara>
|
|
||||||
<simpara>
|
|
||||||
Note that if the upgrade requires a PostgreSQL restart, <application>repmgrd</application>
|
|
||||||
will only function correctly once all nodes have been restarted.
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
On the primary node, execute
|
|
||||||
<programlisting>
|
|
||||||
ALTER EXTENSION repmgr UPDATE</programlisting>
|
|
||||||
in the database where &repmgr; is installed.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
Reenable the <application>repmgrd</application> service on all nodes where it is in use.
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
</orderedlist>
|
|
||||||
</para>
|
|
||||||
<tip>
|
|
||||||
<para>
|
|
||||||
If the &repmgr; upgrade requires a PostgreSQL restart, combine the &repmgr; upgrade
|
|
||||||
with a PostgreSQL minor version upgrade, which will require a restart in any case.
|
|
||||||
New PostgreSQL minor version are usually released every couple of months.
|
|
||||||
</para>
|
|
||||||
</tip>
|
|
||||||
</sect2>
|
|
||||||
|
|
||||||
<sect2 id="upgrading-check-repmgrd" xreflabel="Checking repmgrd status after an upgrade">
|
|
||||||
<indexterm>
|
|
||||||
<primary>upgrading</primary>
|
|
||||||
<secondary>checking repmgrd status</secondary>
|
|
||||||
</indexterm>
|
|
||||||
<title>Checking repmgrd status after an upgrade</title>
|
|
||||||
<para>
|
|
||||||
From &repmgr; 4.2, once the upgrade is complete, execute the <command><link linkend="repmgr-daemon-status">repmgr daemon status</link></command>
|
|
||||||
command (on any node) to show an overview of the status of <application>repmgrd</application> on all nodes.
|
|
||||||
</para>
|
|
||||||
</sect2>
|
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|
||||||
<sect1 id="upgrading-and-pg-upgrade" xreflabel="pg_upgrade and repmgr">
|
<sect1 id="upgrading-and-pg-upgrade" xreflabel="pg_upgrade and repmgr">
|
||||||
@@ -253,13 +89,6 @@ ALTER EXTENSION repmgr UPDATE</programlisting>
|
|||||||
be recreated by <application>pg_upgrade</application>. These will need to
|
be recreated by <application>pg_upgrade</application>. These will need to
|
||||||
be recreated manually.
|
be recreated manually.
|
||||||
</para>
|
</para>
|
||||||
<tip>
|
|
||||||
<para>
|
|
||||||
Use <command><link linkend="repmgr-node-check">repmgr node check</link></command>
|
|
||||||
to determine which replacation slots need to be recreated.
|
|
||||||
</para>
|
|
||||||
</tip>
|
|
||||||
|
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
<!ENTITY repmgrversion "4.2">
|
<!ENTITY repmgrversion "4.0.4">
|
||||||
|
|||||||
@@ -44,9 +44,5 @@
|
|||||||
#define ERR_REGISTRATION_SYNC 20
|
#define ERR_REGISTRATION_SYNC 20
|
||||||
#define ERR_OUT_OF_MEMORY 21
|
#define ERR_OUT_OF_MEMORY 21
|
||||||
#define ERR_SWITCHOVER_INCOMPLETE 22
|
#define ERR_SWITCHOVER_INCOMPLETE 22
|
||||||
#define ERR_FOLLOW_FAIL 23
|
|
||||||
#define ERR_REJOIN_FAIL 24
|
|
||||||
#define ERR_NODE_STATUS 25
|
|
||||||
#define ERR_REPMGRD_PAUSE 26
|
|
||||||
|
|
||||||
#endif /* _ERRCODE_H_ */
|
#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)));
|
__attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 0)));
|
||||||
|
|
||||||
int log_type = REPMGR_STDERR;
|
int log_type = REPMGR_STDERR;
|
||||||
int log_level = LOG_INFO;
|
int log_level = LOG_NOTICE;
|
||||||
int last_log_level = LOG_INFO;
|
int last_log_level = LOG_INFO;
|
||||||
int verbose_logging = false;
|
int verbose_logging = false;
|
||||||
int terse_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
|
* 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;
|
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
|
int
|
||||||
detect_log_level(const char *level)
|
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_verbose(void);
|
||||||
void logger_set_terse(void);
|
void logger_set_terse(void);
|
||||||
void logger_set_min_level(int min_log_level);
|
|
||||||
void logger_set_level(int new_log_level);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
log_detail(const char *fmt,...)
|
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
|
|
||||||
@@ -1,32 +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 FUNCTION get_repmgrd_pid()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'get_repmgrd_pid'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION get_repmgrd_pidfile()
|
|
||||||
RETURNS TEXT
|
|
||||||
AS 'MODULE_PATHNAME', 'get_repmgrd_pidfile'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION set_repmgrd_pid(INT, TEXT)
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'set_repmgrd_pid'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION repmgrd_is_running()
|
|
||||||
RETURNS BOOL
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgrd_is_running'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION repmgrd_pause(BOOL)
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgrd_pause'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION repmgrd_is_paused()
|
|
||||||
RETURNS BOOL
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgrd_is_paused'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
166
repmgr--4.1.sql
166
repmgr--4.1.sql
@@ -1,166 +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
|
|
||||||
);
|
|
||||||
|
|
||||||
197
repmgr--4.2.sql
197
repmgr--4.2.sql
@@ -1,197 +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 FUNCTION get_repmgrd_pid()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'get_repmgrd_pid'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION get_repmgrd_pidfile()
|
|
||||||
RETURNS TEXT
|
|
||||||
AS 'MODULE_PATHNAME', 'get_repmgrd_pidfile'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION set_repmgrd_pid(INT, TEXT)
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'set_repmgrd_pid'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION repmgrd_is_running()
|
|
||||||
RETURNS BOOL
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgrd_is_running'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION repmgrd_pause(BOOL)
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgrd_pause'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION repmgrd_is_paused()
|
|
||||||
RETURNS BOOL
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgrd_is_paused'
|
|
||||||
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);
|
exit(ERR_BAD_CONFIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* BDR 2 implementation is for 2 nodes only */
|
if (bdr_nodes.node_count > 2)
|
||||||
if (get_bdr_version_num() < 3 && 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);
|
log_detail(_("this BDR cluster has %i nodes"), bdr_nodes.node_count);
|
||||||
PQfinish(conn);
|
PQfinish(conn);
|
||||||
pfree(dbname);
|
pfree(dbname);
|
||||||
@@ -177,7 +176,6 @@ do_bdr_register(void)
|
|||||||
|
|
||||||
if (bdr_node_has_repmgr_set(conn, config_file_options.node_name) == false)
|
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);
|
bdr_node_set_repmgr_set(conn, config_file_options.node_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,7 +189,7 @@ do_bdr_register(void)
|
|||||||
{
|
{
|
||||||
NodeInfoList local_node_records = T_NODE_INFO_LIST_INITIALIZER;
|
NodeInfoList local_node_records = T_NODE_INFO_LIST_INITIALIZER;
|
||||||
|
|
||||||
(void) get_all_node_records(conn, &local_node_records);
|
get_all_node_records(conn, &local_node_records);
|
||||||
|
|
||||||
if (local_node_records.node_count == 0)
|
if (local_node_records.node_count == 0)
|
||||||
{
|
{
|
||||||
@@ -203,7 +201,6 @@ do_bdr_register(void)
|
|||||||
if (bdr_nodes.node_count == 0)
|
if (bdr_nodes.node_count == 0)
|
||||||
{
|
{
|
||||||
log_error(_("unable to retrieve any BDR node records"));
|
log_error(_("unable to retrieve any BDR node records"));
|
||||||
log_detail("%s", PQerrorMessage(conn));
|
|
||||||
PQfinish(conn);
|
PQfinish(conn);
|
||||||
exit(ERR_BAD_CONFIG);
|
exit(ERR_BAD_CONFIG);
|
||||||
}
|
}
|
||||||
@@ -239,7 +236,7 @@ do_bdr_register(void)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
(void) get_all_node_records(bdr_node_conn, &existing_nodes);
|
get_all_node_records(bdr_node_conn, &existing_nodes);
|
||||||
|
|
||||||
for (cell = existing_nodes.head; cell; cell = cell->next)
|
for (cell = existing_nodes.head; cell; cell = cell->next)
|
||||||
{
|
{
|
||||||
@@ -255,35 +252,7 @@ do_bdr_register(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Add the repmgr extension tables to a replication set */
|
/* Add the repmgr extension tables to a replication set */
|
||||||
|
add_extension_tables_to_bdr_replication_set(conn);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
initPQExpBuffer(&event_details);
|
initPQExpBuffer(&event_details);
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
#define SHOW_HEADER_COUNT 7
|
#define SHOW_HEADER_COUNT 7
|
||||||
|
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
SHOW_ID = 0,
|
SHOW_ID = 0,
|
||||||
@@ -50,13 +51,21 @@ typedef enum
|
|||||||
} EventHeader;
|
} EventHeader;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct ColHeader
|
||||||
|
{
|
||||||
|
char title[MAXLEN];
|
||||||
|
int max_length;
|
||||||
|
int cur_length;
|
||||||
|
};
|
||||||
|
|
||||||
struct ColHeader headers_show[SHOW_HEADER_COUNT];
|
struct ColHeader headers_show[SHOW_HEADER_COUNT];
|
||||||
struct ColHeader headers_event[EVENT_HEADER_COUNT];
|
struct ColHeader headers_event[EVENT_HEADER_COUNT];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int build_cluster_matrix(t_node_matrix_rec ***matrix_rec_dest, int *name_length, ItemList *warnings, int *error_code);
|
static int build_cluster_matrix(t_node_matrix_rec ***matrix_rec_dest, int *name_length);
|
||||||
static int build_cluster_crosscheck(t_node_status_cube ***cube_dest, int *name_length, ItemList *warnings, int *error_code);
|
static int build_cluster_crosscheck(t_node_status_cube ***cube_dest, int *name_length);
|
||||||
static void cube_set_node_status(t_node_status_cube **cube, int n, int node_id, int matrix_node_id, int connection_node_id, int connection_status);
|
static void cube_set_node_status(t_node_status_cube **cube, int n, int node_id, int matrix_node_id, int connection_node_id, int connection_status);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -74,8 +83,6 @@ do_cluster_show(void)
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
ItemList warnings = {NULL, NULL};
|
ItemList warnings = {NULL, NULL};
|
||||||
bool success = false;
|
bool success = false;
|
||||||
bool error_found = false;
|
|
||||||
bool connection_error_found = false;
|
|
||||||
|
|
||||||
/* Connect to local database to obtain cluster connection data */
|
/* Connect to local database to obtain cluster connection data */
|
||||||
log_verbose(LOG_INFO, _("connecting to database"));
|
log_verbose(LOG_INFO, _("connecting to database"));
|
||||||
@@ -133,26 +140,14 @@ do_cluster_show(void)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
char error[MAXLEN];
|
||||||
|
|
||||||
|
strncpy(error, PQerrorMessage(cell->node_info->conn), MAXLEN);
|
||||||
cell->node_info->node_status = NODE_STATUS_DOWN;
|
cell->node_info->node_status = NODE_STATUS_DOWN;
|
||||||
cell->node_info->recovery_type = RECTYPE_UNKNOWN;
|
cell->node_info->recovery_type = RECTYPE_UNKNOWN;
|
||||||
|
item_list_append_format(&warnings,
|
||||||
connection_error_found = true;
|
"when attempting to connect to node \"%s\" (ID: %i), following error encountered :\n\"%s\"",
|
||||||
|
cell->node_info->node_name, cell->node_info->node_id, trim(error));
|
||||||
if (runtime_options.verbose)
|
|
||||||
{
|
|
||||||
char error[MAXLEN];
|
|
||||||
|
|
||||||
strncpy(error, PQerrorMessage(cell->node_info->conn), MAXLEN);
|
|
||||||
item_list_append_format(&warnings,
|
|
||||||
"when attempting to connect to node \"%s\" (ID: %i), following error encountered :\n\"%s\"",
|
|
||||||
cell->node_info->node_name, cell->node_info->node_id, trim(error));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
item_list_append_format(&warnings,
|
|
||||||
"unable to connect to node \"%s\" (ID: %i)",
|
|
||||||
cell->node_info->node_name, cell->node_info->node_id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
initPQExpBuffer(&details);
|
initPQExpBuffer(&details);
|
||||||
@@ -174,16 +169,16 @@ do_cluster_show(void)
|
|||||||
switch (cell->node_info->recovery_type)
|
switch (cell->node_info->recovery_type)
|
||||||
{
|
{
|
||||||
case RECTYPE_PRIMARY:
|
case RECTYPE_PRIMARY:
|
||||||
appendPQExpBufferStr(&details, "* running");
|
appendPQExpBuffer(&details, "* running");
|
||||||
break;
|
break;
|
||||||
case RECTYPE_STANDBY:
|
case RECTYPE_STANDBY:
|
||||||
appendPQExpBufferStr(&details, "! running as standby");
|
appendPQExpBuffer(&details, "! running as standby");
|
||||||
item_list_append_format(&warnings,
|
item_list_append_format(&warnings,
|
||||||
"node \"%s\" (ID: %i) is registered as primary but running as standby",
|
"node \"%s\" (ID: %i) is registered as primary but running as standby",
|
||||||
cell->node_info->node_name, cell->node_info->node_id);
|
cell->node_info->node_name, cell->node_info->node_id);
|
||||||
break;
|
break;
|
||||||
case RECTYPE_UNKNOWN:
|
case RECTYPE_UNKNOWN:
|
||||||
appendPQExpBufferStr(&details, "! unknown");
|
appendPQExpBuffer(&details, "! unknown");
|
||||||
item_list_append_format(&warnings,
|
item_list_append_format(&warnings,
|
||||||
"node \"%s\" (ID: %i) has unknown replication status",
|
"node \"%s\" (ID: %i) has unknown replication status",
|
||||||
cell->node_info->node_name, cell->node_info->node_id);
|
cell->node_info->node_name, cell->node_info->node_id);
|
||||||
@@ -194,14 +189,14 @@ do_cluster_show(void)
|
|||||||
{
|
{
|
||||||
if (cell->node_info->recovery_type == RECTYPE_PRIMARY)
|
if (cell->node_info->recovery_type == RECTYPE_PRIMARY)
|
||||||
{
|
{
|
||||||
appendPQExpBufferStr(&details, "! running");
|
appendPQExpBuffer(&details, "! running");
|
||||||
item_list_append_format(&warnings,
|
item_list_append_format(&warnings,
|
||||||
"node \"%s\" (ID: %i) is running but the repmgr node record is inactive",
|
"node \"%s\" (ID: %i) is running but the repmgr node record is inactive",
|
||||||
cell->node_info->node_name, cell->node_info->node_id);
|
cell->node_info->node_name, cell->node_info->node_id);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
appendPQExpBufferStr(&details, "! running as standby");
|
appendPQExpBuffer(&details, "! running as standby");
|
||||||
item_list_append_format(&warnings,
|
item_list_append_format(&warnings,
|
||||||
"node \"%s\" (ID: %i) is registered as an inactive primary but running as standby",
|
"node \"%s\" (ID: %i) is registered as an inactive primary but running as standby",
|
||||||
cell->node_info->node_name, cell->node_info->node_id);
|
cell->node_info->node_name, cell->node_info->node_id);
|
||||||
@@ -214,7 +209,7 @@ do_cluster_show(void)
|
|||||||
/* node is unreachable but marked active */
|
/* node is unreachable but marked active */
|
||||||
if (cell->node_info->active == true)
|
if (cell->node_info->active == true)
|
||||||
{
|
{
|
||||||
appendPQExpBufferStr(&details, "? unreachable");
|
appendPQExpBuffer(&details, "? unreachable");
|
||||||
item_list_append_format(&warnings,
|
item_list_append_format(&warnings,
|
||||||
"node \"%s\" (ID: %i) is registered as an active primary but is unreachable",
|
"node \"%s\" (ID: %i) is registered as an active primary but is unreachable",
|
||||||
cell->node_info->node_name, cell->node_info->node_id);
|
cell->node_info->node_name, cell->node_info->node_id);
|
||||||
@@ -222,8 +217,7 @@ do_cluster_show(void)
|
|||||||
/* node is unreachable and marked as inactive */
|
/* node is unreachable and marked as inactive */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
appendPQExpBufferStr(&details, "- failed");
|
appendPQExpBuffer(&details, "- failed");
|
||||||
error_found = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -238,16 +232,16 @@ do_cluster_show(void)
|
|||||||
switch (cell->node_info->recovery_type)
|
switch (cell->node_info->recovery_type)
|
||||||
{
|
{
|
||||||
case RECTYPE_STANDBY:
|
case RECTYPE_STANDBY:
|
||||||
appendPQExpBufferStr(&details, " running");
|
appendPQExpBuffer(&details, " running");
|
||||||
break;
|
break;
|
||||||
case RECTYPE_PRIMARY:
|
case RECTYPE_PRIMARY:
|
||||||
appendPQExpBufferStr(&details, "! running as primary");
|
appendPQExpBuffer(&details, "! running as primary");
|
||||||
item_list_append_format(&warnings,
|
item_list_append_format(&warnings,
|
||||||
"node \"%s\" (ID: %i) is registered as standby but running as primary",
|
"node \"%s\" (ID: %i) is registered as standby but running as primary",
|
||||||
cell->node_info->node_name, cell->node_info->node_id);
|
cell->node_info->node_name, cell->node_info->node_id);
|
||||||
break;
|
break;
|
||||||
case RECTYPE_UNKNOWN:
|
case RECTYPE_UNKNOWN:
|
||||||
appendPQExpBufferStr(&details, "! unknown");
|
appendPQExpBuffer(&details, "! unknown");
|
||||||
item_list_append_format(
|
item_list_append_format(
|
||||||
&warnings,
|
&warnings,
|
||||||
"node \"%s\" (ID: %i) has unknown replication status",
|
"node \"%s\" (ID: %i) has unknown replication status",
|
||||||
@@ -259,14 +253,14 @@ do_cluster_show(void)
|
|||||||
{
|
{
|
||||||
if (cell->node_info->recovery_type == RECTYPE_STANDBY)
|
if (cell->node_info->recovery_type == RECTYPE_STANDBY)
|
||||||
{
|
{
|
||||||
appendPQExpBufferStr(&details, "! running");
|
appendPQExpBuffer(&details, "! running");
|
||||||
item_list_append_format(&warnings,
|
item_list_append_format(&warnings,
|
||||||
"node \"%s\" (ID: %i) is running but the repmgr node record is inactive",
|
"node \"%s\" (ID: %i) is running but the repmgr node record is inactive",
|
||||||
cell->node_info->node_name, cell->node_info->node_id);
|
cell->node_info->node_name, cell->node_info->node_id);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
appendPQExpBufferStr(&details, "! running as primary");
|
appendPQExpBuffer(&details, "! running as primary");
|
||||||
item_list_append_format(&warnings,
|
item_list_append_format(&warnings,
|
||||||
"node \"%s\" (ID: %i) is running as primary but the repmgr node record is inactive",
|
"node \"%s\" (ID: %i) is running as primary but the repmgr node record is inactive",
|
||||||
cell->node_info->node_name, cell->node_info->node_id);
|
cell->node_info->node_name, cell->node_info->node_id);
|
||||||
@@ -279,15 +273,14 @@ do_cluster_show(void)
|
|||||||
/* node is unreachable but marked active */
|
/* node is unreachable but marked active */
|
||||||
if (cell->node_info->active == true)
|
if (cell->node_info->active == true)
|
||||||
{
|
{
|
||||||
appendPQExpBufferStr(&details, "? unreachable");
|
appendPQExpBuffer(&details, "? unreachable");
|
||||||
item_list_append_format(&warnings,
|
item_list_append_format(&warnings,
|
||||||
"node \"%s\" (ID: %i) is registered as an active standby but is unreachable",
|
"node \"%s\" (ID: %i) is registered as an active standby but is unreachable",
|
||||||
cell->node_info->node_name, cell->node_info->node_id);
|
cell->node_info->node_name, cell->node_info->node_id);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
appendPQExpBufferStr(&details, "- failed");
|
appendPQExpBuffer(&details, "- failed");
|
||||||
error_found = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -299,35 +292,24 @@ do_cluster_show(void)
|
|||||||
if (cell->node_info->node_status == NODE_STATUS_UP)
|
if (cell->node_info->node_status == NODE_STATUS_UP)
|
||||||
{
|
{
|
||||||
if (cell->node_info->active == true)
|
if (cell->node_info->active == true)
|
||||||
{
|
appendPQExpBuffer(&details, "* running");
|
||||||
appendPQExpBufferStr(&details, "* running");
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
appendPQExpBuffer(&details, "! running");
|
||||||
appendPQExpBufferStr(&details, "! running");
|
|
||||||
error_found = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/* node is unreachable */
|
/* node is unreachable */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (cell->node_info->active == true)
|
if (cell->node_info->active == true)
|
||||||
{
|
appendPQExpBuffer(&details, "? unreachable");
|
||||||
appendPQExpBufferStr(&details, "? unreachable");
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
appendPQExpBuffer(&details, "- failed");
|
||||||
appendPQExpBufferStr(&details, "- failed");
|
|
||||||
error_found = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case UNKNOWN:
|
case UNKNOWN:
|
||||||
{
|
{
|
||||||
/* this should never happen */
|
/* this should never happen */
|
||||||
appendPQExpBufferStr(&details, "? unknown node type");
|
appendPQExpBuffer(&details, "? unknown node type");
|
||||||
error_found = true;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -355,10 +337,36 @@ do_cluster_show(void)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Print column header row (text mode only) */
|
|
||||||
if (runtime_options.output_mode == OM_TEXT)
|
if (runtime_options.output_mode == OM_TEXT)
|
||||||
{
|
{
|
||||||
print_status_header(SHOW_HEADER_COUNT, headers_show);
|
for (i = 0; i < SHOW_HEADER_COUNT; i++)
|
||||||
|
{
|
||||||
|
if (i == 0)
|
||||||
|
printf(" ");
|
||||||
|
else
|
||||||
|
printf(" | ");
|
||||||
|
|
||||||
|
printf("%-*s",
|
||||||
|
headers_show[i].max_length,
|
||||||
|
headers_show[i].title);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
printf("-");
|
||||||
|
|
||||||
|
for (i = 0; i < SHOW_HEADER_COUNT; i++)
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
|
||||||
|
for (j = 0; j < headers_show[i].max_length; j++)
|
||||||
|
printf("-");
|
||||||
|
|
||||||
|
if (i < (SHOW_HEADER_COUNT - 1))
|
||||||
|
printf("-+-");
|
||||||
|
else
|
||||||
|
printf("-");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
for (cell = nodes.head; cell; cell = cell->next)
|
for (cell = nodes.head; cell; cell = cell->next)
|
||||||
@@ -406,6 +414,7 @@ do_cluster_show(void)
|
|||||||
PQfinish(conn);
|
PQfinish(conn);
|
||||||
|
|
||||||
/* emit any warnings */
|
/* emit any warnings */
|
||||||
|
|
||||||
if (warnings.head != NULL && runtime_options.terse == false && runtime_options.output_mode != OM_CSV)
|
if (warnings.head != NULL && runtime_options.terse == false && runtime_options.output_mode != OM_CSV)
|
||||||
{
|
{
|
||||||
ItemListCell *cell = NULL;
|
ItemListCell *cell = NULL;
|
||||||
@@ -415,25 +424,6 @@ do_cluster_show(void)
|
|||||||
{
|
{
|
||||||
printf(_(" - %s\n"), cell->string);
|
printf(_(" - %s\n"), cell->string);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (runtime_options.verbose == false && connection_error_found == true)
|
|
||||||
{
|
|
||||||
log_hint(_("execute with --verbose option to see connection error messages"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -446,7 +436,6 @@ do_cluster_show(void)
|
|||||||
* --all
|
* --all
|
||||||
* --node-[id|name]
|
* --node-[id|name]
|
||||||
* --event
|
* --event
|
||||||
* --csv
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -491,12 +480,8 @@ do_cluster_event(void)
|
|||||||
strncpy(headers_event[EV_TIMESTAMP].title, _("Timestamp"), MAXLEN);
|
strncpy(headers_event[EV_TIMESTAMP].title, _("Timestamp"), MAXLEN);
|
||||||
strncpy(headers_event[EV_DETAILS].title, _("Details"), MAXLEN);
|
strncpy(headers_event[EV_DETAILS].title, _("Details"), MAXLEN);
|
||||||
|
|
||||||
/*
|
/* if --terse provided, simply omit the "Details" column */
|
||||||
* If --terse or --csv provided, simply omit the "Details" column.
|
if (runtime_options.terse == true)
|
||||||
* 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)
|
|
||||||
column_count --;
|
column_count --;
|
||||||
|
|
||||||
for (i = 0; i < column_count; i++)
|
for (i = 0; i < column_count; i++)
|
||||||
@@ -519,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(" ");
|
||||||
if (i == 0)
|
else
|
||||||
printf(" ");
|
printf(" | ");
|
||||||
else
|
|
||||||
printf(" | ");
|
|
||||||
|
|
||||||
printf("%-*s",
|
printf("%-*s",
|
||||||
headers_event[i].max_length,
|
headers_event[i].max_length,
|
||||||
headers_event[i].title);
|
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("\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++)
|
for (i = 0; i < PQntuples(res); i++)
|
||||||
{
|
{
|
||||||
int j;
|
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",
|
||||||
{
|
headers_event[j].max_length,
|
||||||
printf("%s", PQgetvalue(res, i, j));
|
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));
|
|
||||||
|
|
||||||
if (j < (column_count - 1))
|
if (j < (column_count - 1))
|
||||||
printf(" | ");
|
printf(" | ");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
@@ -586,8 +554,7 @@ do_cluster_event(void)
|
|||||||
|
|
||||||
PQfinish(conn);
|
PQfinish(conn);
|
||||||
|
|
||||||
if (runtime_options.output_mode == OM_TEXT)
|
puts("");
|
||||||
puts("");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -602,12 +569,7 @@ do_cluster_crosscheck(void)
|
|||||||
|
|
||||||
t_node_status_cube **cube;
|
t_node_status_cube **cube;
|
||||||
|
|
||||||
bool connection_error_found = false;
|
n = build_cluster_crosscheck(&cube, &name_length);
|
||||||
int error_code = SUCCESS;
|
|
||||||
ItemList warnings = {NULL, NULL};
|
|
||||||
|
|
||||||
n = build_cluster_crosscheck(&cube, &name_length, &warnings, &error_code);
|
|
||||||
|
|
||||||
if (runtime_options.output_mode == OM_CSV)
|
if (runtime_options.output_mode == OM_CSV)
|
||||||
{
|
{
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++)
|
||||||
@@ -629,11 +591,6 @@ do_cluster_crosscheck(void)
|
|||||||
cube[i]->node_id,
|
cube[i]->node_id,
|
||||||
cube[j]->node_id,
|
cube[j]->node_id,
|
||||||
max_node_status);
|
max_node_status);
|
||||||
|
|
||||||
if (max_node_status == -1)
|
|
||||||
{
|
|
||||||
connection_error_found = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -694,13 +651,11 @@ do_cluster_crosscheck(void)
|
|||||||
break;
|
break;
|
||||||
case -1:
|
case -1:
|
||||||
c = 'x';
|
c = 'x';
|
||||||
connection_error_found = true;
|
|
||||||
break;
|
break;
|
||||||
case 0:
|
case 0:
|
||||||
c = '*';
|
c = '*';
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
log_error("unexpected node status value %i", max_node_status);
|
|
||||||
exit(ERR_INTERNAL);
|
exit(ERR_INTERNAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -709,13 +664,6 @@ do_cluster_crosscheck(void)
|
|||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (warnings.head != NULL && runtime_options.terse == false)
|
|
||||||
{
|
|
||||||
log_warning(_("following problems detected:"));
|
|
||||||
print_item_list(&warnings);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* clean up allocated cube array */
|
/* clean up allocated cube array */
|
||||||
@@ -741,24 +689,9 @@ do_cluster_crosscheck(void)
|
|||||||
|
|
||||||
free(cube);
|
free(cube);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* errors detected by build_cluster_crosscheck() have priority */
|
|
||||||
if (connection_error_found == true)
|
|
||||||
{
|
|
||||||
error_code = ERR_NODE_STATUS;
|
|
||||||
}
|
|
||||||
|
|
||||||
exit(error_code);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* CLUSTER MATRIX
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
* --csv
|
|
||||||
*/
|
|
||||||
void
|
void
|
||||||
do_cluster_matrix()
|
do_cluster_matrix()
|
||||||
{
|
{
|
||||||
@@ -771,30 +704,16 @@ do_cluster_matrix()
|
|||||||
|
|
||||||
t_node_matrix_rec **matrix_rec_list;
|
t_node_matrix_rec **matrix_rec_list;
|
||||||
|
|
||||||
bool connection_error_found = false;
|
n = build_cluster_matrix(&matrix_rec_list, &name_length);
|
||||||
int error_code = SUCCESS;
|
|
||||||
ItemList warnings = {NULL, NULL};
|
|
||||||
|
|
||||||
n = build_cluster_matrix(&matrix_rec_list, &name_length, &warnings, &error_code);
|
|
||||||
|
|
||||||
if (runtime_options.output_mode == OM_CSV)
|
if (runtime_options.output_mode == OM_CSV)
|
||||||
{
|
{
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++)
|
||||||
{
|
|
||||||
for (j = 0; j < n; j++)
|
for (j = 0; j < n; j++)
|
||||||
{
|
|
||||||
printf("%d,%d,%d\n",
|
printf("%d,%d,%d\n",
|
||||||
matrix_rec_list[i]->node_id,
|
matrix_rec_list[i]->node_id,
|
||||||
matrix_rec_list[i]->node_status_list[j]->node_id,
|
matrix_rec_list[i]->node_status_list[j]->node_id,
|
||||||
matrix_rec_list[i]->node_status_list[j]->node_status);
|
matrix_rec_list[i]->node_status_list[j]->node_status);
|
||||||
|
|
||||||
if (matrix_rec_list[i]->node_status_list[j]->node_status == -2
|
|
||||||
|| matrix_rec_list[i]->node_status_list[j]->node_status == -1)
|
|
||||||
{
|
|
||||||
connection_error_found = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -826,13 +745,11 @@ do_cluster_matrix()
|
|||||||
break;
|
break;
|
||||||
case -1:
|
case -1:
|
||||||
c = 'x';
|
c = 'x';
|
||||||
connection_error_found = true;
|
|
||||||
break;
|
break;
|
||||||
case 0:
|
case 0:
|
||||||
c = '*';
|
c = '*';
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
log_error("unexpected node status value %i", matrix_rec_list[i]->node_status_list[j]->node_status);
|
|
||||||
exit(ERR_INTERNAL);
|
exit(ERR_INTERNAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -840,13 +757,6 @@ do_cluster_matrix()
|
|||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (warnings.head != NULL && runtime_options.terse == false)
|
|
||||||
{
|
|
||||||
log_warning(_("following problems detected:"));
|
|
||||||
print_item_list(&warnings);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < n; i++)
|
for (i = 0; i < n; i++)
|
||||||
@@ -860,14 +770,6 @@ do_cluster_matrix()
|
|||||||
}
|
}
|
||||||
|
|
||||||
free(matrix_rec_list);
|
free(matrix_rec_list);
|
||||||
|
|
||||||
/* actual database connection errors have priority */
|
|
||||||
if (connection_error_found == true)
|
|
||||||
{
|
|
||||||
error_code = ERR_NODE_STATUS;
|
|
||||||
}
|
|
||||||
|
|
||||||
exit(error_code);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -896,7 +798,7 @@ matrix_set_node_status(t_node_matrix_rec **matrix_rec_list, int n, int node_id,
|
|||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
build_cluster_matrix(t_node_matrix_rec ***matrix_rec_dest, int *name_length, ItemList *warnings, int *error_code)
|
build_cluster_matrix(t_node_matrix_rec ***matrix_rec_dest, int *name_length)
|
||||||
{
|
{
|
||||||
PGconn *conn = NULL;
|
PGconn *conn = NULL;
|
||||||
int i = 0,
|
int i = 0,
|
||||||
@@ -925,12 +827,7 @@ build_cluster_matrix(t_node_matrix_rec ***matrix_rec_dest, int *name_length, Ite
|
|||||||
local_node_id = runtime_options.node_id;
|
local_node_id = runtime_options.node_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_all_node_records(conn, &nodes) == false)
|
get_all_node_records(conn, &nodes);
|
||||||
{
|
|
||||||
/* get_all_node_records() will display the error */
|
|
||||||
PQfinish(conn);
|
|
||||||
exit(ERR_BAD_CONFIG);
|
|
||||||
}
|
|
||||||
|
|
||||||
PQfinish(conn);
|
PQfinish(conn);
|
||||||
conn = NULL;
|
conn = NULL;
|
||||||
@@ -944,7 +841,7 @@ build_cluster_matrix(t_node_matrix_rec ***matrix_rec_dest, int *name_length, Ite
|
|||||||
/*
|
/*
|
||||||
* Allocate an empty matrix record list
|
* Allocate an empty matrix record list
|
||||||
*
|
*
|
||||||
* -2 == NULL ? -1 == Error x 0 == OK
|
* -2 == NULL ? -1 == Error x 0 == OK *
|
||||||
*/
|
*/
|
||||||
|
|
||||||
matrix_rec_list = (t_node_matrix_rec **) pg_malloc0(sizeof(t_node_matrix_rec) * nodes.node_count);
|
matrix_rec_list = (t_node_matrix_rec **) pg_malloc0(sizeof(t_node_matrix_rec) * nodes.node_count);
|
||||||
@@ -1007,7 +904,7 @@ build_cluster_matrix(t_node_matrix_rec ***matrix_rec_dest, int *name_length, Ite
|
|||||||
|
|
||||||
host = param_get(&remote_conninfo, "host");
|
host = param_get(&remote_conninfo, "host");
|
||||||
|
|
||||||
node_conn = establish_db_connection_quiet(cell->node_info->conninfo);
|
node_conn = establish_db_connection(cell->node_info->conninfo, false);
|
||||||
|
|
||||||
connection_status =
|
connection_status =
|
||||||
(PQstatus(node_conn) == CONNECTION_OK) ? 0 : -1;
|
(PQstatus(node_conn) == CONNECTION_OK) ? 0 : -1;
|
||||||
@@ -1044,18 +941,31 @@ build_cluster_matrix(t_node_matrix_rec ***matrix_rec_dest, int *name_length, Ite
|
|||||||
* remote repmgr - those are the only values it needs to work, and
|
* remote repmgr - those are the only values it needs to work, and
|
||||||
* saves us making assumptions about the location of repmgr.conf
|
* saves us making assumptions about the location of repmgr.conf
|
||||||
*/
|
*/
|
||||||
appendPQExpBufferChar(&command, '"');
|
appendPQExpBuffer(&command,
|
||||||
|
"\"%s -d '%s' ",
|
||||||
|
make_pg_path(progname()),
|
||||||
|
cell->node_info->conninfo);
|
||||||
|
|
||||||
make_remote_repmgr_path(&command, cell->node_info);
|
|
||||||
|
|
||||||
appendPQExpBufferStr(&command,
|
if (strlen(pg_bindir))
|
||||||
" cluster show --csv -L NOTICE --terse\"");
|
{
|
||||||
|
appendPQExpBuffer(&command,
|
||||||
|
"--pg_bindir=");
|
||||||
|
appendShellString(&command,
|
||||||
|
pg_bindir);
|
||||||
|
appendPQExpBuffer(&command,
|
||||||
|
" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
appendPQExpBuffer(&command,
|
||||||
|
" cluster show --csv\"");
|
||||||
|
|
||||||
log_verbose(LOG_DEBUG, "build_cluster_matrix(): executing:\n %s", command.data);
|
log_verbose(LOG_DEBUG, "build_cluster_matrix(): executing:\n %s", command.data);
|
||||||
|
|
||||||
initPQExpBuffer(&command_output);
|
initPQExpBuffer(&command_output);
|
||||||
|
|
||||||
(void) remote_command(host,
|
(void) remote_command(
|
||||||
|
host,
|
||||||
runtime_options.remote_user,
|
runtime_options.remote_user,
|
||||||
command.data,
|
command.data,
|
||||||
&command_output);
|
&command_output);
|
||||||
@@ -1064,50 +974,32 @@ build_cluster_matrix(t_node_matrix_rec ***matrix_rec_dest, int *name_length, Ite
|
|||||||
|
|
||||||
termPQExpBuffer(&command);
|
termPQExpBuffer(&command);
|
||||||
|
|
||||||
/* no output returned - probably SSH error */
|
for (j = 0; j < nodes.node_count; j++)
|
||||||
if (p[0] == '\0' || p[0] == '\n')
|
|
||||||
{
|
{
|
||||||
item_list_append_format(warnings,
|
if (sscanf(p, "%d,%d", &x, &y) != 2)
|
||||||
"node %i inaccessible via SSH",
|
|
||||||
connection_node_id);
|
|
||||||
*error_code = ERR_BAD_SSH;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (j = 0; j < nodes.node_count; j++)
|
|
||||||
{
|
{
|
||||||
if (sscanf(p, "%d,%d", &x, &y) != 2)
|
fprintf(stderr, _("cannot parse --csv output: %s\n"), p);
|
||||||
{
|
PQfinish(node_conn);
|
||||||
matrix_set_node_status(matrix_rec_list,
|
exit(ERR_INTERNAL);
|
||||||
nodes.node_count,
|
|
||||||
connection_node_id,
|
|
||||||
x,
|
|
||||||
-2);
|
|
||||||
|
|
||||||
item_list_append_format(warnings,
|
|
||||||
"unable to parse --csv output for node %i; output returned was:\n\"%s\"",
|
|
||||||
connection_node_id, p);
|
|
||||||
*error_code = ERR_INTERNAL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
matrix_set_node_status(matrix_rec_list,
|
|
||||||
nodes.node_count,
|
|
||||||
connection_node_id,
|
|
||||||
x,
|
|
||||||
(y == -1) ? -1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (*p && (*p != '\n'))
|
|
||||||
p++;
|
|
||||||
if (*p == '\n')
|
|
||||||
p++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
matrix_set_node_status(matrix_rec_list,
|
||||||
|
nodes.node_count,
|
||||||
|
connection_node_id,
|
||||||
|
x,
|
||||||
|
(y == -1) ? -1 : 0);
|
||||||
|
|
||||||
|
while (*p && (*p != '\n'))
|
||||||
|
p++;
|
||||||
|
if (*p == '\n')
|
||||||
|
p++;
|
||||||
}
|
}
|
||||||
|
|
||||||
termPQExpBuffer(&command_output);
|
termPQExpBuffer(&command_output);
|
||||||
PQfinish(node_conn);
|
PQfinish(node_conn);
|
||||||
free_conninfo_params(&remote_conninfo);
|
free_conninfo_params(&remote_conninfo);
|
||||||
|
|
||||||
|
node_conn = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
*matrix_rec_dest = matrix_rec_list;
|
*matrix_rec_dest = matrix_rec_list;
|
||||||
@@ -1120,7 +1012,7 @@ build_cluster_matrix(t_node_matrix_rec ***matrix_rec_dest, int *name_length, Ite
|
|||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
build_cluster_crosscheck(t_node_status_cube ***dest_cube, int *name_length, ItemList *warnings, int *error_code)
|
build_cluster_crosscheck(t_node_status_cube ***dest_cube, int *name_length)
|
||||||
{
|
{
|
||||||
PGconn *conn = NULL;
|
PGconn *conn = NULL;
|
||||||
int h,
|
int h,
|
||||||
@@ -1141,12 +1033,7 @@ build_cluster_crosscheck(t_node_status_cube ***dest_cube, int *name_length, Item
|
|||||||
else
|
else
|
||||||
conn = establish_db_connection_by_params(&source_conninfo, true);
|
conn = establish_db_connection_by_params(&source_conninfo, true);
|
||||||
|
|
||||||
if (get_all_node_records(conn, &nodes) == false)
|
get_all_node_records(conn, &nodes);
|
||||||
{
|
|
||||||
/* get_all_node_records() will display the error */
|
|
||||||
PQfinish(conn);
|
|
||||||
exit(ERR_BAD_CONFIG);
|
|
||||||
}
|
|
||||||
|
|
||||||
PQfinish(conn);
|
PQfinish(conn);
|
||||||
conn = NULL;
|
conn = NULL;
|
||||||
@@ -1233,17 +1120,33 @@ build_cluster_crosscheck(t_node_status_cube ***dest_cube, int *name_length, Item
|
|||||||
|
|
||||||
initPQExpBuffer(&command);
|
initPQExpBuffer(&command);
|
||||||
|
|
||||||
make_remote_repmgr_path(&command, cell->node_info);
|
appendPQExpBuffer(&command,
|
||||||
|
"%s -d '%s' --node-id=%i ",
|
||||||
|
make_pg_path(progname()),
|
||||||
|
cell->node_info->conninfo,
|
||||||
|
remote_node_id);
|
||||||
|
|
||||||
appendPQExpBufferStr(&command,
|
if (strlen(pg_bindir))
|
||||||
" cluster matrix --csv -L NOTICE --terse");
|
{
|
||||||
|
appendPQExpBuffer(&command,
|
||||||
|
"--pg_bindir=");
|
||||||
|
appendShellString(&command,
|
||||||
|
pg_bindir);
|
||||||
|
appendPQExpBuffer(&command,
|
||||||
|
" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
appendPQExpBuffer(&command,
|
||||||
|
"cluster matrix --csv 2>/dev/null");
|
||||||
|
|
||||||
initPQExpBuffer(&command_output);
|
initPQExpBuffer(&command_output);
|
||||||
|
|
||||||
|
/* fix to work with --node-id */
|
||||||
if (cube[i]->node_id == config_file_options.node_id)
|
if (cube[i]->node_id == config_file_options.node_id)
|
||||||
{
|
{
|
||||||
(void) local_command_simple(command.data,
|
(void) local_command(
|
||||||
&command_output);
|
command.data,
|
||||||
|
&command_output);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1267,7 +1170,8 @@ build_cluster_crosscheck(t_node_status_cube ***dest_cube, int *name_length, Item
|
|||||||
|
|
||||||
log_verbose(LOG_DEBUG, "build_cluster_crosscheck(): executing\n %s", quoted_command.data);
|
log_verbose(LOG_DEBUG, "build_cluster_crosscheck(): executing\n %s", quoted_command.data);
|
||||||
|
|
||||||
(void) remote_command(host,
|
(void) remote_command(
|
||||||
|
host,
|
||||||
runtime_options.remote_user,
|
runtime_options.remote_user,
|
||||||
quoted_command.data,
|
quoted_command.data,
|
||||||
&command_output);
|
&command_output);
|
||||||
@@ -1280,13 +1184,9 @@ build_cluster_crosscheck(t_node_status_cube ***dest_cube, int *name_length, Item
|
|||||||
|
|
||||||
p = command_output.data;
|
p = command_output.data;
|
||||||
|
|
||||||
if (p[0] == '\0' || p[0] == '\n')
|
if (!strlen(command_output.data))
|
||||||
{
|
{
|
||||||
item_list_append_format(warnings,
|
|
||||||
"node %i inaccessible via SSH",
|
|
||||||
remote_node_id);
|
|
||||||
termPQExpBuffer(&command_output);
|
termPQExpBuffer(&command_output);
|
||||||
*error_code = ERR_BAD_SSH;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1298,24 +1198,17 @@ build_cluster_crosscheck(t_node_status_cube ***dest_cube, int *name_length, Item
|
|||||||
|
|
||||||
if (sscanf(p, "%d,%d,%d", &matrix_rec_node_id, &node_status_node_id, &node_status) != 3)
|
if (sscanf(p, "%d,%d,%d", &matrix_rec_node_id, &node_status_node_id, &node_status) != 3)
|
||||||
{
|
{
|
||||||
cube_set_node_status(cube,
|
fprintf(stderr, _("cannot parse --csv output: %s\n"), p);
|
||||||
nodes.node_count,
|
exit(ERR_INTERNAL);
|
||||||
remote_node_id,
|
|
||||||
matrix_rec_node_id,
|
|
||||||
node_status_node_id,
|
|
||||||
-2);
|
|
||||||
*error_code = ERR_INTERNAL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cube_set_node_status(cube,
|
|
||||||
nodes.node_count,
|
|
||||||
remote_node_id,
|
|
||||||
matrix_rec_node_id,
|
|
||||||
node_status_node_id,
|
|
||||||
node_status);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cube_set_node_status(cube,
|
||||||
|
nodes.node_count,
|
||||||
|
remote_node_id,
|
||||||
|
matrix_rec_node_id,
|
||||||
|
node_status_node_id,
|
||||||
|
node_status);
|
||||||
|
|
||||||
while (*p && (*p != '\n'))
|
while (*p && (*p != '\n'))
|
||||||
p++;
|
p++;
|
||||||
if (*p == '\n')
|
if (*p == '\n')
|
||||||
@@ -1374,7 +1267,6 @@ do_cluster_cleanup(void)
|
|||||||
PGconn *conn = NULL;
|
PGconn *conn = NULL;
|
||||||
PGconn *primary_conn = NULL;
|
PGconn *primary_conn = NULL;
|
||||||
int entries_to_delete = 0;
|
int entries_to_delete = 0;
|
||||||
PQExpBufferData event_details;
|
|
||||||
|
|
||||||
conn = establish_db_connection(config_file_options.conninfo, true);
|
conn = establish_db_connection(config_file_options.conninfo, true);
|
||||||
|
|
||||||
@@ -1386,17 +1278,9 @@ do_cluster_cleanup(void)
|
|||||||
|
|
||||||
log_debug(_("number of days of monitoring history to retain: %i"), runtime_options.keep_history);
|
log_debug(_("number of days of monitoring history to retain: %i"), runtime_options.keep_history);
|
||||||
|
|
||||||
entries_to_delete = get_number_of_monitoring_records_to_delete(primary_conn,
|
entries_to_delete = get_number_of_monitoring_records_to_delete(primary_conn, runtime_options.keep_history);
|
||||||
runtime_options.keep_history,
|
|
||||||
runtime_options.node_id);
|
|
||||||
|
|
||||||
if (entries_to_delete < 0)
|
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)
|
|
||||||
{
|
{
|
||||||
log_info(_("no monitoring records to delete"));
|
log_info(_("no monitoring records to delete"));
|
||||||
PQfinish(primary_conn);
|
PQfinish(primary_conn);
|
||||||
@@ -1406,23 +1290,10 @@ do_cluster_cleanup(void)
|
|||||||
log_debug("at least %i monitoring records for deletion",
|
log_debug("at least %i monitoring records for deletion",
|
||||||
entries_to_delete);
|
entries_to_delete);
|
||||||
|
|
||||||
initPQExpBuffer(&event_details);
|
if (delete_monitoring_records(primary_conn, runtime_options.keep_history) == false)
|
||||||
|
|
||||||
if (delete_monitoring_records(primary_conn, runtime_options.keep_history, runtime_options.node_id) == false)
|
|
||||||
{
|
{
|
||||||
appendPQExpBufferStr(&event_details,
|
log_error(_("unable to delete monitoring records"));
|
||||||
_("unable to delete monitoring records"));
|
|
||||||
|
|
||||||
log_error("%s", event_details.data);
|
|
||||||
log_detail("%s", PQerrorMessage(primary_conn));
|
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);
|
PQfinish(primary_conn);
|
||||||
exit(ERR_DB_QUERY);
|
exit(ERR_DB_QUERY);
|
||||||
}
|
}
|
||||||
@@ -1434,40 +1305,19 @@ do_cluster_cleanup(void)
|
|||||||
log_detail("%s", PQerrorMessage(primary_conn));
|
log_detail("%s", PQerrorMessage(primary_conn));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (runtime_options.keep_history == 0)
|
|
||||||
|
PQfinish(primary_conn);
|
||||||
|
|
||||||
|
if (runtime_options.keep_history > 0)
|
||||||
{
|
{
|
||||||
appendPQExpBufferStr(&event_details,
|
log_notice(_("monitoring records older than %i day(s) deleted"),
|
||||||
_("all monitoring records deleted"));
|
runtime_options.keep_history);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
appendPQExpBufferStr(&event_details,
|
log_info(_("all monitoring records deleted"));
|
||||||
_("monitoring records deleted"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (runtime_options.node_id != UNKNOWN_NODE_ID)
|
|
||||||
appendPQExpBuffer(&event_details,
|
|
||||||
_(" for node %i"),
|
|
||||||
runtime_options.node_id);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
log_notice("%s", event_details.data);
|
|
||||||
|
|
||||||
termPQExpBuffer(&event_details);
|
|
||||||
PQfinish(primary_conn);
|
|
||||||
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1482,7 +1332,6 @@ do_cluster_help(void)
|
|||||||
printf(_(" %s [OPTIONS] cluster matrix\n"), progname());
|
printf(_(" %s [OPTIONS] cluster matrix\n"), progname());
|
||||||
printf(_(" %s [OPTIONS] cluster crosscheck\n"), progname());
|
printf(_(" %s [OPTIONS] cluster crosscheck\n"), progname());
|
||||||
printf(_(" %s [OPTIONS] cluster event\n"), progname());
|
printf(_(" %s [OPTIONS] cluster event\n"), progname());
|
||||||
printf(_(" %s [OPTIONS] cluster cleanup\n"), progname());
|
|
||||||
puts("");
|
puts("");
|
||||||
|
|
||||||
printf(_("CLUSTER SHOW\n"));
|
printf(_("CLUSTER SHOW\n"));
|
||||||
@@ -1522,7 +1371,6 @@ do_cluster_help(void)
|
|||||||
printf(_(" --event filter specific event\n"));
|
printf(_(" --event filter specific event\n"));
|
||||||
printf(_(" --node-id restrict entries to node with this ID\n"));
|
printf(_(" --node-id restrict entries to node with this ID\n"));
|
||||||
printf(_(" --node-name restrict entries to node with this name\n"));
|
printf(_(" --node-name restrict entries to node with this name\n"));
|
||||||
printf(_(" --csv emit output as CSV\n"));
|
|
||||||
puts("");
|
puts("");
|
||||||
|
|
||||||
printf(_("CLUSTER CLEANUP\n"));
|
printf(_("CLUSTER CLEANUP\n"));
|
||||||
|
|||||||
@@ -1,420 +0,0 @@
|
|||||||
/*
|
|
||||||
* repmgr-action-daemon.c
|
|
||||||
*
|
|
||||||
* Implements repmgrd actions for the repmgr command line utility
|
|
||||||
* Copyright (c) 2ndQuadrant, 2010-2018
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "repmgr.h"
|
|
||||||
|
|
||||||
#include "repmgr-client-global.h"
|
|
||||||
#include "repmgr-action-daemon.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Possibly also show:
|
|
||||||
* - repmgrd start time?
|
|
||||||
* - repmgrd mode
|
|
||||||
* - priority
|
|
||||||
* - whether promotion candidate (due to zero priority/different location)
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
STATUS_ID = 0,
|
|
||||||
STATUS_NAME,
|
|
||||||
STATUS_ROLE,
|
|
||||||
STATUS_PG,
|
|
||||||
STATUS_RUNNING,
|
|
||||||
STATUS_PID,
|
|
||||||
STATUS_PAUSED
|
|
||||||
} StatusHeader;
|
|
||||||
|
|
||||||
#define STATUS_HEADER_COUNT 7
|
|
||||||
|
|
||||||
struct ColHeader headers_status[STATUS_HEADER_COUNT];
|
|
||||||
|
|
||||||
static void fetch_node_records(PGconn *conn, NodeInfoList *node_list);
|
|
||||||
static void _do_repmgr_pause(bool pause);
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
do_daemon_status(void)
|
|
||||||
{
|
|
||||||
PGconn *conn = NULL;
|
|
||||||
NodeInfoList nodes = T_NODE_INFO_LIST_INITIALIZER;
|
|
||||||
NodeInfoListCell *cell = NULL;
|
|
||||||
int i;
|
|
||||||
RepmgrdInfo **repmgrd_info;
|
|
||||||
ItemList warnings = {NULL, NULL};
|
|
||||||
|
|
||||||
/* Connect to local database to obtain cluster connection data */
|
|
||||||
log_verbose(LOG_INFO, _("connecting to database"));
|
|
||||||
|
|
||||||
if (strlen(config_file_options.conninfo))
|
|
||||||
conn = establish_db_connection(config_file_options.conninfo, true);
|
|
||||||
else
|
|
||||||
conn = establish_db_connection_by_params(&source_conninfo, true);
|
|
||||||
|
|
||||||
fetch_node_records(conn, &nodes);
|
|
||||||
|
|
||||||
repmgrd_info = (RepmgrdInfo **) pg_malloc0(sizeof(RepmgrdInfo *) * nodes.node_count);
|
|
||||||
|
|
||||||
if (repmgrd_info == NULL)
|
|
||||||
{
|
|
||||||
log_error(_("unable to allocate memory"));
|
|
||||||
exit(ERR_OUT_OF_MEMORY);
|
|
||||||
}
|
|
||||||
|
|
||||||
strncpy(headers_status[STATUS_ID].title, _("ID"), MAXLEN);
|
|
||||||
strncpy(headers_status[STATUS_NAME].title, _("Name"), MAXLEN);
|
|
||||||
strncpy(headers_status[STATUS_ROLE].title, _("Role"), MAXLEN);
|
|
||||||
strncpy(headers_status[STATUS_PG].title, _("Status"), MAXLEN);
|
|
||||||
strncpy(headers_status[STATUS_RUNNING].title, _("repmgrd"), MAXLEN);
|
|
||||||
strncpy(headers_status[STATUS_PID].title, _("PID"), MAXLEN);
|
|
||||||
strncpy(headers_status[STATUS_PAUSED].title, _("Paused?"), MAXLEN);
|
|
||||||
|
|
||||||
for (i = 0; i < STATUS_HEADER_COUNT; i++)
|
|
||||||
{
|
|
||||||
headers_status[i].max_length = strlen(headers_status[i].title);
|
|
||||||
}
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
|
|
||||||
for (cell = nodes.head; cell; cell = cell->next)
|
|
||||||
{
|
|
||||||
int j;
|
|
||||||
|
|
||||||
repmgrd_info[i] = pg_malloc0(sizeof(RepmgrdInfo));
|
|
||||||
repmgrd_info[i]->node_id = cell->node_info->node_id;
|
|
||||||
repmgrd_info[i]->pid = UNKNOWN_PID;
|
|
||||||
repmgrd_info[i]->paused = false;
|
|
||||||
repmgrd_info[i]->running = false;
|
|
||||||
repmgrd_info[i]->pg_running = true;
|
|
||||||
|
|
||||||
cell->node_info->conn = establish_db_connection_quiet(cell->node_info->conninfo);
|
|
||||||
|
|
||||||
if (PQstatus(cell->node_info->conn) != CONNECTION_OK)
|
|
||||||
{
|
|
||||||
if (runtime_options.verbose)
|
|
||||||
{
|
|
||||||
char error[MAXLEN];
|
|
||||||
|
|
||||||
strncpy(error, PQerrorMessage(cell->node_info->conn), MAXLEN);
|
|
||||||
|
|
||||||
item_list_append_format(&warnings,
|
|
||||||
"when attempting to connect to node \"%s\" (ID: %i), following error encountered :\n\"%s\"",
|
|
||||||
cell->node_info->node_name, cell->node_info->node_id, trim(error));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
item_list_append_format(&warnings,
|
|
||||||
"unable to connect to node \"%s\" (ID: %i)",
|
|
||||||
cell->node_info->node_name, cell->node_info->node_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
repmgrd_info[i]->pg_running = false;
|
|
||||||
maxlen_snprintf(repmgrd_info[i]->pg_running_text, "%s", _("not running"));
|
|
||||||
maxlen_snprintf(repmgrd_info[i]->repmgrd_running, "%s", _("n/a"));
|
|
||||||
maxlen_snprintf(repmgrd_info[i]->pid_text, "%s", _("n/a"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
maxlen_snprintf(repmgrd_info[i]->pg_running_text, "%s", _("running"));
|
|
||||||
|
|
||||||
repmgrd_info[i]->pid = repmgrd_get_pid(cell->node_info->conn);
|
|
||||||
|
|
||||||
repmgrd_info[i]->running = repmgrd_is_running(cell->node_info->conn);
|
|
||||||
|
|
||||||
if (repmgrd_info[i]->running == true)
|
|
||||||
{
|
|
||||||
maxlen_snprintf(repmgrd_info[i]->repmgrd_running, "%s", _("running"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
maxlen_snprintf(repmgrd_info[i]->repmgrd_running, "%s", _("not running"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (repmgrd_info[i]->pid == UNKNOWN_PID)
|
|
||||||
{
|
|
||||||
maxlen_snprintf(repmgrd_info[i]->pid_text, "%s", _("n/a"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
maxlen_snprintf(repmgrd_info[i]->pid_text, "%i", repmgrd_info[i]->pid);
|
|
||||||
}
|
|
||||||
|
|
||||||
repmgrd_info[i]->paused = repmgrd_is_paused(cell->node_info->conn);
|
|
||||||
|
|
||||||
PQfinish(cell->node_info->conn);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
headers_status[STATUS_NAME].cur_length = strlen(cell->node_info->node_name);
|
|
||||||
headers_status[STATUS_ROLE].cur_length = strlen(get_node_type_string(cell->node_info->type));
|
|
||||||
headers_status[STATUS_PID].cur_length = strlen(repmgrd_info[i]->pid_text);
|
|
||||||
headers_status[STATUS_RUNNING].cur_length = strlen(repmgrd_info[i]->repmgrd_running);
|
|
||||||
headers_status[STATUS_PG].cur_length = strlen(repmgrd_info[i]->pg_running_text);
|
|
||||||
|
|
||||||
for (j = 0; j < STATUS_HEADER_COUNT; j++)
|
|
||||||
{
|
|
||||||
if (headers_status[j].cur_length > headers_status[j].max_length)
|
|
||||||
{
|
|
||||||
headers_status[j].max_length = headers_status[j].cur_length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Print column header row (text mode only) */
|
|
||||||
if (runtime_options.output_mode == OM_TEXT)
|
|
||||||
{
|
|
||||||
print_status_header(STATUS_HEADER_COUNT, headers_status);
|
|
||||||
}
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
|
|
||||||
for (cell = nodes.head; cell; cell = cell->next)
|
|
||||||
{
|
|
||||||
if (runtime_options.output_mode == OM_CSV)
|
|
||||||
{
|
|
||||||
printf("%i,%s,%s,%i,%i,%i,%i\n",
|
|
||||||
cell->node_info->node_id,
|
|
||||||
cell->node_info->node_name,
|
|
||||||
get_node_type_string(cell->node_info->type),
|
|
||||||
repmgrd_info[i]->pg_running ? 1 : 0,
|
|
||||||
repmgrd_info[i]->running ? 1 : 0,
|
|
||||||
repmgrd_info[i]->pid,
|
|
||||||
repmgrd_info[i]->paused ? 1 : 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf(" %-*i ", headers_status[STATUS_ID].max_length, cell->node_info->node_id);
|
|
||||||
printf("| %-*s ", headers_status[STATUS_NAME].max_length, cell->node_info->node_name);
|
|
||||||
printf("| %-*s ", headers_status[STATUS_ROLE].max_length, get_node_type_string(cell->node_info->type));
|
|
||||||
|
|
||||||
printf("| %-*s ", headers_status[STATUS_PG].max_length, repmgrd_info[i]->pg_running_text);
|
|
||||||
printf("| %-*s ", headers_status[STATUS_RUNNING].max_length, repmgrd_info[i]->repmgrd_running);
|
|
||||||
printf("| %-*s ", headers_status[STATUS_PID].max_length, repmgrd_info[i]->pid_text);
|
|
||||||
|
|
||||||
if (repmgrd_info[i]->pid == UNKNOWN_PID)
|
|
||||||
printf("| %-*s ", headers_status[STATUS_PAUSED].max_length, "n/a");
|
|
||||||
else
|
|
||||||
printf("| %-*s ", headers_status[STATUS_PAUSED].max_length, repmgrd_info[i]->paused ? "yes" : "no");
|
|
||||||
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
free(repmgrd_info[i]);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(repmgrd_info);
|
|
||||||
|
|
||||||
/* emit any warnings */
|
|
||||||
|
|
||||||
if (warnings.head != NULL && runtime_options.terse == false && runtime_options.output_mode != OM_CSV)
|
|
||||||
{
|
|
||||||
ItemListCell *cell = NULL;
|
|
||||||
|
|
||||||
printf(_("\nWARNING: following issues were detected\n"));
|
|
||||||
for (cell = warnings.head; cell; cell = cell->next)
|
|
||||||
{
|
|
||||||
printf(_(" - %s\n"), cell->string);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (runtime_options.verbose == false)
|
|
||||||
{
|
|
||||||
log_hint(_("execute with --verbose option to see connection error messages"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
do_daemon_pause(void)
|
|
||||||
{
|
|
||||||
_do_repmgr_pause(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
do_daemon_unpause(void)
|
|
||||||
{
|
|
||||||
_do_repmgr_pause(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
_do_repmgr_pause(bool pause)
|
|
||||||
{
|
|
||||||
PGconn *conn = NULL;
|
|
||||||
NodeInfoList nodes = T_NODE_INFO_LIST_INITIALIZER;
|
|
||||||
NodeInfoListCell *cell = NULL;
|
|
||||||
RepmgrdInfo **repmgrd_info;
|
|
||||||
int i;
|
|
||||||
int error_nodes = 0;
|
|
||||||
|
|
||||||
repmgrd_info = (RepmgrdInfo **) pg_malloc0(sizeof(RepmgrdInfo *) * nodes.node_count);
|
|
||||||
|
|
||||||
if (repmgrd_info == NULL)
|
|
||||||
{
|
|
||||||
log_error(_("unable to allocate memory"));
|
|
||||||
exit(ERR_OUT_OF_MEMORY);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Connect to local database to obtain cluster connection data */
|
|
||||||
log_verbose(LOG_INFO, _("connecting to database"));
|
|
||||||
|
|
||||||
if (strlen(config_file_options.conninfo))
|
|
||||||
conn = establish_db_connection(config_file_options.conninfo, true);
|
|
||||||
else
|
|
||||||
conn = establish_db_connection_by_params(&source_conninfo, true);
|
|
||||||
|
|
||||||
fetch_node_records(conn, &nodes);
|
|
||||||
|
|
||||||
i = 0;
|
|
||||||
|
|
||||||
for (cell = nodes.head; cell; cell = cell->next)
|
|
||||||
{
|
|
||||||
repmgrd_info[i] = pg_malloc0(sizeof(RepmgrdInfo));
|
|
||||||
repmgrd_info[i]->node_id = cell->node_info->node_id;
|
|
||||||
|
|
||||||
log_verbose(LOG_DEBUG, "pausing node %i (%s)",
|
|
||||||
cell->node_info->node_id,
|
|
||||||
cell->node_info->node_name);
|
|
||||||
cell->node_info->conn = establish_db_connection_quiet(cell->node_info->conninfo);
|
|
||||||
|
|
||||||
if (PQstatus(cell->node_info->conn) != CONNECTION_OK)
|
|
||||||
{
|
|
||||||
log_warning(_("unable to connect to node %i"),
|
|
||||||
cell->node_info->node_id);
|
|
||||||
error_nodes++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (runtime_options.dry_run == true)
|
|
||||||
{
|
|
||||||
if (pause == true)
|
|
||||||
{
|
|
||||||
log_info(_("would pause node %i (%s) "),
|
|
||||||
cell->node_info->node_id,
|
|
||||||
cell->node_info->node_name);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
log_info(_("would unpause node %i (%s) "),
|
|
||||||
cell->node_info->node_id,
|
|
||||||
cell->node_info->node_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bool success = repmgrd_pause(cell->node_info->conn, pause);
|
|
||||||
|
|
||||||
if (success == false)
|
|
||||||
error_nodes++;
|
|
||||||
|
|
||||||
log_notice(_("node %i (%s) %s"),
|
|
||||||
cell->node_info->node_id,
|
|
||||||
cell->node_info->node_name,
|
|
||||||
success == true
|
|
||||||
? pause == true ? "paused" : "unpaused"
|
|
||||||
: pause == true ? "not paused" : "not unpaused");
|
|
||||||
}
|
|
||||||
PQfinish(cell->node_info->conn);
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error_nodes > 0)
|
|
||||||
{
|
|
||||||
if (pause == true)
|
|
||||||
{
|
|
||||||
log_error(_("unable to pause %i node(s)"), error_nodes);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
log_error(_("unable to unpause %i node(s)"), error_nodes);
|
|
||||||
}
|
|
||||||
|
|
||||||
log_hint(_("execute \"repmgr daemon status\" to view current status"));
|
|
||||||
|
|
||||||
exit(ERR_REPMGRD_PAUSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
exit(SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
fetch_node_records(PGconn *conn, NodeInfoList *node_list)
|
|
||||||
{
|
|
||||||
bool success = get_all_node_records(conn, node_list);
|
|
||||||
|
|
||||||
if (success == false)
|
|
||||||
{
|
|
||||||
/* get_all_node_records() will display any error message */
|
|
||||||
PQfinish(conn);
|
|
||||||
exit(ERR_BAD_CONFIG);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node_list->node_count == 0)
|
|
||||||
{
|
|
||||||
log_error(_("no node records were found"));
|
|
||||||
log_hint(_("ensure at least one node is registered"));
|
|
||||||
PQfinish(conn);
|
|
||||||
exit(ERR_BAD_CONFIG);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void do_daemon_help(void)
|
|
||||||
{
|
|
||||||
print_help_header();
|
|
||||||
|
|
||||||
printf(_("Usage:\n"));
|
|
||||||
printf(_(" %s [OPTIONS] daemon status\n"), progname());
|
|
||||||
printf(_(" %s [OPTIONS] daemon pause\n"), progname());
|
|
||||||
printf(_(" %s [OPTIONS] daemon unpause\n"), progname());
|
|
||||||
puts("");
|
|
||||||
|
|
||||||
printf(_("DAEMON STATUS\n"));
|
|
||||||
puts("");
|
|
||||||
printf(_(" \"daemon status\" shows the status of repmgrd on each node in the cluster\n"));
|
|
||||||
puts("");
|
|
||||||
printf(_(" --csv emit output as CSV\n"));
|
|
||||||
printf(_(" --verbose show text of database connection error messages\n"));
|
|
||||||
puts("");
|
|
||||||
|
|
||||||
printf(_("DAEMON PAUSE\n"));
|
|
||||||
puts("");
|
|
||||||
printf(_(" \"daemon pause\" instructs repmgrd on each node to pause failover detection\n"));
|
|
||||||
puts("");
|
|
||||||
printf(_(" --dry-run check if nodes are reachable but don't pause repmgrd\n"));
|
|
||||||
puts("");
|
|
||||||
|
|
||||||
printf(_("DAEMON PAUSE\n"));
|
|
||||||
puts("");
|
|
||||||
printf(_(" \"daemon unpause\" instructs repmgrd on each node to resume failover detection\n"));
|
|
||||||
puts("");
|
|
||||||
printf(_(" --dry-run check if nodes are reachable but don't unpause repmgrd\n"));
|
|
||||||
puts("");
|
|
||||||
|
|
||||||
|
|
||||||
puts("");
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
/*
|
|
||||||
* repmgr-action-daemon.h
|
|
||||||
* Copyright (c) 2ndQuadrant, 2010-2018
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _REPMGR_ACTION_DAEMON_H_
|
|
||||||
#define _REPMGR_ACTION_DAEMON_H_
|
|
||||||
|
|
||||||
|
|
||||||
extern void do_daemon_status(void);
|
|
||||||
extern void do_daemon_pause(void);
|
|
||||||
extern void do_daemon_unpause(void);
|
|
||||||
|
|
||||||
extern void do_daemon_help(void);
|
|
||||||
#endif
|
|
||||||
1568
repmgr-action-node.c
1568
repmgr-action-node.c
File diff suppressed because it is too large
Load Diff
@@ -64,10 +64,12 @@ do_primary_register(void)
|
|||||||
PQfinish(conn);
|
PQfinish(conn);
|
||||||
exit(ERR_BAD_CONFIG);
|
exit(ERR_BAD_CONFIG);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
log_error(_("unable to determine server's recovery type"));
|
{
|
||||||
PQfinish(conn);
|
log_error(_("connection to node lost"));
|
||||||
exit(ERR_DB_CONN);
|
PQfinish(conn);
|
||||||
|
exit(ERR_DB_CONN);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log_verbose(LOG_INFO, _("server is not in recovery"));
|
log_verbose(LOG_INFO, _("server is not in recovery"));
|
||||||
@@ -170,8 +172,8 @@ do_primary_register(void)
|
|||||||
&node_info);
|
&node_info);
|
||||||
if (record_created == true)
|
if (record_created == true)
|
||||||
{
|
{
|
||||||
appendPQExpBufferStr(&event_description,
|
appendPQExpBuffer(&event_description,
|
||||||
"existing primary record updated");
|
"existing primary record updated");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -65,7 +65,7 @@ do_witness_register(void)
|
|||||||
if (recovery_type == RECTYPE_STANDBY)
|
if (recovery_type == RECTYPE_STANDBY)
|
||||||
{
|
{
|
||||||
log_error(_("provided node is a standby"));
|
log_error(_("provided node is a standby"));
|
||||||
log_hint(_("a witness node must run on an independent primary server"));
|
log_error(_("a witness node must run on an independent primary server"));
|
||||||
|
|
||||||
PQfinish(witness_conn);
|
PQfinish(witness_conn);
|
||||||
|
|
||||||
@@ -86,7 +86,6 @@ do_witness_register(void)
|
|||||||
|
|
||||||
/* connect to primary with provided parameters */
|
/* connect to primary with provided parameters */
|
||||||
log_info(_("connecting to primary node"));
|
log_info(_("connecting to primary node"));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Extract the repmgr user and database names from the conninfo string
|
* Extract the repmgr user and database names from the conninfo string
|
||||||
* provided in repmgr.conf
|
* provided in repmgr.conf
|
||||||
@@ -136,11 +135,8 @@ do_witness_register(void)
|
|||||||
exit(ERR_BAD_CONFIG);
|
exit(ERR_BAD_CONFIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* XXX sanity check witness node is not part of main cluster */
|
||||||
* 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* create repmgr extension, if does not exist */
|
/* create repmgr extension, if does not exist */
|
||||||
if (runtime_options.dry_run == false && !create_repmgr_extension(witness_conn))
|
if (runtime_options.dry_run == false && !create_repmgr_extension(witness_conn))
|
||||||
@@ -186,6 +182,7 @@ do_witness_register(void)
|
|||||||
log_error(_("witness node is already registered"));
|
log_error(_("witness node is already registered"));
|
||||||
log_hint(_("use option -F/--force to reregister the node"));
|
log_hint(_("use option -F/--force to reregister the node"));
|
||||||
|
|
||||||
|
|
||||||
PQfinish(witness_conn);
|
PQfinish(witness_conn);
|
||||||
PQfinish(primary_conn);
|
PQfinish(primary_conn);
|
||||||
|
|
||||||
@@ -193,38 +190,14 @@ 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,
|
// XXX check other node with same name does not exist
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* if repmgr.nodes contains entries, delete if -F/--force provided,
|
* if repmgr.nodes contains entries, delete if -F/--force provided,
|
||||||
* otherwise exit with error
|
* otherwise exit with error
|
||||||
*/
|
*/
|
||||||
if (get_all_node_records(witness_conn, &nodes) == false)
|
get_all_node_records(witness_conn, &nodes);
|
||||||
{
|
|
||||||
/* get_all_node_records() will display the error */
|
|
||||||
PQfinish(witness_conn);
|
|
||||||
PQfinish(primary_conn);
|
|
||||||
exit(ERR_BAD_CONFIG);
|
|
||||||
}
|
|
||||||
|
|
||||||
log_verbose(LOG_DEBUG, "%i node records found", nodes.node_count);
|
log_verbose(LOG_DEBUG, "%i node records found", nodes.node_count);
|
||||||
|
|
||||||
@@ -249,7 +222,6 @@ do_witness_register(void)
|
|||||||
PQfinish(witness_conn);
|
PQfinish(witness_conn);
|
||||||
exit(SUCCESS);
|
exit(SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* create record on primary */
|
/* create record on primary */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -316,59 +288,55 @@ do_witness_register(void)
|
|||||||
void
|
void
|
||||||
do_witness_unregister(void)
|
do_witness_unregister(void)
|
||||||
{
|
{
|
||||||
PGconn *local_conn = NULL;
|
PGconn *witness_conn = NULL;
|
||||||
PGconn *primary_conn = NULL;
|
PGconn *primary_conn = NULL;
|
||||||
t_node_info node_record = T_NODE_INFO_INITIALIZER;
|
t_node_info node_record = T_NODE_INFO_INITIALIZER;
|
||||||
RecordStatus record_status = RECORD_NOT_FOUND;
|
RecordStatus record_status = RECORD_NOT_FOUND;
|
||||||
bool node_record_deleted = false;
|
bool node_record_deleted = false;
|
||||||
bool local_node_available = true;
|
bool witness_available = true;
|
||||||
int witness_node_id = UNKNOWN_NODE_ID;
|
|
||||||
|
|
||||||
if (runtime_options.node_id != UNKNOWN_NODE_ID)
|
log_info(_("connecting to witness node \"%s\" (ID: %i)"),
|
||||||
{
|
|
||||||
/* 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)"),
|
|
||||||
config_file_options.node_name,
|
config_file_options.node_name,
|
||||||
config_file_options.node_id);
|
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)
|
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_name,
|
||||||
config_file_options.node_id);
|
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);
|
exit(ERR_BAD_CONFIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
log_notice(_("unable to connect to witness node \"%s\" (ID: %i), removing node record on cluster primary only"),
|
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_name,
|
||||||
config_file_options.node_id);
|
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
|
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);
|
primary_conn = establish_db_connection_by_params(&source_conninfo, false);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PQstatus(primary_conn) != CONNECTION_OK)
|
if (PQstatus(primary_conn) != CONNECTION_OK)
|
||||||
@@ -376,26 +344,26 @@ do_witness_unregister(void)
|
|||||||
log_error(_("unable to connect to primary"));
|
log_error(_("unable to connect to primary"));
|
||||||
log_detail("%s", PQerrorMessage(primary_conn));
|
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);
|
exit(ERR_BAD_CONFIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check node exists and is really a witness */
|
/* 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)
|
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)
|
if (witness_available == true)
|
||||||
PQfinish(local_conn);
|
PQfinish(witness_conn);
|
||||||
PQfinish(primary_conn);
|
PQfinish(primary_conn);
|
||||||
|
|
||||||
exit(ERR_BAD_CONFIG);
|
exit(ERR_BAD_CONFIG);
|
||||||
@@ -403,17 +371,11 @@ do_witness_unregister(void)
|
|||||||
|
|
||||||
if (node_record.type != WITNESS)
|
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_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));
|
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)
|
if (witness_available == true)
|
||||||
PQfinish(local_conn);
|
PQfinish(witness_conn);
|
||||||
PQfinish(primary_conn);
|
PQfinish(primary_conn);
|
||||||
|
|
||||||
exit(ERR_BAD_CONFIG);
|
exit(ERR_BAD_CONFIG);
|
||||||
@@ -422,43 +384,49 @@ do_witness_unregister(void)
|
|||||||
if (runtime_options.dry_run == true)
|
if (runtime_options.dry_run == true)
|
||||||
{
|
{
|
||||||
log_info(_("prerequisites for unregistering the witness node are met"));
|
log_info(_("prerequisites for unregistering the witness node are met"));
|
||||||
if (local_node_available == true)
|
if (witness_available == true)
|
||||||
PQfinish(local_conn);
|
PQfinish(witness_conn);
|
||||||
PQfinish(primary_conn);
|
PQfinish(primary_conn);
|
||||||
|
|
||||||
exit(SUCCESS);
|
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,
|
node_record_deleted = delete_node_record(primary_conn,
|
||||||
witness_node_id);
|
config_file_options.node_id);
|
||||||
|
|
||||||
if (node_record_deleted == false)
|
if (node_record_deleted == false)
|
||||||
{
|
{
|
||||||
PQfinish(primary_conn);
|
PQfinish(primary_conn);
|
||||||
|
PQfinish(witness_conn);
|
||||||
|
exit(ERR_BAD_CONFIG);
|
||||||
|
}
|
||||||
|
|
||||||
if (local_node_available == true)
|
/* sync records from primary */
|
||||||
PQfinish(local_conn);
|
if (witness_available == true && witness_copy_node_records(primary_conn, witness_conn) == false)
|
||||||
PQfinish(local_conn);
|
{
|
||||||
|
log_error(_("unable to copy repmgr node records from primary"));
|
||||||
|
PQfinish(primary_conn);
|
||||||
|
PQfinish(witness_conn);
|
||||||
exit(ERR_BAD_CONFIG);
|
exit(ERR_BAD_CONFIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Log the event */
|
/* Log the event */
|
||||||
create_event_record(primary_conn,
|
create_event_record(primary_conn,
|
||||||
&config_file_options,
|
&config_file_options,
|
||||||
witness_node_id,
|
config_file_options.node_id,
|
||||||
"witness_unregister",
|
"witness_unregister",
|
||||||
true,
|
true,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
PQfinish(primary_conn);
|
PQfinish(primary_conn);
|
||||||
|
|
||||||
if (local_node_available == true)
|
if (witness_available == true)
|
||||||
PQfinish(local_conn);
|
PQfinish(witness_conn);
|
||||||
|
|
||||||
log_info(_("witness unregistration complete"));
|
log_info(_("witness unregistration complete"));
|
||||||
log_detail(_("witness node with ID %i successfully unregistered"),
|
log_detail(_("witness node with id %i (conninfo: %s) successfully unregistered"),
|
||||||
witness_node_id);
|
config_file_options.node_id, config_file_options.conninfo);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -478,19 +446,16 @@ void do_witness_help(void)
|
|||||||
puts("");
|
puts("");
|
||||||
printf(_(" Requires provision of connection information for the primary\n"));
|
printf(_(" Requires provision of connection information for the primary\n"));
|
||||||
puts("");
|
puts("");
|
||||||
printf(_(" --dry-run check prerequisites but don't make any changes\n"));
|
printf(_(" --dry-run check prerequisites but don't make any changes\n"));
|
||||||
printf(_(" -F, --force overwrite an existing node record\n"));
|
printf(_(" -F, --force overwrite an existing node record\n"));
|
||||||
puts("");
|
puts("");
|
||||||
|
|
||||||
printf(_("WITNESS UNREGISTER\n"));
|
printf(_("WITNESS UNREGISTER\n"));
|
||||||
puts("");
|
puts("");
|
||||||
printf(_(" \"witness register\" unregisters a witness node.\n"));
|
printf(_(" \"witness register\" unregisters a witness node.\n"));
|
||||||
puts("");
|
puts("");
|
||||||
printf(_(" --dry-run check prerequisites but don't make any changes\n"));
|
printf(_(" --dry-run check prerequisites but don't make any changes\n"));
|
||||||
printf(_(" -F, --force unregister when witness node not running\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"));
|
|
||||||
|
|
||||||
puts("");
|
puts("");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -42,12 +42,10 @@ typedef struct
|
|||||||
bool force;
|
bool force;
|
||||||
char pg_bindir[MAXLEN]; /* overrides setting in repmgr.conf */
|
char pg_bindir[MAXLEN]; /* overrides setting in repmgr.conf */
|
||||||
bool wait;
|
bool wait;
|
||||||
bool no_wait;
|
|
||||||
|
|
||||||
/* logging options */
|
/* logging options */
|
||||||
char log_level[MAXLEN]; /* overrides setting in repmgr.conf */
|
char log_level[MAXLEN]; /* overrides setting in repmgr.conf */
|
||||||
bool log_to_file;
|
bool log_to_file;
|
||||||
bool quiet;
|
|
||||||
bool terse;
|
bool terse;
|
||||||
bool verbose;
|
bool verbose;
|
||||||
|
|
||||||
@@ -94,10 +92,8 @@ typedef struct
|
|||||||
|
|
||||||
/* "standby switchover" options */
|
/* "standby switchover" options */
|
||||||
bool always_promote;
|
bool always_promote;
|
||||||
bool force_rewind_used;
|
bool force_rewind;
|
||||||
char force_rewind_path[MAXPGPATH];
|
|
||||||
bool siblings_follow;
|
bool siblings_follow;
|
||||||
bool repmgrd_no_pause;
|
|
||||||
|
|
||||||
/* "node status" options */
|
/* "node status" options */
|
||||||
bool is_shutdown_cleanly;
|
bool is_shutdown_cleanly;
|
||||||
@@ -108,7 +104,6 @@ typedef struct
|
|||||||
bool replication_lag;
|
bool replication_lag;
|
||||||
bool role;
|
bool role;
|
||||||
bool slots;
|
bool slots;
|
||||||
bool missing_slots;
|
|
||||||
bool has_passfile;
|
bool has_passfile;
|
||||||
bool replication_connection;
|
bool replication_connection;
|
||||||
|
|
||||||
@@ -138,9 +133,9 @@ typedef struct
|
|||||||
/* configuration metadata */ \
|
/* configuration metadata */ \
|
||||||
false, false, false, false, \
|
false, false, false, false, \
|
||||||
/* general configuration options */ \
|
/* general configuration options */ \
|
||||||
"", false, false, "", false, false, \
|
"", false, false, "", false, \
|
||||||
/* logging options */ \
|
/* logging options */ \
|
||||||
"", false, false, false, false, \
|
"", false, false, false, \
|
||||||
/* output options */ \
|
/* output options */ \
|
||||||
false, false, false, \
|
false, false, false, \
|
||||||
/* database connection options */ \
|
/* database connection options */ \
|
||||||
@@ -155,13 +150,13 @@ typedef struct
|
|||||||
/* "standby clone"/"standby follow" options */ \
|
/* "standby clone"/"standby follow" options */ \
|
||||||
NO_UPSTREAM_NODE, \
|
NO_UPSTREAM_NODE, \
|
||||||
/* "standby register" options */ \
|
/* "standby register" options */ \
|
||||||
false, -1, DEFAULT_WAIT_START, \
|
false, 0, DEFAULT_WAIT_START, \
|
||||||
/* "standby switchover" options */ \
|
/* "standby switchover" options */ \
|
||||||
false, false, "", false, false, \
|
false, false, false, \
|
||||||
/* "node status" options */ \
|
/* "node status" options */ \
|
||||||
false, \
|
false, \
|
||||||
/* "node check" options */ \
|
/* "node check" options */ \
|
||||||
false, false, false, false, false, false, false, false, \
|
false, false, false, false, false, false, false, \
|
||||||
/* "node join" options */ \
|
/* "node join" options */ \
|
||||||
"", \
|
"", \
|
||||||
/* "node service" options */ \
|
/* "node service" options */ \
|
||||||
@@ -194,14 +189,6 @@ typedef enum
|
|||||||
} t_server_action;
|
} t_server_action;
|
||||||
|
|
||||||
|
|
||||||
typedef struct ColHeader
|
|
||||||
{
|
|
||||||
char title[MAXLEN];
|
|
||||||
int max_length;
|
|
||||||
int cur_length;
|
|
||||||
} ColHeader;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* global configuration structures */
|
/* global configuration structures */
|
||||||
extern t_runtime_options runtime_options;
|
extern t_runtime_options runtime_options;
|
||||||
@@ -221,7 +208,6 @@ extern void check_93_config(void);
|
|||||||
extern bool create_repmgr_extension(PGconn *conn);
|
extern bool create_repmgr_extension(PGconn *conn);
|
||||||
extern int test_ssh_connection(char *host, char *remote_user);
|
extern int test_ssh_connection(char *host, char *remote_user);
|
||||||
extern bool local_command(const char *command, PQExpBufferData *outputbuf);
|
extern bool local_command(const char *command, PQExpBufferData *outputbuf);
|
||||||
extern bool local_command_simple(const char *command, PQExpBufferData *outputbuf);
|
|
||||||
|
|
||||||
extern standy_clone_mode get_standby_clone_mode(void);
|
extern standy_clone_mode get_standby_clone_mode(void);
|
||||||
|
|
||||||
@@ -237,18 +223,12 @@ extern void get_superuser_connection(PGconn **conn, PGconn **superuser_conn, PGc
|
|||||||
extern bool remote_command(const char *host, const char *user, const char *command, PQExpBufferData *outputbuf);
|
extern bool remote_command(const char *host, const char *user, const char *command, PQExpBufferData *outputbuf);
|
||||||
|
|
||||||
extern void make_remote_repmgr_path(PQExpBufferData *outputbuf, t_node_info *remote_node_record);
|
extern void make_remote_repmgr_path(PQExpBufferData *outputbuf, t_node_info *remote_node_record);
|
||||||
|
|
||||||
/* display functions */
|
|
||||||
extern void print_help_header(void);
|
extern void print_help_header(void);
|
||||||
extern void print_status_header(int cols, ColHeader *headers);
|
|
||||||
|
|
||||||
/* server control functions */
|
/* server control functions */
|
||||||
extern void get_server_action(t_server_action action, char *script, char *data_dir);
|
extern void get_server_action(t_server_action action, char *script, char *data_dir);
|
||||||
extern bool data_dir_required_for_action(t_server_action action);
|
extern bool data_dir_required_for_action(t_server_action action);
|
||||||
extern void get_node_config_directory(char *config_dir_buf);
|
|
||||||
extern void get_node_data_directory(char *data_dir_buf);
|
extern void get_node_data_directory(char *data_dir_buf);
|
||||||
extern void init_node_record(t_node_info *node_record);
|
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_ */
|
#endif /* _REPMGR_CLIENT_GLOBAL_H_ */
|
||||||
|
|||||||
450
repmgr-client.c
450
repmgr-client.c
@@ -30,15 +30,10 @@
|
|||||||
* NODE STATUS
|
* NODE STATUS
|
||||||
* NODE CHECK
|
* NODE CHECK
|
||||||
*
|
*
|
||||||
* DAEMON STATUS
|
|
||||||
* DAEMON PAUSE
|
|
||||||
* DAEMON UNPAUSE
|
|
||||||
*
|
|
||||||
* For internal use:
|
* For internal use:
|
||||||
* NODE REJOIN
|
* NODE REJOIN
|
||||||
* NODE SERVICE
|
* NODE SERVICE
|
||||||
*
|
*
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
@@ -58,7 +53,6 @@
|
|||||||
|
|
||||||
#include "repmgr.h"
|
#include "repmgr.h"
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include "controldata.h"
|
|
||||||
#include "repmgr-client.h"
|
#include "repmgr-client.h"
|
||||||
#include "repmgr-client-global.h"
|
#include "repmgr-client-global.h"
|
||||||
#include "repmgr-action-primary.h"
|
#include "repmgr-action-primary.h"
|
||||||
@@ -67,7 +61,6 @@
|
|||||||
#include "repmgr-action-bdr.h"
|
#include "repmgr-action-bdr.h"
|
||||||
#include "repmgr-action-node.h"
|
#include "repmgr-action-node.h"
|
||||||
#include "repmgr-action-cluster.h"
|
#include "repmgr-action-cluster.h"
|
||||||
#include "repmgr-action-daemon.h"
|
|
||||||
|
|
||||||
#include <storage/fd.h> /* for PG_TEMP_FILE_PREFIX */
|
#include <storage/fd.h> /* for PG_TEMP_FILE_PREFIX */
|
||||||
|
|
||||||
@@ -97,14 +90,13 @@ t_node_info target_node_info = T_NODE_INFO_INITIALIZER;
|
|||||||
static ItemList cli_errors = {NULL, NULL};
|
static ItemList cli_errors = {NULL, NULL};
|
||||||
static ItemList cli_warnings = {NULL, NULL};
|
static ItemList cli_warnings = {NULL, NULL};
|
||||||
|
|
||||||
static bool _local_command(const char *command, PQExpBufferData *outputbuf, bool simple);
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
t_conninfo_param_list default_conninfo = T_CONNINFO_PARAM_LIST_INITIALIZER;
|
t_conninfo_param_list default_conninfo = T_CONNINFO_PARAM_LIST_INITIALIZER;
|
||||||
|
|
||||||
int optindex = 0;
|
int optindex;
|
||||||
int c;
|
int c;
|
||||||
|
|
||||||
char *repmgr_command = NULL;
|
char *repmgr_command = NULL;
|
||||||
@@ -114,7 +106,6 @@ main(int argc, char **argv)
|
|||||||
char *dummy_action = "";
|
char *dummy_action = "";
|
||||||
|
|
||||||
bool help_option = false;
|
bool help_option = false;
|
||||||
bool option_error_found = false;
|
|
||||||
|
|
||||||
set_progname(argv[0]);
|
set_progname(argv[0]);
|
||||||
|
|
||||||
@@ -185,10 +176,7 @@ main(int argc, char **argv)
|
|||||||
strncpy(runtime_options.username, pw->pw_name, MAXLEN);
|
strncpy(runtime_options.username, pw->pw_name, MAXLEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make getopt emitting errors */
|
while ((c = getopt_long(argc, argv, "?Vb:f:FWd:h:p:U:R:S:D:ck:L:tvC:", long_options,
|
||||||
opterr = 1;
|
|
||||||
|
|
||||||
while ((c = getopt_long(argc, argv, "?Vb:f:FwWd:h:p:U:R:S:D:ck:L:qtvC:", long_options,
|
|
||||||
&optindex)) != -1)
|
&optindex)) != -1)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@@ -206,7 +194,13 @@ main(int argc, char **argv)
|
|||||||
case OPT_HELP: /* --help */
|
case OPT_HELP: /* --help */
|
||||||
help_option = true;
|
help_option = true;
|
||||||
break;
|
break;
|
||||||
|
case '?':
|
||||||
|
/* Actual help option given */
|
||||||
|
if (strcmp(argv[optind - 1], "-?") == 0)
|
||||||
|
{
|
||||||
|
help_option = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'V':
|
case 'V':
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -247,14 +241,9 @@ main(int argc, char **argv)
|
|||||||
strncpy(runtime_options.replication_user, optarg, MAXLEN);
|
strncpy(runtime_options.replication_user, optarg, MAXLEN);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* -w/--wait */
|
/* -W/--wait */
|
||||||
case 'w':
|
|
||||||
runtime_options.wait = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* -W/--no-wait */
|
|
||||||
case 'W':
|
case 'W':
|
||||||
runtime_options.no_wait = true;
|
runtime_options.wait = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/*----------------------------
|
/*----------------------------
|
||||||
@@ -431,23 +420,13 @@ main(int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case OPT_FORCE_REWIND:
|
case OPT_FORCE_REWIND:
|
||||||
runtime_options.force_rewind_used = true;
|
runtime_options.force_rewind = true;
|
||||||
|
|
||||||
if (optarg != NULL)
|
|
||||||
{
|
|
||||||
strncpy(runtime_options.force_rewind_path, optarg, MAXPGPATH);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OPT_SIBLINGS_FOLLOW:
|
case OPT_SIBLINGS_FOLLOW:
|
||||||
runtime_options.siblings_follow = true;
|
runtime_options.siblings_follow = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OPT_REPMGRD_NO_PAUSE:
|
|
||||||
runtime_options.repmgrd_no_pause = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
/*----------------------
|
/*----------------------
|
||||||
* "node status" options
|
* "node status" options
|
||||||
*----------------------
|
*----------------------
|
||||||
@@ -481,10 +460,6 @@ main(int argc, char **argv)
|
|||||||
runtime_options.slots = true;
|
runtime_options.slots = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OPT_MISSING_SLOTS:
|
|
||||||
runtime_options.missing_slots = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OPT_HAS_PASSFILE:
|
case OPT_HAS_PASSFILE:
|
||||||
runtime_options.has_passfile = true;
|
runtime_options.has_passfile = true;
|
||||||
break;
|
break;
|
||||||
@@ -584,12 +559,6 @@ main(int argc, char **argv)
|
|||||||
logger_output_mode = OM_DAEMON;
|
logger_output_mode = OM_DAEMON;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
/* --quiet */
|
|
||||||
case 'q':
|
|
||||||
runtime_options.quiet = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* --terse */
|
/* --terse */
|
||||||
case 't':
|
case 't':
|
||||||
runtime_options.terse = true;
|
runtime_options.terse = true;
|
||||||
@@ -645,29 +614,14 @@ main(int argc, char **argv)
|
|||||||
_("--recovery-min-apply-delay is now a configuration file parameter, \"recovery_min_apply_delay\""));
|
_("--recovery-min-apply-delay is now a configuration file parameter, \"recovery_min_apply_delay\""));
|
||||||
break;
|
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
|
* If -d/--dbname appears to be a conninfo string, validate by attempting
|
||||||
* to parse it (and if successful, store the parsed parameters)
|
* 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 ||
|
if (strncmp(runtime_options.dbname, "postgresql://", 13) == 0 ||
|
||||||
strncmp(runtime_options.dbname, "postgres://", 11) == 0 ||
|
strncmp(runtime_options.dbname, "postgres://", 11) == 0 ||
|
||||||
@@ -763,10 +717,9 @@ main(int argc, char **argv)
|
|||||||
if (cli_errors.head != NULL)
|
if (cli_errors.head != NULL)
|
||||||
{
|
{
|
||||||
free_conninfo_params(&source_conninfo);
|
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:
|
* Determine the node type and action; following are valid:
|
||||||
*
|
*
|
||||||
@@ -910,21 +863,6 @@ main(int argc, char **argv)
|
|||||||
else if (strcasecmp(repmgr_action, "CLEANUP") == 0)
|
else if (strcasecmp(repmgr_action, "CLEANUP") == 0)
|
||||||
action = CLUSTER_CLEANUP;
|
action = CLUSTER_CLEANUP;
|
||||||
}
|
}
|
||||||
else if (strcasecmp(repmgr_command, "DAEMON") == 0)
|
|
||||||
{
|
|
||||||
if (help_option == true)
|
|
||||||
{
|
|
||||||
do_daemon_help();
|
|
||||||
exit(SUCCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcasecmp(repmgr_action, "STATUS") == 0)
|
|
||||||
action = DAEMON_STATUS;
|
|
||||||
else if (strcasecmp(repmgr_action, "PAUSE") == 0)
|
|
||||||
action = DAEMON_PAUSE;
|
|
||||||
else if (strcasecmp(repmgr_action, "UNPAUSE") == 0)
|
|
||||||
action = DAEMON_UNPAUSE;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
valid_repmgr_command_found = false;
|
valid_repmgr_command_found = false;
|
||||||
@@ -1028,30 +966,9 @@ main(int argc, char **argv)
|
|||||||
if (cli_errors.head != NULL)
|
if (cli_errors.head != NULL)
|
||||||
{
|
{
|
||||||
free_conninfo_params(&source_conninfo);
|
free_conninfo_params(&source_conninfo);
|
||||||
|
exit_with_cli_errors(&cli_errors);
|
||||||
exit_with_cli_errors(&cli_errors, valid_repmgr_command_found == true ? repmgr_command : NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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
|
* Print any warnings about inappropriate command line options, unless
|
||||||
* -t/--terse set
|
* -t/--terse set
|
||||||
@@ -1080,6 +997,7 @@ main(int argc, char **argv)
|
|||||||
runtime_options.output_mode = OM_OPTFORMAT;
|
runtime_options.output_mode = OM_OPTFORMAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check for configuration file items which can be overriden by runtime
|
* Check for configuration file items which can be overriden by runtime
|
||||||
* options
|
* options
|
||||||
@@ -1137,28 +1055,6 @@ main(int argc, char **argv)
|
|||||||
if (runtime_options.terse)
|
if (runtime_options.terse)
|
||||||
logger_set_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
|
* Node configuration information is not needed for all actions, with
|
||||||
* STANDBY CLONE being the main exception.
|
* STANDBY CLONE being the main exception.
|
||||||
@@ -1323,17 +1219,6 @@ main(int argc, char **argv)
|
|||||||
do_cluster_cleanup();
|
do_cluster_cleanup();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* DAEMON */
|
|
||||||
case DAEMON_STATUS:
|
|
||||||
do_daemon_status();
|
|
||||||
break;
|
|
||||||
case DAEMON_PAUSE:
|
|
||||||
do_daemon_pause();
|
|
||||||
break;
|
|
||||||
case DAEMON_UNPAUSE:
|
|
||||||
do_daemon_unpause();
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* An action will have been determined by this point */
|
/* An action will have been determined by this point */
|
||||||
break;
|
break;
|
||||||
@@ -1430,15 +1315,6 @@ check_cli_parameters(const int action)
|
|||||||
_("--no-upstream-connection only effective in Barman mode"));
|
_("--no-upstream-connection only effective in Barman mode"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strlen(config_file_options.config_directory))
|
|
||||||
{
|
|
||||||
if (runtime_options.copy_external_config_files == false)
|
|
||||||
{
|
|
||||||
item_list_append(&cli_warnings,
|
|
||||||
_("\"config_directory\" set in repmgr.conf, but --copy-external-config-files not provided"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1555,8 +1431,6 @@ check_cli_parameters(const int action)
|
|||||||
{
|
{
|
||||||
case PRIMARY_UNREGISTER:
|
case PRIMARY_UNREGISTER:
|
||||||
case STANDBY_UNREGISTER:
|
case STANDBY_UNREGISTER:
|
||||||
case WITNESS_UNREGISTER:
|
|
||||||
case CLUSTER_CLEANUP:
|
|
||||||
case CLUSTER_EVENT:
|
case CLUSTER_EVENT:
|
||||||
case CLUSTER_MATRIX:
|
case CLUSTER_MATRIX:
|
||||||
case CLUSTER_CROSSCHECK:
|
case CLUSTER_CROSSCHECK:
|
||||||
@@ -1597,7 +1471,6 @@ check_cli_parameters(const int action)
|
|||||||
case STANDBY_CLONE:
|
case STANDBY_CLONE:
|
||||||
case STANDBY_REGISTER:
|
case STANDBY_REGISTER:
|
||||||
case STANDBY_FOLLOW:
|
case STANDBY_FOLLOW:
|
||||||
case BDR_REGISTER:
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
item_list_append_format(&cli_warnings,
|
item_list_append_format(&cli_warnings,
|
||||||
@@ -1690,41 +1563,6 @@ check_cli_parameters(const int action)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --wait/--no-wait */
|
|
||||||
|
|
||||||
if (runtime_options.wait == true && runtime_options.no_wait == true)
|
|
||||||
{
|
|
||||||
item_list_append_format(&cli_errors,
|
|
||||||
_("both --wait and --no-wait options provided"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (runtime_options.wait)
|
|
||||||
{
|
|
||||||
switch (action)
|
|
||||||
{
|
|
||||||
case STANDBY_FOLLOW:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
item_list_append_format(&cli_warnings,
|
|
||||||
_("--wait will be ignored when executing %s"),
|
|
||||||
action_name(action));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (runtime_options.wait)
|
|
||||||
{
|
|
||||||
switch (action)
|
|
||||||
{
|
|
||||||
case NODE_REJOIN:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
item_list_append_format(&cli_warnings,
|
|
||||||
_("--no-wait will be ignored when executing %s"),
|
|
||||||
action_name(action));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* repmgr node service --action */
|
/* repmgr node service --action */
|
||||||
if (runtime_options.action[0] != '\0')
|
if (runtime_options.action[0] != '\0')
|
||||||
{
|
{
|
||||||
@@ -1766,7 +1604,7 @@ check_cli_parameters(const int action)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (runtime_options.force_rewind_used == true)
|
if (runtime_options.force_rewind == true)
|
||||||
{
|
{
|
||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
@@ -1780,18 +1618,6 @@ check_cli_parameters(const int action)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (runtime_options.repmgrd_no_pause == true)
|
|
||||||
{
|
|
||||||
switch (action)
|
|
||||||
{
|
|
||||||
case STANDBY_SWITCHOVER:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
item_list_append_format(&cli_warnings,
|
|
||||||
_("--repmgrd-no-pause will be ignored when executing %s"),
|
|
||||||
action_name(action));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (runtime_options.config_files[0] != '\0')
|
if (runtime_options.config_files[0] != '\0')
|
||||||
{
|
{
|
||||||
@@ -1820,8 +1646,6 @@ check_cli_parameters(const int action)
|
|||||||
case WITNESS_UNREGISTER:
|
case WITNESS_UNREGISTER:
|
||||||
case NODE_REJOIN:
|
case NODE_REJOIN:
|
||||||
case NODE_SERVICE:
|
case NODE_SERVICE:
|
||||||
case DAEMON_PAUSE:
|
|
||||||
case DAEMON_UNPAUSE:
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
item_list_append_format(&cli_warnings,
|
item_list_append_format(&cli_warnings,
|
||||||
@@ -1901,14 +1725,6 @@ action_name(const int action)
|
|||||||
return "CLUSTER MATRIX";
|
return "CLUSTER MATRIX";
|
||||||
case CLUSTER_CROSSCHECK:
|
case CLUSTER_CROSSCHECK:
|
||||||
return "CLUSTER CROSSCHECK";
|
return "CLUSTER CROSSCHECK";
|
||||||
|
|
||||||
case DAEMON_STATUS:
|
|
||||||
return "DAEMON STATUS";
|
|
||||||
case DAEMON_PAUSE:
|
|
||||||
return "DAEMON PAUSE";
|
|
||||||
case DAEMON_UNPAUSE:
|
|
||||||
return "DAEMON UNPAUSE";
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return "UNKNOWN ACTION";
|
return "UNKNOWN ACTION";
|
||||||
@@ -1936,42 +1752,6 @@ print_error_list(ItemList *error_list, int log_level)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
print_status_header(int cols, ColHeader *headers)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < cols; i++)
|
|
||||||
{
|
|
||||||
if (i == 0)
|
|
||||||
printf(" ");
|
|
||||||
else
|
|
||||||
printf(" | ");
|
|
||||||
|
|
||||||
printf("%-*s",
|
|
||||||
headers[i].max_length,
|
|
||||||
headers[i].title);
|
|
||||||
}
|
|
||||||
printf("\n");
|
|
||||||
printf("-");
|
|
||||||
|
|
||||||
for (i = 0; i < cols; i++)
|
|
||||||
{
|
|
||||||
int j;
|
|
||||||
|
|
||||||
for (j = 0; j < headers[i].max_length; j++)
|
|
||||||
printf("-");
|
|
||||||
|
|
||||||
if (i < (cols - 1))
|
|
||||||
printf("-+-");
|
|
||||||
else
|
|
||||||
printf("-");
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
print_help_header(void)
|
print_help_header(void)
|
||||||
{
|
{
|
||||||
@@ -1998,9 +1778,8 @@ do_help(void)
|
|||||||
printf(_(" %s [OPTIONS] standby {register|unregister|clone|promote|follow|switchover}\n"), progname());
|
printf(_(" %s [OPTIONS] standby {register|unregister|clone|promote|follow|switchover}\n"), progname());
|
||||||
printf(_(" %s [OPTIONS] bdr {register|unregister}\n"), progname());
|
printf(_(" %s [OPTIONS] bdr {register|unregister}\n"), progname());
|
||||||
printf(_(" %s [OPTIONS] node {status|check|rejoin|service}\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());
|
printf(_(" %s [OPTIONS] witness {register|unregister}\n"), progname());
|
||||||
printf(_(" %s [OPTIONS] daemon {status|pause|unpause}\n"), progname());
|
|
||||||
|
|
||||||
puts("");
|
puts("");
|
||||||
|
|
||||||
@@ -2048,7 +1827,6 @@ do_help(void)
|
|||||||
printf(_(" --dry-run show what would happen for action, but don't execute it\n"));
|
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(_(" -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(_(" --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(_(" -t, --terse don't display detail, hints and other non-critical output\n"));
|
||||||
printf(_(" -v, --verbose display additional log output (useful for debugging)\n"));
|
printf(_(" -v, --verbose display additional log output (useful for debugging)\n"));
|
||||||
|
|
||||||
@@ -2318,28 +2096,12 @@ test_ssh_connection(char *host, char *remote_user)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Execute a command locally. "outputbuf" should either be an
|
* Execute a command locally. "outputbuf" should either be an
|
||||||
* initialised PQexpbuffer, or NULL
|
* initialised PQexpbuffer, or NULL
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
local_command(const char *command, PQExpBufferData *outputbuf)
|
local_command(const char *command, PQExpBufferData *outputbuf)
|
||||||
{
|
|
||||||
return _local_command(command, outputbuf, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
local_command_simple(const char *command, PQExpBufferData *outputbuf)
|
|
||||||
{
|
|
||||||
return _local_command(command, outputbuf, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static bool
|
|
||||||
_local_command(const char *command, PQExpBufferData *outputbuf, bool simple)
|
|
||||||
{
|
{
|
||||||
FILE *fp = NULL;
|
FILE *fp = NULL;
|
||||||
char output[MAXLEN];
|
char output[MAXLEN];
|
||||||
@@ -2366,8 +2128,7 @@ _local_command(const char *command, PQExpBufferData *outputbuf, bool simple)
|
|||||||
while (fgets(output, MAXLEN, fp) != NULL)
|
while (fgets(output, MAXLEN, fp) != NULL)
|
||||||
{
|
{
|
||||||
appendPQExpBuffer(outputbuf, "%s", output);
|
appendPQExpBuffer(outputbuf, "%s", output);
|
||||||
|
if (!feof(fp))
|
||||||
if (!feof(fp) && simple == false)
|
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -2410,7 +2171,6 @@ get_superuser_connection(PGconn **conn, PGconn **superuser_conn, PGconn **privil
|
|||||||
log_error(_("no database connection available"));
|
log_error(_("no database connection available"));
|
||||||
exit(ERR_INTERNAL);
|
exit(ERR_INTERNAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
is_superuser = is_superuser_connection(*conn, &userinfo);
|
is_superuser = is_superuser_connection(*conn, &userinfo);
|
||||||
|
|
||||||
if (is_superuser == true)
|
if (is_superuser == true)
|
||||||
@@ -2452,8 +2212,6 @@ get_superuser_connection(PGconn **conn, PGconn **superuser_conn, PGconn **privil
|
|||||||
exit(ERR_BAD_CONFIG);
|
exit(ERR_BAD_CONFIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
log_debug("established superuser connection as \"%s\"", runtime_options.superuser);
|
|
||||||
|
|
||||||
*privileged_conn = *superuser_conn;
|
*privileged_conn = *superuser_conn;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2595,6 +2353,9 @@ copy_remote_files(char *host, char *remote_user, char *remote_path,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Execute a command via ssh on the remote host.
|
* Execute a command via ssh on the remote host.
|
||||||
*
|
*
|
||||||
@@ -2660,7 +2421,7 @@ remote_command(const char *host, const char *user, const char *command, PQExpBuf
|
|||||||
if (outputbuf != NULL)
|
if (outputbuf != NULL)
|
||||||
{
|
{
|
||||||
if (strlen(outputbuf->data))
|
if (strlen(outputbuf->data))
|
||||||
log_verbose(LOG_DEBUG, "remote_command(): output returned was:\n%s", outputbuf->data);
|
log_verbose(LOG_DEBUG, "remote_command(): output returned was:\n %s", outputbuf->data);
|
||||||
else
|
else
|
||||||
log_verbose(LOG_DEBUG, "remote_command(): no output returned");
|
log_verbose(LOG_DEBUG, "remote_command(): no output returned");
|
||||||
}
|
}
|
||||||
@@ -2672,29 +2433,11 @@ remote_command(const char *host, const char *user, const char *command, PQExpBuf
|
|||||||
void
|
void
|
||||||
make_remote_repmgr_path(PQExpBufferData *output_buf, t_node_info *remote_node_record)
|
make_remote_repmgr_path(PQExpBufferData *output_buf, t_node_info *remote_node_record)
|
||||||
{
|
{
|
||||||
if (config_file_options.repmgr_bindir[0] != '\0')
|
|
||||||
{
|
|
||||||
int len = strlen(config_file_options.repmgr_bindir);
|
|
||||||
|
|
||||||
appendPQExpBufferStr(output_buf,
|
|
||||||
config_file_options.repmgr_bindir);
|
|
||||||
|
|
||||||
/* Add trailing slash */
|
|
||||||
if (config_file_options.repmgr_bindir[len - 1] != '/')
|
|
||||||
{
|
|
||||||
appendPQExpBufferChar(output_buf, '/');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (pg_bindir[0] != '\0')
|
|
||||||
{
|
|
||||||
appendPQExpBufferStr(output_buf,
|
|
||||||
pg_bindir);
|
|
||||||
}
|
|
||||||
|
|
||||||
appendPQExpBuffer(output_buf,
|
appendPQExpBuffer(output_buf,
|
||||||
"%s -f %s ",
|
"%s -f %s ",
|
||||||
progname(),
|
make_pg_path(progname()),
|
||||||
remote_node_record->config_file);
|
remote_node_record->config_file);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2927,33 +2670,6 @@ data_dir_required_for_action(t_server_action action)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copy the location of the configuration file directory into the
|
|
||||||
* provided buffer; if "config_directory" provided, use that, otherwise
|
|
||||||
* default to the data directory.
|
|
||||||
*
|
|
||||||
* This is primarily intended for use with "pg_ctl" (which itself shouldn't
|
|
||||||
* be used outside of development environments).
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
get_node_config_directory(char *config_dir_buf)
|
|
||||||
{
|
|
||||||
if (config_file_options.config_directory[0] != '\0')
|
|
||||||
{
|
|
||||||
strncpy(config_dir_buf, config_file_options.config_directory, MAXPGPATH);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config_file_options.data_directory[0] != '\0')
|
|
||||||
{
|
|
||||||
strncpy(config_dir_buf, config_file_options.data_directory, MAXPGPATH);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
get_node_data_directory(char *data_dir_buf)
|
get_node_data_directory(char *data_dir_buf)
|
||||||
{
|
{
|
||||||
@@ -3018,119 +2734,3 @@ init_node_record(t_node_info *node_record)
|
|||||||
create_slot_name(node_record->slot_name, config_file_options.node_id);
|
create_slot_name(node_record->slot_name, config_file_options.node_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
can_use_pg_rewind(PGconn *conn, const char *data_directory, PQExpBufferData *reason)
|
|
||||||
{
|
|
||||||
bool can_use = true;
|
|
||||||
int server_version_num = get_server_version(conn, NULL);
|
|
||||||
|
|
||||||
/* wal_log_hints not available in 9.3, so just determine if data checksums enabled */
|
|
||||||
if (server_version_num < 90400)
|
|
||||||
{
|
|
||||||
int data_checksum_version = get_data_checksum_version(data_directory);
|
|
||||||
|
|
||||||
if (data_checksum_version < 0)
|
|
||||||
{
|
|
||||||
appendPQExpBuffer(reason,
|
|
||||||
_("unable to determine data checksum version"));
|
|
||||||
can_use = false;
|
|
||||||
}
|
|
||||||
else if (data_checksum_version == 0)
|
|
||||||
{
|
|
||||||
appendPQExpBuffer(reason,
|
|
||||||
_("this cluster was initialised without data checksums"));
|
|
||||||
can_use = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return can_use;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* "full_page_writes" must be on in any case */
|
|
||||||
if (guc_set(conn, "full_page_writes", "=", "off"))
|
|
||||||
{
|
|
||||||
if (can_use == false)
|
|
||||||
appendPQExpBuffer(reason, "; ");
|
|
||||||
|
|
||||||
appendPQExpBuffer(reason,
|
|
||||||
_("\"full_page_writes\" must be set to \"on\""));
|
|
||||||
|
|
||||||
can_use = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* "wal_log_hints" off - are data checksums available? Note: we're
|
|
||||||
* checking the local pg_control file here as the value will be the same
|
|
||||||
* throughout the cluster and saves a round-trip to the demotion
|
|
||||||
* candidate.
|
|
||||||
*/
|
|
||||||
if (guc_set(conn, "wal_log_hints", "=", "on") == false)
|
|
||||||
{
|
|
||||||
int data_checksum_version = get_data_checksum_version(data_directory);
|
|
||||||
|
|
||||||
if (data_checksum_version < 0)
|
|
||||||
{
|
|
||||||
if (can_use == false)
|
|
||||||
appendPQExpBuffer(reason, "; ");
|
|
||||||
|
|
||||||
appendPQExpBuffer(reason,
|
|
||||||
_("\"wal_log_hints\" is set to \"off\" but unable to determine data checksum version"));
|
|
||||||
can_use = false;
|
|
||||||
}
|
|
||||||
else if (data_checksum_version == 0)
|
|
||||||
{
|
|
||||||
if (can_use == false)
|
|
||||||
appendPQExpBuffer(reason, "; ");
|
|
||||||
|
|
||||||
appendPQExpBuffer(reason,
|
|
||||||
_("\"wal_log_hints\" is set to \"off\" and data checksums are disabled"));
|
|
||||||
|
|
||||||
can_use = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -45,9 +45,6 @@
|
|||||||
#define CLUSTER_MATRIX 19
|
#define CLUSTER_MATRIX 19
|
||||||
#define CLUSTER_CROSSCHECK 20
|
#define CLUSTER_CROSSCHECK 20
|
||||||
#define CLUSTER_EVENT 21
|
#define CLUSTER_EVENT 21
|
||||||
#define DAEMON_STATUS 22
|
|
||||||
#define DAEMON_PAUSE 23
|
|
||||||
#define DAEMON_UNPAUSE 24
|
|
||||||
|
|
||||||
/* command line options without short versions */
|
/* command line options without short versions */
|
||||||
#define OPT_HELP 1001
|
#define OPT_HELP 1001
|
||||||
@@ -89,9 +86,6 @@
|
|||||||
#define OPT_REPL_CONN 1037
|
#define OPT_REPL_CONN 1037
|
||||||
#define OPT_REMOTE_NODE_ID 1038
|
#define OPT_REMOTE_NODE_ID 1038
|
||||||
#define OPT_RECOVERY_CONF_ONLY 1039
|
#define OPT_RECOVERY_CONF_ONLY 1039
|
||||||
#define OPT_NO_WAIT 1040
|
|
||||||
#define OPT_MISSING_SLOTS 1041
|
|
||||||
#define OPT_REPMGRD_NO_PAUSE 1042
|
|
||||||
|
|
||||||
/* deprecated since 3.3 */
|
/* deprecated since 3.3 */
|
||||||
#define OPT_DATA_DIR 999
|
#define OPT_DATA_DIR 999
|
||||||
@@ -110,8 +104,7 @@ static struct option long_options[] =
|
|||||||
{"dry-run", no_argument, NULL, OPT_DRY_RUN},
|
{"dry-run", no_argument, NULL, OPT_DRY_RUN},
|
||||||
{"force", no_argument, NULL, 'F'},
|
{"force", no_argument, NULL, 'F'},
|
||||||
{"pg_bindir", required_argument, NULL, 'b'},
|
{"pg_bindir", required_argument, NULL, 'b'},
|
||||||
{"wait", no_argument, NULL, 'w'},
|
{"wait", no_argument, NULL, 'W'},
|
||||||
{"no-wait", no_argument, NULL, 'W'},
|
|
||||||
|
|
||||||
/* connection options */
|
/* connection options */
|
||||||
{"dbname", required_argument, NULL, 'd'},
|
{"dbname", required_argument, NULL, 'd'},
|
||||||
@@ -130,7 +123,6 @@ static struct option long_options[] =
|
|||||||
/* logging options */
|
/* logging options */
|
||||||
{"log-level", required_argument, NULL, 'L'},
|
{"log-level", required_argument, NULL, 'L'},
|
||||||
{"log-to-file", no_argument, NULL, OPT_LOG_TO_FILE},
|
{"log-to-file", no_argument, NULL, OPT_LOG_TO_FILE},
|
||||||
{"quiet", no_argument, NULL, 'q'},
|
|
||||||
{"terse", no_argument, NULL, 't'},
|
{"terse", no_argument, NULL, 't'},
|
||||||
{"verbose", no_argument, NULL, 'v'},
|
{"verbose", no_argument, NULL, 'v'},
|
||||||
|
|
||||||
@@ -160,7 +152,6 @@ static struct option long_options[] =
|
|||||||
*/
|
*/
|
||||||
{"always-promote", no_argument, NULL, OPT_ALWAYS_PROMOTE},
|
{"always-promote", no_argument, NULL, OPT_ALWAYS_PROMOTE},
|
||||||
{"siblings-follow", no_argument, NULL, OPT_SIBLINGS_FOLLOW},
|
{"siblings-follow", no_argument, NULL, OPT_SIBLINGS_FOLLOW},
|
||||||
{"repmgrd-no-pause", no_argument, NULL, OPT_REPMGRD_NO_PAUSE},
|
|
||||||
|
|
||||||
/* "node status" options */
|
/* "node status" options */
|
||||||
{"is-shutdown-cleanly", no_argument, NULL, OPT_IS_SHUTDOWN_CLEANLY},
|
{"is-shutdown-cleanly", no_argument, NULL, OPT_IS_SHUTDOWN_CLEANLY},
|
||||||
@@ -171,14 +162,13 @@ static struct option long_options[] =
|
|||||||
{"replication-lag", no_argument, NULL, OPT_REPLICATION_LAG},
|
{"replication-lag", no_argument, NULL, OPT_REPLICATION_LAG},
|
||||||
{"role", no_argument, NULL, OPT_ROLE},
|
{"role", no_argument, NULL, OPT_ROLE},
|
||||||
{"slots", no_argument, NULL, OPT_SLOTS},
|
{"slots", no_argument, NULL, OPT_SLOTS},
|
||||||
{"missing-slots", no_argument, NULL, OPT_MISSING_SLOTS},
|
|
||||||
{"has-passfile", no_argument, NULL, OPT_HAS_PASSFILE},
|
{"has-passfile", no_argument, NULL, OPT_HAS_PASSFILE},
|
||||||
{"replication-connection", no_argument, NULL, OPT_REPL_CONN},
|
{"replication-connection", no_argument, NULL, OPT_REPL_CONN},
|
||||||
|
|
||||||
/* "node rejoin" options */
|
/* "node rejoin" options */
|
||||||
{"config-files", required_argument, NULL, OPT_CONFIG_FILES},
|
{"config-files", required_argument, NULL, OPT_CONFIG_FILES},
|
||||||
{"config-archive-dir", required_argument, NULL, OPT_CONFIG_ARCHIVE_DIR},
|
{"config-archive-dir", required_argument, NULL, OPT_CONFIG_ARCHIVE_DIR},
|
||||||
{"force-rewind", optional_argument, NULL, OPT_FORCE_REWIND},
|
{"force-rewind", no_argument, NULL, OPT_FORCE_REWIND},
|
||||||
|
|
||||||
/* "node service" options */
|
/* "node service" options */
|
||||||
{"action", required_argument, NULL, OPT_ACTION},
|
{"action", required_argument, NULL, OPT_ACTION},
|
||||||
|
|||||||
264
repmgr.c
264
repmgr.c
@@ -26,7 +26,6 @@
|
|||||||
#include "access/xlog.h"
|
#include "access/xlog.h"
|
||||||
#include "miscadmin.h"
|
#include "miscadmin.h"
|
||||||
#include "replication/walreceiver.h"
|
#include "replication/walreceiver.h"
|
||||||
#include "storage/fd.h"
|
|
||||||
#include "storage/ipc.h"
|
#include "storage/ipc.h"
|
||||||
#include "storage/lwlock.h"
|
#include "storage/lwlock.h"
|
||||||
#include "storage/procarray.h"
|
#include "storage/procarray.h"
|
||||||
@@ -44,21 +43,14 @@
|
|||||||
#include "lib/stringinfo.h"
|
#include "lib/stringinfo.h"
|
||||||
#include "access/xact.h"
|
#include "access/xact.h"
|
||||||
#include "utils/snapmgr.h"
|
#include "utils/snapmgr.h"
|
||||||
|
|
||||||
#if (PG_VERSION_NUM >= 90400)
|
|
||||||
#include "pgstat.h"
|
#include "pgstat.h"
|
||||||
#else
|
|
||||||
#define PGSTAT_STAT_PERMANENT_DIRECTORY "pg_stat"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "voting.h"
|
#include "voting.h"
|
||||||
|
|
||||||
#define UNKNOWN_NODE_ID -1
|
#define UNKNOWN_NODE_ID -1
|
||||||
#define UNKNOWN_PID -1
|
|
||||||
|
|
||||||
#define TRANCHE_NAME "repmgrd"
|
#define TRANCHE_NAME "repmgrd"
|
||||||
#define REPMGRD_STATE_FILE PGSTAT_STAT_PERMANENT_DIRECTORY "/repmgrd_state.txt"
|
|
||||||
|
|
||||||
|
|
||||||
PG_MODULE_MAGIC;
|
PG_MODULE_MAGIC;
|
||||||
|
|
||||||
@@ -74,9 +66,6 @@ typedef struct repmgrdSharedState
|
|||||||
LWLockId lock; /* protects search/modification */
|
LWLockId lock; /* protects search/modification */
|
||||||
TimestampTz last_updated;
|
TimestampTz last_updated;
|
||||||
int local_node_id;
|
int local_node_id;
|
||||||
int repmgrd_pid;
|
|
||||||
char repmgrd_pidfile[MAXPGPATH];
|
|
||||||
bool repmgrd_paused;
|
|
||||||
/* streaming failover */
|
/* streaming failover */
|
||||||
NodeVotingStatus voting_status;
|
NodeVotingStatus voting_status;
|
||||||
int current_electoral_term;
|
int current_electoral_term;
|
||||||
@@ -123,25 +112,6 @@ PG_FUNCTION_INFO_V1(am_bdr_failover_handler);
|
|||||||
Datum unset_bdr_failover_handler(PG_FUNCTION_ARGS);
|
Datum unset_bdr_failover_handler(PG_FUNCTION_ARGS);
|
||||||
PG_FUNCTION_INFO_V1(unset_bdr_failover_handler);
|
PG_FUNCTION_INFO_V1(unset_bdr_failover_handler);
|
||||||
|
|
||||||
Datum set_repmgrd_pid(PG_FUNCTION_ARGS);
|
|
||||||
PG_FUNCTION_INFO_V1(set_repmgrd_pid);
|
|
||||||
|
|
||||||
Datum get_repmgrd_pid(PG_FUNCTION_ARGS);
|
|
||||||
PG_FUNCTION_INFO_V1(get_repmgrd_pid);
|
|
||||||
|
|
||||||
Datum get_repmgrd_pidfile(PG_FUNCTION_ARGS);
|
|
||||||
PG_FUNCTION_INFO_V1(get_repmgrd_pidfile);
|
|
||||||
|
|
||||||
Datum repmgrd_is_running(PG_FUNCTION_ARGS);
|
|
||||||
PG_FUNCTION_INFO_V1(repmgrd_is_running);
|
|
||||||
|
|
||||||
Datum repmgrd_pause(PG_FUNCTION_ARGS);
|
|
||||||
PG_FUNCTION_INFO_V1(repmgrd_pause);
|
|
||||||
|
|
||||||
Datum repmgrd_is_paused(PG_FUNCTION_ARGS);
|
|
||||||
PG_FUNCTION_INFO_V1(repmgrd_is_paused);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Module load callback
|
* Module load callback
|
||||||
@@ -215,9 +185,6 @@ repmgr_shmem_startup(void)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
shared_state->local_node_id = UNKNOWN_NODE_ID;
|
shared_state->local_node_id = UNKNOWN_NODE_ID;
|
||||||
shared_state->repmgrd_pid = UNKNOWN_PID;
|
|
||||||
memset(shared_state->repmgrd_pidfile, 0, MAXPGPATH);
|
|
||||||
shared_state->repmgrd_paused = false;
|
|
||||||
shared_state->current_electoral_term = 0;
|
shared_state->current_electoral_term = 0;
|
||||||
shared_state->voting_status = VS_NO_VOTE;
|
shared_state->voting_status = VS_NO_VOTE;
|
||||||
shared_state->candidate_node_id = UNKNOWN_NODE_ID;
|
shared_state->candidate_node_id = UNKNOWN_NODE_ID;
|
||||||
@@ -237,8 +204,6 @@ Datum
|
|||||||
set_local_node_id(PG_FUNCTION_ARGS)
|
set_local_node_id(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
int local_node_id = UNKNOWN_NODE_ID;
|
int local_node_id = UNKNOWN_NODE_ID;
|
||||||
int stored_node_id = UNKNOWN_NODE_ID;
|
|
||||||
int paused = -1;
|
|
||||||
|
|
||||||
if (!shared_state)
|
if (!shared_state)
|
||||||
PG_RETURN_NULL();
|
PG_RETURN_NULL();
|
||||||
@@ -248,34 +213,6 @@ set_local_node_id(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
local_node_id = PG_GETARG_INT32(0);
|
local_node_id = PG_GETARG_INT32(0);
|
||||||
|
|
||||||
/* read state file and if exists/valid, update "repmgrd_paused" */
|
|
||||||
{
|
|
||||||
FILE *file = NULL;
|
|
||||||
|
|
||||||
file = AllocateFile(REPMGRD_STATE_FILE, PG_BINARY_R);
|
|
||||||
|
|
||||||
if (file != NULL)
|
|
||||||
{
|
|
||||||
int buffer_size = 128;
|
|
||||||
char buffer[buffer_size];
|
|
||||||
|
|
||||||
if (fgets(buffer, buffer_size, file) != NULL)
|
|
||||||
{
|
|
||||||
if (sscanf(buffer, "%i:%i", &stored_node_id, &paused) != 2)
|
|
||||||
{
|
|
||||||
elog(WARNING, "unable to parse repmgrd state file");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
elog(DEBUG1, "node_id: %i; paused: %i", stored_node_id, paused);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FreeFile(file);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
LWLockAcquire(shared_state->lock, LW_EXCLUSIVE);
|
LWLockAcquire(shared_state->lock, LW_EXCLUSIVE);
|
||||||
|
|
||||||
/* only set local_node_id once, as it should never change */
|
/* only set local_node_id once, as it should never change */
|
||||||
@@ -284,19 +221,6 @@ set_local_node_id(PG_FUNCTION_ARGS)
|
|||||||
shared_state->local_node_id = local_node_id;
|
shared_state->local_node_id = local_node_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* only update if state file valid */
|
|
||||||
if (stored_node_id == shared_state->local_node_id)
|
|
||||||
{
|
|
||||||
if (paused == 0)
|
|
||||||
{
|
|
||||||
shared_state->repmgrd_paused = false;
|
|
||||||
}
|
|
||||||
else if (paused == 1)
|
|
||||||
{
|
|
||||||
shared_state->repmgrd_paused = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LWLockRelease(shared_state->lock);
|
LWLockRelease(shared_state->lock);
|
||||||
|
|
||||||
PG_RETURN_VOID();
|
PG_RETURN_VOID();
|
||||||
@@ -492,191 +416,9 @@ unset_bdr_failover_handler(PG_FUNCTION_ARGS)
|
|||||||
LWLockAcquire(shared_state->lock, LW_EXCLUSIVE);
|
LWLockAcquire(shared_state->lock, LW_EXCLUSIVE);
|
||||||
|
|
||||||
shared_state->bdr_failover_handler = UNKNOWN_NODE_ID;
|
shared_state->bdr_failover_handler = UNKNOWN_NODE_ID;
|
||||||
}
|
|
||||||
|
|
||||||
LWLockRelease(shared_state->lock);
|
LWLockRelease(shared_state->lock);
|
||||||
|
}
|
||||||
|
|
||||||
PG_RETURN_VOID();
|
PG_RETURN_VOID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Returns the repmgrd pid; or NULL if none set; or -1 if set but repmgrd
|
|
||||||
* process not running (TODO!)
|
|
||||||
*/
|
|
||||||
Datum
|
|
||||||
get_repmgrd_pid(PG_FUNCTION_ARGS)
|
|
||||||
{
|
|
||||||
int repmgrd_pid = UNKNOWN_PID;
|
|
||||||
|
|
||||||
if (!shared_state)
|
|
||||||
PG_RETURN_NULL();
|
|
||||||
|
|
||||||
LWLockAcquire(shared_state->lock, LW_SHARED);
|
|
||||||
repmgrd_pid = shared_state->repmgrd_pid;
|
|
||||||
LWLockRelease(shared_state->lock);
|
|
||||||
|
|
||||||
PG_RETURN_INT32(repmgrd_pid);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Returns the repmgrd pidfile
|
|
||||||
*/
|
|
||||||
Datum
|
|
||||||
get_repmgrd_pidfile(PG_FUNCTION_ARGS)
|
|
||||||
{
|
|
||||||
char repmgrd_pidfile[MAXPGPATH];
|
|
||||||
|
|
||||||
if (!shared_state)
|
|
||||||
PG_RETURN_NULL();
|
|
||||||
|
|
||||||
memset(repmgrd_pidfile, 0, MAXPGPATH);
|
|
||||||
|
|
||||||
LWLockAcquire(shared_state->lock, LW_SHARED);
|
|
||||||
strncpy(repmgrd_pidfile, shared_state->repmgrd_pidfile, MAXPGPATH);
|
|
||||||
LWLockRelease(shared_state->lock);
|
|
||||||
|
|
||||||
if (repmgrd_pidfile[0] == '\0')
|
|
||||||
PG_RETURN_NULL();
|
|
||||||
|
|
||||||
PG_RETURN_TEXT_P(cstring_to_text(repmgrd_pidfile));
|
|
||||||
}
|
|
||||||
|
|
||||||
Datum
|
|
||||||
set_repmgrd_pid(PG_FUNCTION_ARGS)
|
|
||||||
{
|
|
||||||
int repmgrd_pid = UNKNOWN_PID;
|
|
||||||
char *repmgrd_pidfile = NULL;
|
|
||||||
|
|
||||||
if (!shared_state)
|
|
||||||
PG_RETURN_VOID();
|
|
||||||
|
|
||||||
if (PG_ARGISNULL(0))
|
|
||||||
{
|
|
||||||
repmgrd_pid = UNKNOWN_PID;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
repmgrd_pid = PG_GETARG_INT32(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
elog(DEBUG3, "set_repmgrd_pid(): provided pid is %i", repmgrd_pid);
|
|
||||||
|
|
||||||
if (repmgrd_pid != UNKNOWN_PID && !PG_ARGISNULL(1))
|
|
||||||
{
|
|
||||||
repmgrd_pidfile = text_to_cstring(PG_GETARG_TEXT_PP(1));
|
|
||||||
elog(INFO, "set_repmgrd_pid(): provided pidfile is %s", repmgrd_pidfile);
|
|
||||||
}
|
|
||||||
|
|
||||||
LWLockAcquire(shared_state->lock, LW_EXCLUSIVE);
|
|
||||||
|
|
||||||
shared_state->repmgrd_pid = repmgrd_pid;
|
|
||||||
memset(shared_state->repmgrd_pidfile, 0, MAXPGPATH);
|
|
||||||
|
|
||||||
if(repmgrd_pidfile != NULL)
|
|
||||||
{
|
|
||||||
strncpy(shared_state->repmgrd_pidfile, repmgrd_pidfile, MAXPGPATH);
|
|
||||||
}
|
|
||||||
|
|
||||||
LWLockRelease(shared_state->lock);
|
|
||||||
PG_RETURN_VOID();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Datum
|
|
||||||
repmgrd_is_running(PG_FUNCTION_ARGS)
|
|
||||||
{
|
|
||||||
int repmgrd_pid = UNKNOWN_PID;
|
|
||||||
int kill_ret;
|
|
||||||
|
|
||||||
if (!shared_state)
|
|
||||||
PG_RETURN_NULL();
|
|
||||||
|
|
||||||
LWLockAcquire(shared_state->lock, LW_SHARED);
|
|
||||||
repmgrd_pid = shared_state->repmgrd_pid;
|
|
||||||
LWLockRelease(shared_state->lock);
|
|
||||||
|
|
||||||
/* No PID registered - assume not running */
|
|
||||||
if (repmgrd_pid == UNKNOWN_PID)
|
|
||||||
{
|
|
||||||
PG_RETURN_BOOL(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
kill_ret = kill(repmgrd_pid, 0);
|
|
||||||
|
|
||||||
if (kill_ret == 0)
|
|
||||||
{
|
|
||||||
PG_RETURN_BOOL(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
PG_RETURN_BOOL(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Datum
|
|
||||||
repmgrd_pause(PG_FUNCTION_ARGS)
|
|
||||||
{
|
|
||||||
bool pause;
|
|
||||||
FILE *file = NULL;
|
|
||||||
StringInfoData buf;
|
|
||||||
|
|
||||||
if (!shared_state)
|
|
||||||
PG_RETURN_NULL();
|
|
||||||
|
|
||||||
if (PG_ARGISNULL(0))
|
|
||||||
PG_RETURN_NULL();
|
|
||||||
|
|
||||||
pause = PG_GETARG_BOOL(0);
|
|
||||||
|
|
||||||
LWLockAcquire(shared_state->lock, LW_EXCLUSIVE);
|
|
||||||
shared_state->repmgrd_paused = pause;
|
|
||||||
LWLockRelease(shared_state->lock);
|
|
||||||
|
|
||||||
/* write state to file */
|
|
||||||
file = AllocateFile(REPMGRD_STATE_FILE, PG_BINARY_W);
|
|
||||||
|
|
||||||
if (file == NULL)
|
|
||||||
{
|
|
||||||
elog(DEBUG1, "unable to allocate %s", REPMGRD_STATE_FILE);
|
|
||||||
|
|
||||||
// XXX anything else we can do? log?
|
|
||||||
PG_RETURN_VOID();
|
|
||||||
}
|
|
||||||
|
|
||||||
elog(DEBUG1, "allocated");
|
|
||||||
|
|
||||||
initStringInfo(&buf);
|
|
||||||
|
|
||||||
LWLockAcquire(shared_state->lock, LW_SHARED);
|
|
||||||
|
|
||||||
appendStringInfo(&buf, "%i:%i",
|
|
||||||
shared_state->local_node_id,
|
|
||||||
pause ? 1 : 0);
|
|
||||||
LWLockRelease(shared_state->lock);
|
|
||||||
|
|
||||||
// XXX check success
|
|
||||||
fwrite(buf.data, strlen(buf.data) + 1, 1, file);
|
|
||||||
|
|
||||||
|
|
||||||
resetStringInfo(&buf);
|
|
||||||
FreeFile(file);
|
|
||||||
|
|
||||||
PG_RETURN_VOID();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Datum
|
|
||||||
repmgrd_is_paused(PG_FUNCTION_ARGS)
|
|
||||||
{
|
|
||||||
bool is_paused;
|
|
||||||
|
|
||||||
if (!shared_state)
|
|
||||||
PG_RETURN_NULL();
|
|
||||||
|
|
||||||
LWLockAcquire(shared_state->lock, LW_SHARED);
|
|
||||||
is_paused = shared_state->repmgrd_paused;
|
|
||||||
LWLockRelease(shared_state->lock);
|
|
||||||
|
|
||||||
PG_RETURN_BOOL(is_paused);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -40,28 +40,18 @@
|
|||||||
# is not running and there's no other way of determining
|
# is not running and there's no other way of determining
|
||||||
# the data directory.
|
# the data directory.
|
||||||
|
|
||||||
|
#replication_user='repmgr' # User to make replication connections with, if not set defaults
|
||||||
|
# to the user defined in "conninfo".
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
# Optional configuration items
|
# Optional configuration items
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
# Server settings
|
|
||||||
#------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#config_directory='' # If configuration files are located outside the data
|
|
||||||
# directory, specify the directory where the main
|
|
||||||
# postgresql.conf file is located.
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
# Replication settings
|
# Replication settings
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
|
|
||||||
#replication_user='repmgr' # User to make replication connections with, if not set defaults
|
|
||||||
# to the user defined in "conninfo".
|
|
||||||
|
|
||||||
#replication_type=physical # Must be one of 'physical' or 'bdr'.
|
#replication_type=physical # Must be one of 'physical' or 'bdr'.
|
||||||
|
|
||||||
#location=default # arbitrary string defining the location of the node; this
|
#location=default # arbitrary string defining the location of the node; this
|
||||||
@@ -75,6 +65,9 @@
|
|||||||
# at least the number of standbys which will connect
|
# at least the number of standbys which will connect
|
||||||
# to the primary.
|
# to the primary.
|
||||||
|
|
||||||
|
#recovery_min_apply_delay= # If provided, "recovery_min_apply_delay" in recovery.conf
|
||||||
|
# will be set to this value.
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
# Witness server settings
|
# Witness server settings
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
@@ -98,7 +91,7 @@
|
|||||||
#log_facility=STDERR # Logging facility: possible values are STDERR, or for
|
#log_facility=STDERR # Logging facility: possible values are STDERR, or for
|
||||||
# syslog integration, one of LOCAL0, LOCAL1, ..., LOCAL7, USER
|
# 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
|
#log_status_interval=300 # interval (in seconds) for repmgrd to log a status message
|
||||||
|
|
||||||
|
|
||||||
@@ -143,15 +136,6 @@
|
|||||||
# Debian/Ubuntu users: you will probably need to
|
# Debian/Ubuntu users: you will probably need to
|
||||||
# set this to the directory where `pg_ctl` is located,
|
# set this to the directory where `pg_ctl` is located,
|
||||||
# e.g. /usr/lib/postgresql/9.6/bin/
|
# 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
|
|
||||||
|
|
||||||
#repmgr_bindir='' # Path to repmgr binary directory (location of the repmgr
|
|
||||||
# binary. Only needed if the repmgr executable is not in
|
|
||||||
# the system $PATH or the path defined in "pg_bindir".
|
|
||||||
|
|
||||||
#use_primary_conninfo_password=false # explicitly set "password" in recovery.conf's
|
#use_primary_conninfo_password=false # explicitly set "password" in recovery.conf's
|
||||||
# "primary_conninfo" parameter using the value contained
|
# "primary_conninfo" parameter using the value contained
|
||||||
# in the environment variable PGPASSWORD
|
# in the environment variable PGPASSWORD
|
||||||
@@ -165,7 +149,7 @@
|
|||||||
# Examples:
|
# Examples:
|
||||||
#
|
#
|
||||||
# pg_ctl_options='-s'
|
# pg_ctl_options='-s'
|
||||||
# pg_basebackup_options='--label=repmgr_backup'
|
# pg_basebackup_options='--label=repmgr_backup
|
||||||
# rsync_options=--archive --checksum --compress --progress --rsh="ssh -o \"StrictHostKeyChecking no\""
|
# rsync_options=--archive --checksum --compress --progress --rsh="ssh -o \"StrictHostKeyChecking no\""
|
||||||
# ssh_options=-o "StrictHostKeyChecking no"
|
# ssh_options=-o "StrictHostKeyChecking no"
|
||||||
|
|
||||||
@@ -191,15 +175,8 @@ ssh_options='-q -o ConnectTimeout=10' # Options to append to "ssh"
|
|||||||
# file system location to another. This
|
# file system location to another. This
|
||||||
# parameter can be provided multiple times.
|
# parameter can be provided multiple times.
|
||||||
|
|
||||||
#restore_command='' # This will be placed in the recovery.conf file generated
|
#restore_command='' # This will be placed in the recovery.conf
|
||||||
# by repmgr.
|
# file generated 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 )
|
|
||||||
|
|
||||||
#recovery_min_apply_delay= # If provided, "recovery_min_apply_delay" in recovery.conf
|
|
||||||
# will be set to this value (PostgreSQL 9.4 and later).
|
|
||||||
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
@@ -216,42 +193,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
|
# These settings apply when instructing a standby to follow the new primary
|
||||||
# ("repmgr standby follow").
|
# ("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
|
# 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").
|
|
||||||
|
|
||||||
#shutdown_check_timeout=60 # The max length of time (in seconds) to wait for the demotion
|
|
||||||
# candidate (current primary) to shut down
|
|
||||||
#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
|
# Barman options
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
@@ -269,11 +220,6 @@ ssh_options='-q -o ConnectTimeout=10' # Options to append to "ssh"
|
|||||||
# These settings are only applied when repmgrd is running. Values shown
|
# These settings are only applied when repmgrd is running. Values shown
|
||||||
# are defaults.
|
# 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'.
|
#failover=manual # one of 'automatic', 'manual'.
|
||||||
# determines what action to take in the event of upstream failure
|
# determines what action to take in the event of upstream failure
|
||||||
#
|
#
|
||||||
@@ -283,19 +229,19 @@ ssh_options='-q -o ConnectTimeout=10' # Options to append to "ssh"
|
|||||||
# manual attention to reattach it to replication
|
# manual attention to reattach it to replication
|
||||||
# (does not apply to BDR mode)
|
# (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
|
# a value of zero prevents the node being promoted to primary
|
||||||
# (default: 100)
|
# (default: 100)
|
||||||
|
|
||||||
#reconnect_attempts=6 # Number of attempts which will be made to reconnect to an unreachable
|
#reconnect_attempts=6 # Number attempts which will be made to reconnect to an unreachable
|
||||||
# primary (or other upstream node)
|
# primary (or other upstream node)
|
||||||
#reconnect_interval=10 # Interval between attempts to reconnect to an unreachable
|
#reconnect_interval=10 # Interval between attempts to reconnect to an unreachable
|
||||||
# primary (or other upstream node)
|
# 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
|
# 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:
|
# use something like:
|
||||||
#
|
#
|
||||||
# repmgr standby follow -f /etc/repmgr.conf -W --upstream-node-id=%n
|
# repmgr standby follow -f /etc/repmgr.conf -W --upstream-node-id=%n
|
||||||
@@ -303,9 +249,8 @@ ssh_options='-q -o ConnectTimeout=10' # Options to append to "ssh"
|
|||||||
#primary_notification_timeout=60 # Interval (in seconds) which repmgrd on a standby
|
#primary_notification_timeout=60 # Interval (in seconds) which repmgrd on a standby
|
||||||
# will wait for a notification from the new primary,
|
# will wait for a notification from the new primary,
|
||||||
# before falling back to degraded monitoring
|
# before falling back to degraded monitoring
|
||||||
#repmgrd_standby_startup_timeout=60 # Interval (in seconds) which repmgrd on a standby will wait
|
#standby_reconnect_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
|
# to reconnect to the local node after executing "follow_command"
|
||||||
# executing "follow_command" (defaults to the value set in "standby_reconnect_timeout")
|
|
||||||
|
|
||||||
#monitoring_history=no # Whether to write monitoring data to the "montoring_history" table
|
#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
|
#monitor_interval_secs=2 # Interval (in seconds) at which to write monitoring data
|
||||||
@@ -341,19 +286,16 @@ ssh_options='-q -o ConnectTimeout=10' # Options to append to "ssh"
|
|||||||
# /usr/bin/systemctl start postgresql-9.6, \
|
# /usr/bin/systemctl start postgresql-9.6, \
|
||||||
# /usr/bin/systemctl restart postgresql-9.6
|
# /usr/bin/systemctl restart postgresql-9.6
|
||||||
#
|
#
|
||||||
# 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
|
|
||||||
|
|
||||||
#service_start_command = ''
|
#service_start_command = ''
|
||||||
#service_stop_command = ''
|
#service_stop_command = ''
|
||||||
#service_restart_command = ''
|
#service_restart_command = ''
|
||||||
#service_reload_command = ''
|
#service_reload_command = ''
|
||||||
#service_promote_command = '' # This parameter is intended for systems which provide a
|
#service_promote_command = '' # Note: this overrides any value contained in the setting
|
||||||
# package-level promote command, such as Debian's
|
# "promote_command". This is intended for systems which
|
||||||
# "pg_ctlcluster". *IMPORTANT*: it is *not* a substitute
|
# provide a package-level promote command, such as Debian's
|
||||||
# for "promote_command"; do not use "repmgr standby promote"
|
# "pg_ctlcluster"
|
||||||
# (or a script which executes "repmgr standby promote") here.
|
|
||||||
|
|
||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
# Status check thresholds
|
# Status check thresholds
|
||||||
@@ -387,7 +329,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
|
#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
|
#bdr_recovery_timeout # If a BDR node was offline and has become available
|
||||||
# maximum length of time in seconds to wait for the
|
# maximum length of time in seconds to wait for the
|
||||||
# node to reconnect to the cluster
|
# node to reconnect to the cluster
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# repmgr extension
|
# repmgr extension
|
||||||
comment = 'Replication manager for PostgreSQL'
|
comment = 'Replication manager for PostgreSQL'
|
||||||
default_version = '4.2'
|
default_version = '4.0'
|
||||||
module_pathname = '$libdir/repmgr'
|
module_pathname = '$libdir/repmgr'
|
||||||
relocatable = false
|
relocatable = false
|
||||||
schema = repmgr
|
schema = repmgr
|
||||||
|
|||||||
8
repmgr.h
8
repmgr.h
@@ -49,11 +49,8 @@
|
|||||||
#define REPLICATION_TYPE_BDR 2
|
#define REPLICATION_TYPE_BDR 2
|
||||||
|
|
||||||
#define UNKNOWN_SERVER_VERSION_NUM -1
|
#define UNKNOWN_SERVER_VERSION_NUM -1
|
||||||
#define UNKNOWN_BDR_VERSION_NUM -1
|
|
||||||
|
|
||||||
#define UNKNOWN_TIMELINE_ID -1
|
#define UNKNOWN_TIMELINE_ID -1
|
||||||
#define UNKNOWN_SYSTEM_IDENTIFIER 0
|
#define UNKNOWN_SYSTEM_IDENTIFIER 0
|
||||||
#define UNKNOWN_PID -1
|
|
||||||
|
|
||||||
#define NODE_NOT_FOUND -1
|
#define NODE_NOT_FOUND -1
|
||||||
#define NO_UPSTREAM_NODE -1
|
#define NO_UPSTREAM_NODE -1
|
||||||
@@ -61,8 +58,6 @@
|
|||||||
|
|
||||||
#define VOTING_TERM_NOT_SET -1
|
#define VOTING_TERM_NOT_SET -1
|
||||||
|
|
||||||
#define BDR2_REPLICATION_SET_NAME "repmgr"
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* various default values - ensure repmgr.conf.sample is update
|
* various default values - ensure repmgr.conf.sample is update
|
||||||
* if any of these are changed
|
* if any of these are changed
|
||||||
@@ -75,7 +70,6 @@
|
|||||||
#define DEFAULT_ASYNC_QUERY_TIMEOUT 60 /* seconds */
|
#define DEFAULT_ASYNC_QUERY_TIMEOUT 60 /* seconds */
|
||||||
#define DEFAULT_PRIMARY_NOTIFICATION_TIMEOUT 60 /* seconds */
|
#define DEFAULT_PRIMARY_NOTIFICATION_TIMEOUT 60 /* seconds */
|
||||||
#define DEFAULT_PRIMARY_FOLLOW_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_BDR_RECOVERY_TIMEOUT 30 /* seconds */
|
||||||
#define DEFAULT_ARCHIVE_READY_WARNING 16 /* WAL files */
|
#define DEFAULT_ARCHIVE_READY_WARNING 16 /* WAL files */
|
||||||
#define DEFAULT_ARCHIVE_READY_CRITICAL 128 /* WAL files */
|
#define DEFAULT_ARCHIVE_READY_CRITICAL 128 /* WAL files */
|
||||||
@@ -85,9 +79,7 @@
|
|||||||
#define DEFAULT_WAIT_START 30 /* seconds */
|
#define DEFAULT_WAIT_START 30 /* seconds */
|
||||||
#define DEFAULT_PROMOTE_CHECK_TIMEOUT 60 /* seconds */
|
#define DEFAULT_PROMOTE_CHECK_TIMEOUT 60 /* seconds */
|
||||||
#define DEFAULT_PROMOTE_CHECK_INTERVAL 1 /* seconds */
|
#define DEFAULT_PROMOTE_CHECK_INTERVAL 1 /* seconds */
|
||||||
#define DEFAULT_SHUTDOWN_CHECK_TIMEOUT 60 /* seconds */
|
|
||||||
#define DEFAULT_STANDBY_RECONNECT_TIMEOUT 60 /* seconds */
|
#define DEFAULT_STANDBY_RECONNECT_TIMEOUT 60 /* seconds */
|
||||||
#define DEFAULT_NODE_REJOIN_TIMEOUT 60 /* seconds */
|
|
||||||
|
|
||||||
#ifndef RECOVERY_COMMAND_FILE
|
#ifndef RECOVERY_COMMAND_FILE
|
||||||
#define RECOVERY_COMMAND_FILE "recovery.conf"
|
#define RECOVERY_COMMAND_FILE "recovery.conf"
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
#define REPMGR_VERSION_DATE ""
|
#define REPMGR_VERSION_DATE ""
|
||||||
#define REPMGR_VERSION "4.2"
|
#define REPMGR_VERSION "4.0.4"
|
||||||
|
|
||||||
|
|||||||
@@ -150,13 +150,7 @@ monitor_bdr(void)
|
|||||||
* retrieve list of all nodes - we'll need these if the DB connection goes
|
* retrieve list of all nodes - we'll need these if the DB connection goes
|
||||||
* away
|
* away
|
||||||
*/
|
*/
|
||||||
if (get_all_node_records(local_conn, &nodes) == false)
|
get_all_node_records(local_conn, &nodes);
|
||||||
{
|
|
||||||
/* get_all_node_records() will display the error */
|
|
||||||
PQfinish(local_conn);
|
|
||||||
exit(ERR_BAD_CONFIG);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* we're expecting all (both) nodes to be up */
|
/* we're expecting all (both) nodes to be up */
|
||||||
for (cell = nodes.head; cell; cell = cell->next)
|
for (cell = nodes.head; cell; cell = cell->next)
|
||||||
@@ -220,8 +214,7 @@ monitor_bdr(void)
|
|||||||
|
|
||||||
log_warning(_("unable to connect to node %s (ID %i)"),
|
log_warning(_("unable to connect to node %s (ID %i)"),
|
||||||
cell->node_info->node_name, cell->node_info->node_id);
|
cell->node_info->node_name, cell->node_info->node_id);
|
||||||
//cell->node_info->conn = try_reconnect(cell->node_info);
|
cell->node_info->conn = try_reconnect(cell->node_info);
|
||||||
try_reconnect(&cell->node_info->conn, cell->node_info);
|
|
||||||
|
|
||||||
/* node has recovered - log and continue */
|
/* node has recovered - log and continue */
|
||||||
if (cell->node_info->node_status == NODE_STATUS_UP)
|
if (cell->node_info->node_status == NODE_STATUS_UP)
|
||||||
@@ -300,7 +293,7 @@ loop:
|
|||||||
/*
|
/*
|
||||||
* if we can reload, then could need to change local_conn
|
* 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);
|
PQfinish(local_conn);
|
||||||
local_conn = establish_db_connection(config_file_options.conninfo, true);
|
local_conn = establish_db_connection(config_file_options.conninfo, true);
|
||||||
@@ -310,12 +303,11 @@ loop:
|
|||||||
got_SIGHUP = false;
|
got_SIGHUP = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX this looks like it will never be called */
|
|
||||||
if (got_SIGHUP)
|
if (got_SIGHUP)
|
||||||
{
|
{
|
||||||
log_debug("SIGHUP received");
|
log_debug("SIGHUP received");
|
||||||
|
|
||||||
if (reload_config(&config_file_options, BDR))
|
if (reload_config(&config_file_options))
|
||||||
{
|
{
|
||||||
PQfinish(local_conn);
|
PQfinish(local_conn);
|
||||||
local_conn = establish_db_connection(config_file_options.conninfo, true);
|
local_conn = establish_db_connection(config_file_options.conninfo, true);
|
||||||
|
|||||||
1433
repmgrd-physical.c
1433
repmgrd-physical.c
File diff suppressed because it is too large
Load Diff
@@ -24,6 +24,7 @@ void do_physical_node_check(void);
|
|||||||
void monitor_streaming_primary(void);
|
void monitor_streaming_primary(void);
|
||||||
void monitor_streaming_standby(void);
|
void monitor_streaming_standby(void);
|
||||||
void monitor_streaming_witness(void);
|
void monitor_streaming_witness(void);
|
||||||
|
void close_connections_physical(void);
|
||||||
|
|
||||||
void handle_sigint_physical(SIGNAL_ARGS);
|
void handle_sigint_physical(SIGNAL_ARGS);
|
||||||
|
|
||||||
|
|||||||
206
repmgrd.c
206
repmgrd.c
@@ -35,10 +35,8 @@
|
|||||||
|
|
||||||
static char *config_file = NULL;
|
static char *config_file = NULL;
|
||||||
static bool verbose = false;
|
static bool verbose = false;
|
||||||
char pid_file[MAXPGPATH];
|
static char *pid_file = NULL;
|
||||||
static bool daemonize = true;
|
static bool daemonize = false;
|
||||||
static bool show_pid_file = false;
|
|
||||||
static bool no_pid_file = false;
|
|
||||||
|
|
||||||
t_configuration_options config_file_options = T_CONFIGURATION_OPTIONS_INITIALIZER;
|
t_configuration_options config_file_options = T_CONFIGURATION_OPTIONS_INITIALIZER;
|
||||||
|
|
||||||
@@ -55,6 +53,9 @@ bool startup_event_logged = false;
|
|||||||
MonitoringState monitoring_state = MS_NORMAL;
|
MonitoringState monitoring_state = MS_NORMAL;
|
||||||
instr_time degraded_monitoring_start;
|
instr_time degraded_monitoring_start;
|
||||||
|
|
||||||
|
static void close_connections(void);
|
||||||
|
void (*_close_connections) (void) = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Record receipt of SIGHUP; will cause configuration file to be reread
|
* Record receipt of SIGHUP; will cause configuration file to be reread
|
||||||
* at the appropriate point in the main loop.
|
* at the appropriate point in the main loop.
|
||||||
@@ -101,11 +102,8 @@ main(int argc, char **argv)
|
|||||||
{"config-file", required_argument, NULL, 'f'},
|
{"config-file", required_argument, NULL, 'f'},
|
||||||
|
|
||||||
/* daemon options */
|
/* daemon options */
|
||||||
{"daemonize-short", optional_argument, NULL, 'd'},
|
{"daemonize", no_argument, NULL, 'd'},
|
||||||
{"daemonize", optional_argument, NULL, OPT_DAEMONIZE},
|
|
||||||
{"pid-file", required_argument, NULL, 'p'},
|
{"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 */
|
/* logging options */
|
||||||
{"log-level", required_argument, NULL, 'L'},
|
{"log-level", required_argument, NULL, 'L'},
|
||||||
@@ -118,6 +116,8 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
set_progname(argv[0]);
|
set_progname(argv[0]);
|
||||||
|
|
||||||
|
srand(time(NULL));
|
||||||
|
|
||||||
/* Disallow running as root */
|
/* Disallow running as root */
|
||||||
if (geteuid() == 0)
|
if (geteuid() == 0)
|
||||||
{
|
{
|
||||||
@@ -131,10 +131,6 @@ main(int argc, char **argv)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
srand(time(NULL));
|
|
||||||
|
|
||||||
memset(pid_file, 0, MAXPGPATH);
|
|
||||||
|
|
||||||
while ((c = getopt_long(argc, argv, "?Vf:L:vdp:m", long_options, &optindex)) != -1)
|
while ((c = getopt_long(argc, argv, "?Vf:L:vdp:m", long_options, &optindex)) != -1)
|
||||||
{
|
{
|
||||||
switch (c)
|
switch (c)
|
||||||
@@ -179,20 +175,8 @@ main(int argc, char **argv)
|
|||||||
daemonize = true;
|
daemonize = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OPT_DAEMONIZE:
|
|
||||||
daemonize = parse_bool(optarg, "-d/--daemonize", &cli_errors);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'p':
|
case 'p':
|
||||||
strncpy(pid_file, optarg, MAXPGPATH);
|
pid_file = optarg;
|
||||||
break;
|
|
||||||
|
|
||||||
case 's':
|
|
||||||
show_pid_file = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OPT_NO_PID_FILE:
|
|
||||||
no_pid_file = true;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* logging options */
|
/* logging options */
|
||||||
@@ -239,7 +223,7 @@ main(int argc, char **argv)
|
|||||||
/* Exit here already if errors in command line options found */
|
/* Exit here already if errors in command line options found */
|
||||||
if (cli_errors.head != NULL)
|
if (cli_errors.head != NULL)
|
||||||
{
|
{
|
||||||
exit_with_cli_errors(&cli_errors, NULL);
|
exit_with_cli_errors(&cli_errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
startup_event_logged = false;
|
startup_event_logged = false;
|
||||||
@@ -258,58 +242,6 @@ main(int argc, char **argv)
|
|||||||
*/
|
*/
|
||||||
load_config(config_file, verbose, false, &config_file_options, argv[0]);
|
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 */
|
/* Some configuration file items can be overriden by command line options */
|
||||||
|
|
||||||
@@ -322,6 +254,8 @@ main(int argc, char **argv)
|
|||||||
strncpy(config_file_options.log_level, cli_log_level, MAXLEN);
|
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
|
* -m/--monitoring-history, if provided, will override repmgr.conf's
|
||||||
* monitoring_history; this is for backwards compatibility as it's
|
* monitoring_history; this is for backwards compatibility as it's
|
||||||
@@ -349,8 +283,6 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
logger_init(&config_file_options, progname());
|
logger_init(&config_file_options, progname());
|
||||||
|
|
||||||
log_notice(_("repmgrd (%s %s) starting up"), progname(), REPMGR_VERSION);
|
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
logger_set_verbose();
|
logger_set_verbose();
|
||||||
|
|
||||||
@@ -398,7 +330,7 @@ main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
log_error(_("unable to determine status of \"repmgr\" extension"));
|
log_error(_("unable to determine status of \"repmgr\" extension"));
|
||||||
log_detail("%s", PQerrorMessage(local_conn));
|
log_detail("%s", PQerrorMessage(local_conn));
|
||||||
close_connection(&local_conn);
|
PQfinish(local_conn);
|
||||||
exit(ERR_DB_QUERY);
|
exit(ERR_DB_QUERY);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -415,7 +347,7 @@ main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
log_hint(_("check that this node is part of a repmgr cluster"));
|
log_hint(_("check that this node is part of a repmgr cluster"));
|
||||||
close_connection(&local_conn);
|
PQfinish(local_conn);
|
||||||
exit(ERR_BAD_CONFIG);
|
exit(ERR_BAD_CONFIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -441,7 +373,7 @@ main(int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
close_connection(&local_conn);
|
PQfinish(local_conn);
|
||||||
terminate(ERR_BAD_CONFIG);
|
terminate(ERR_BAD_CONFIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -460,7 +392,7 @@ main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
log_error(_("unable to write to shared memory"));
|
log_error(_("unable to write to shared memory"));
|
||||||
log_hint(_("ensure \"shared_preload_libraries\" includes \"repmgr\""));
|
log_hint(_("ensure \"shared_preload_libraries\" includes \"repmgr\""));
|
||||||
close_connection(&local_conn);
|
PQfinish(local_conn);
|
||||||
terminate(ERR_BAD_CONFIG);
|
terminate(ERR_BAD_CONFIG);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -472,6 +404,7 @@ main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
_close_connections = close_connections_physical;
|
||||||
log_debug("node id is %i, upstream node id is %i",
|
log_debug("node id is %i, upstream node id is %i",
|
||||||
local_node_info.node_id,
|
local_node_info.node_id,
|
||||||
local_node_info.upstream_node_id);
|
local_node_info.upstream_node_id);
|
||||||
@@ -485,14 +418,11 @@ main(int argc, char **argv)
|
|||||||
daemonize_process();
|
daemonize_process();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pid_file[0] != '\0')
|
if (pid_file != NULL)
|
||||||
{
|
{
|
||||||
check_and_create_pid_file(pid_file);
|
check_and_create_pid_file(pid_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
repmgrd_set_pid(local_conn, getpid(), pid_file);
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
setup_event_handlers();
|
setup_event_handlers();
|
||||||
#endif
|
#endif
|
||||||
@@ -743,8 +673,6 @@ show_help(void)
|
|||||||
{
|
{
|
||||||
printf(_("%s: replication management daemon for PostgreSQL\n"), progname());
|
printf(_("%s: replication management daemon for PostgreSQL\n"), progname());
|
||||||
puts("");
|
puts("");
|
||||||
printf(_("%s monitors a cluster of servers and optionally performs failover.\n"), progname());
|
|
||||||
puts("");
|
|
||||||
|
|
||||||
printf(_("Usage:\n"));
|
printf(_("Usage:\n"));
|
||||||
printf(_(" %s [OPTIONS]\n"), progname());
|
printf(_(" %s [OPTIONS]\n"), progname());
|
||||||
@@ -764,44 +692,30 @@ show_help(void)
|
|||||||
|
|
||||||
puts("");
|
puts("");
|
||||||
|
|
||||||
printf(_("Daemon configuration options:\n"));
|
printf(_("General configuration options:\n"));
|
||||||
printf(_(" -d\n"));
|
printf(_(" -d, --daemonize detach process from foreground\n"));
|
||||||
printf(_(" --daemonize[=true/false]\n"));
|
printf(_(" -p, --pid-file=PATH write a PID file\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"));
|
|
||||||
puts("");
|
puts("");
|
||||||
|
|
||||||
|
printf(_("%s monitors a cluster of servers and optionally performs failover.\n"), progname());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
PGconn *
|
||||||
try_reconnect(PGconn **conn, t_node_info *node_info)
|
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;
|
int i;
|
||||||
|
|
||||||
int max_attempts = config_file_options.reconnect_attempts;
|
int max_attempts = config_file_options.reconnect_attempts;
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
/* set some default values if not explicitly provided */
|
|
||||||
param_set_ine(&conninfo_params, "connect_timeout", "2");
|
|
||||||
param_set_ine(&conninfo_params, "fallback_application_name", "repmgr");
|
|
||||||
|
|
||||||
for (i = 0; i < max_attempts; i++)
|
for (i = 0; i < max_attempts; i++)
|
||||||
{
|
{
|
||||||
log_info(_("checking state of node %i, %i of %i attempts"),
|
log_info(_("checking state of node %i, %i of %i attempts"),
|
||||||
node_info->node_id, i + 1, max_attempts);
|
node_info->node_id, i + 1, max_attempts);
|
||||||
if (is_server_available_params(&conninfo_params) == true)
|
if (is_server_available(node_info->conninfo) == true)
|
||||||
{
|
{
|
||||||
|
|
||||||
log_notice(_("node has recovered, reconnecting"));
|
log_notice(_("node has recovered, reconnecting"));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -809,48 +723,15 @@ try_reconnect(PGconn **conn, t_node_info *node_info)
|
|||||||
* connection denied due to connection exhaustion - fall back to
|
* connection denied due to connection exhaustion - fall back to
|
||||||
* degraded monitoring? - make that configurable
|
* degraded monitoring? - make that configurable
|
||||||
*/
|
*/
|
||||||
|
conn = establish_db_connection(node_info->conninfo, false);
|
||||||
our_conn = establish_db_connection_by_params(&conninfo_params, false);
|
if (PQstatus(conn) == CONNECTION_OK)
|
||||||
|
|
||||||
if (PQstatus(our_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;
|
node_info->node_status = NODE_STATUS_UP;
|
||||||
|
return conn;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
close_connection(&our_conn);
|
PQfinish(conn);
|
||||||
log_notice(_("unable to reconnect to node %i"), node_info->node_id);
|
log_notice(_("unable to reconnect to node"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i + 1 < max_attempts)
|
if (i + 1 < max_attempts)
|
||||||
@@ -861,15 +742,14 @@ try_reconnect(PGconn **conn, t_node_info *node_info)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
log_warning(_("unable to reconnect to node %i after %i attempts"),
|
log_warning(_("unable to reconnect to node %i after %i attempts"),
|
||||||
node_info->node_id,
|
node_info->node_id,
|
||||||
max_attempts);
|
max_attempts);
|
||||||
|
|
||||||
node_info->node_status = NODE_STATUS_DOWN;
|
node_info->node_status = NODE_STATUS_DOWN;
|
||||||
|
|
||||||
free_conninfo_params(&conninfo_params);
|
return NULL;
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -904,15 +784,27 @@ print_monitoring_state(MonitoringState monitoring_state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
close_connections()
|
||||||
|
{
|
||||||
|
if (_close_connections != NULL)
|
||||||
|
_close_connections();
|
||||||
|
|
||||||
|
if (local_conn != NULL && PQstatus(local_conn) == CONNECTION_OK)
|
||||||
|
{
|
||||||
|
PQfinish(local_conn);
|
||||||
|
local_conn = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
terminate(int retval)
|
terminate(int retval)
|
||||||
{
|
{
|
||||||
if (PQstatus(local_conn) == CONNECTION_OK)
|
close_connections();
|
||||||
repmgrd_set_pid(local_conn, UNKNOWN_PID, NULL);
|
|
||||||
|
|
||||||
logger_shutdown();
|
logger_shutdown();
|
||||||
|
|
||||||
if (pid_file[0] != '\0')
|
if (pid_file)
|
||||||
{
|
{
|
||||||
unlink(pid_file);
|
unlink(pid_file);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,9 +10,6 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include "portability/instr_time.h"
|
#include "portability/instr_time.h"
|
||||||
|
|
||||||
#define OPT_NO_PID_FILE 1000
|
|
||||||
#define OPT_DAEMONIZE 1001
|
|
||||||
|
|
||||||
extern volatile sig_atomic_t got_SIGHUP;
|
extern volatile sig_atomic_t got_SIGHUP;
|
||||||
extern MonitoringState monitoring_state;
|
extern MonitoringState monitoring_state;
|
||||||
extern instr_time degraded_monitoring_start;
|
extern instr_time degraded_monitoring_start;
|
||||||
@@ -21,15 +18,12 @@ extern t_configuration_options config_file_options;
|
|||||||
extern t_node_info local_node_info;
|
extern t_node_info local_node_info;
|
||||||
extern PGconn *local_conn;
|
extern PGconn *local_conn;
|
||||||
extern bool startup_event_logged;
|
extern bool startup_event_logged;
|
||||||
extern char pid_file[MAXPGPATH];
|
|
||||||
|
|
||||||
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);
|
int calculate_elapsed(instr_time start_time);
|
||||||
const char *print_monitoring_state(MonitoringState monitoring_state);
|
const char *print_monitoring_state(MonitoringState monitoring_state);
|
||||||
|
|
||||||
void update_registration(PGconn *conn);
|
void update_registration(PGconn *conn);
|
||||||
void terminate(int retval);
|
void terminate(int retval);
|
||||||
|
|
||||||
|
|
||||||
#endif /* _REPMGRD_H_ */
|
#endif /* _REPMGRD_H_ */
|
||||||
|
|||||||
12
strutil.c
12
strutil.c
@@ -87,17 +87,17 @@ append_where_clause(PQExpBufferData *where_clause, const char *format,...)
|
|||||||
|
|
||||||
if (where_clause->data[0] == '\0')
|
if (where_clause->data[0] == '\0')
|
||||||
{
|
{
|
||||||
appendPQExpBufferStr(where_clause,
|
appendPQExpBuffer(where_clause,
|
||||||
" WHERE ");
|
" WHERE ");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
appendPQExpBufferStr(where_clause,
|
appendPQExpBuffer(where_clause,
|
||||||
" AND ");
|
" AND ");
|
||||||
}
|
}
|
||||||
|
|
||||||
appendPQExpBufferStr(where_clause,
|
appendPQExpBuffer(where_clause,
|
||||||
stringbuf);
|
"%s", stringbuf);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user