mirror of
https://github.com/EnterpriseDB/repmgr.git
synced 2026-03-23 15:16:29 +00:00
Compare commits
34 Commits
dev/update
...
v5.2.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
54851e8df1 | ||
|
|
a2166d0024 | ||
|
|
abe55e60e6 | ||
|
|
220bcbd620 | ||
|
|
e824dfd499 | ||
|
|
9fb9decf13 | ||
|
|
ad6dde4218 | ||
|
|
7cbaec6469 | ||
|
|
9d2c5921ee | ||
|
|
21f94e6de3 | ||
|
|
7418c7b8f0 | ||
|
|
7cee09dd95 | ||
|
|
53774d6998 | ||
|
|
5a251ef268 | ||
|
|
b83ce6b147 | ||
|
|
5f9f1f65ae | ||
|
|
9d7eebef1b | ||
|
|
5cff7fab64 | ||
|
|
2a8ac36aec | ||
|
|
a5a5b506f9 | ||
|
|
bd6871817d | ||
|
|
bd35e503ec | ||
|
|
15801b8f9e | ||
|
|
4d3262d306 | ||
|
|
36a8dfcf4f | ||
|
|
94612a336a | ||
|
|
de567d584f | ||
|
|
0fb3432398 | ||
|
|
5e59e543d6 | ||
|
|
4f6b642320 | ||
|
|
c1973438f7 | ||
|
|
fe5904e04e | ||
|
|
2cb1f4f728 | ||
|
|
5b90842c55 |
@@ -2,7 +2,7 @@ License and Contributions
|
|||||||
=========================
|
=========================
|
||||||
|
|
||||||
`repmgr` is licensed under the GPL v3. All of its code and documentation is
|
`repmgr` is licensed under the GPL v3. All of its code and documentation is
|
||||||
Copyright 2010-2021, EnterpriseDB Corporation. See the files COPYRIGHT and LICENSE for
|
Copyright 2010-2020, 2ndQuadrant Limited. See the files COPYRIGHT and LICENSE for
|
||||||
details.
|
details.
|
||||||
|
|
||||||
The development of repmgr has primarily been sponsored by 2ndQuadrant customers.
|
The development of repmgr has primarily been sponsored by 2ndQuadrant customers.
|
||||||
@@ -12,10 +12,10 @@ which has received funding from the European Union's Seventh Framework Programme
|
|||||||
(FP7/2007-2013) under grant agreement 258862.
|
(FP7/2007-2013) under grant agreement 258862.
|
||||||
|
|
||||||
Contributions to `repmgr` are welcome, and will be listed in the file `CREDITS`.
|
Contributions to `repmgr` are welcome, and will be listed in the file `CREDITS`.
|
||||||
EnterpriseDB Corporation requires that any contributions provide a copyright
|
2ndQuadrant Limited requires that any contributions provide a copyright
|
||||||
assignment and a disclaimer of any work-for-hire ownership claims from the
|
assignment and a disclaimer of any work-for-hire ownership claims from the
|
||||||
employer of the developer. This lets us make sure that all of the repmgr
|
employer of the developer. This lets us make sure that all of the repmgr
|
||||||
distribution remains free code. Please contact info@enterprise.com for a
|
distribution remains free code. Please contact info@2ndQuadrant.com for a
|
||||||
copy of the relevant Copyright Assignment Form.
|
copy of the relevant Copyright Assignment Form.
|
||||||
|
|
||||||
Code style
|
Code style
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2010-2021, EnterpriseDB Corporation
|
Copyright (c) 2010-2020, 2ndQuadrant Limited
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
|||||||
2
FAQ.md
2
FAQ.md
@@ -5,6 +5,6 @@ The repmgr 4 FAQ is located here: [repmgr FAQ (Frequently Asked Questions)](http
|
|||||||
|
|
||||||
The repmgr 3.x FAQ can be found here:
|
The repmgr 3.x FAQ can be found here:
|
||||||
|
|
||||||
https://github.com/EnterpriseDB/repmgr/blob/REL3_3_STABLE/FAQ.md
|
https://github.com/2ndQuadrant/repmgr/blob/REL3_3_STABLE/FAQ.md
|
||||||
|
|
||||||
Note that repmgr 3.x is no longer supported.
|
Note that repmgr 3.x is no longer supported.
|
||||||
|
|||||||
37
HISTORY
37
HISTORY
@@ -1,36 +1,3 @@
|
|||||||
5.4.1 2023-07-04
|
|
||||||
repmgrd: ensure witness node metadata is updated (Ian)
|
|
||||||
|
|
||||||
5.4.0 2023-03-16
|
|
||||||
Support cloning replicas using pg-backup-api
|
|
||||||
|
|
||||||
5.3.3 2022-10-17
|
|
||||||
Support for PostgreSQL added
|
|
||||||
repmgrd: ensure event notification script is called for event
|
|
||||||
"repmgrd_upstream_disconnect"; GitHub #760 (Ian)
|
|
||||||
|
|
||||||
5.3.2 2022-05-25
|
|
||||||
standby clone: don't error out if unable to determine cluster size (Ian)
|
|
||||||
node check: fix --downstream --nagios output; GitHub #749 (Ian)
|
|
||||||
repmgrd: ensure witness node marked active (hslightdb)
|
|
||||||
repmgrd: improve walsender disable check (Ian)
|
|
||||||
general: ensure replication slots can be dropped by a
|
|
||||||
replication-only user (Ian)
|
|
||||||
|
|
||||||
5.3.1 2022-02-15
|
|
||||||
repmgrd: fixes for potential connection leaks (hslightdb)
|
|
||||||
repmgr: fix upgrade path from repmgr 4.2 and 4.3 to repmgr 5.3 (Ian)
|
|
||||||
|
|
||||||
5.3.0 2021-10-12
|
|
||||||
standby switchover: improve handling of node rejoin failure (Ian)
|
|
||||||
repmgrd: prefix all shared library functions with "repmgr_" to
|
|
||||||
minimize the risk of clashes with other shared libraries (Ian)
|
|
||||||
repmgrd: at startup, if node record is marked as "inactive", attempt
|
|
||||||
to set it to "active" (Ian)
|
|
||||||
standby clone: set "slot_name" in node record if required (Ian)
|
|
||||||
node rejoin: emit rejoin target note information as NOTICE (Ian)
|
|
||||||
repmgrd: ensure short option "-s" is accepted (Ian)
|
|
||||||
|
|
||||||
5.2.1 2020-12-07
|
5.2.1 2020-12-07
|
||||||
config: fix parsing of "replication_type"; GitHub #672 (Ian)
|
config: fix parsing of "replication_type"; GitHub #672 (Ian)
|
||||||
standby clone: handle missing "postgresql.auto.conf" (Ian)
|
standby clone: handle missing "postgresql.auto.conf" (Ian)
|
||||||
@@ -76,11 +43,11 @@
|
|||||||
repmgr: ensure postgresql.auto.conf is created with correct permissions (Ian)
|
repmgr: ensure postgresql.auto.conf is created with correct permissions (Ian)
|
||||||
repmgr: minimize requirement to check upstream data directory location
|
repmgr: minimize requirement to check upstream data directory location
|
||||||
during "standby clone" (Ian)
|
during "standby clone" (Ian)
|
||||||
repmgr: warn about missing pg_rewind prerequisites when executing
|
repmgr: warn about missing pg_rewind prerequisites when excuting
|
||||||
"standby clone" (Ian)
|
"standby clone" (Ian)
|
||||||
repmgr: add --upstream option to "node check"
|
repmgr: add --upstream option to "node check"
|
||||||
repmgr: report error code on follow/rejoin failure due to non-available
|
repmgr: report error code on follow/rejoin failure due to non-available
|
||||||
replication slot (Ian)
|
0 replication slot (Ian)
|
||||||
repmgr: ensure "node rejoin" checks for available replication slots (Ian)
|
repmgr: ensure "node rejoin" checks for available replication slots (Ian)
|
||||||
repmgr: improve "standby switchover" completion checks (Ian)
|
repmgr: improve "standby switchover" completion checks (Ian)
|
||||||
repmgr: add replication configuration file ownership check to
|
repmgr: add replication configuration file ownership check to
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ GIT_WORK_TREE=${repmgr_abs_srcdir}
|
|||||||
GIT_DIR=${repmgr_abs_srcdir}/.git
|
GIT_DIR=${repmgr_abs_srcdir}/.git
|
||||||
export GIT_DIR
|
export GIT_DIR
|
||||||
export GIT_WORK_TREE
|
export GIT_WORK_TREE
|
||||||
PG_LDFLAGS=-lcurl -ljson-c
|
|
||||||
include $(PGXS)
|
include $(PGXS)
|
||||||
|
|
||||||
-include ${repmgr_abs_srcdir}/Makefile.custom
|
-include ${repmgr_abs_srcdir}/Makefile.custom
|
||||||
|
|||||||
13
Makefile.in
13
Makefile.in
@@ -13,7 +13,6 @@ DATA = \
|
|||||||
repmgr--unpackaged--4.0.sql \
|
repmgr--unpackaged--4.0.sql \
|
||||||
repmgr--unpackaged--5.1.sql \
|
repmgr--unpackaged--5.1.sql \
|
||||||
repmgr--unpackaged--5.2.sql \
|
repmgr--unpackaged--5.2.sql \
|
||||||
repmgr--unpackaged--5.3.sql \
|
|
||||||
repmgr--4.0.sql \
|
repmgr--4.0.sql \
|
||||||
repmgr--4.0--4.1.sql \
|
repmgr--4.0--4.1.sql \
|
||||||
repmgr--4.1.sql \
|
repmgr--4.1.sql \
|
||||||
@@ -28,11 +27,7 @@ DATA = \
|
|||||||
repmgr--5.0--5.1.sql \
|
repmgr--5.0--5.1.sql \
|
||||||
repmgr--5.1.sql \
|
repmgr--5.1.sql \
|
||||||
repmgr--5.1--5.2.sql \
|
repmgr--5.1--5.2.sql \
|
||||||
repmgr--5.2.sql \
|
repmgr--5.2.sql
|
||||||
repmgr--5.2--5.3.sql \
|
|
||||||
repmgr--5.3.sql \
|
|
||||||
repmgr--5.3--5.4.sql \
|
|
||||||
repmgr--5.4.sql
|
|
||||||
|
|
||||||
REGRESS = repmgr_extension
|
REGRESS = repmgr_extension
|
||||||
|
|
||||||
@@ -66,7 +61,7 @@ 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-cluster.o repmgr-action-node.o repmgr-action-service.o repmgr-action-daemon.o \
|
repmgr-action-cluster.o repmgr-action-node.o repmgr-action-service.o repmgr-action-daemon.o \
|
||||||
configdata.o configfile.o configfile-scan.o log.o strutil.o controldata.o dirutil.o compat.o \
|
configdata.o configfile.o configfile-scan.o log.o strutil.o controldata.o dirutil.o compat.o \
|
||||||
dbutils.o sysutils.o pgbackupapi.o
|
dbutils.o sysutils.o
|
||||||
REPMGRD_OBJS = repmgrd.o repmgrd-physical.o configdata.o configfile.o configfile-scan.o log.o \
|
REPMGRD_OBJS = repmgrd.o repmgrd-physical.o configdata.o configfile.o configfile-scan.o log.o \
|
||||||
dbutils.o strutil.o controldata.o compat.o sysutils.o
|
dbutils.o strutil.o controldata.o compat.o sysutils.o
|
||||||
|
|
||||||
@@ -81,10 +76,10 @@ configfile-scan.c: configfile-scan.l
|
|||||||
$(REPMGR_CLIENT_OBJS): repmgr-client.h repmgr_version.h
|
$(REPMGR_CLIENT_OBJS): repmgr-client.h repmgr_version.h
|
||||||
|
|
||||||
repmgr: $(REPMGR_CLIENT_OBJS)
|
repmgr: $(REPMGR_CLIENT_OBJS)
|
||||||
$(CC) $(CFLAGS) $(REPMGR_CLIENT_OBJS) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
|
$(CC) $(CFLAGS) $(REPMGR_CLIENT_OBJS) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) -o $@$(X)
|
||||||
|
|
||||||
repmgrd: $(REPMGRD_OBJS)
|
repmgrd: $(REPMGRD_OBJS)
|
||||||
$(CC) $(CFLAGS) $(REPMGRD_OBJS) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@$(X)
|
$(CC) $(CFLAGS) $(REPMGRD_OBJS) $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) -o $@$(X)
|
||||||
|
|
||||||
$(REPMGR_CLIENT_OBJS): $(HEADERS)
|
$(REPMGR_CLIENT_OBJS): $(HEADERS)
|
||||||
$(REPMGRD_OBJS): $(HEADERS)
|
$(REPMGRD_OBJS): $(HEADERS)
|
||||||
|
|||||||
34
README.md
34
README.md
@@ -7,10 +7,10 @@ replication capabilities with utilities to set up standby servers, monitor
|
|||||||
replication, and perform administrative tasks such as failover or switchover
|
replication, and perform administrative tasks such as failover or switchover
|
||||||
operations.
|
operations.
|
||||||
|
|
||||||
The most recent `repmgr` version (5.3.2) supports all PostgreSQL versions from
|
The most recent `repmgr` version (5.2.0) supports all PostgreSQL versions from
|
||||||
9.5 to 15. PostgreSQL 9.4 is also supported, with some restrictions.
|
9.5 to 13. PostgreSQL 9.4 is also supported, with some restrictions.
|
||||||
|
|
||||||
`repmgr` is distributed under the GNU GPL 3 and maintained by EnterpriseDB.
|
`repmgr` is distributed under the GNU GPL 3 and maintained by 2ndQuadrant.
|
||||||
|
|
||||||
Documentation
|
Documentation
|
||||||
-------------
|
-------------
|
||||||
@@ -19,6 +19,14 @@ The full `repmgr` documentation is available here:
|
|||||||
|
|
||||||
> [repmgr documentation](https://repmgr.org/docs/current/index.html)
|
> [repmgr documentation](https://repmgr.org/docs/current/index.html)
|
||||||
|
|
||||||
|
The old `README` file for `repmgr` 3.x is available here:
|
||||||
|
|
||||||
|
> https://github.com/2ndQuadrant/repmgr/blob/REL3_3_STABLE/README.md
|
||||||
|
|
||||||
|
Note that the `repmgr` 3.x series is no longer supported and contains known bugs;
|
||||||
|
please upgrade to the [current repmgr version](https://repmgr.org/docs/current/appendix-release-notes.html)
|
||||||
|
as soon as possible.
|
||||||
|
|
||||||
Versions
|
Versions
|
||||||
--------
|
--------
|
||||||
|
|
||||||
@@ -40,17 +48,18 @@ Directories
|
|||||||
- `contrib/`: additional utilities
|
- `contrib/`: additional utilities
|
||||||
- `doc/`: DocBook-based documentation files
|
- `doc/`: DocBook-based documentation files
|
||||||
- `expected/`: expected regression test output
|
- `expected/`: expected regression test output
|
||||||
|
- `scripts/`: example scripts
|
||||||
- `sql/`: regression test input
|
- `sql/`: regression test input
|
||||||
|
|
||||||
|
|
||||||
Support and Assistance
|
Support and Assistance
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
EnterpriseDB provides 24x7 production support for `repmgr`, including
|
2ndQuadrant provides 24x7 production support for `repmgr`, including
|
||||||
configuration assistance, installation verification and training for
|
configuration assistance, installation verification and training for
|
||||||
running a robust replication cluster. For further details see:
|
running a robust replication cluster. For further details see:
|
||||||
|
|
||||||
* [EDB Support Services](https://www.enterprisedb.com/support/postgresql-support-overview-get-the-most-out-of-postgresql)
|
* https://2ndquadrant.com/en/support/
|
||||||
|
|
||||||
There is a mailing list/forum to discuss contributions or issues:
|
There is a mailing list/forum to discuss contributions or issues:
|
||||||
|
|
||||||
@@ -60,15 +69,25 @@ The IRC channel #repmgr is registered with freenode.
|
|||||||
|
|
||||||
Please report bugs and other issues to:
|
Please report bugs and other issues to:
|
||||||
|
|
||||||
* https://github.com/EnterpriseDB/repmgr
|
* https://github.com/2ndQuadrant/repmgr
|
||||||
|
|
||||||
Further information is available at https://repmgr.org/
|
Further information is available at https://repmgr.org/
|
||||||
|
|
||||||
We'd love to hear from you about how you use repmgr. Case studies and
|
We'd love to hear from you about how you use repmgr. Case studies and
|
||||||
news are always welcome.
|
news are always welcome. Send us an email at info@2ndQuadrant.com, or
|
||||||
|
send a postcard to
|
||||||
|
|
||||||
|
repmgr
|
||||||
|
c/o 2ndQuadrant
|
||||||
|
7200 The Quorum
|
||||||
|
Oxford Business Park North
|
||||||
|
Oxford
|
||||||
|
OX4 2JZ
|
||||||
|
United Kingdom
|
||||||
|
|
||||||
Thanks from the repmgr core team.
|
Thanks from the repmgr core team.
|
||||||
|
|
||||||
|
* Ian Barwick
|
||||||
* Jaime Casanova
|
* Jaime Casanova
|
||||||
* Abhijit Menon-Sen
|
* Abhijit Menon-Sen
|
||||||
* Simon Riggs
|
* Simon Riggs
|
||||||
@@ -80,4 +99,3 @@ Further reading
|
|||||||
* [repmgr documentation](https://repmgr.org/docs/current/index.html)
|
* [repmgr documentation](https://repmgr.org/docs/current/index.html)
|
||||||
* [How to Automate PostgreSQL 12 Replication and Failover with repmgr - Part 1](https://www.2ndquadrant.com/en/blog/how-to-automate-postgresql-12-replication-and-failover-with-repmgr-part-1/)
|
* [How to Automate PostgreSQL 12 Replication and Failover with repmgr - Part 1](https://www.2ndquadrant.com/en/blog/how-to-automate-postgresql-12-replication-and-failover-with-repmgr-part-1/)
|
||||||
* [How to Automate PostgreSQL 12 Replication and Failover with repmgr - Part 2](https://www.2ndquadrant.com/en/blog/how-to-automate-postgresql-12-replication-and-failover-with-repmgr-part-2/)
|
* [How to Automate PostgreSQL 12 Replication and Failover with repmgr - Part 2](https://www.2ndquadrant.com/en/blog/how-to-automate-postgresql-12-replication-and-failover-with-repmgr-part-2/)
|
||||||
* [How to implement repmgr for PostgreSQL automatic failover](https://www.enterprisedb.com/postgres-tutorials/how-implement-repmgr-postgresql-automatic-failover)
|
|
||||||
|
|||||||
4
TODO.md
4
TODO.md
@@ -1,7 +1,7 @@
|
|||||||
TODO
|
TODO
|
||||||
====
|
====
|
||||||
|
|
||||||
This file contains a list of improvements which are desirable and/or have
|
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
|
been requested, and which we aim to address/implement when time and resources
|
||||||
permit.
|
permit.
|
||||||
|
|
||||||
@@ -17,4 +17,4 @@ repmgrd nodes to prevent unintended failover; this is obviously inconvenient.
|
|||||||
We'll need to implement some way of notifying each repmgrd to suspend automatic
|
We'll need to implement some way of notifying each repmgrd to suspend automatic
|
||||||
failover until further notice.
|
failover until further notice.
|
||||||
|
|
||||||
Requested in GitHub #410 ( https://github.com/EnterpriseDB/repmgr/issues/410 )
|
Requested in GitHub #410 ( https://github.com/2ndQuadrant/repmgr/issues/410 )
|
||||||
|
|||||||
2
compat.c
2
compat.c
@@ -6,7 +6,7 @@
|
|||||||
* supported PostgreSQL versions. They're unlikely to change but
|
* supported PostgreSQL versions. They're unlikely to change but
|
||||||
* it would be worth keeping an eye on them for any fixes/improvements.
|
* it would be worth keeping an eye on them for any fixes/improvements.
|
||||||
*
|
*
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
* Copyright (c) 2ndQuadrant, 2010-2020
|
||||||
*
|
*
|
||||||
* Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
|
|||||||
2
compat.h
2
compat.h
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* compat.h
|
* compat.h
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
* Copyright (c) 2ndQuadrant, 2010-2020
|
||||||
*
|
*
|
||||||
* Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
|
|||||||
52
configdata.c
52
configdata.c
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* configdata.c - contains structs with parsed configuration data
|
* configdata.c - contains structs with parsed configuration data
|
||||||
*
|
*
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
* Copyright (c) 2ndQuadrant, 2010-2020
|
||||||
*
|
*
|
||||||
* 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
|
||||||
@@ -291,46 +291,6 @@ struct ConfigFileSetting config_file_settings[] =
|
|||||||
{},
|
{},
|
||||||
{}
|
{}
|
||||||
},
|
},
|
||||||
/* pg_backupapi_backup_id*/
|
|
||||||
{
|
|
||||||
"pg_backupapi_backup_id",
|
|
||||||
CONFIG_STRING,
|
|
||||||
{ .strptr = config_file_options.pg_backupapi_backup_id },
|
|
||||||
{ .strdefault = "" },
|
|
||||||
{},
|
|
||||||
{ .strmaxlen = sizeof(config_file_options.pg_backupapi_backup_id) },
|
|
||||||
{}
|
|
||||||
},
|
|
||||||
/* pg_backupapi_host*/
|
|
||||||
{
|
|
||||||
"pg_backupapi_host",
|
|
||||||
CONFIG_STRING,
|
|
||||||
{ .strptr = config_file_options.pg_backupapi_host },
|
|
||||||
{ .strdefault = "" },
|
|
||||||
{},
|
|
||||||
{ .strmaxlen = sizeof(config_file_options.pg_backupapi_host) },
|
|
||||||
{}
|
|
||||||
},
|
|
||||||
/* pg_backupapi_node_name */
|
|
||||||
{
|
|
||||||
"pg_backupapi_node_name",
|
|
||||||
CONFIG_STRING,
|
|
||||||
{ .strptr = config_file_options.pg_backupapi_node_name },
|
|
||||||
{ .strdefault = "" },
|
|
||||||
{},
|
|
||||||
{ .strmaxlen = sizeof(config_file_options.pg_backupapi_node_name) },
|
|
||||||
{}
|
|
||||||
},
|
|
||||||
/* pg_backupapi_remote_ssh_command */
|
|
||||||
{
|
|
||||||
"pg_backupapi_remote_ssh_command",
|
|
||||||
CONFIG_STRING,
|
|
||||||
{ .strptr = config_file_options.pg_backupapi_remote_ssh_command },
|
|
||||||
{ .strdefault = "" },
|
|
||||||
{},
|
|
||||||
{ .strmaxlen = sizeof(config_file_options.pg_backupapi_remote_ssh_command) },
|
|
||||||
{}
|
|
||||||
},
|
|
||||||
|
|
||||||
/* =======================
|
/* =======================
|
||||||
* standby follow settings
|
* standby follow settings
|
||||||
@@ -621,16 +581,6 @@ struct ConfigFileSetting config_file_settings[] =
|
|||||||
{ .strmaxlen = sizeof(config_file_options.repmgrd_pid_file) },
|
{ .strmaxlen = sizeof(config_file_options.repmgrd_pid_file) },
|
||||||
{ .postprocess_func = &repmgr_canonicalize_path }
|
{ .postprocess_func = &repmgr_canonicalize_path }
|
||||||
},
|
},
|
||||||
/* repmgrd_exit_on_inactive_node */
|
|
||||||
{
|
|
||||||
"repmgrd_exit_on_inactive_node",
|
|
||||||
CONFIG_BOOL,
|
|
||||||
{ .boolptr = &config_file_options.repmgrd_exit_on_inactive_node},
|
|
||||||
{ .booldefault = DEFAULT_REPMGRD_EXIT_ON_INACTIVE_NODE },
|
|
||||||
{},
|
|
||||||
{},
|
|
||||||
{}
|
|
||||||
},
|
|
||||||
/* standby_disconnect_on_failover */
|
/* standby_disconnect_on_failover */
|
||||||
{
|
{
|
||||||
"standby_disconnect_on_failover",
|
"standby_disconnect_on_failover",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* configfile.c - parse repmgr.conf and other configuration-related functionality
|
* configfile.c - parse repmgr.conf and other configuration-related functionality
|
||||||
*
|
*
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
* Copyright (c) 2ndQuadrant, 2010-2020
|
||||||
*
|
*
|
||||||
* 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
|
||||||
@@ -1889,7 +1889,7 @@ modify_auto_conf(const char *data_dir, KeyValueList *items)
|
|||||||
/*
|
/*
|
||||||
* Note: durable_rename() is not exposed to frontend code before Pg 10.
|
* Note: durable_rename() is not exposed to frontend code before Pg 10.
|
||||||
* We only really need to be modifying postgresql.auto.conf from Pg 12,
|
* We only really need to be modifying postgresql.auto.conf from Pg 12,
|
||||||
* but provide backwards compatibility for Pg 9.6 and earlier for the
|
* but provide backwards compatibitilty for Pg 9.6 and earlier for the
|
||||||
* (unlikely) event that a repmgr built against one of those versions
|
* (unlikely) event that a repmgr built against one of those versions
|
||||||
* is being used against Pg 12 and later.
|
* is being used against Pg 12 and later.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* configfile.h
|
* configfile.h
|
||||||
*
|
*
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
* Copyright (c) 2ndQuadrant, 2010-2020
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
@@ -164,10 +164,6 @@ typedef struct
|
|||||||
char archive_cleanup_command[MAXLEN];
|
char archive_cleanup_command[MAXLEN];
|
||||||
bool use_primary_conninfo_password;
|
bool use_primary_conninfo_password;
|
||||||
char passfile[MAXPGPATH];
|
char passfile[MAXPGPATH];
|
||||||
char pg_backupapi_backup_id[NAMEDATALEN];
|
|
||||||
char pg_backupapi_host[NAMEDATALEN];
|
|
||||||
char pg_backupapi_node_name[NAMEDATALEN];
|
|
||||||
char pg_backupapi_remote_ssh_command[MAXLEN];
|
|
||||||
|
|
||||||
/* standby promote settings */
|
/* standby promote settings */
|
||||||
int promote_check_timeout;
|
int promote_check_timeout;
|
||||||
@@ -210,7 +206,6 @@ typedef struct
|
|||||||
int primary_notification_timeout;
|
int primary_notification_timeout;
|
||||||
int repmgrd_standby_startup_timeout;
|
int repmgrd_standby_startup_timeout;
|
||||||
char repmgrd_pid_file[MAXPGPATH];
|
char repmgrd_pid_file[MAXPGPATH];
|
||||||
bool repmgrd_exit_on_inactive_node;
|
|
||||||
bool standby_disconnect_on_failover;
|
bool standby_disconnect_on_failover;
|
||||||
int sibling_nodes_disconnect_timeout;
|
int sibling_nodes_disconnect_timeout;
|
||||||
ConnectionCheckType connection_check_type;
|
ConnectionCheckType connection_check_type;
|
||||||
@@ -254,7 +249,7 @@ typedef struct
|
|||||||
/*
|
/*
|
||||||
* undocumented settings
|
* undocumented settings
|
||||||
*
|
*
|
||||||
* These settings are for testing or experimental features
|
* These settings are for testing or experimential features
|
||||||
* and may be changed without notice.
|
* and may be changed without notice.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
28
configure
vendored
28
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 5.4.0.
|
# Generated by GNU Autoconf 2.69 for repmgr 5.2.1.
|
||||||
#
|
#
|
||||||
# Report bugs to <repmgr@googlegroups.com>.
|
# Report bugs to <repmgr@googlegroups.com>.
|
||||||
#
|
#
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
# This configure script is free software; the Free Software Foundation
|
# This configure script is free software; the Free Software Foundation
|
||||||
# gives unlimited permission to copy, distribute and modify it.
|
# gives unlimited permission to copy, distribute and modify it.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2010-2021, EnterpriseDB Corporation
|
# Copyright (c) 2010-2020, 2ndQuadrant Ltd.
|
||||||
## -------------------- ##
|
## -------------------- ##
|
||||||
## M4sh Initialization. ##
|
## M4sh Initialization. ##
|
||||||
## -------------------- ##
|
## -------------------- ##
|
||||||
@@ -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='5.4.0'
|
PACKAGE_VERSION='5.2.1'
|
||||||
PACKAGE_STRING='repmgr 5.4.0'
|
PACKAGE_STRING='repmgr 5.2.1'
|
||||||
PACKAGE_BUGREPORT='repmgr@googlegroups.com'
|
PACKAGE_BUGREPORT='repmgr@googlegroups.com'
|
||||||
PACKAGE_URL='https://repmgr.org/'
|
PACKAGE_URL='https://repmgr.org/'
|
||||||
|
|
||||||
@@ -1181,7 +1181,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 5.4.0 to adapt to many kinds of systems.
|
\`configure' configures repmgr 5.2.1 to adapt to many kinds of systems.
|
||||||
|
|
||||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||||
|
|
||||||
@@ -1242,7 +1242,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 5.4.0:";;
|
short | recursive ) echo "Configuration of repmgr 5.2.1:";;
|
||||||
esac
|
esac
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
|
|
||||||
@@ -1316,14 +1316,14 @@ 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 5.4.0
|
repmgr configure 5.2.1
|
||||||
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.
|
||||||
This configure script is free software; the Free Software Foundation
|
This configure script is free software; the Free Software Foundation
|
||||||
gives unlimited permission to copy, distribute and modify it.
|
gives unlimited permission to copy, distribute and modify it.
|
||||||
|
|
||||||
Copyright (c) 2010-2021, EnterpriseDB Corporation
|
Copyright (c) 2010-2020, 2ndQuadrant Ltd.
|
||||||
_ACEOF
|
_ACEOF
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
@@ -1335,7 +1335,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 5.4.0, which was
|
It was created by repmgr $as_me 5.2.1, which was
|
||||||
generated by GNU Autoconf 2.69. Invocation command line was
|
generated by GNU Autoconf 2.69. Invocation command line was
|
||||||
|
|
||||||
$ $0 $@
|
$ $0 $@
|
||||||
@@ -1811,11 +1811,11 @@ fi
|
|||||||
pgac_pg_config_version=$($PG_CONFIG --version 2>/dev/null)
|
pgac_pg_config_version=$($PG_CONFIG --version 2>/dev/null)
|
||||||
|
|
||||||
major_version_num=$(echo "$pgac_pg_config_version"|
|
major_version_num=$(echo "$pgac_pg_config_version"|
|
||||||
$SED -e 's/^[^0-9]\+ \([0-9]\{1,2\}\).*$/\1/')
|
$SED -e 's/^PostgreSQL \([0-9]\{1,2\}\).*$/\1/')
|
||||||
|
|
||||||
if test "$major_version_num" -lt '10'; then
|
if test "$major_version_num" -lt '10'; then
|
||||||
version_num=$(echo "$pgac_pg_config_version"|
|
version_num=$(echo "$pgac_pg_config_version"|
|
||||||
$SED -e 's/^[^0-9]\+ \([0-9]*\)\.\([0-9]*\)\([a-zA-Z0-9.]*\)$/\1.\2/')
|
$SED -e 's/^PostgreSQL \([0-9]*\)\.\([0-9]*\)\([a-zA-Z0-9.]*\)$/\1.\2/')
|
||||||
|
|
||||||
if test -z "$version_num"; then
|
if test -z "$version_num"; then
|
||||||
as_fn_error $? "could not detect the PostgreSQL version, wrong or broken pg_config?" "$LINENO" 5
|
as_fn_error $? "could not detect the PostgreSQL version, wrong or broken pg_config?" "$LINENO" 5
|
||||||
@@ -1829,7 +1829,7 @@ if test "$major_version_num" -lt '10'; then
|
|||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
version_num=$(echo "$pgac_pg_config_version"|
|
version_num=$(echo "$pgac_pg_config_version"|
|
||||||
$SED -e 's/^[^0-9]\+ \(.\+\)$/\1/')
|
$SED -e 's/^PostgreSQL \(.\+\)$/\1/')
|
||||||
|
|
||||||
if test -z "$version_num"; then
|
if test -z "$version_num"; then
|
||||||
as_fn_error $? "could not detect the PostgreSQL version, wrong or broken pg_config?" "$LINENO" 5
|
as_fn_error $? "could not detect the PostgreSQL version, wrong or broken pg_config?" "$LINENO" 5
|
||||||
@@ -2487,7 +2487,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 5.4.0, which was
|
This file was extended by repmgr $as_me 5.2.1, 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
|
||||||
@@ -2550,7 +2550,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 5.4.0
|
repmgr config.status 5.2.1
|
||||||
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\\"
|
||||||
|
|
||||||
|
|||||||
32
configure.in
32
configure.in
@@ -1,8 +1,8 @@
|
|||||||
AC_INIT([repmgr],[5.4.1],[repmgr@googlegroups.com],[repmgr],[https://www.repmgr.org/])
|
AC_INIT([repmgr], [5.2.1], [repmgr@googlegroups.com], [repmgr], [https://repmgr.org/])
|
||||||
|
|
||||||
AC_COPYRIGHT([Copyright (c) 2010-2021, EnterpriseDB Corporation])
|
AC_COPYRIGHT([Copyright (c) 2010-2020, 2ndQuadrant Ltd.])
|
||||||
|
|
||||||
AC_CONFIG_HEADERS([config.h])
|
AC_CONFIG_HEADER(config.h)
|
||||||
|
|
||||||
AC_ARG_VAR([PG_CONFIG], [Location to find pg_config for target PostgreSQL (default PATH)])
|
AC_ARG_VAR([PG_CONFIG], [Location to find pg_config for target PostgreSQL (default PATH)])
|
||||||
|
|
||||||
@@ -19,11 +19,11 @@ fi
|
|||||||
pgac_pg_config_version=$($PG_CONFIG --version 2>/dev/null)
|
pgac_pg_config_version=$($PG_CONFIG --version 2>/dev/null)
|
||||||
|
|
||||||
major_version_num=$(echo "$pgac_pg_config_version"|
|
major_version_num=$(echo "$pgac_pg_config_version"|
|
||||||
$SED -e 's/^[[^0-9]]\+ \([[0-9]]\{1,2\}\).*$/\1/')
|
$SED -e 's/^PostgreSQL \([[0-9]]\{1,2\}\).*$/\1/')
|
||||||
|
|
||||||
if test "$major_version_num" -lt '10'; then
|
if test "$major_version_num" -lt '10'; then
|
||||||
version_num=$(echo "$pgac_pg_config_version"|
|
version_num=$(echo "$pgac_pg_config_version"|
|
||||||
$SED -e 's/^[[^0-9]]\+ \([[0-9]]*\)\.\([[0-9]]*\)\([[a-zA-Z0-9.]]*\)$/\1.\2/')
|
$SED -e 's/^PostgreSQL \([[0-9]]*\)\.\([[0-9]]*\)\([[a-zA-Z0-9.]]*\)$/\1.\2/')
|
||||||
|
|
||||||
if test -z "$version_num"; then
|
if test -z "$version_num"; then
|
||||||
AC_MSG_ERROR([could not detect the PostgreSQL version, wrong or broken pg_config?])
|
AC_MSG_ERROR([could not detect the PostgreSQL version, wrong or broken pg_config?])
|
||||||
@@ -37,7 +37,7 @@ if test "$major_version_num" -lt '10'; then
|
|||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
version_num=$(echo "$pgac_pg_config_version"|
|
version_num=$(echo "$pgac_pg_config_version"|
|
||||||
$SED -e 's/^[[^0-9]]\+ \(.\+\)$/\1/')
|
$SED -e 's/^PostgreSQL \(.\+\)$/\1/')
|
||||||
|
|
||||||
if test -z "$version_num"; then
|
if test -z "$version_num"; then
|
||||||
AC_MSG_ERROR([could not detect the PostgreSQL version, wrong or broken pg_config?])
|
AC_MSG_ERROR([could not detect the PostgreSQL version, wrong or broken pg_config?])
|
||||||
@@ -60,7 +60,6 @@ AC_SUBST(vpath_build)
|
|||||||
AC_CHECK_PROG(HAVE_GNUSED,gnused,yes,no)
|
AC_CHECK_PROG(HAVE_GNUSED,gnused,yes,no)
|
||||||
AC_CHECK_PROG(HAVE_GSED,gsed,yes,no)
|
AC_CHECK_PROG(HAVE_GSED,gsed,yes,no)
|
||||||
AC_CHECK_PROG(HAVE_SED,sed,yes,no)
|
AC_CHECK_PROG(HAVE_SED,sed,yes,no)
|
||||||
AC_CHECK_PROG(HAVE_FLEX,flex,yes,no)
|
|
||||||
|
|
||||||
if test "$HAVE_GNUSED" = yes; then
|
if test "$HAVE_GNUSED" = yes; then
|
||||||
SED=gnused
|
SED=gnused
|
||||||
@@ -73,25 +72,6 @@ else
|
|||||||
fi
|
fi
|
||||||
AC_SUBST(SED)
|
AC_SUBST(SED)
|
||||||
|
|
||||||
AS_IF([test x"$HAVE_FLEX" != x"yes"], AC_MSG_ERROR([flex should be installed first]))
|
|
||||||
|
|
||||||
#Checking libraries
|
|
||||||
GENERIC_LIB_FAILED_MSG="library should be installed"
|
|
||||||
|
|
||||||
AC_CHECK_LIB(selinux, is_selinux_enabled, [],
|
|
||||||
[AC_MSG_ERROR(['selinux' $GENERIC_LIB_FAILED_MSG])])
|
|
||||||
|
|
||||||
AC_CHECK_LIB(lz4, LZ4_compress_default, [],
|
|
||||||
[AC_MSG_ERROR(['Z4' $GENERIC_LIB_FAILED_MSG])])
|
|
||||||
|
|
||||||
AC_CHECK_LIB(xslt, xsltCleanupGlobals, [],
|
|
||||||
[AC_MSG_ERROR(['xslt' $GENERIC_LIB_FAILED_MSG])])
|
|
||||||
|
|
||||||
AC_CHECK_LIB(pam, pam_start, [],
|
|
||||||
[AC_MSG_ERROR(['pam' $GENERIC_LIB_FAILED_MSG])])
|
|
||||||
|
|
||||||
AC_CHECK_LIB(gssapi_krb5, gss_init_sec_context, [],
|
|
||||||
[AC_MSG_ERROR([gssapi_krb5 $GENERIC_LIB_FAILED_MSG])])
|
|
||||||
|
|
||||||
AC_CONFIG_FILES([Makefile])
|
AC_CONFIG_FILES([Makefile])
|
||||||
AC_CONFIG_FILES([Makefile.global])
|
AC_CONFIG_FILES([Makefile.global])
|
||||||
|
|||||||
@@ -2,11 +2,11 @@
|
|||||||
* controldata.c - functions for reading the pg_control file
|
* controldata.c - functions for reading the pg_control file
|
||||||
*
|
*
|
||||||
* The functions provided here enable repmgr to read a pg_control file
|
* The functions provided here enable repmgr to read a pg_control file
|
||||||
* in a version-independent way, even if the PostgreSQL instance is not
|
* in a version-indepent way, even if the PostgreSQL instance is not
|
||||||
* running. For that reason we can't use on the pg_control_*() functions
|
* running. For that reason we can't use on the pg_control_*() functions
|
||||||
* provided in PostgreSQL 9.6 and later.
|
* provided in PostgreSQL 9.6 and later.
|
||||||
*
|
*
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
* Copyright (c) 2ndQuadrant, 2010-2020
|
||||||
*
|
*
|
||||||
* Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* controldata.h
|
* controldata.h
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
* Copyright (c) 2ndQuadrant, 2010-2020
|
||||||
*
|
*
|
||||||
* Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
|
|||||||
185
dbutils.c
185
dbutils.c
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* dbutils.c - Database connection/management functions
|
* dbutils.c - Database connection/management functions
|
||||||
*
|
*
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
* Copyright (c) 2ndQuadrant, 2010-2020
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
@@ -61,8 +61,6 @@ static ReplSlotStatus _verify_replication_slot(PGconn *conn, char *slot_name, PQ
|
|||||||
|
|
||||||
static bool _create_event(PGconn *conn, t_configuration_options *options, int node_id, char *event, bool successful, char *details, t_event_info *event_info, bool send_notification);
|
static bool _create_event(PGconn *conn, t_configuration_options *options, int node_id, char *event, bool successful, char *details, t_event_info *event_info, bool send_notification);
|
||||||
|
|
||||||
static NodeAttached _is_downstream_node_attached(PGconn *conn, char *node_name, char **node_state, bool quiet);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This provides a standardized way of logging database errors. Note
|
* This provides a standardized way of logging database errors. Note
|
||||||
* that the provided PGconn can be a normal or a replication connection;
|
* that the provided PGconn can be a normal or a replication connection;
|
||||||
@@ -732,8 +730,6 @@ validate_conninfo_string(const char *conninfo_str, char **errmsg)
|
|||||||
if (connOptions == NULL)
|
if (connOptions == NULL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
PQconninfoFree(connOptions);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1291,16 +1287,21 @@ get_cluster_size(PGconn *conn, char *size)
|
|||||||
initPQExpBuffer(&query);
|
initPQExpBuffer(&query);
|
||||||
appendPQExpBufferStr(&query,
|
appendPQExpBufferStr(&query,
|
||||||
"SELECT pg_catalog.pg_size_pretty(pg_catalog.sum(pg_catalog.pg_database_size(oid))::bigint) "
|
"SELECT pg_catalog.pg_size_pretty(pg_catalog.sum(pg_catalog.pg_database_size(oid))::bigint) "
|
||||||
" FROM pg_catalog.pg_database ");
|
" FROM pg_catalog.pg_database ");
|
||||||
|
|
||||||
log_verbose(LOG_DEBUG, "get_cluster_size():\n%s", query.data);
|
log_verbose(LOG_DEBUG, "get_cluster_size():\n%s", query.data);
|
||||||
|
|
||||||
res = PQexec(conn, query.data);
|
res = PQexec(conn, query.data);
|
||||||
|
|
||||||
if (PQresultStatus(res) != PGRES_TUPLES_OK)
|
if (PQresultStatus(res) != PGRES_TUPLES_OK)
|
||||||
|
{
|
||||||
|
log_db_error(conn, query.data, _("get_cluster_size(): unable to execute query"));
|
||||||
success = false;
|
success = false;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
snprintf(size, MAXLEN, "%s", PQgetvalue(res, 0, 0));
|
snprintf(size, MAXLEN, "%s", PQgetvalue(res, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
termPQExpBuffer(&query);
|
termPQExpBuffer(&query);
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
@@ -1823,30 +1824,6 @@ get_timeline_history(PGconn *repl_conn, TimeLineID tli)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pid_t
|
|
||||||
get_wal_receiver_pid(PGconn *conn)
|
|
||||||
{
|
|
||||||
PGresult *res = NULL;
|
|
||||||
pid_t wal_receiver_pid = UNKNOWN_PID;
|
|
||||||
|
|
||||||
res = PQexec(conn, "SELECT repmgr.get_wal_receiver_pid()");
|
|
||||||
|
|
||||||
if (PQresultStatus(res) != PGRES_TUPLES_OK)
|
|
||||||
{
|
|
||||||
log_error(_("unable to execute \"SELECT repmgr.get_wal_receiver_pid()\""));
|
|
||||||
log_detail("%s", PQerrorMessage(conn));
|
|
||||||
}
|
|
||||||
else if (!PQgetisnull(res, 0, 0))
|
|
||||||
{
|
|
||||||
wal_receiver_pid = atoi(PQgetvalue(res, 0, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
PQclear(res);
|
|
||||||
|
|
||||||
return wal_receiver_pid;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* =============================== */
|
/* =============================== */
|
||||||
/* user/role information functions */
|
/* user/role information functions */
|
||||||
/* =============================== */
|
/* =============================== */
|
||||||
@@ -1888,42 +1865,6 @@ can_execute_pg_promote(PGconn *conn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Determine if the user associated with the current connection
|
|
||||||
* has sufficient permissions to disable the walsender
|
|
||||||
*/
|
|
||||||
bool
|
|
||||||
can_disable_walsender(PGconn *conn)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Requires PostgreSQL 9.5 or later, because ALTER SYSTEM
|
|
||||||
*/
|
|
||||||
if (PQserverVersion(conn) < 90500)
|
|
||||||
{
|
|
||||||
log_warning(_("\"standby_disconnect_on_failover\" specified, but not available for this PostgreSQL version"));
|
|
||||||
/* TODO: format server version */
|
|
||||||
log_detail(_("available from PostgreSQL 9.5; this PostgreSQL version is %i"), PQserverVersion(conn));
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Superusers can do anything
|
|
||||||
*/
|
|
||||||
if (is_superuser_connection(conn, NULL) == true)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* As of PostgreSQL 14, it is not possible for a non-superuser
|
|
||||||
* to execute ALTER SYSTEM, so further checks are superfluous.
|
|
||||||
* This will need modifying for PostgreSQL 15.
|
|
||||||
*/
|
|
||||||
log_warning(_("\"standby_disconnect_on_failover\" specified, but repmgr user is not a superuser"));
|
|
||||||
log_detail(_("superuser permission required to disable standbys on failover"));
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Determine if the user associated with the current connection is
|
* Determine if the user associated with the current connection is
|
||||||
* a member of the "pg_monitor" default role, or optionally one
|
* a member of the "pg_monitor" default role, or optionally one
|
||||||
@@ -2139,13 +2080,7 @@ server_in_exclusive_backup_mode(PGconn *conn)
|
|||||||
{
|
{
|
||||||
BackupState backup_state = BACKUP_STATE_UNKNOWN;
|
BackupState backup_state = BACKUP_STATE_UNKNOWN;
|
||||||
const char *sqlquery = "SELECT pg_catalog.pg_is_in_backup()";
|
const char *sqlquery = "SELECT pg_catalog.pg_is_in_backup()";
|
||||||
PGresult *res = NULL;
|
PGresult *res = PQexec(conn, sqlquery);
|
||||||
|
|
||||||
/* Exclusive backup removed from PostgreSQL 15 */
|
|
||||||
if (PQserverVersion(conn) >= 150000)
|
|
||||||
return BACKUP_STATE_NO_BACKUP;
|
|
||||||
|
|
||||||
res = PQexec(conn, sqlquery);
|
|
||||||
|
|
||||||
if (PQresultStatus(res) != PGRES_TUPLES_OK)
|
if (PQresultStatus(res) != PGRES_TUPLES_OK)
|
||||||
{
|
{
|
||||||
@@ -2309,6 +2244,29 @@ repmgrd_pause(PGconn *conn, bool pause)
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pid_t
|
||||||
|
get_wal_receiver_pid(PGconn *conn)
|
||||||
|
{
|
||||||
|
PGresult *res = NULL;
|
||||||
|
pid_t wal_receiver_pid = UNKNOWN_PID;
|
||||||
|
|
||||||
|
res = PQexec(conn, "SELECT repmgr.get_wal_receiver_pid()");
|
||||||
|
|
||||||
|
if (PQresultStatus(res) != PGRES_TUPLES_OK)
|
||||||
|
{
|
||||||
|
log_error(_("unable to execute \"SELECT repmgr.get_wal_receiver_pid()\""));
|
||||||
|
log_detail("%s", PQerrorMessage(conn));
|
||||||
|
}
|
||||||
|
else if (!PQgetisnull(res, 0, 0))
|
||||||
|
{
|
||||||
|
wal_receiver_pid = atoi(PQgetvalue(res, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
PQclear(res);
|
||||||
|
|
||||||
|
return wal_receiver_pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
repmgrd_get_upstream_node_id(PGconn *conn)
|
repmgrd_get_upstream_node_id(PGconn *conn)
|
||||||
@@ -4282,7 +4240,7 @@ _create_event(PGconn *conn, t_configuration_options *options, int node_id, char
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
/* %p: primary id ("standby_switchover"/"repmgrd_failover_promote": former primary id) */
|
/* %p: primary id ("standby_switchover": former primary id) */
|
||||||
src_ptr++;
|
src_ptr++;
|
||||||
if (event_info->node_id != UNKNOWN_NODE_ID)
|
if (event_info->node_id != UNKNOWN_NODE_ID)
|
||||||
{
|
{
|
||||||
@@ -4616,17 +4574,17 @@ drop_replication_slot_replprot(PGconn *repl_conn, char *slot_name)
|
|||||||
initPQExpBuffer(&query);
|
initPQExpBuffer(&query);
|
||||||
|
|
||||||
appendPQExpBuffer(&query,
|
appendPQExpBuffer(&query,
|
||||||
"DROP_REPLICATION_SLOT %s;",
|
"DROP_REPLICATION_SLOT %s",
|
||||||
slot_name);
|
slot_name);
|
||||||
|
|
||||||
log_verbose(LOG_DEBUG, "drop_replication_slot_replprot():\n %s", query.data);
|
log_verbose(LOG_DEBUG, "drop_replication_slot_replprot():\n %s", query.data);
|
||||||
|
|
||||||
res = PQexec(repl_conn, query.data);
|
res = PQexec(repl_conn, query.data);
|
||||||
|
|
||||||
if (PQresultStatus(res) != PGRES_TUPLES_OK || !PQntuples(res))
|
if (PQresultStatus(res) != PGRES_TUPLES_OK)
|
||||||
{
|
{
|
||||||
log_db_error(repl_conn, query.data,
|
log_db_error(repl_conn, query.data,
|
||||||
_("drop_replication_slot_replprot(): unable to drop replication slot \"%s\""),
|
_("drop_replication_slot_sql(): unable to drop replication slot \"%s\""),
|
||||||
slot_name);
|
slot_name);
|
||||||
|
|
||||||
success = false;
|
success = false;
|
||||||
@@ -4867,7 +4825,7 @@ cancel_query(PGconn *conn, int timeout)
|
|||||||
* Wait until current query finishes, ignoring any results.
|
* Wait until current query finishes, ignoring any results.
|
||||||
* Usually this will be an async query or query cancellation.
|
* Usually this will be an async query or query cancellation.
|
||||||
*
|
*
|
||||||
* Returns 1 for success; 0 if any error occurred; -1 if timeout reached.
|
* Returns 1 for success; 0 if any error ocurred; -1 if timeout reached.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
wait_connection_availability(PGconn *conn, int timeout)
|
wait_connection_availability(PGconn *conn, int timeout)
|
||||||
@@ -5744,7 +5702,7 @@ get_node_timeline(PGconn *conn, char *timeline_id_str)
|
|||||||
TimeLineID timeline_id = UNKNOWN_TIMELINE_ID;
|
TimeLineID timeline_id = UNKNOWN_TIMELINE_ID;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* pg_control_checkpoint() was introduced in PostgreSQL 9.6
|
* PG_control_checkpoint() was introduced in PostgreSQL 9.6
|
||||||
*/
|
*/
|
||||||
if (PQserverVersion(conn) >= 90600)
|
if (PQserverVersion(conn) >= 90600)
|
||||||
{
|
{
|
||||||
@@ -5832,19 +5790,6 @@ get_node_replication_stats(PGconn *conn, t_node_info *node_info)
|
|||||||
NodeAttached
|
NodeAttached
|
||||||
is_downstream_node_attached(PGconn *conn, char *node_name, char **node_state)
|
is_downstream_node_attached(PGconn *conn, char *node_name, char **node_state)
|
||||||
{
|
{
|
||||||
return _is_downstream_node_attached(conn, node_name, node_state, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeAttached
|
|
||||||
is_downstream_node_attached_quiet(PGconn *conn, char *node_name, char **node_state)
|
|
||||||
{
|
|
||||||
return _is_downstream_node_attached(conn, node_name, node_state, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeAttached
|
|
||||||
_is_downstream_node_attached(PGconn *conn, char *node_name, char **node_state, bool quiet)
|
|
||||||
{
|
|
||||||
|
|
||||||
PQExpBufferData query;
|
PQExpBufferData query;
|
||||||
PGresult *res = NULL;
|
PGresult *res = NULL;
|
||||||
|
|
||||||
@@ -5879,12 +5824,9 @@ _is_downstream_node_attached(PGconn *conn, char *node_name, char **node_state, b
|
|||||||
*/
|
*/
|
||||||
if (PQntuples(res) > 1)
|
if (PQntuples(res) > 1)
|
||||||
{
|
{
|
||||||
if (quiet == false)
|
log_error(_("multiple entries with \"application_name\" set to \"%s\" found in \"pg_stat_replication\""),
|
||||||
{
|
node_name);
|
||||||
log_error(_("multiple entries with \"application_name\" set to \"%s\" found in \"pg_stat_replication\""),
|
log_hint(_("verify that a unique node name is configured for each node"));
|
||||||
node_name);
|
|
||||||
log_hint(_("verify that a unique node name is configured for each node"));
|
|
||||||
}
|
|
||||||
|
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
|
|
||||||
@@ -5893,8 +5835,7 @@ _is_downstream_node_attached(PGconn *conn, char *node_name, char **node_state, b
|
|||||||
|
|
||||||
if (PQntuples(res) == 0)
|
if (PQntuples(res) == 0)
|
||||||
{
|
{
|
||||||
if (quiet == false)
|
log_warning(_("node \"%s\" not found in \"pg_stat_replication\""), node_name);
|
||||||
log_warning(_("node \"%s\" not found in \"pg_stat_replication\""), node_name);
|
|
||||||
|
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
|
|
||||||
@@ -5920,10 +5861,9 @@ _is_downstream_node_attached(PGconn *conn, char *node_name, char **node_state, b
|
|||||||
|
|
||||||
if (strcmp(state, "streaming") != 0)
|
if (strcmp(state, "streaming") != 0)
|
||||||
{
|
{
|
||||||
if (quiet == false)
|
log_warning(_("node \"%s\" attached in state \"%s\""),
|
||||||
log_warning(_("node \"%s\" attached in state \"%s\""),
|
node_name,
|
||||||
node_name,
|
state);
|
||||||
state);
|
|
||||||
|
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
|
|
||||||
@@ -6066,43 +6006,6 @@ is_wal_replay_paused(PGconn *conn, bool check_pending_wal)
|
|||||||
return is_paused;
|
return is_paused;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* repmgrd status functions */
|
|
||||||
|
|
||||||
CheckStatus
|
|
||||||
get_repmgrd_status(PGconn *conn)
|
|
||||||
{
|
|
||||||
PQExpBufferData query;
|
|
||||||
PGresult *res = NULL;
|
|
||||||
CheckStatus repmgrd_status = CHECK_STATUS_CRITICAL;
|
|
||||||
|
|
||||||
initPQExpBuffer(&query);
|
|
||||||
|
|
||||||
appendPQExpBufferStr(&query,
|
|
||||||
" SELECT "
|
|
||||||
" CASE "
|
|
||||||
" WHEN repmgr.repmgrd_is_running() "
|
|
||||||
" THEN "
|
|
||||||
" CASE "
|
|
||||||
" WHEN repmgr.repmgrd_is_paused() THEN 1 ELSE 0 "
|
|
||||||
" END "
|
|
||||||
" ELSE 2 "
|
|
||||||
" END AS repmgrd_status");
|
|
||||||
res = PQexec(conn, query.data);
|
|
||||||
|
|
||||||
if (PQresultStatus(res) != PGRES_TUPLES_OK)
|
|
||||||
{
|
|
||||||
log_db_error(conn, query.data, _("unable to execute repmgrd status query"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
repmgrd_status = atoi(PQgetvalue(res, 0, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
termPQExpBuffer(&query);
|
|
||||||
PQclear(res);
|
|
||||||
return repmgrd_status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* miscellaneous debugging functions */
|
/* miscellaneous debugging functions */
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* dbutils.h
|
* dbutils.h
|
||||||
*
|
*
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
* Copyright (c) 2ndQuadrant, 2010-2020
|
||||||
*
|
*
|
||||||
* 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
|
||||||
@@ -450,11 +450,9 @@ 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);
|
||||||
uint64 system_identifier(PGconn *conn);
|
uint64 system_identifier(PGconn *conn);
|
||||||
TimeLineHistoryEntry *get_timeline_history(PGconn *repl_conn, TimeLineID tli);
|
TimeLineHistoryEntry *get_timeline_history(PGconn *repl_conn, TimeLineID tli);
|
||||||
pid_t get_wal_receiver_pid(PGconn *conn);
|
|
||||||
|
|
||||||
/* user/role information functions */
|
/* user/role information functions */
|
||||||
bool can_execute_pg_promote(PGconn *conn);
|
bool can_execute_pg_promote(PGconn *conn);
|
||||||
bool can_disable_walsender(PGconn *conn);
|
|
||||||
bool connection_has_pg_monitor_role(PGconn *conn, const char *subrole);
|
bool connection_has_pg_monitor_role(PGconn *conn, const char *subrole);
|
||||||
bool is_replication_role(PGconn *conn, char *rolname);
|
bool is_replication_role(PGconn *conn, char *rolname);
|
||||||
bool is_superuser_connection(PGconn *conn, t_connection_user *userinfo);
|
bool is_superuser_connection(PGconn *conn, t_connection_user *userinfo);
|
||||||
@@ -469,6 +467,7 @@ pid_t repmgrd_get_pid(PGconn *conn);
|
|||||||
bool repmgrd_is_running(PGconn *conn);
|
bool repmgrd_is_running(PGconn *conn);
|
||||||
bool repmgrd_is_paused(PGconn *conn);
|
bool repmgrd_is_paused(PGconn *conn);
|
||||||
bool repmgrd_pause(PGconn *conn, bool pause);
|
bool repmgrd_pause(PGconn *conn, bool pause);
|
||||||
|
pid_t get_wal_receiver_pid(PGconn *conn);
|
||||||
int repmgrd_get_upstream_node_id(PGconn *conn);
|
int repmgrd_get_upstream_node_id(PGconn *conn);
|
||||||
bool repmgrd_set_upstream_node_id(PGconn *conn, int node_id);
|
bool repmgrd_set_upstream_node_id(PGconn *conn, int node_id);
|
||||||
|
|
||||||
@@ -598,15 +597,11 @@ int get_replication_lag_seconds(PGconn *conn);
|
|||||||
TimeLineID get_node_timeline(PGconn *conn, char *timeline_id_str);
|
TimeLineID get_node_timeline(PGconn *conn, char *timeline_id_str);
|
||||||
void get_node_replication_stats(PGconn *conn, t_node_info *node_info);
|
void get_node_replication_stats(PGconn *conn, t_node_info *node_info);
|
||||||
NodeAttached is_downstream_node_attached(PGconn *conn, char *node_name, char **node_state);
|
NodeAttached is_downstream_node_attached(PGconn *conn, char *node_name, char **node_state);
|
||||||
NodeAttached is_downstream_node_attached_quiet(PGconn *conn, char *node_name, char **node_state);
|
|
||||||
void set_upstream_last_seen(PGconn *conn, int upstream_node_id);
|
void set_upstream_last_seen(PGconn *conn, int upstream_node_id);
|
||||||
int get_upstream_last_seen(PGconn *conn, t_server_type node_type);
|
int get_upstream_last_seen(PGconn *conn, t_server_type node_type);
|
||||||
|
|
||||||
bool is_wal_replay_paused(PGconn *conn, bool check_pending_wal);
|
bool is_wal_replay_paused(PGconn *conn, bool check_pending_wal);
|
||||||
|
|
||||||
/* repmgrd status functions */
|
|
||||||
CheckStatus get_repmgrd_status(PGconn *conn);
|
|
||||||
|
|
||||||
/* miscellaneous debugging functions */
|
/* miscellaneous debugging functions */
|
||||||
const char *print_node_status(NodeStatus node_status);
|
const char *print_node_status(NodeStatus node_status);
|
||||||
const char *print_pqping_status(PGPing ping_status);
|
const char *print_pqping_status(PGPing ping_status);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* dirmod.c
|
* dirmod.c
|
||||||
* directory handling functions
|
* directory handling functions
|
||||||
*
|
*
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
* Copyright (c) 2ndQuadrant, 2010-2020
|
||||||
*
|
*
|
||||||
* 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
|
||||||
@@ -205,7 +205,7 @@ mkdir_p(char *path, mode_t omode)
|
|||||||
/*
|
/*
|
||||||
* POSIX 1003.2: For each dir operand that does not name an
|
* POSIX 1003.2: For each dir operand that does not name an
|
||||||
* existing directory, effects equivalent to those caused by the
|
* existing directory, effects equivalent to those caused by the
|
||||||
* following command shall occur:
|
* following command shall occcur:
|
||||||
*
|
*
|
||||||
* mkdir -p -m $(umask -S),u+wx $(dirname dir) && mkdir [-m mode]
|
* mkdir -p -m $(umask -S),u+wx $(dirname dir) && mkdir [-m mode]
|
||||||
* dir
|
* dir
|
||||||
@@ -289,7 +289,7 @@ is_pg_running(const char *path)
|
|||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* No PID file - PostgreSQL shouldn't be running. From 9.3 (the
|
* No PID file - PostgreSQL shouldn't be running. From 9.3 (the
|
||||||
* earliest version we care about) removal of the PID file will
|
* earliesty version we care about) removal of the PID file will
|
||||||
* cause the postmaster to shut down, so it's highly unlikely
|
* cause the postmaster to shut down, so it's highly unlikely
|
||||||
* that PostgreSQL will still be running.
|
* that PostgreSQL will still be running.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* dirutil.h
|
* dirutil.h
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
* Copyright (c) 2ndQuadrant, 2010-2020
|
||||||
*
|
*
|
||||||
* 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
|
||||||
|
|||||||
@@ -95,7 +95,6 @@ clean:
|
|||||||
rm -f repmgr.html
|
rm -f repmgr.html
|
||||||
rm -f repmgr-A4.pdf
|
rm -f repmgr-A4.pdf
|
||||||
rm -f repmgr-US.pdf
|
rm -f repmgr-US.pdf
|
||||||
rm -f *.fo
|
|
||||||
rm -f html/*
|
rm -f html/*
|
||||||
|
|
||||||
maintainer-clean:
|
maintainer-clean:
|
||||||
|
|||||||
@@ -62,7 +62,7 @@
|
|||||||
|
|
||||||
<tip>
|
<tip>
|
||||||
<para>
|
<para>
|
||||||
Our recommended configuration is to configure
|
2ndQuadrant's recommended configuration is to configure
|
||||||
<ulink url="https://www.pgbarman.org/">Barman</ulink> as a fallback
|
<ulink url="https://www.pgbarman.org/">Barman</ulink> as a fallback
|
||||||
source of WAL files, rather than maintain replication slots for
|
source of WAL files, rather than maintain replication slots for
|
||||||
each standby. See also: <link linkend="cloning-from-barman-restore-command">Using Barman as a WAL file source</link>.
|
each standby. See also: <link linkend="cloning-from-barman-restore-command">Using Barman as a WAL file source</link>.
|
||||||
@@ -127,7 +127,7 @@
|
|||||||
filesystem layouts.
|
filesystem layouts.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Either use PostgreSQL packages provided by the community or EnterpriseDB; if this
|
Either use PostgreSQL packages provided by the community or 2ndQuadrant; if this
|
||||||
is not possible, contact your vendor for assistance.
|
is not possible, contact your vendor for assistance.
|
||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
@@ -170,7 +170,7 @@
|
|||||||
<para>
|
<para>
|
||||||
If different "minor" &repmgr; versions (e.g. 4.1.1 and 4.1.6) are installed,
|
If different "minor" &repmgr; versions (e.g. 4.1.1 and 4.1.6) are installed,
|
||||||
&repmgr; will function, but we strongly recommend always running the same version
|
&repmgr; will function, but we strongly recommend always running the same version
|
||||||
to ensure there are no unexpected surprises, e.g. a newer version behaving slightly
|
to ensure there are no unexpected suprises, e.g. a newer version behaving slightly
|
||||||
differently to the older version.
|
differently to the older version.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
@@ -212,11 +212,11 @@
|
|||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
|
|
||||||
<sect2 id="faq-third-party-packages" xreflabel="Compatibility with third party vendor packages">
|
<sect2 id="faq-third-party-packages" xreflabel="Compatability with third party vendor packages">
|
||||||
<title>Are &repmgr; packages compatible with <literal>$third_party_vendor</literal>'s packages?</title>
|
<title>Are &repmgr; packages compatible with <literal>$third_party_vendor</literal>'s packages?</title>
|
||||||
<para>
|
<para>
|
||||||
&repmgr; packages provided by EnterpriseDB are compatible with the community-provided PostgreSQL
|
&repmgr; packages provided by 2ndQuadrant are compatible with the community-provided PostgreSQL
|
||||||
packages and specified software provided by EnterpriseDB.
|
packages and any software provided by 2ndQuadrant.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
A number of other vendors provide their own versions of PostgreSQL packages, often with different
|
A number of other vendors provide their own versions of PostgreSQL packages, often with different
|
||||||
@@ -249,16 +249,16 @@
|
|||||||
For a standby which has been manually cloned or recovered from an external
|
For a standby which has been manually cloned or recovered from an external
|
||||||
backup manager such as Barman, the command
|
backup manager such as Barman, the command
|
||||||
<command><link linkend="repmgr-standby-clone">repmgr standby clone --replication-conf-only</link></command>
|
<command><link linkend="repmgr-standby-clone">repmgr standby clone --replication-conf-only</link></command>
|
||||||
can be used to create the correct replication configuration file for
|
can be used to create the correct <filename>recovery.conf</filename> file for
|
||||||
use with &repmgr; (and will create a replication slot if required). Once this has been done,
|
use with &repmgr; (and will create a replication slot if required). Once this has been done,
|
||||||
<link linkend="repmgr-standby-register">register the node</link> as usual.
|
<link linkend="repmgr-standby-register">register the node</link> as usual.
|
||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
|
|
||||||
<sect2 id="faq-repmgr-recovery-conf" >
|
<sect2 id="faq-repmgr-recovery-conf" >
|
||||||
<title>What does &repmgr; write in the replication configuration, and what options can be set there?</title>
|
<title>What does &repmgr; write in <filename>recovery.conf</filename>, and what options can be set there?</title>
|
||||||
<para>
|
<para>
|
||||||
See section <link linkend="repmgr-standby-clone-recovery-conf">Customising replication configuration</link>.
|
See section <link linkend="repmgr-standby-clone-recovery-conf">Customising recovery.conf</link>.
|
||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
|
|
||||||
@@ -311,7 +311,7 @@
|
|||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
|
|
||||||
<sect2 id="faq-repmgr-shared-preload-libraries-no-repmgrd" xreflabel="shared_preload_libraries without repmgrd">
|
<sect2 id="faq-repmgr-shared-preload-libaries-no-repmgrd" xreflabel="shared_preload_libraries without repmgrd">
|
||||||
<title>Do I need to include <literal>shared_preload_libraries = 'repmgr'</literal>
|
<title>Do I need to include <literal>shared_preload_libraries = 'repmgr'</literal>
|
||||||
in <filename>postgresql.conf</filename> if I'm not using &repmgrd;?</title>
|
in <filename>postgresql.conf</filename> if I'm not using &repmgrd;?</title>
|
||||||
<para>
|
<para>
|
||||||
@@ -366,11 +366,11 @@
|
|||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
|
|
||||||
<sect2 id="faq-repmgr-recovery-conf-quoted-values" xreflabel="Quoted values in replication.conf">
|
<sect2 id="faq-repmgr-recovery-conf-quoted-values" xreflabel="Quoted values in recovery.conf">
|
||||||
<title>Why are some values in <filename>recovery.conf</filename> (PostgreSQL 11 and earlier) surrounded by pairs of single quotes?</title>
|
<title>Why are some values in <filename>recovery.conf</filename> surrounded by pairs of single quotes?</title>
|
||||||
<para>
|
<para>
|
||||||
This is to ensure that user-supplied values which are written as parameter values in <filename>recovery.conf</filename>
|
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 the file is parsed.
|
are escaped correctly and do not cause errors when <filename>recovery.conf</filename> is parsed.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
The escaping is performed by an internal PostgreSQL routine, which leaves strings consisting
|
The escaping is performed by an internal PostgreSQL routine, which leaves strings consisting
|
||||||
@@ -419,9 +419,9 @@
|
|||||||
<para>
|
<para>
|
||||||
&repmgrd; can monitor delayed standbys - those set up with
|
&repmgrd; can monitor delayed standbys - those set up with
|
||||||
<varname>recovery_min_apply_delay</varname> set to a non-zero value
|
<varname>recovery_min_apply_delay</varname> set to a non-zero value
|
||||||
in the replication configuration. However &repmgrd; does not currently
|
in <filename>recovery.conf</filename> - but as it's not currently possible
|
||||||
consider this setting, and therefore may not be able to properly evaluate
|
to directly examine the value applied to the standby, &repmgrd;
|
||||||
the node as a promotion candidate.
|
may not be able to properly evaluate the node as a promotion candidate.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
We recommend that delayed standbys are explicitly excluded from promotion
|
We recommend that delayed standbys are explicitly excluded from promotion
|
||||||
@@ -459,7 +459,7 @@
|
|||||||
</title>
|
</title>
|
||||||
<para>
|
<para>
|
||||||
<varname>promote_command</varname> or <varname>follow_command</varname> can be user-defined scripts,
|
<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 executing &repmgr;. Always provide the full
|
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.
|
path; see <xref linkend="repmgrd-automatic-failover-configuration"/> for more details.
|
||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
@@ -479,7 +479,7 @@
|
|||||||
is out-of-date, which may lead to incorrect failover behaviour.
|
is out-of-date, which may lead to incorrect failover behaviour.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
The onus is therefore on the administrator to manually set the cluster to a stable, healthy state before
|
The onus is therefore on the adminstrator to manually set the cluster to a stable, healthy state before
|
||||||
starting &repmgrd;.
|
starting &repmgrd;.
|
||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
|
|||||||
@@ -50,18 +50,19 @@
|
|||||||
<title>CentOS repositories</title>
|
<title>CentOS repositories</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
&repmgr; packages are available from the public EDB repository, and also the
|
&repmgr; packages are available from the public 2ndQuadrant repository, and also the
|
||||||
PostgreSQL community repository. The EDB repository is updated immediately
|
PostgreSQL community repository. The 2ndQuadrant repository is updated immediately
|
||||||
after each &repmgr; release.
|
after each
|
||||||
|
&repmgr; release.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<table id="centos-2ndquadrant-repository">
|
<table id="centos-2ndquadrant-repository">
|
||||||
<title>EDB public repository</title>
|
<title>2ndQuadrant public repository</title>
|
||||||
<tgroup cols="2">
|
<tgroup cols="2">
|
||||||
<tbody>
|
<tbody>
|
||||||
<row>
|
<row>
|
||||||
<entry>Repository URL:</entry>
|
<entry>Repository URL:</entry>
|
||||||
<entry><ulink url="https://dl.enterprisedb.com/">https://dl.enterprisedb.com/</ulink></entry>
|
<entry><ulink url="https://dl.2ndquadrant.com/">https://dl.2ndquadrant.com/</ulink></entry>
|
||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry>Repository documentation:</entry>
|
<entry>Repository documentation:</entry>
|
||||||
@@ -252,7 +253,7 @@
|
|||||||
</indexterm>
|
</indexterm>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
&repmgr; <literal>.deb</literal> packages are provided by EDB as well as the
|
&repmgr; <literal>.deb</literal> packages are provided by 2ndQuadrant as well as the
|
||||||
PostgreSQL Community APT repository, and are available for each community-supported
|
PostgreSQL Community APT repository, and are available for each community-supported
|
||||||
PostgreSQL version, currently supported Debian releases, and currently supported
|
PostgreSQL version, currently supported Debian releases, and currently supported
|
||||||
Ubuntu LTS releases.
|
Ubuntu LTS releases.
|
||||||
@@ -262,12 +263,12 @@
|
|||||||
<title>APT repositories</title>
|
<title>APT repositories</title>
|
||||||
|
|
||||||
<table id="apt-2ndquadrant-repository">
|
<table id="apt-2ndquadrant-repository">
|
||||||
<title>EDB public repository</title>
|
<title>2ndQuadrant public repository</title>
|
||||||
<tgroup cols="2">
|
<tgroup cols="2">
|
||||||
<tbody>
|
<tbody>
|
||||||
<row>
|
<row>
|
||||||
<entry>Repository URL:</entry>
|
<entry>Repository URL:</entry>
|
||||||
<entry><ulink url="https://dl.enterprisedb.com/">https://dl.enterprisedb.com/</ulink></entry>
|
<entry><ulink url="https://dl.2ndquadrant.com/">https://dl.2ndquadrant.com/</ulink></entry>
|
||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry>Repository documentation:</entry>
|
<entry>Repository documentation:</entry>
|
||||||
@@ -397,11 +398,11 @@
|
|||||||
</indexterm>
|
</indexterm>
|
||||||
<indexterm>
|
<indexterm>
|
||||||
<primary>packages</primary>
|
<primary>packages</primary>
|
||||||
<secondary>snapshots</secondary>
|
<secondary>snaphots</secondary>
|
||||||
</indexterm>
|
</indexterm>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
For testing new features and bug fixes, from time to time EDB provides
|
For testing new features and bug fixes, from time to time 2ndQuadrant provides
|
||||||
so-called "snapshot packages" via its public repository. These packages
|
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
|
are built from the &repmgr; source at a particular point in time, and are not formal
|
||||||
releases.
|
releases.
|
||||||
@@ -413,22 +414,22 @@
|
|||||||
</para>
|
</para>
|
||||||
</note>
|
</note>
|
||||||
<para>
|
<para>
|
||||||
To install a snapshot package, it's necessary to install the EDB public snapshot repository,
|
To install a snapshot package, it's necessary to install the 2ndQuadrant public snapshot repository,
|
||||||
following the instructions here: <ulink url="https://dl.enterprisedb.com/default/release/site/">https://dl.enterprisedb.com/default/release/site/</ulink> but replace <literal>release</literal> with <literal>snapshot</literal>
|
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.
|
in the appropriate URL.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
For example, to install the snapshot RPM repository for PostgreSQL 9.6, execute (as <literal>root</literal>):
|
For example, to install the snapshot RPM repository for PostgreSQL 9.6, execute (as <literal>root</literal>):
|
||||||
<programlisting>
|
<programlisting>
|
||||||
curl https://dl.enterprisedb.com/default/snapshot/get/9.6/rpm | bash</programlisting>
|
curl https://dl.2ndquadrant.com/default/snapshot/get/9.6/rpm | bash</programlisting>
|
||||||
|
|
||||||
or as a normal user with root sudo access:
|
or as a normal user with root sudo access:
|
||||||
<programlisting>
|
<programlisting>
|
||||||
curl https://dl.enterprisedb.com/default/snapshot/get/9.6/rpm | sudo bash</programlisting>
|
curl https://dl.2ndquadrant.com/default/snapshot/get/9.6/rpm | sudo bash</programlisting>
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Alternatively you can browse the repository here:
|
Alternatively you can browse the repository here:
|
||||||
<ulink url="https://dl.enterprisedb.com/default/snapshot/browse/">https://dl.enterprisedb.com/default/snapshot/browse/</ulink>.
|
<ulink url="https://dl.2ndquadrant.com/default/snapshot/browse/">https://dl.2ndquadrant.com/default/snapshot/browse/</ulink>.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Once the repository is installed, installing or updating &repmgr; will result in the latest snapshot
|
Once the repository is installed, installing or updating &repmgr; will result in the latest snapshot
|
||||||
@@ -438,7 +439,7 @@ curl https://dl.enterprisedb.com/default/snapshot/get/9.6/rpm | sudo bash</progr
|
|||||||
The package name will be formatted like this:
|
The package name will be formatted like this:
|
||||||
<programlisting>
|
<programlisting>
|
||||||
repmgr96-4.1.1-0.0git320.g5113ab0.1.el7.x86_64.rpm</programlisting>
|
repmgr96-4.1.1-0.0git320.g5113ab0.1.el7.x86_64.rpm</programlisting>
|
||||||
containing the snapshot build number (here: <literal>320</literal>) and the hash
|
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>).
|
of the <application>git</application> commit it was built from (here: <literal>g5113ab0</literal>).
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
@@ -493,6 +494,32 @@ repmgr96-4.1.1-0.0git320.g5113ab0.1.el7.x86_64.rpm</programlisting>
|
|||||||
yum install repmgr96-4.0.6-1.rhel6</programlisting>
|
yum install repmgr96-4.0.6-1.rhel6</programlisting>
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
<sect3 id="packages-old-versions-rhel-centos-repmgr3">
|
||||||
|
<title>repmgr 3 packages</title>
|
||||||
|
<para>
|
||||||
|
Old &repmgr; 3 RPM packages (<literal>3.2</literal> and later) can be retrieved from the
|
||||||
|
(deprecated) 2ndQuadrant repository at
|
||||||
|
<ulink url="http://packages.2ndquadrant.com/repmgr/yum/">http://packages.2ndquadrant.com/repmgr/yum/</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>
|
||||||
|
</sect3>
|
||||||
|
|
||||||
</sect2>
|
</sect2>
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|
||||||
|
|||||||
@@ -15,286 +15,10 @@
|
|||||||
See also: <xref linkend="upgrading-repmgr"/>
|
See also: <xref linkend="upgrading-repmgr"/>
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<!-- remember to update the release date in ../repmgr_version.h.in -->
|
<!-- remember to update the release date in ../repmgr_version.h.in -->
|
||||||
<sect1 id="release-5.4.1">
|
|
||||||
<title id="release-current">Release 5.4.1</title>
|
|
||||||
<para><emphasis>Tue 04 July, 2023</emphasis></para>
|
|
||||||
<para>
|
|
||||||
&repmgr; 5.4.1 is a minor release providing a fix for witness metadata update
|
|
||||||
</para>
|
|
||||||
<sect2>
|
|
||||||
<title>Bug fixes</title>
|
|
||||||
<para>
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
&repmgrd;: ensure witness node metadata is updated if the primary
|
|
||||||
node changed while the witness &repmgrd; was not running.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
</sect2>
|
|
||||||
</sect1>
|
|
||||||
|
|
||||||
<sect1 id="release-5.4.0">
|
|
||||||
<title>Release 5.4.0</title>
|
|
||||||
<para><emphasis>Thu 15 March, 2023</emphasis></para>
|
|
||||||
<para>
|
|
||||||
&repmgr; 5.4.0 is a major release.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
This release provides support for cloning standbys using backups taken with <ulink url="http://www.pgbarman.org">barman</ulink>
|
|
||||||
with the use of <ulink url="https://github.com/EnterpriseDB/pg-backup-api">pg-backup-api</ulink>.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Minor fixes to the documentation.
|
|
||||||
</para>
|
|
||||||
</sect1>
|
|
||||||
|
|
||||||
<sect1 id="release-5.3.3">
|
|
||||||
<title>Release 5.3.3</title>
|
|
||||||
<para><emphasis>Mon 17 October, 2022</emphasis></para>
|
|
||||||
<para>
|
|
||||||
&repmgr; 5.3.3 is a minor release providing support for
|
|
||||||
<ulink url="https://www.postgresql.org/docs/15/release-15.html">PostgreSQL 15</ulink>
|
|
||||||
and a &repmgrd; bug fix.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
If upgrading from an earlier &repmgr; version, any running &repmgrd; instances should be restarted.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
If upgrading from &repmgr; 5.2.1 or earlier, a PostgreSQL restart <emphasis>is</emphasis> required.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<sect2>
|
|
||||||
<title>Bug fixes</title>
|
|
||||||
<para>
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
&repmgrd;: ensure <link linkend="event-notifications">event notification</link> script is called for event
|
|
||||||
<literal>repmgrd_upstream_disconnect</literal>. GitHub #760.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
</sect2>
|
|
||||||
</sect1>
|
|
||||||
|
|
||||||
<sect1 id="release-5.3.2">
|
|
||||||
<title>Release 5.3.2</title>
|
|
||||||
<para><emphasis>Wed 25 May, 2022</emphasis></para>
|
|
||||||
<para>
|
|
||||||
&repmgr; 5.3.2 is a minor release.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Any running &repmgrd; instances should be restarted following this upgrade.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
If upgrading from &repmgr; 5.2.1 or earlier, a PostgreSQL restart <emphasis>is</emphasis> required.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<sect2>
|
|
||||||
<title>Bug fixes</title>
|
|
||||||
<para>
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<command><link linkend="repmgr-node-status">repmgr node status</link></command>:
|
|
||||||
fix output with <option>--downstream</option> <option>--nagios</option> option combination.
|
|
||||||
GitHub #749.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<command><link linkend="repmgr-standby-clone">repmgr standby clone</link></command>:
|
|
||||||
don't treat inability to determine the cluster size as a fatal error.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The cluster size is displayed for informational purposes and is not essential
|
|
||||||
for execution of the clone operation. As the &repmgr; user may not have permissions
|
|
||||||
for all databases in the cluster, ignore the cluster size query if it fails.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
&repmgrd;: ensure the witness node record on the primary is always marked
|
|
||||||
as <literal>active</literal> if previously marked <literal>inactive</literal>.
|
|
||||||
GitHub #754.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
&repmgrd;: if <varname>standby_disconnect_on_failover</varname> is set, verify
|
|
||||||
&repmgr; is a superuser before attempting to disable the WAL receiver.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
If the &repmgr; user is a non-superuser, and a replication-only user exists,
|
|
||||||
ensure redundant replication slots are dropped correctly even
|
|
||||||
if the <option>-S/--superuser</option> option is not provided.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
</sect2>
|
|
||||||
</sect1>
|
|
||||||
|
|
||||||
<sect1 id="release-5.3.1">
|
|
||||||
<title>Release 5.3.1</title>
|
|
||||||
<para><emphasis>Tue 15 February, 2022</emphasis></para>
|
|
||||||
<para>
|
|
||||||
&repmgr; 5.3.1 is a minor release.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
If &repmgrd; is in use, it should be restarted on all nodes where it is running.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
If upgrading from &repmgr; 5.2.1 or earlier, a PostgreSQL restart <emphasis>is</emphasis> required.
|
|
||||||
</para>
|
|
||||||
<sect2>
|
|
||||||
<title>Bug fixes</title>
|
|
||||||
<para>
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Fix upgrade path from &repmgr; 4.2 and 4.3 to &repmgr; 5.3.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
&repmgrd;: ensure potentially open connections are closed.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
In some cases, when recovering from degraded state in local node monitoring,
|
|
||||||
new connection was opened to the local node without closing
|
|
||||||
the old one, which will result in memory leakage.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
</sect2>
|
|
||||||
</sect1>
|
|
||||||
|
|
||||||
<sect1 id="release-5.3.0">
|
|
||||||
<title>Release 5.3.0</title>
|
|
||||||
<para><emphasis>Tue 12 October, 2021</emphasis></para>
|
|
||||||
<para>
|
|
||||||
&repmgr; 5.3.0 is a major release.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
This release provides support for <ulink url="https://www.postgresql.org/docs/14/release-14.html">PostgreSQL 14</ulink>,
|
|
||||||
released in September 2021.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Note that this release includes changes to the &repmgr; shared library module, meaning a
|
|
||||||
PostgreSQL restart <emphasis>is</emphasis> required on all nodes where &repmgr; is installed.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<sect2>
|
|
||||||
<title>Improvements</title>
|
|
||||||
<para>
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<link linkend="repmgr-standby-switchover"><command>repmgr standby switchover</command></link>:
|
|
||||||
Improve handling of node rejoin failure on the demotion candidate.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Previously &repmgr; did not check whether <command>repmgr node rejoin</command> actually
|
|
||||||
succeeded on the demotion candidate, and would always wait up to <varname>node_rejoin_timeout</varname>
|
|
||||||
seconds for it to attach to the promotion candidate, even if this would never happen.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
This makes it easier to identify unexpected events during a switchover operation, such as
|
|
||||||
the demotion candidate being unexpectedly restarted by an external process.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Note that the output of the <link linkend="repmgr-node-rejoin"><command>repmgr node rejoin</command></link>
|
|
||||||
operation on the demotion candidate will now be logged to a temporary file on that node;
|
|
||||||
the location of the file will be reported in the error message, if one is emitted.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
&repmgrd;: at startup, if node record is marked as "inactive", attempt
|
|
||||||
to set it to "active".
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
This behaviour can be overridden by setting the configuration parameter
|
|
||||||
<varname>repmgrd_exit_on_inactive_node</varname> to <literal>true</literal>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<command><link linkend="repmgr-node-rejoin">repmgr node rejoin</link></command>:
|
|
||||||
emit rejoin target note information as <literal>NOTICE</literal>.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
This makes it clearer what &repmgr; is trying to do.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<link linkend="repmgr-node-check">repmgr node check</link>:
|
|
||||||
option <option>--repmgrd</option> added to check &repmgrd;
|
|
||||||
status.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Add <literal>%p</literal> <link linkend="event-notifications">event notification parameter</link>
|
|
||||||
providing the node ID of the former primary for the <literal>repmgrd_failover_promote</literal> event.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
</itemizedlist>
|
|
||||||
|
|
||||||
</para>
|
|
||||||
</sect2>
|
|
||||||
|
|
||||||
<sect2>
|
|
||||||
<title>Bug fixes</title>
|
|
||||||
<para>
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<command><link linkend="repmgr-standby-clone">repmgr standby clone</link></command>:
|
|
||||||
if using <option>--replication-conf-only</option> on a node
|
|
||||||
which was set up without replication slots, but the &repmgr; configuration
|
|
||||||
was since changed to <option>use_replication_slots=1</option>,
|
|
||||||
&repmgr; will now set <varname>slot_name</varname> in the
|
|
||||||
node record, if it was previously empty.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
&repmgrd;: rename internal shared library functions to minimize the
|
|
||||||
risk of clashes with other shared libraries.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
This does not affect user-facing SQL functions. Howe
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
&repmgrd;: ensure short option <option>-s</option> is accepted.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
</sect2>
|
|
||||||
</sect1>
|
|
||||||
|
|
||||||
<sect1 id="release-5.2.1">
|
<sect1 id="release-5.2.1">
|
||||||
<title>Release 5.2.1</title>
|
<title id="release-current">Release 5.2.1</title>
|
||||||
<para><emphasis>Mon 7 December, 2020</emphasis></para>
|
<para><emphasis>Mon 7 December, 2020</emphasis></para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@@ -1475,7 +1199,7 @@ REPMGRD_OPTS="--daemonize=false"</programlisting>
|
|||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Possible values are <literal>ping</literal> (default; uses <command>PQping()</command> to
|
Possible values are <literal>ping</literal> (default; uses <command>PQping()</command> to
|
||||||
determine server availability), <literal>connection</literal> (attempts to make a new connection to
|
determine server availability), <literal>connection</literal> (attempst to make a new connection to
|
||||||
the upstream node), and <literal>query</literal> (determines server availability
|
the upstream node), and <literal>query</literal> (determines server availability
|
||||||
by executing an SQL statement on the node via the existing connection).
|
by executing an SQL statement on the node via the existing connection).
|
||||||
</para>
|
</para>
|
||||||
|
|||||||
@@ -7,20 +7,20 @@
|
|||||||
</indexterm>
|
</indexterm>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
<ulink url="https://www.enterprisedb.com/">EDB</ulink> provides 24x7
|
<ulink url="https://2ndquadrant.com/">2ndQuadrant</ulink> provides 24x7
|
||||||
production support for &repmgr; and other PostgreSQL
|
production support for &repmgr; and other PostgreSQL
|
||||||
products, including configuration assistance, installation
|
products, including configuration assistance, installation
|
||||||
verification and training for running a robust replication cluster.
|
verification and training for running a robust replication cluster.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
For further details see: <ulink url="https://www.enterprisedb.com/support/postgresql-support-overview-get-the-most-out-of-postgresql">Support Center</ulink>
|
For further details see: <ulink url="https://2ndquadrant.com/en/support/">https://2ndquadrant.com/en/support/</ulink>
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
A mailing list/forum is provided via Google groups to discuss contributions or issues: <ulink url="https://groups.google.com/group/repmgr">https://groups.google.com/group/repmgr</ulink>.
|
A mailing list/forum is provided via Google groups to discuss contributions or issues: <ulink url="https://groups.google.com/group/repmgr">https://groups.google.com/group/repmgr</ulink>.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Please report bugs and other issues to: <ulink url="https://github.com/EnterpriseDB/repmgr">https://github.com/EnterpriseDB/repmgr</ulink>.
|
Please report bugs and other issues to: <ulink url="https://github.com/2ndQuadrant/repmgr">https://github.com/2ndQuadrant/repmgr</ulink>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<important>
|
<important>
|
||||||
@@ -64,7 +64,7 @@
|
|||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<simpara>
|
<simpara>
|
||||||
<filename>repmgr.conf</filename> files (suitably anonymized if necessary)
|
<filename>repmpgr.conf</filename> files (suitably anonymized if necessary)
|
||||||
</simpara>
|
</simpara>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
<para>
|
<para>
|
||||||
<xref linkend="repmgr-standby-clone"/> can use
|
<xref linkend="repmgr-standby-clone"/> can use
|
||||||
<ulink url="https://www.enterprisedb.com/">EDB</ulink>'s
|
<ulink url="https://www.2ndquadrant.com/">2ndQuadrant</ulink>'s
|
||||||
<ulink url="https://www.pgbarman.org/">Barman</ulink> application
|
<ulink url="https://www.pgbarman.org/">Barman</ulink> application
|
||||||
to clone a standby (and also as a fallback source for WAL files).
|
to clone a standby (and also as a fallback source for WAL files).
|
||||||
</para>
|
</para>
|
||||||
@@ -197,7 +197,7 @@ description = "Main cluster"
|
|||||||
<para>
|
<para>
|
||||||
As a fallback in case streaming replication is interrupted, PostgreSQL can optionally
|
As a fallback in case streaming replication is interrupted, PostgreSQL can optionally
|
||||||
retrieve WAL files from an archive, such as that provided by Barman. This is done by
|
retrieve WAL files from an archive, such as that provided by Barman. This is done by
|
||||||
setting <varname>restore_command</varname> in the replication configuration to
|
setting <varname>restore_command</varname> in <filename>recovery.conf</filename> to
|
||||||
a valid shell command which can retrieve a specified WAL file from the archive.
|
a valid shell command which can retrieve a specified WAL file from the archive.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
@@ -225,109 +225,6 @@ description = "Main cluster"
|
|||||||
</note>
|
</note>
|
||||||
|
|
||||||
</sect2>
|
</sect2>
|
||||||
|
|
||||||
<sect2 id="cloning-from-barman-pg_backupapi-mode" xreflabel="Using Barman through its API (pg-backup-api)">
|
|
||||||
<title>Using Barman through its API (pg-backup-api)</title>
|
|
||||||
<indexterm>
|
|
||||||
<primary>cloning</primary>
|
|
||||||
<secondary>pg-backup-api</secondary>
|
|
||||||
</indexterm>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
You can find information on how to install and setup pg-backup-api in
|
|
||||||
<ulink url="https://www.enterprisedb.com/docs/supported-open-source/barman/pg-backup-api/">the pg-backup-api
|
|
||||||
documentation</ulink>.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
This mode (`pg-backupapi`) was introduced in v5.4.0 as a way to further integrate with Barman letting Barman
|
|
||||||
handle the restore. This also reduces the ssh keys that need to share between the backup and postgres nodes.
|
|
||||||
As long as you have access to the API service by HTTP calls, you could perform recoveries right away.
|
|
||||||
You just need to instruct Barman through the API which backup you need and on which node the backup needs to
|
|
||||||
to be restored on.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
In order to enable <literal>pg_backupapi mode</literal> support for <command>repmgr standby clone</command>,
|
|
||||||
you need the following lines in repmgr.conf:
|
|
||||||
<itemizedlist spacing="compact" mark="bullet">
|
|
||||||
<listitem><para>pg_backupapi_host: Where pg-backup-api is hosted</para></listitem>
|
|
||||||
<listitem><para>pg_backupapi_node_name: Name of the server as understood by Barman</para></listitem>
|
|
||||||
<listitem><para>pg_backupapi_remote_ssh_command: How Barman will be connecting as to the node</para></listitem>
|
|
||||||
<listitem><para>pg_backupapi_backup_id: ID of the existing backup you need to restore</para></listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
|
|
||||||
This is an example of how repmgr.conf would look like:
|
|
||||||
|
|
||||||
<programlisting>
|
|
||||||
pg_backupapi_host = '192.168.122.154'
|
|
||||||
pg_backupapi_node_name = 'burrito'
|
|
||||||
pg_backupapi_remote_ssh_command = 'ssh john_doe@192.168.122.1'
|
|
||||||
pg_backupapi_backup_id = '20230223T093201'
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
<literal>pg_backupapi_host</literal> is the variable name that enables this mode, and when you set it,
|
|
||||||
all the rest of the above variables are required. Also, remember that this service is just an interface
|
|
||||||
between Barman and repmgr, hence if something fails during a recovery, you should check Barman's logs upon
|
|
||||||
why the process couldn't finish properly.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<note>
|
|
||||||
<simpara>
|
|
||||||
Despite in Barman you can define shortcuts like "lastest" or "oldest", they are not supported for the
|
|
||||||
time being in pg-backup-api. These shortcuts will be supported in a future release.
|
|
||||||
</simpara>
|
|
||||||
</note>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
This is a real example of repmgr's output cloning with the API. Note that during this operation, we stopped
|
|
||||||
the service for a little while and repmgr had to retry but that doesn't affect the final outcome. The primary
|
|
||||||
is listening on localhost's port 6001:
|
|
||||||
|
|
||||||
<programlisting>
|
|
||||||
$ repmgr -f ~/nodes/node_3/repmgr.conf standby clone -U repmgr -p 6001 -h localhost
|
|
||||||
NOTICE: destination directory "/home/mario/nodes/node_3/data" provided
|
|
||||||
INFO: Attempting to use `pg_backupapi` new restore mode
|
|
||||||
INFO: connecting to source node
|
|
||||||
DETAIL: connection string is: user=repmgr port=6001 host=localhost
|
|
||||||
DETAIL: current installation size is 8541 MB
|
|
||||||
DEBUG: 1 node records returned by source node
|
|
||||||
DEBUG: connecting to: "user=repmgr dbname=repmgr host=localhost port=6001 connect_timeout=2 fallback_application_name=repmgr options=-csearch_path="
|
|
||||||
DEBUG: upstream_node_id determined as 1
|
|
||||||
INFO: Attempting to use `pg_backupapi` new restore mode
|
|
||||||
INFO: replication slot usage not requested; no replication slot will be set up for this standby
|
|
||||||
NOTICE: starting backup (using pg_backupapi)...
|
|
||||||
INFO: Success creating the task: operation id '20230309T150647'
|
|
||||||
INFO: status IN_PROGRESS
|
|
||||||
INFO: status IN_PROGRESS
|
|
||||||
Incorrect reply received for that operation ID.
|
|
||||||
INFO: Retrying...
|
|
||||||
INFO: status IN_PROGRESS
|
|
||||||
INFO: status IN_PROGRESS
|
|
||||||
INFO: status IN_PROGRESS
|
|
||||||
INFO: status IN_PROGRESS
|
|
||||||
INFO: status IN_PROGRESS
|
|
||||||
INFO: status IN_PROGRESS
|
|
||||||
INFO: status IN_PROGRESS
|
|
||||||
INFO: status IN_PROGRESS
|
|
||||||
INFO: status IN_PROGRESS
|
|
||||||
INFO: status IN_PROGRESS
|
|
||||||
INFO: status IN_PROGRESS
|
|
||||||
INFO: status IN_PROGRESS
|
|
||||||
INFO: status IN_PROGRESS
|
|
||||||
INFO: status IN_PROGRESS
|
|
||||||
INFO: status IN_PROGRESS
|
|
||||||
INFO: status DONE
|
|
||||||
NOTICE: standby clone (from pg_backupapi) complete
|
|
||||||
NOTICE: you can now start your PostgreSQL server
|
|
||||||
HINT: for example: pg_ctl -D /home/mario/nodes/node_3/data start
|
|
||||||
HINT: after starting the server, you need to register this standby with "repmgr standby register"
|
|
||||||
</programlisting>
|
|
||||||
|
|
||||||
</para>
|
|
||||||
</sect2> <!--END cloning-from-barman-pg_backupapi-mode !-->
|
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|
||||||
<sect1 id="cloning-replication-slots" xreflabel="Cloning and replication slots">
|
<sect1 id="cloning-replication-slots" xreflabel="Cloning and replication slots">
|
||||||
@@ -402,7 +299,7 @@ HINT: after starting the server, you need to register this standby with "repmgr
|
|||||||
build up indefinitely, possibly leading to server failure.
|
build up indefinitely, possibly leading to server failure.
|
||||||
</simpara>
|
</simpara>
|
||||||
<simpara>
|
<simpara>
|
||||||
As an alternative we recommend using EDB's <ulink url="https://www.pgbarman.org/">Barman</ulink>,
|
As an alternative we recommend using 2ndQuadrant's <ulink url="https://www.pgbarman.org/">Barman</ulink>,
|
||||||
which offloads WAL management to a separate server, removing the requirement to use a replication
|
which offloads WAL management to a separate server, removing the requirement to use a replication
|
||||||
slot for each individual standby to reserve WAL. See section <xref linkend="cloning-from-barman"/>
|
slot for each individual standby to reserve WAL. See section <xref linkend="cloning-from-barman"/>
|
||||||
for more details on using &repmgr; together with Barman.
|
for more details on using &repmgr; together with Barman.
|
||||||
@@ -422,7 +319,7 @@ HINT: after starting the server, you need to register this standby with "repmgr
|
|||||||
Cascading replication, introduced with PostgreSQL 9.2, enables a standby server
|
Cascading replication, introduced with PostgreSQL 9.2, enables a standby server
|
||||||
to replicate from another standby server rather than directly from the primary,
|
to replicate from another standby server rather than directly from the primary,
|
||||||
meaning replication changes "cascade" down through a hierarchy of servers. This
|
meaning replication changes "cascade" down through a hierarchy of servers. This
|
||||||
can be used to reduce load on the primary and minimize bandwidth usage between
|
can be used to reduce load on the primary and minimize bandwith usage between
|
||||||
sites. For more details, see the
|
sites. For more details, see the
|
||||||
<ulink url="https://www.postgresql.org/docs/current/warm-standby.html#CASCADING-REPLICATION">
|
<ulink url="https://www.postgresql.org/docs/current/warm-standby.html#CASCADING-REPLICATION">
|
||||||
PostgreSQL cascading replication documentation</ulink>.
|
PostgreSQL cascading replication documentation</ulink>.
|
||||||
@@ -431,9 +328,9 @@ HINT: after starting the server, you need to register this standby with "repmgr
|
|||||||
&repmgr; supports cascading replication. When cloning a standby,
|
&repmgr; supports cascading replication. When cloning a standby,
|
||||||
set the command-line parameter <literal>--upstream-node-id</literal> to the
|
set the command-line parameter <literal>--upstream-node-id</literal> to the
|
||||||
<varname>node_id</varname> of the server the standby should connect to, and
|
<varname>node_id</varname> of the server the standby should connect to, and
|
||||||
&repmgr; will create a replication configuration file to point to it. Note
|
&repmgr; will create <filename>recovery.conf</filename> to point to it. Note
|
||||||
that if <literal>--upstream-node-id</literal> is not explicitly provided,
|
that if <literal>--upstream-node-id</literal> is not explicitly provided,
|
||||||
&repmgr; will set the standby's replication configuration to
|
&repmgr; will set the standby's <filename>recovery.conf</filename> to
|
||||||
point to the primary node.
|
point to the primary node.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
@@ -494,8 +391,8 @@ HINT: after starting the server, you need to register this standby with "repmgr
|
|||||||
cluster, you may wish to clone a downstream standby whose upstream node
|
cluster, you may wish to clone a downstream standby whose upstream node
|
||||||
does not yet exist. In this case you can clone from the primary (or
|
does not yet exist. In this case you can clone from the primary (or
|
||||||
another upstream node); provide the parameter <literal>--upstream-conninfo</literal>
|
another upstream node); provide the parameter <literal>--upstream-conninfo</literal>
|
||||||
to explicitly set the upstream's <varname>primary_conninfo</varname> string
|
to explictly set the upstream's <varname>primary_conninfo</varname> string
|
||||||
in the replication configuration.
|
in <filename>recovery.conf</filename>.
|
||||||
</simpara>
|
</simpara>
|
||||||
</tip>
|
</tip>
|
||||||
</sect1>
|
</sect1>
|
||||||
@@ -594,12 +491,12 @@ HINT: after starting the server, you need to register this standby with "repmgr
|
|||||||
</note>
|
</note>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
If, for whatever reason, you wish to include the password in the replication configuration file,
|
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
|
||||||
<filename>repmgr.conf</filename>. This will read a password set in <varname>PGPASSWORD</varname>
|
<filename>repmgr.conf</filename>. This will read a password set in <varname>PGPASSWORD</varname>
|
||||||
(but not <filename>~/.pgpass</filename>) and place it into the <varname>primary_conninfo</varname>
|
(but not <filename>~/.pgpass</filename>) and place it into the <varname>primary_conninfo</varname>
|
||||||
string in the replication configuration. Note that <varname>PGPASSWORD</varname>
|
string in <filename>recovery.conf</filename>. Note that <varname>PGPASSWORD</varname>
|
||||||
will need to be set during any action which causes the replication configuration file to be
|
will need to be set during any action which causes <filename>recovery.conf</filename> to be
|
||||||
rewritten, e.g. <xref linkend="repmgr-standby-follow"/>.
|
rewritten, e.g. <xref linkend="repmgr-standby-follow"/>.
|
||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
@@ -611,7 +508,7 @@ HINT: after starting the server, you need to register this standby with "repmgr
|
|||||||
user (in addition to the user who manages the &repmgr; metadata). In this case,
|
user (in addition to the user who manages the &repmgr; metadata). In this case,
|
||||||
the replication user should be set in <filename>repmgr.conf</filename> via the parameter
|
the replication user should be set in <filename>repmgr.conf</filename> via the parameter
|
||||||
<varname>replication_user</varname>; &repmgr; will use this value when making
|
<varname>replication_user</varname>; &repmgr; will use this value when making
|
||||||
replication connections and generating the replication configuration. This
|
replication connections and generating <filename>recovery.conf</filename>. This
|
||||||
value will also be stored in the parameter <literal>repmgr.nodes</literal>
|
value will also be stored in the parameter <literal>repmgr.nodes</literal>
|
||||||
table for each node; it no longer needs to be explicitly specified when
|
table for each node; it no longer needs to be explicitly specified when
|
||||||
cloning a node or executing <xref linkend="repmgr-standby-follow"/>.
|
cloning a node or executing <xref linkend="repmgr-standby-follow"/>.
|
||||||
|
|||||||
@@ -7,14 +7,6 @@
|
|||||||
<secondary>optional settings</secondary>
|
<secondary>optional settings</secondary>
|
||||||
</indexterm>
|
</indexterm>
|
||||||
|
|
||||||
<note>
|
|
||||||
<simpara>
|
|
||||||
This section documents a subset of optional configuration settings; for a full
|
|
||||||
and annotated view of all configuration options see the
|
|
||||||
<ulink url="https://raw.githubusercontent.com/EnterpriseDB/repmgr/master/repmgr.conf.sample">sample repmgr.conf file</ulink>
|
|
||||||
</simpara>
|
|
||||||
</note>
|
|
||||||
|
|
||||||
<variablelist>
|
<variablelist>
|
||||||
|
|
||||||
|
|
||||||
@@ -140,50 +132,5 @@ ssh_options='-q -o ConnectTimeout=10'</programlisting>
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry id="repmgr-conf-pg-bindir" xreflabel="pg_bindir">
|
|
||||||
<term><varname>pg_bindir</varname> (<type>string</type>)
|
|
||||||
<indexterm>
|
|
||||||
<primary><varname>pg_bindir</varname> configuration file parameter</primary>
|
|
||||||
</indexterm>
|
|
||||||
</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Path to the PostgreSQL binary directory (location of <application>pg_ctl</application>,
|
|
||||||
<application>pg_basebackup</application> etc.). Only required
|
|
||||||
if these are not in the system <varname>PATH</varname>.
|
|
||||||
</para>
|
|
||||||
<tip>
|
|
||||||
<para>
|
|
||||||
When &repmgr; is executed via <application>SSH</application> (e.g. when running
|
|
||||||
<command><link linkend="repmgr-standby-switchover">repmgr standby switchover</link></command>,
|
|
||||||
<command><link linkend="repmgr-cluster-matrix">repmgr cluster matrix</link></command> or
|
|
||||||
<command><link linkend="repmgr-cluster-crosscheck">repmgr cluster crosscheck</link></command>,
|
|
||||||
or if it is executed as cronjob), a login shell will not be used and only the
|
|
||||||
default system <varname>PATH</varname> will be set. Therefore it's recommended to set
|
|
||||||
<varname>pg_bindir</varname> so &repmgr; can correctly invoke binaries on a remote
|
|
||||||
system and avoid potential path issues.
|
|
||||||
</para>
|
|
||||||
</tip>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Debian/Ubuntu users: you will probably need to set this to the directory where
|
|
||||||
<application>pg_ctl</application> is located, e.g. <filename>/usr/lib/postgresql/9.6/bin/</filename>.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<emphasis>NOTE</emphasis>: <varname>pg_bindir</varname> is only used when &repmgr; directly
|
|
||||||
executes PostgreSQL binaries; any user-defined scripts
|
|
||||||
<emphasis>must</emphasis> be specified with the full path.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
</variablelist>
|
||||||
|
|
||||||
<tip>
|
|
||||||
<simpara>
|
|
||||||
See the <ulink url="https://raw.githubusercontent.com/EnterpriseDB/repmgr/master/repmgr.conf.sample">sample repmgr.conf file</ulink>
|
|
||||||
for a full and annotated view of all configuration options.
|
|
||||||
</simpara>
|
|
||||||
</tip>
|
|
||||||
|
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|||||||
@@ -96,9 +96,6 @@
|
|||||||
</variablelist>
|
</variablelist>
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
|
||||||
See <xref linkend="configuration-file-optional-settings"/> for further configuration options.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
|
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|||||||
@@ -27,9 +27,7 @@
|
|||||||
<note>
|
<note>
|
||||||
<para>
|
<para>
|
||||||
If using <application>systemd</application>, ensure you have <varname>RemoveIPC</varname> set to <literal>off</literal>.
|
If using <application>systemd</application>, ensure you have <varname>RemoveIPC</varname> set to <literal>off</literal>.
|
||||||
See the <ulink url="https://www.postgresql.org/docs/current/index.html">PostgreSQL documentation</ulink> section
|
See the <ulink url="https://wiki.postgresql.org/wiki/Systemd">systemd</ulink>
|
||||||
<ulink url="https://www.postgresql.org/docs/current/kernel-resources.html#SYSTEMD-REMOVEIPC">systemd RemoveIPC</ulink>
|
|
||||||
and also 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.
|
entry in the <ulink url="https://wiki.postgresql.org/wiki/Main_Page">PostgreSQL wiki</ulink> for details.
|
||||||
</para>
|
</para>
|
||||||
</note>
|
</note>
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ conninfo='host=node1 user=repmgr dbname=repmgr connect_timeout=2'</programlistin
|
|||||||
</para>
|
</para>
|
||||||
<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/EnterpriseDB/repmgr/master/repmgr.conf.sample">repmgr.conf.sample</ulink>.
|
<ulink url="https://raw.githubusercontent.com/2ndQuadrant/repmgr/master/repmgr.conf.sample">repmgr.conf.sample</ulink>.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
For &repmgrd;-specific settings, see <xref linkend="repmgrd-configuration"/>.
|
For &repmgrd;-specific settings, see <xref linkend="repmgrd-configuration"/>.
|
||||||
@@ -262,7 +262,7 @@ conninfo='host=node1 user=repmgr dbname=repmgr connect_timeout=2'</programlistin
|
|||||||
|
|
||||||
<indexterm>
|
<indexterm>
|
||||||
<primary>repmgr.conf</primary>
|
<primary>repmgr.conf</primary>
|
||||||
<secondary>PostgreSQL major version upgrades</secondary>
|
<secondary>ostgreSQL major version upgrades</secondary>
|
||||||
</indexterm>
|
</indexterm>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
|
|||||||
@@ -7,186 +7,19 @@
|
|||||||
</indexterm>
|
</indexterm>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
If the &repmgr; database user (the PostgreSQL user defined in the
|
&repmgr; requires that the database defined in the <varname>conninfo</varname>
|
||||||
<varname>conninfo</varname> setting is a superuser, no further user permissions need
|
setting contains the <literal>repmgr</literal> extension. The database user defined in the
|
||||||
to be granted.
|
<varname>conninfo</varname> setting must be able to access this database and
|
||||||
|
the database objects contained within the extension.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The <literal>repmgr</literal> extension can only be installed by a superuser.
|
||||||
|
If the &repmgr; user is a superuser, &repmgr; will create the extension automatically.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<sect2 id="configuration-permissions-no-superuser" xreflabel="Non-super user permissions">
|
<para>
|
||||||
<title>repmgr user as a non-superuser</title>
|
Alternatively, the extension can be created manually by a superuser
|
||||||
<para>
|
(with "<command>CREATE EXTENSION repmgr</command>") before executing
|
||||||
In principle the &repmgr; database user does not need to be a superuser.
|
<link linkend="repmgr-primary-register">repmgr primary register</link>.
|
||||||
In this case the &repmgr; will need to be granted execution permissions on certain
|
</para>
|
||||||
functions, and membership of certain roles. However be aware that &repmgr; does
|
|
||||||
expect to be able to execute certain commands which are restricted to superusers;
|
|
||||||
in this case either a superuser must be specified with the <option>-S</option>/<option>--superuser</option>
|
|
||||||
(where available) option, or the corresponding action should be executed manually as a superuser.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The following sections describe the actions needed to use &repmgr; with a non-superuser,
|
|
||||||
and relevant caveats.
|
|
||||||
</para>
|
|
||||||
<sect3 id="configuration-permissions-replication" xreflabel="Replication role">
|
|
||||||
<title>Replication role</title>
|
|
||||||
<para>
|
|
||||||
&repmgr; requires a database user with the <literal>REPLICATION</literal> role
|
|
||||||
to be able to create a replication connection and (if configured) to administer
|
|
||||||
replication slots.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
By default this is the database user defined in the <varname>conninfo</varname>
|
|
||||||
setting. This user can be:
|
|
||||||
<itemizedlist spacing="compact" mark="bullet">
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
a superuser
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
a non-superuser with the <literal>REPLICATION</literal> role
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
another user defined in the <filename>repmgr.conf</filename> parameter <varname>replication_user</varname> with the <literal>REPLICATION</literal> role
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
</sect3>
|
|
||||||
|
|
||||||
<sect3 id="configuration-permissions-roles" xreflabel="Database roles for non-superusers">
|
|
||||||
<title>Database roles</title>
|
|
||||||
<para>
|
|
||||||
A non-superuser &repmgr; database user should be a member of the following
|
|
||||||
<ulink url="https://www.postgresql.org/docs/current/predefined-roles.html">predefined roles</ulink>
|
|
||||||
(PostgreSQL 10 and later):
|
|
||||||
<itemizedlist spacing="compact" mark="bullet">
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<varname>pg_read_all_stats</varname>
|
|
||||||
(to read the <varname>status</varname> column of <literal>pg_stat_replication</literal>
|
|
||||||
and execute <function>pg_database_size()</function> on all databases)
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<varname>pg_read_all_settings</varname> (to access the <varname>data_directory</varname> setting)
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
Alternatively the meta-role <varname>pg_monitor</varname> can be granted, which includes membership
|
|
||||||
of the above predefined roles.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Membership of these roles can be granted with e.g. <command>GRANT pg_read_all_stats TO repmgr</command>.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Users of PostgreSQL 9.6 or earlier should upgrade to a supported PostgreSQL version, or provide
|
|
||||||
the <option>-S</option>/<option>--superuser</option> where available.
|
|
||||||
</para>
|
|
||||||
</sect3>
|
|
||||||
|
|
||||||
<sect3 id="configuration-permissions-extension" xreflabel="Extension creation">
|
|
||||||
<title>Extension creation</title>
|
|
||||||
<para>
|
|
||||||
&repmgr; requires that the database defined in the <varname>conninfo</varname>
|
|
||||||
setting contains the <literal>repmgr</literal> extension. The database user defined in the
|
|
||||||
<varname>conninfo</varname> setting must be able to access this database and
|
|
||||||
the database objects contained within the extension.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The <literal>repmgr</literal> extension can only be installed by a superuser.
|
|
||||||
If the &repmgr; user is a superuser, &repmgr; will create the extension automatically.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Alternatively, the extension can be created manually by a superuser
|
|
||||||
(with "<command>CREATE EXTENSION repmgr</command>") before executing
|
|
||||||
<link linkend="repmgr-primary-register">repmgr primary register</link>.
|
|
||||||
</para>
|
|
||||||
</sect3>
|
|
||||||
|
|
||||||
|
|
||||||
<sect3 id="configuration-permissions-functions" xreflabel="Function permissions for non-superusers">
|
|
||||||
<title>Function permissions</title>
|
|
||||||
<para>
|
|
||||||
If the &repmgr; database user is not a superuser, <literal>EXECUTE</literal> permission should be
|
|
||||||
granted on the following function:
|
|
||||||
<itemizedlist spacing="compact" mark="bullet">
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<function>pg_wal_replay_resume()</function> (required by &repmgrd; during failover operations;
|
|
||||||
if permission is not granted, the failoved process may not function reliably if a node
|
|
||||||
has WAL replay paused)
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<function>pg_promote()</function> (PostgreSQL 12 and later; if permission is not granted,
|
|
||||||
&repmgr; will fall back to <command>pg_ctl promote</command>)
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<literal>EXECUTE</literal> permission on functions can be granted with e.g.:
|
|
||||||
<command>GRANT EXECUTE ON FUNCTION pg_catalog.pg_wal_replay_resume() TO repmgr</command>.
|
|
||||||
</para>
|
|
||||||
</sect3>
|
|
||||||
|
|
||||||
<sect3 id="configuration-permissions-superuser-required" xreflabel="repmgr actions requiring a superuser">
|
|
||||||
<title>repmgr actions requiring a superuser</title>
|
|
||||||
<para>
|
|
||||||
In some circumstances, &repmgr; may need to perform an operation which cannot be delegated to a
|
|
||||||
non-superuser.
|
|
||||||
<itemizedlist spacing="compact" mark="bullet">
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
The <command>CHECKPOINT</command> command is executed by
|
|
||||||
<link linkend="repmgr-standby-switchover">repmgr standby switchover</link>. This can only
|
|
||||||
be executed by a superuser; if the &repmgr; user is not a superuser,
|
|
||||||
the <option>-S</option>/<option>--superuser</option> should be used.
|
|
||||||
</simpara>
|
|
||||||
<simpara>
|
|
||||||
If &repmgr; is not able to execute <command>CHECKPOINT</command>,
|
|
||||||
there is a risk that the demotion candidate may not be able to shut down as smoothly as might otherwise
|
|
||||||
have been the case.
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
The <command>ALTER SYSTEM</command> is executed by &repmgrd; if
|
|
||||||
<varname>standby_disconnect_on_failover</varname> is set to <literal>true</literal> in
|
|
||||||
<filename>repmgr.conf</filename>. <command>ALTER SYSTEM</command> can only be executed by
|
|
||||||
a superuser; if the &repmgr; user is not a superuser, this functionality will not be available.
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
</sect3>
|
|
||||||
|
|
||||||
<sect3 id="configuration-permissions-superuser-option" xreflabel="repmgr commands with --superuser option">
|
|
||||||
<title>repmgr commands with --superuser option</title>
|
|
||||||
<para>
|
|
||||||
The following repmgr commands provide the <option>-S</option>/<option>--superuser</option> option:
|
|
||||||
<itemizedlist spacing="compact" mark="bullet">
|
|
||||||
<listitem>
|
|
||||||
<simpara><link linkend="repmgr-standby-clone">repmgr standby clone</link> (to be able to copy configuration files outside of the data directory if <option>--copy-external-config-files</option> provided)</simpara>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<simpara><link linkend="repmgr-standby-switchover">repmgr standby switchover</link> (to execute <command>CHECKPOINT</command>)</simpara>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<simpara><link linkend="repmgr-node-check">repmgr node check</link> (to execute <command>repmgr node check --data-directory-config</command>; note this is also called by <link linkend="repmgr-standby-switchover">repmgr standby switchover</link>)</simpara>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<simpara><link linkend="repmgr-node-service">repmgr node service</link> (to execute <command>CHECKPOINT</command> via the <option>--checkpoint</option>; note this is also called by <link linkend="repmgr-standby-switchover">repmgr standby switchover</link>)</simpara>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
</sect3>
|
|
||||||
|
|
||||||
</sect2>
|
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|||||||
@@ -95,8 +95,7 @@
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The following parameters are provided for a subset of event notifications; their meaning may
|
The following parameters are provided for a subset of event notifications:
|
||||||
change according to context:
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<variablelist>
|
<variablelist>
|
||||||
@@ -109,9 +108,6 @@
|
|||||||
<para>
|
<para>
|
||||||
node ID of the demoted primary (<xref linkend="repmgr-standby-switchover"/> only)
|
node ID of the demoted primary (<xref linkend="repmgr-standby-switchover"/> only)
|
||||||
</para>
|
</para>
|
||||||
<para>
|
|
||||||
node ID of the former primary (<literal>repmgrd_failover_promote</literal> only)
|
|
||||||
</para>
|
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
@@ -137,7 +133,7 @@
|
|||||||
|
|
||||||
<para>
|
<para>
|
||||||
The values provided for <literal>%c</literal> and <literal>%a</literal>
|
The values provided for <literal>%c</literal> and <literal>%a</literal>
|
||||||
may contain spaces, so should always be quoted.
|
will probably contain spaces, so should always be quoted.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
|
|||||||
@@ -22,15 +22,16 @@
|
|||||||
|
|
||||||
<para>
|
<para>
|
||||||
&repmgr; RPM packages for RedHat/CentOS variants and Fedora are available from the
|
&repmgr; RPM packages for RedHat/CentOS variants and Fedora are available from the
|
||||||
<ulink url="https://www.enterprisedb.com">EDB</ulink>
|
<ulink url="https://2ndquadrant.com">2ndQuadrant</ulink>
|
||||||
<ulink url="https://dl.enterprisedb.com/">public repository</ulink>; see following
|
<ulink url="https://dl.2ndquadrant.com/">public repository</ulink>; see following
|
||||||
section for details.
|
section for details.
|
||||||
</para>
|
</para>
|
||||||
<note>
|
<note>
|
||||||
<para>
|
<para>
|
||||||
Currently the <ulink url="https://www.enterprisedb.com">EDB</ulink>
|
Currently the <ulink url="https://2ndquadrant.com">2ndQuadrant</ulink>
|
||||||
<ulink url="https://dl.enterprisedb.com/">public repository</ulink> provides
|
<ulink url="https://dl.2ndquadrant.com/">public repository</ulink> provides
|
||||||
support for RedHat/CentOS versions 6,7 and 8.
|
support for RedHat/CentOS versions 5, 6 and 7. Support for version 8 is
|
||||||
|
available via the PGDG repository; see below for details.
|
||||||
</para>
|
</para>
|
||||||
</note>
|
</note>
|
||||||
<para>
|
<para>
|
||||||
@@ -44,7 +45,7 @@
|
|||||||
<note>
|
<note>
|
||||||
<para>
|
<para>
|
||||||
&repmgr; RPM packages are designed to be compatible with the community-provided PostgreSQL packages
|
&repmgr; RPM packages are designed to be compatible with the community-provided PostgreSQL packages
|
||||||
and EDB's PostgreSQL Extended Server (formerly 2ndQPostgres).
|
and 2ndQuadrant's <ulink url="https://www.2ndquadrant.com/en/resources/2ndqpostgres/">2ndQPostgres</ulink>.
|
||||||
They may not work with vendor-specific packages such as those provided by RedHat for RHEL
|
They may not work with vendor-specific packages such as those provided by RedHat for RHEL
|
||||||
customers, as the PostgreSQL filesystem layout may be different to the community RPMs.
|
customers, as the PostgreSQL filesystem layout may be different to the community RPMs.
|
||||||
Please contact your support vendor for assistance.
|
Please contact your support vendor for assistance.
|
||||||
@@ -63,16 +64,16 @@
|
|||||||
|
|
||||||
|
|
||||||
<sect3 id="installation-packages-redhat-2ndq">
|
<sect3 id="installation-packages-redhat-2ndq">
|
||||||
<title>EDB public RPM yum repository</title>
|
<title>2ndQuadrant public RPM yum repository</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
<ulink url="https://www.enterprisedb.com/">EDB</ulink> provides a dedicated <literal>yum</literal>
|
<ulink url="https://2ndquadrant.com/">2ndQuadrant</ulink> provides a dedicated <literal>yum</literal>
|
||||||
<ulink url="https://dl.enterprisedb.com/">public repository</ulink> for EDB software,
|
<ulink url="https://dl.2ndquadrant.com/">public repository</ulink> for 2ndQuadrant software,
|
||||||
including &repmgr;. We recommend using this for all future &repmgr; releases.
|
including &repmgr;. We recommend using this for all future &repmgr; releases.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
General instructions for using this repository can be found on its
|
General instructions for using this repository can be found on its
|
||||||
<ulink url="https://dl.enterprisedb.com/">homepage</ulink>. Specific instructions
|
<ulink url="https://dl.2ndquadrant.com/">homepage</ulink>. Specific instructions
|
||||||
for installing &repmgr; follow below.
|
for installing &repmgr; follow below.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
@@ -82,46 +83,57 @@
|
|||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Locate the repository RPM for your PostgreSQL version from the list at:
|
Locate the repository RPM for your PostgreSQL version from the list at:
|
||||||
<ulink url="https://dl.enterprisedb.com/">https://dl.enterprisedb.com/</ulink>
|
<ulink url="https://dl.2ndquadrant.com/">https://dl.2ndquadrant.com/</ulink>
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Install the repository definition for your distribution and PostgreSQL version
|
|
||||||
(this enables the EDB repository as a source of &repmgr; packages).
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
For example, for PostgreSQL 14 on Rocky Linux 8, execute:
|
|
||||||
<programlisting>
|
|
||||||
curl https://dl.enterprisedb.com/default/release/get/14/rpm | sudo bash</programlisting>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Verify that the repository is installed with:
|
|
||||||
<programlisting>
|
|
||||||
sudo dnf repolist</programlisting>
|
|
||||||
The output should contain two entries like this:
|
|
||||||
<programlisting>
|
|
||||||
2ndquadrant-dl-default-release-pg14 2ndQuadrant packages (PG14) for 8 - x86_64
|
|
||||||
2ndquadrant-dl-default-release-pg14-debug 2ndQuadrant packages (PG14) for 8 - x86_64 - Debug</programlisting>
|
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Install the &repmgr; version appropriate for your PostgreSQL version (e.g. <literal>repmgr14</literal>):
|
Install the repository definition for your distribution and PostgreSQL version
|
||||||
|
(this enables the 2ndQuadrant repository as a source of &repmgr; packages).
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
For example, for PostgreSQL 11 on CentOS, execute:
|
||||||
|
<programlisting>
|
||||||
|
curl https://dl.2ndquadrant.com/default/release/get/11/rpm | sudo bash</programlisting>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
For PostgreSQL 9.6 on CentOS, execute:
|
||||||
|
<programlisting>
|
||||||
|
curl https://dl.2ndquadrant.com/default/release/get/9.6/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-pg11/7/x86_64 2ndQuadrant packages (PG11) for 7 - x86_64 18
|
||||||
|
2ndquadrant-dl-default-release-pg11-debug/7/x86_64 2ndQuadrant packages (PG11) for 7 - x86_64 - Debug 8</programlisting>
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Install the &repmgr; version appropriate for your PostgreSQL version (e.g. <literal>repmgr10</literal>):
|
||||||
<programlisting>
|
<programlisting>
|
||||||
sudo dnf install repmgr14</programlisting>
|
sudo yum install repmgr11</programlisting>
|
||||||
</para>
|
</para>
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
For packages for PostgreSQL 9.6 and earlier, the package name does not contain
|
||||||
|
a period between major and minor version numbers, e.g.
|
||||||
|
<literal>repmgr96</literal>.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
<tip>
|
<tip>
|
||||||
<para>
|
<para>
|
||||||
To determine the names of available packages, execute:
|
To determine the names of available packages, execute:
|
||||||
<programlisting>
|
<programlisting>
|
||||||
dnf search repmgr</programlisting>
|
yum search repmgr</programlisting>
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
In CentOS 7 and earlier, use <literal>yum</literal> instead of <literal>dnf</literal>.
|
|
||||||
</para>
|
</para>
|
||||||
</tip>
|
</tip>
|
||||||
|
|
||||||
@@ -133,7 +145,7 @@ dnf search repmgr</programlisting>
|
|||||||
<emphasis>Compatibility with PGDG Repositories</emphasis>
|
<emphasis>Compatibility with PGDG Repositories</emphasis>
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
The EDB &repmgr; yum repository packages use the same definitions and file system layout as the
|
The 2ndQuadrant &repmgr; yum repository packages use the same definitions and file system layout as the
|
||||||
main PGDG repository.
|
main PGDG repository.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
@@ -142,42 +154,36 @@ dnf search repmgr</programlisting>
|
|||||||
the packages are installed from.
|
the packages are installed from.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
To ensure the EDB repository is always prioritised, set the <literal>priority</literal> option
|
To ensure the 2ndQuadrant repository is always prioritised, install <literal>yum-plugin-priorities</literal>
|
||||||
in the repository configuration file (e.g. <filename>/etc/yum.repos.d/2ndquadrant-dl-default-release-pg14.repo</filename>
|
and set the repository priorities accordingly.
|
||||||
accordingly.
|
|
||||||
</para>
|
</para>
|
||||||
<note>
|
|
||||||
<para>
|
|
||||||
With CentOS 7 and earlier, the package <literal>yum-plugin-priorities</literal> must be installed
|
|
||||||
to be able to set the repository priority.
|
|
||||||
</para>
|
|
||||||
</note>
|
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
<emphasis>Installing a specific package version</emphasis>
|
<emphasis>Installing a specific package version</emphasis>
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
To install a specific package version, execute <command>dnf --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 ~]# dnf --showduplicates list repmgr10
|
[root@localhost ~]# yum --showduplicates list repmgr11
|
||||||
Last metadata expiration check: 0:09:15 ago on Fri 11 Mar 2022 01:09:19 AM UTC.
|
Loaded plugins: fastestmirror
|
||||||
|
Loading mirror speeds from cached hostfile
|
||||||
|
* base: ftp.tsukuba.wide.ad.jp
|
||||||
|
* epel: nrt.edge.kernel.org
|
||||||
|
* extras: ftp.tsukuba.wide.ad.jp
|
||||||
|
* updates: ftp.tsukuba.wide.ad.jp
|
||||||
Installed Packages
|
Installed Packages
|
||||||
repmgr10.x86_64 5.3.1-1.el8 @2ndquadrant-dl-default-release-pg10
|
repmgr11.x86_64 4.4.0-1.rhel7 @pgdg11
|
||||||
Available Packages
|
Available Packages
|
||||||
repmgr10.x86_64 5.0.0-1.rhel8 pgdg10
|
repmgr11.x86_64 4.2-1.el7 2ndquadrant-dl-default-release-pg11
|
||||||
repmgr10.x86_64 5.1.0-1.el8 2ndquadrant-dl-default-release-pg10
|
repmgr11.x86_64 4.2-2.el7 2ndquadrant-dl-default-release-pg11
|
||||||
repmgr10.x86_64 5.1.0-1.rhel8 pgdg10
|
repmgr11.x86_64 4.3-1.el7 2ndquadrant-dl-default-release-pg11
|
||||||
repmgr10.x86_64 5.1.0-2.el8 2ndquadrant-dl-default-release-pg10
|
repmgr11.x86_64 4.4-1.el7 2ndquadrant-dl-default-release-pg11</programlisting>
|
||||||
repmgr10.x86_64 5.2.0-1.el8 2ndquadrant-dl-default-release-pg10
|
|
||||||
repmgr10.x86_64 5.2.0-1.rhel8 pgdg10
|
|
||||||
repmgr10.x86_64 5.2.1-1.el8 2ndquadrant-dl-default-release-pg10
|
|
||||||
repmgr10.x86_64 5.3.0-1.el8 2ndquadrant-dl-default-release-pg10
|
|
||||||
repmgr10.x86_64 5.3.1-1.el8 2ndquadrant-dl-default-release-pg10</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 ~]# dnf install repmgr10-5.3.0-1.el8</programlisting>
|
[root@localhost ~]# yum install repmgr11-4.3-1.el7</programlisting>
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
<emphasis>Installing old packages</emphasis>
|
<emphasis>Installing old packages</emphasis>
|
||||||
</para>
|
</para>
|
||||||
@@ -185,6 +191,7 @@ repmgr10.x86_64 5.3.1-1.el8
|
|||||||
See appendix <link linkend="packages-old-versions-rhel-centos">Installing old package versions</link>
|
See appendix <link linkend="packages-old-versions-rhel-centos">Installing old package versions</link>
|
||||||
for details on how to retrieve older package versions.
|
for details on how to retrieve older package versions.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
</sect3>
|
</sect3>
|
||||||
|
|
||||||
</sect2>
|
</sect2>
|
||||||
@@ -210,16 +217,16 @@ repmgr10.x86_64 5.3.1-1.el8
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<sect3 id="installation-packages-debian-ubuntu-2ndq">
|
<sect3 id="installation-packages-debian-ubuntu-2ndq">
|
||||||
<title>EDB public apt repository for Debian/Ubuntu</title>
|
<title>2ndQuadrant public apt repository for Debian/Ubuntu</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
<ulink url="https://www.enterprisedb.com/">EDB</ulink> provides a
|
<ulink url="https://2ndquadrant.com/">2ndQuadrant</ulink> provides a
|
||||||
<ulink url="https://dl.enterprisedb.com/">public apt repository</ulink> for EDB software,
|
<ulink url="https://dl.2ndquadrant.com/">public apt repository</ulink> for 2ndQuadrant software,
|
||||||
including &repmgr;.
|
including &repmgr;.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
General instructions for using this repository can be found on its
|
General instructions for using this repository can be found on its
|
||||||
<ulink url="https://dl.enterprisedb.com/">homepage</ulink>. Specific instructions
|
<ulink url="https://dl.2ndquadrant.com/">homepage</ulink>. Specific instructions
|
||||||
for installing &repmgr; follow below.
|
for installing &repmgr; follow below.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
@@ -232,9 +239,9 @@ repmgr10.x86_64 5.3.1-1.el8
|
|||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Install the repository definition for your distribution and PostgreSQL version
|
Install the repository definition for your distribution and PostgreSQL version
|
||||||
(this enables the EDB repository as a source of &repmgr; packages) by executing:
|
(this enables the 2ndQuadrant repository as a source of &repmgr; packages) by executing:
|
||||||
<programlisting>
|
<programlisting>
|
||||||
curl https://dl.enterprisedb.com/default/release/get/deb | sudo bash</programlisting>
|
curl https://dl.2ndquadrant.com/default/release/get/deb | sudo bash</programlisting>
|
||||||
</para>
|
</para>
|
||||||
<note>
|
<note>
|
||||||
<para>
|
<para>
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
&repmgr; &repmgrversion; is compatible with all PostgreSQL versions from 10. See
|
&repmgr; &repmgrversion; is compatible with all PostgreSQL versions from 9.4. See
|
||||||
section <link linkend="install-compatibility-matrix">&repmgr; compatibility matrix</link>
|
section <link linkend="install-compatibility-matrix">&repmgr; compatibility matrix</link>
|
||||||
for an overview of version compatibility.
|
for an overview of version compatibility.
|
||||||
</para>
|
</para>
|
||||||
@@ -93,7 +93,7 @@
|
|||||||
<table id="repmgr-compatibility-matrix">
|
<table id="repmgr-compatibility-matrix">
|
||||||
<title>&repmgr; compatibility matrix</title>
|
<title>&repmgr; compatibility matrix</title>
|
||||||
|
|
||||||
<tgroup cols="4">
|
<tgroup cols="3">
|
||||||
<thead>
|
<thead>
|
||||||
<row>
|
<row>
|
||||||
<entry>
|
<entry>
|
||||||
@@ -108,65 +108,24 @@
|
|||||||
<entry>
|
<entry>
|
||||||
Supported PostgreSQL versions
|
Supported PostgreSQL versions
|
||||||
</entry>
|
</entry>
|
||||||
<entry>
|
|
||||||
Notes
|
|
||||||
</entry>
|
|
||||||
</row>
|
</row>
|
||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
<tbody>
|
<tbody>
|
||||||
<row>
|
|
||||||
<entry>
|
|
||||||
&repmgr; 5.4
|
|
||||||
</entry>
|
|
||||||
<entry>
|
|
||||||
YES
|
|
||||||
</entry>
|
|
||||||
<entry>
|
|
||||||
<link linkend="release-current">&repmgrversion;</link> (&releasedate;)
|
|
||||||
</entry>
|
|
||||||
<entry>
|
|
||||||
10, 11, 12, 13, 14, 15, 16
|
|
||||||
</entry>
|
|
||||||
<entry>
|
|
||||||
|
|
||||||
</entry>
|
|
||||||
</row>
|
|
||||||
|
|
||||||
<row>
|
|
||||||
<entry>
|
|
||||||
&repmgr; 5.3
|
|
||||||
</entry>
|
|
||||||
<entry>
|
|
||||||
YES
|
|
||||||
</entry>
|
|
||||||
<entry>
|
|
||||||
<link linkend="release-current">&repmgrversion;</link> (&releasedate;)
|
|
||||||
</entry>
|
|
||||||
<entry>
|
|
||||||
9.4, 9.5, 9.6, 10, 11, 12, 13, 14, 15
|
|
||||||
</entry>
|
|
||||||
<entry>
|
|
||||||
PostgreSQL 15 supported from &repmgr; 5.3.3
|
|
||||||
</entry>
|
|
||||||
</row>
|
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
<entry>
|
<entry>
|
||||||
&repmgr; 5.2
|
&repmgr; 5.2
|
||||||
</entry>
|
</entry>
|
||||||
<entry>
|
<entry>
|
||||||
NO
|
YES
|
||||||
</entry>
|
</entry>
|
||||||
<entry>
|
<entry>
|
||||||
<link linkend="release-5.2.1">5.2.1</link> (2020-12-07)
|
<link linkend="release-current">&repmgrversion;</link> (&releasedate;)
|
||||||
</entry>
|
</entry>
|
||||||
<entry>
|
<entry>
|
||||||
9.4, 9.5, 9.6, 10, 11, 12, 13
|
9.4, 9.5, 9.6, 10, 11, 12, 13
|
||||||
</entry>
|
</entry>
|
||||||
<entry>
|
|
||||||
|
|
||||||
</entry>
|
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
@@ -182,9 +141,6 @@
|
|||||||
<entry>
|
<entry>
|
||||||
9.3, 9.4, 9.5, 9.6, 10, 11, 12
|
9.3, 9.4, 9.5, 9.6, 10, 11, 12
|
||||||
</entry>
|
</entry>
|
||||||
<entry>
|
|
||||||
|
|
||||||
</entry>
|
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
@@ -200,9 +156,6 @@
|
|||||||
<entry>
|
<entry>
|
||||||
9.3, 9.4, 9.5, 9.6, 10, 11, 12
|
9.3, 9.4, 9.5, 9.6, 10, 11, 12
|
||||||
</entry>
|
</entry>
|
||||||
<entry>
|
|
||||||
|
|
||||||
</entry>
|
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
|
|
||||||
@@ -219,9 +172,6 @@
|
|||||||
<entry>
|
<entry>
|
||||||
9.3, 9.4, 9.5, 9.6, 10, 11
|
9.3, 9.4, 9.5, 9.6, 10, 11
|
||||||
</entry>
|
</entry>
|
||||||
<entry>
|
|
||||||
|
|
||||||
</entry>
|
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
@@ -237,9 +187,6 @@
|
|||||||
<entry>
|
<entry>
|
||||||
9.3, 9.4, 9.5, 9.6
|
9.3, 9.4, 9.5, 9.6
|
||||||
</entry>
|
</entry>
|
||||||
<entry>
|
|
||||||
|
|
||||||
</entry>
|
|
||||||
</row>
|
</row>
|
||||||
|
|
||||||
<row>
|
<row>
|
||||||
@@ -255,9 +202,6 @@
|
|||||||
<entry>
|
<entry>
|
||||||
9.0, 9.1, 9.2, 9.3, 9.4
|
9.0, 9.1, 9.2, 9.3, 9.4
|
||||||
</entry>
|
</entry>
|
||||||
<entry>
|
|
||||||
|
|
||||||
</entry>
|
|
||||||
</row>
|
</row>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
||||||
|
|||||||
@@ -178,18 +178,18 @@ deb-src https://apt.postgresql.org/pub/repos/apt/ stretch-pgdg main</programlist
|
|||||||
|
|
||||||
<para>
|
<para>
|
||||||
The source for &repmgr; is maintained at
|
The source for &repmgr; is maintained at
|
||||||
<ulink url="https://github.com/EnterpriseDB/repmgr">https://github.com/EnterpriseDB/repmgr</ulink>.
|
<ulink url="https://github.com/2ndQuadrant/repmgr">https://github.com/2ndQuadrant/repmgr</ulink>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
There are also tags for each <ulink url="https://github.com/EnterpriseDB/repmgr/releases">&repmgr; release</ulink>, e.g.
|
There are also tags for each <ulink url="https://github.com/2ndQuadrant/repmgr/releases">&repmgr; release</ulink>, e.g.
|
||||||
<literal><ulink url="https://github.com/EnterpriseDB/repmgr/releases/tag/v4.4.0">v4.4.0</ulink></literal>.
|
<literal><ulink url="https://github.com/2ndQuadrant/repmgr/releases/tag/v4.4.0">v4.4.0</ulink></literal>.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Clone the source code using <application>git</application>:
|
Clone the source code using <application>git</application>:
|
||||||
<programlisting>
|
<programlisting>
|
||||||
git clone https://github.com/EnterpriseDB/repmgr</programlisting>
|
git clone https://github.com/2ndQuadrant/repmgr</programlisting>
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
<!-- doc/legal.xml -->
|
<!-- doc/legal.xml -->
|
||||||
|
|
||||||
<date>2022</date>
|
<date>2017</date>
|
||||||
|
|
||||||
<copyright>
|
<copyright>
|
||||||
<year>2010-2022</year>
|
<year>2010-2020</year>
|
||||||
<holder>EDB</holder>
|
<holder>2ndQuadrant, Ltd.</holder>
|
||||||
</copyright>
|
</copyright>
|
||||||
|
|
||||||
<legalnotice id="legalnotice">
|
<legalnotice id="legalnotice">
|
||||||
<title>Legal Notice</title>
|
<title>Legal Notice</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
<productname>repmgr</productname> is Copyright © 2010-2022
|
<productname>repmgr</productname> is Copyright © 2010-2020
|
||||||
by EDB All rights reserved.
|
by 2ndQuadrant, Ltd. All rights reserved.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
|
|||||||
@@ -284,7 +284,7 @@
|
|||||||
|
|
||||||
<tip>
|
<tip>
|
||||||
<simpara>
|
<simpara>
|
||||||
For Debian-based distributions we recommend explicitly setting
|
For Debian-based distributions we recommend explictly setting
|
||||||
<option>pg_bindir</option> to the directory where <command>pg_ctl</command> and other binaries
|
<option>pg_bindir</option> 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>
|
||||||
@@ -302,7 +302,7 @@
|
|||||||
|
|
||||||
<para>
|
<para>
|
||||||
See the file
|
See the file
|
||||||
<ulink url="https://raw.githubusercontent.com/EnterpriseDB/repmgr/master/repmgr.conf.sample">repmgr.conf.sample</ulink>
|
<ulink url="https://raw.githubusercontent.com/2ndQuadrant/repmgr/master/repmgr.conf.sample">repmgr.conf.sample</ulink>
|
||||||
for details of all available configuration parameters.
|
for details of all available configuration parameters.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
@@ -405,10 +405,9 @@
|
|||||||
</programlisting>
|
</programlisting>
|
||||||
<para>
|
<para>
|
||||||
This has cloned the PostgreSQL data directory files from the primary <literal>node1</literal>
|
This has cloned the PostgreSQL data directory files from the primary <literal>node1</literal>
|
||||||
using PostgreSQL's <command>pg_basebackup</command> utility. Replication configuration
|
using PostgreSQL's <command>pg_basebackup</command> utility. A <filename>recovery.conf</filename>
|
||||||
containing the correct parameters to start streaming from this primary server will be
|
file containing the correct parameters to start streaming from this primary server will be created
|
||||||
automatically appended to <filename>postgresql.auto.conf</filename>. (In PostgreSQL 11
|
automatically.
|
||||||
and earlier the file <filename>recovery.conf</filename> will be created).
|
|
||||||
</para>
|
</para>
|
||||||
<note>
|
<note>
|
||||||
<simpara>
|
<simpara>
|
||||||
@@ -482,10 +481,9 @@
|
|||||||
sender_port | 5432
|
sender_port | 5432
|
||||||
conninfo | user=repmgr dbname=replication host=node1 application_name=node2
|
conninfo | user=repmgr dbname=replication host=node1 application_name=node2
|
||||||
</programlisting>
|
</programlisting>
|
||||||
Note that the <varname>conninfo</varname> value is that generated in <filename>postgresql.auto.conf</filename>
|
Note that the <varname>conninfo</varname> value is that generated in <filename>recovery.conf</filename>
|
||||||
(PostgreSQL 11 and earlier: <filename>recovery.conf</filename>) and will differ slightly from the primary's
|
and will differ slightly from the primary's <varname>conninfo</varname> as set in <filename>repmgr.conf</filename> -
|
||||||
<varname>conninfo</varname> as set in <filename>repmgr.conf</filename> - among others it will contain the
|
among others it will contain the connecting node's name as <varname>application_name</varname>.
|
||||||
connecting node's name as <varname>application_name</varname>.
|
|
||||||
</para>
|
</para>
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
By default, &repmgr; will wait for up to 15 seconds to confirm that &repmgrd;
|
By default, &repmgr; will wait for up to 15 seconds to confirm that &repmgrd;
|
||||||
started. This behaviour can be overridden by specifying a different value using the <option>--wait</option>
|
started. This behaviour can be overridden by specifying a diffent value using the <option>--wait</option>
|
||||||
option, or disabled altogether with the <option>--no-wait</option> option.
|
option, or disabled altogether with the <option>--no-wait</option> option.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
<para>
|
<para>
|
||||||
By default, &repmgr; will wait for up to 15 seconds to confirm that &repmgrd;
|
By default, &repmgr; will wait for up to 15 seconds to confirm that &repmgrd;
|
||||||
stopped. This behaviour can be overridden by specifying a different value using the <option>--wait</option>
|
stopped. This behaviour can be overridden by specifying a diffent value using the <option>--wait</option>
|
||||||
option, or disabled altogether with the <option>--no-wait</option> option.
|
option, or disabled altogether with the <option>--no-wait</option> option.
|
||||||
</para>
|
</para>
|
||||||
<note>
|
<note>
|
||||||
|
|||||||
@@ -125,29 +125,12 @@
|
|||||||
is correctly configured.
|
is correctly configured.
|
||||||
</simpara>
|
</simpara>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
|
||||||
|
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
|
||||||
<refsect1>
|
|
||||||
<title>repmgrd</title>
|
|
||||||
<para>
|
|
||||||
A separate check is available to verify whether &repmgrd; is running,
|
|
||||||
This is not included in the general output, as this does not
|
|
||||||
per-se constitute a check of the node's replication status.
|
|
||||||
</para>
|
|
||||||
<itemizedlist spacing="compact" mark="bullet">
|
|
||||||
<listitem>
|
|
||||||
<simpara>
|
|
||||||
<option>--repmgrd</option>: checks whether &repmgrd; is running.
|
|
||||||
If &repmgrd; is running but paused, status <literal>1</literal>
|
|
||||||
(<literal>WARNING</literal>) is returned.
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</refsect1>
|
|
||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
<title>Additional checks</title>
|
<title>Additional checks</title>
|
||||||
<para>
|
<para>
|
||||||
|
|||||||
@@ -22,10 +22,6 @@
|
|||||||
This can optionally use <application>pg_rewind</application> to re-integrate
|
This can optionally use <application>pg_rewind</application> to re-integrate
|
||||||
a node which has diverged from the rest of the cluster, typically a failed primary.
|
a node which has diverged from the rest of the cluster, typically a failed primary.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
|
||||||
Note that <command>repmgr node rejoin</command> can only be used to attach
|
|
||||||
a standby to the current primary, not another standby.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<tip>
|
<tip>
|
||||||
<para>
|
<para>
|
||||||
@@ -73,16 +69,16 @@
|
|||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>--force-rewind</option></term>
|
<term><option>--force-rewind[=/path/to/pg_rewind]</option></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Execute <application>pg_rewind</application>.
|
Execute <application>pg_rewind</application>.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
See <xref linkend="repmgr-node-rejoin-pg-rewind"/> for more details on using
|
It is only necessary to provide the <application>pg_rewind</application> path
|
||||||
<application>pg_rewind</application>.
|
if using PostgreSQL 9.4, and <application>pg_rewind</application>
|
||||||
|
is not installed in the PostgreSQL <filename>bin</filename> directory.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
@@ -261,6 +257,8 @@
|
|||||||
<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,
|
||||||
|
and can be installed from external sources for PostgreSQL 9.4.
|
||||||
</para>
|
</para>
|
||||||
<note>
|
<note>
|
||||||
<para>
|
<para>
|
||||||
@@ -269,10 +267,6 @@
|
|||||||
data checksums were enabled when the cluster was initialized. See the
|
data checksums were enabled when the cluster was initialized. See the
|
||||||
<ulink url="https://www.postgresql.org/docs/current/app-pgrewind.html"><command>pg_rewind</command> documentation</ulink> for details.
|
<ulink url="https://www.postgresql.org/docs/current/app-pgrewind.html"><command>pg_rewind</command> documentation</ulink> for details.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
|
||||||
Additionally, <varname>full_page_writes</varname> must be enabled; this is the default and
|
|
||||||
normally should never be disabled.
|
|
||||||
</para>
|
|
||||||
</note>
|
</note>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@@ -287,7 +281,6 @@
|
|||||||
<programlisting>
|
<programlisting>
|
||||||
$ repmgr node rejoin -f /etc/repmgr.conf -d 'host=node3 dbname=repmgr user=repmgr' \
|
$ repmgr node rejoin -f /etc/repmgr.conf -d 'host=node3 dbname=repmgr user=repmgr' \
|
||||||
--force-rewind --config-files=postgresql.local.conf,postgresql.conf --verbose --dry-run
|
--force-rewind --config-files=postgresql.local.conf,postgresql.conf --verbose --dry-run
|
||||||
NOTICE: rejoin target is node "node3" (node ID: 3)
|
|
||||||
INFO: replication connection to the rejoin target node was successful
|
INFO: replication connection to the rejoin target node was successful
|
||||||
INFO: local and rejoin target system identifiers match
|
INFO: local and rejoin target system identifiers match
|
||||||
DETAIL: system identifier is 6652184002263212600
|
DETAIL: system identifier is 6652184002263212600
|
||||||
@@ -346,7 +339,6 @@
|
|||||||
<programlisting>
|
<programlisting>
|
||||||
$ repmgr node rejoin -f /etc/repmgr.conf -d 'host=node3 dbname=repmgr user=repmgr' \
|
$ repmgr node rejoin -f /etc/repmgr.conf -d 'host=node3 dbname=repmgr user=repmgr' \
|
||||||
--config-files=postgresql.local.conf,postgresql.conf --verbose --force-rewind --dry-run
|
--config-files=postgresql.local.conf,postgresql.conf --verbose --force-rewind --dry-run
|
||||||
NOTICE: rejoin target is node "node3" (node ID: 3)
|
|
||||||
INFO: replication connection to the rejoin target node was successful
|
INFO: replication connection to the rejoin target node was successful
|
||||||
INFO: local and rejoin target system identifiers match
|
INFO: local and rejoin target system identifiers match
|
||||||
DETAIL: system identifier is 6652460429293670710
|
DETAIL: system identifier is 6652460429293670710
|
||||||
@@ -384,29 +376,6 @@
|
|||||||
DETAIL: node 2 is now attached to node 3</programlisting>
|
DETAIL: node 2 is now attached to node 3</programlisting>
|
||||||
</para>
|
</para>
|
||||||
</refsect2>
|
</refsect2>
|
||||||
|
|
||||||
<refsect2 id="repmgr-node-rejoin-postgresql-94" xreflabel="pg_rewind and PostgreSQL 9.4">
|
|
||||||
|
|
||||||
<title><command>pg_rewind</command> and PostgreSQL 9.4</title>
|
|
||||||
|
|
||||||
<indexterm>
|
|
||||||
<primary>pg_rewind</primary>
|
|
||||||
<secondary>PostgreSQL 9.4</secondary>
|
|
||||||
</indexterm>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
<application>pg_rewind</application> is available in PostgreSQL 9.5 and later as part of the core distribution.
|
|
||||||
Users of PostgreSQL 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.4 version of <application>pg_rewind</application> requires the PostgreSQL
|
|
||||||
source code.
|
|
||||||
</para>
|
|
||||||
</refsect2>
|
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
<refsect1 id="repmgr-node-rejoin-caveats" xreflabel="Caveats">
|
<refsect1 id="repmgr-node-rejoin-caveats" xreflabel="Caveats">
|
||||||
@@ -451,7 +420,7 @@
|
|||||||
|
|
||||||
<warning>
|
<warning>
|
||||||
<para>
|
<para>
|
||||||
In all PostgreSQL released before February 2021, <application>pg_rewind</application>
|
In all current PostgreSQL versions (as of September 2020), <application>pg_rewind</application>
|
||||||
contains a corner-case bug which affects standbys in a very specific situation.
|
contains a corner-case bug which affects standbys in a very specific situation.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
@@ -480,15 +449,15 @@
|
|||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Currently it is not possible to resolve this situation using <application>pg_rewind</application>.
|
Currently it is not possible to resolve this situation using <application>pg_rewind</application>.
|
||||||
A <ulink url="https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=2b4f3130382fe2f8705863e4d38589d4d69cd695">patch</ulink>
|
A <ulink url="https://www.postgresql.org/message-id/flat/CABvVfJU-LDWvoz4-Yow3Ay5LZYTuPD7eSjjE4kGyNZpXC6FrVQ@mail.gmail.com">patch</ulink>
|
||||||
was submitted and is included in all PostgreSQL versions released in February 2021 or later.
|
has been submitted and will hopefully be included in a forthcoming PostgreSQL minor release.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
As a workaround, start the primary server the standby was previously attached to,
|
As a workaround, start the primary server the standby was previously attached to,
|
||||||
and ensure the standby can be attached to it. If <application>pg_rewind</application> was actually executed,
|
and ensure the standby can be attached to it. If <application>pg_rewind</application> was actually executed,
|
||||||
it will have copied in the <filename>.history</filename> file from the target primary server; this must
|
it will have copied in the <filename>.history</filename> file from the target primary server; this must
|
||||||
be removed. <command>repmgr node rejoin</command> can then be used to attach the standby to the original
|
be removed. <command>repmgr node rejoin</command> can then be used to attach the standby to the original
|
||||||
primary. Ensure any changes pending on the primary have propagated to the standby. Then shut down the primary
|
primary. Ensure any changes pending on the primary have propogated to the standby. Then shut down the primary
|
||||||
server <emphasis>first</emphasis>, before shutting down the standby. It should then be possible to
|
server <emphasis>first</emphasis>, before shutting down the standby. It should then be possible to
|
||||||
use <command>repmgr node rejoin</command> to attach the standby to the new primary.
|
use <command>repmgr node rejoin</command> to attach the standby to the new primary.
|
||||||
</para>
|
</para>
|
||||||
@@ -499,7 +468,7 @@
|
|||||||
<refsect1>
|
<refsect1>
|
||||||
<title>See also</title>
|
<title>See also</title>
|
||||||
<para>
|
<para>
|
||||||
<xref linkend="repmgr-standby-follow"/>, <xref linkend="repmgr-standby-switchover"/>
|
<xref linkend="repmgr-standby-follow"/>
|
||||||
</para>
|
</para>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
</refentry>
|
</refentry>
|
||||||
|
|||||||
@@ -332,12 +332,6 @@ pg_basebackup_options='--waldir=/path/to/wal-directory'</programlisting>
|
|||||||
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>
|
||||||
<para>
|
|
||||||
Note that to be able to use this option, the &repmgr; user must be a superuser or
|
|
||||||
member of the <literal>pg_read_all_settings</literal> predefined role.
|
|
||||||
If this is not the case, provide a valid superuser with the
|
|
||||||
<option>-S</option>/<option>--superuser</option> option.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
@@ -405,15 +399,11 @@ pg_basebackup_options='--waldir=/path/to/wal-directory'</programlisting>
|
|||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>-S</option>/<option>--superuser</option></term>
|
<term><option>--superuser</option></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
The name of a valid PostgreSQL superuser can be provided with this option.
|
If the &repmgr; user is not a superuser, the name of a valid superuser must
|
||||||
</para>
|
be provided with this option.
|
||||||
<para>
|
|
||||||
This is only required if the <option>--copy-external-config-files</option> was provided
|
|
||||||
and the &repmgr; user is not a superuser or member of the <literal>pg_read_all_settings</literal>
|
|
||||||
predefined role.
|
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|||||||
@@ -189,14 +189,14 @@
|
|||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<simpara>
|
<simpara>
|
||||||
If the promotion candidate has insufficient free walsenders to accommodate the standbys which will
|
If the promotion candidate has insufficient free walsenders to accomodate the standbys which will
|
||||||
be attached to it, the standby will be promoted anyway.
|
be attached to it, the standby will be promoted anyway.
|
||||||
</simpara>
|
</simpara>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<simpara>
|
<simpara>
|
||||||
If replication slots are in use but the promotion candidate has insufficient free replication slots
|
If replication slots are in use but the promotion candidate has insufficient free replication slots
|
||||||
to accommodate the standbys which will be attached to it, the standby will be promoted anyway.
|
to accomodate the standbys which will be attached to it, the standby will be promoted anyway.
|
||||||
</simpara>
|
</simpara>
|
||||||
</listitem>
|
</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
|
|||||||
@@ -64,13 +64,6 @@
|
|||||||
|
|
||||||
<refsect1>
|
<refsect1>
|
||||||
<title>User permission requirements</title>
|
<title>User permission requirements</title>
|
||||||
<para><emphasis>data_directory</emphasis></para>
|
|
||||||
<para>
|
|
||||||
&repmgr; needs to be able to determine the location of the data directory on the
|
|
||||||
demotion candidate. If the &repmgr; is not a superuser or member of the <varname>pg_read_all_settings</varname>
|
|
||||||
<ulink url="https://www.postgresql.org/docs/current/predefined-roles.html">predefined roles</ulink>,
|
|
||||||
the name of a superuser should be provided with the <option>-S</option>/<option>--superuser</option> option.
|
|
||||||
</para>
|
|
||||||
<para><emphasis>CHECKPOINT</emphasis></para>
|
<para><emphasis>CHECKPOINT</emphasis></para>
|
||||||
<para>
|
<para>
|
||||||
&repmgr; executes <command>CHECKPOINT</command> on the demotion candidate as part of the shutdown
|
&repmgr; executes <command>CHECKPOINT</command> on the demotion candidate as part of the shutdown
|
||||||
@@ -79,7 +72,7 @@
|
|||||||
<para>
|
<para>
|
||||||
Note that <command>CHECKPOINT</command> requires database superuser permissions to execute.
|
Note that <command>CHECKPOINT</command> requires database superuser permissions to execute.
|
||||||
If the <literal>repmgr</literal> user is not a superuser, the name of a superuser should be
|
If the <literal>repmgr</literal> user is not a superuser, the name of a superuser should be
|
||||||
provided with the <option>-S</option>/<option>--superuser</option> option.
|
provided with the <option>-S</option>/<option>--superuser</option>.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
If &repmgr; is unable to execute the <command>CHECKPOINT</command> command, the switchover
|
If &repmgr; is unable to execute the <command>CHECKPOINT</command> command, the switchover
|
||||||
@@ -154,12 +147,9 @@
|
|||||||
<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).
|
(and the prerequisites for using <application>pg_rewind</application> are met).
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
If using PostgreSQL 9.4, and the <application>pg_rewind</application>
|
If using PostgreSQL 9.4, and the <application>pg_rewind</application>
|
||||||
binary is not installed in the PostgreSQL <filename>bin</filename> directory,
|
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"/>
|
provide its full path. For more details see also <xref linkend="switchover-pg-rewind"/>.
|
||||||
and <xref linkend="repmgr-node-rejoin-pg-rewind"/>.
|
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
<title>repmgr &repmgrversion; Documentation</title>
|
<title>repmgr &repmgrversion; Documentation</title>
|
||||||
|
|
||||||
<bookinfo>
|
<bookinfo>
|
||||||
<corpauthor>EDB</corpauthor>
|
<corpauthor>2ndQuadrant Ltd</corpauthor>
|
||||||
<productname>repmgr</productname>
|
<productname>repmgr</productname>
|
||||||
<productnumber>&repmgrversion;</productnumber>
|
<productnumber>&repmgrversion;</productnumber>
|
||||||
&legal;
|
&legal;
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
<abstract>
|
<abstract>
|
||||||
<para>
|
<para>
|
||||||
This is the official documentation of &repmgr; &repmgrversion; for
|
This is the official documentation of &repmgr; &repmgrversion; for
|
||||||
use with PostgreSQL 10 - PostgreSQL 16.
|
use with PostgreSQL 9.4 - PostgreSQL 13.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
&repmgr; is being continually developed and we strongly recommend using the
|
&repmgr; is being continually developed and we strongly recommend using the
|
||||||
@@ -38,19 +38,20 @@
|
|||||||
|
|
||||||
<para>
|
<para>
|
||||||
&repmgr; is developed by
|
&repmgr; is developed by
|
||||||
<ulink url="https://www.enterprisedb.com/">EDB</ulink>
|
<ulink url="https://2ndquadrant.com">2ndQuadrant</ulink>
|
||||||
along with contributions from other individuals and organisations.
|
along with contributions from other individuals and organisations.
|
||||||
Contributions from the community are appreciated and welcome - get
|
Contributions from the community are appreciated and welcome - get
|
||||||
in touch via <ulink url="https://github.com/EnterpriseDB/repmgr">github</ulink>
|
in touch via <ulink url="https://github.com/2ndQuadrant/repmgr">github</ulink>
|
||||||
or <ulink url="https://groups.google.com/group/repmgr">the mailing list/forum</ulink>.
|
or <ulink url="https://groups.google.com/group/repmgr">the mailing list/forum</ulink>.
|
||||||
Multiple EDB customers contribute funding to make &repmgr; development possible.
|
Multiple 2ndQuadrant customers contribute funding
|
||||||
|
to make repmgr development possible.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
&repmgr; is fully supported by EDB's
|
&repmgr; is fully supported by 2ndQuadrant's
|
||||||
<ulink url="https://www.enterprisedb.com/support/postgresql-support-overview-get-the-most-out-of-postgresql">24/7 Production Support</ulink>.
|
<ulink url="https://www.2ndquadrant.com/en/support/support-postgresql/">24/7 Production Support</ulink>.
|
||||||
EDB, a Major Sponsor of the PostgreSQL project, continues to maintain &repmgr;.
|
2ndQuadrant, a Major Sponsor of the PostgreSQL project, continues to develop and maintain &repmgr;.
|
||||||
We welcome participation from other organisations and individual developers.
|
Other organisations as well as individual developers are welcome to participate in the efforts.
|
||||||
</para>
|
</para>
|
||||||
</abstract>
|
</abstract>
|
||||||
|
|
||||||
|
|||||||
@@ -81,15 +81,11 @@
|
|||||||
</para>
|
</para>
|
||||||
<note>
|
<note>
|
||||||
<simpara>
|
<simpara>
|
||||||
A PostgreSQL instance can only accommodate a single witness server.
|
&repmgr; 3.3 and earlier provided a <command>repmgr create witness</command>
|
||||||
</simpara>
|
command, which would automatically create a PostgreSQL instance. However
|
||||||
<simpara>
|
this often resulted in an unsatisfactory, hard-to-customise instance.
|
||||||
If you are planning to use a single server to support more than one
|
|
||||||
witness server, a separate PostgreSQL instance is required for each
|
|
||||||
witness server in use.
|
|
||||||
</simpara>
|
</simpara>
|
||||||
</note>
|
</note>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The witness server should be configured in the same way as a normal
|
The witness server should be configured in the same way as a normal
|
||||||
&repmgr; node; see section <xref linkend="configuration"/>.
|
&repmgr; node; see section <xref linkend="configuration"/>.
|
||||||
@@ -590,7 +586,7 @@ INFO: node 3 received notification to rerun promotion candidate election
|
|||||||
<sect2 id="repmgrd-primary-child-disconnection-caveats">
|
<sect2 id="repmgrd-primary-child-disconnection-caveats">
|
||||||
<title>Standby disconnections monitoring caveats</title>
|
<title>Standby disconnections monitoring caveats</title>
|
||||||
<para>
|
<para>
|
||||||
The following caveats should be considered if you are intending to use this functionality.
|
The follwing caveats should be considered if you are intending to use this functionality.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
<itemizedlist mark="bullet">
|
<itemizedlist mark="bullet">
|
||||||
|
|||||||
@@ -89,10 +89,6 @@
|
|||||||
<literal>query</literal> - determines server availability
|
<literal>query</literal> - determines server availability
|
||||||
by executing an SQL statement on the node via the existing connection
|
by executing an SQL statement on the node via the existing connection
|
||||||
</simpara>
|
</simpara>
|
||||||
<simpara>
|
|
||||||
The query is a minimal throwaway query - <command>SELECT 1</command> -
|
|
||||||
which is used to determine that the server can accept queries.
|
|
||||||
</simpara>
|
|
||||||
</listitem>
|
</listitem>
|
||||||
|
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
@@ -156,7 +152,7 @@
|
|||||||
</variablelist>
|
</variablelist>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
See also <filename><ulink url="https://raw.githubusercontent.com/EnterpriseDB/repmgr/master/repmgr.conf.sample">repmgr.conf.sample</ulink></filename> for an annotated sample configuration file.
|
See also <filename><ulink url="https://raw.githubusercontent.com/2ndQuadrant/repmgr/master/repmgr.conf.sample">repmgr.conf.sample</ulink></filename> for an annotated sample configuration file.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<sect2 id="repmgrd-automatic-failover-configuration">
|
<sect2 id="repmgrd-automatic-failover-configuration">
|
||||||
@@ -333,7 +329,7 @@
|
|||||||
<title>Optional configuration for automatic failover</title>
|
<title>Optional configuration for automatic failover</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
The following configuraton options can be used to fine-tune automatic failover:
|
The following configuraton options can be use to fine-tune automatic failover:
|
||||||
</para>
|
</para>
|
||||||
<variablelist>
|
<variablelist>
|
||||||
|
|
||||||
@@ -345,18 +341,14 @@
|
|||||||
</indexterm>
|
</indexterm>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Indicates a preferred priority (default: <literal>100</literal>) for promoting nodes.
|
Indicates a preferred priority (default: <literal>100</literal>) for promoting nodes;
|
||||||
|
a value of zero prevents the node being promoted to primary.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Note that the priority setting is only applied if two or more nodes are
|
Note that the priority setting is only applied if two or more nodes are
|
||||||
determined as promotion candidates; in that case the node with the
|
determined as promotion candidates; in that case the node with the
|
||||||
higher priority is selected.
|
higher priority is selected.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
|
||||||
A value of zero will always prevent the node being promoted to primary, even if there
|
|
||||||
is no other promotion candidate.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
@@ -489,32 +481,6 @@
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
|
|
||||||
<term><option>repmgrd_exit_on_inactive_node</option></term>
|
|
||||||
<listitem>
|
|
||||||
<indexterm>
|
|
||||||
<primary>repmgrd_exit_on_inactive_node</primary>
|
|
||||||
</indexterm>
|
|
||||||
<para>
|
|
||||||
This parameter is available in &repmgr; 5.3 and later.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
If a node was marked as inactive but is running, and this option is set to
|
|
||||||
<literal>true</literal>, &repmgrd; will abort on startup.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
By default, <option>repmgrd_exit_on_inactive_node</option> is set
|
|
||||||
to <literal>false</literal>, in which case &repmgrd; will set the
|
|
||||||
node record to active on startup.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Setting this parameter to <literal>true</literal> causes &repmgrd;
|
|
||||||
to behave in the same way it did in &repmgr; 5.2 and earlier.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
</variablelist>
|
</variablelist>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@@ -573,7 +539,7 @@
|
|||||||
</indexterm>
|
</indexterm>
|
||||||
<para>
|
<para>
|
||||||
For further details and a reference implementation, see the separate document
|
For further details and a reference implementation, see the separate document
|
||||||
<ulink url="https://github.com/EnterpriseDB/repmgr/blob/master/doc/repmgrd-node-fencing.md">Fencing a failed master node with repmgrd and PgBouncer</ulink>.
|
<ulink url="https://github.com/2ndQuadrant/repmgr/blob/master/doc/repmgrd-node-fencing.md">Fencing a failed master node with repmgrd and PgBouncer</ulink>.
|
||||||
</para>
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
|
|
||||||
@@ -1003,7 +969,7 @@ repmgrd_service_stop_command='sudo systemctl repmgr12 stop'
|
|||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
If none of the above apply, &repmgrd; will create a PID file
|
If none of the above apply, &repmgrd; will create a PID file
|
||||||
in the operating system's temporary directory (as determined by the environment variable
|
in the operating system's temporary directory (as setermined by the environment variable
|
||||||
<varname>TMPDIR</varname>, or if that is not set, will use <filename>/tmp</filename>).
|
<varname>TMPDIR</varname>, or if that is not set, will use <filename>/tmp</filename>).
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
@@ -1083,29 +1049,6 @@ REPMGRD_OPTS="--daemonize=false"
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
</sect2>
|
</sect2>
|
||||||
|
|
||||||
<sect2 id="repmgrd-daemon-monitoring">
|
|
||||||
<title>repmgrd daemon monitoring</title>
|
|
||||||
<indexterm>
|
|
||||||
<primary>repmgrd</primary>
|
|
||||||
<secondary>monitoring</secondary>
|
|
||||||
</indexterm>
|
|
||||||
<indexterm>
|
|
||||||
<primary>monitoring</primary>
|
|
||||||
<secondary>repmgrd</secondary>
|
|
||||||
</indexterm>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
The command <command><link linkend="repmgr-service-status">repmgr service status</link></command>
|
|
||||||
provides an overview of the &repmgrd; daemon status (including pause status)
|
|
||||||
on all nodes in the cluster.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
From &repmgr; 5.3, <command><link linkend="repmgr-node-check">repmgr node check --repmgrd</link></command>
|
|
||||||
can be used to check the status of &repmgrd; (including pause status)
|
|
||||||
on the local node.
|
|
||||||
</para>
|
|
||||||
</sect2>
|
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|
||||||
<sect1 id="repmgrd-connection-settings">
|
<sect1 id="repmgrd-connection-settings">
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<simpara>
|
<simpara>
|
||||||
option to execute custom scripts ("<link linkend="event-notifications">event notifications</link>")
|
option to execute custom scripts ("<link linkend="event-notifications">event notifications</link>
|
||||||
at different points in the failover sequence
|
at different points in the failover sequence
|
||||||
</simpara>
|
</simpara>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
|||||||
@@ -120,19 +120,16 @@
|
|||||||
</important>
|
</important>
|
||||||
|
|
||||||
<note>
|
<note>
|
||||||
<para>
|
<simpara>
|
||||||
On <literal>systemd</literal> systems we strongly recommend using the appropriate
|
On <literal>systemd</literal> systems we strongly recommend using the appropriate
|
||||||
<command>systemctl</command> commands (typically run via <command>sudo</command>) to ensure
|
<command>systemctl</command> commands (typically run via <command>sudo</command>) to ensure
|
||||||
<literal>systemd</literal> is informed about the status of the PostgreSQL service.
|
<literal>systemd</literal> is informed about the status of the PostgreSQL service.
|
||||||
</para>
|
</simpara>
|
||||||
<para>
|
<simpara>
|
||||||
If using <command>sudo</command> for the <command>systemctl</command> calls, make sure the
|
If using <command>sudo</command> for the <command>systemctl</command> calls, make sure the
|
||||||
<command>sudo</command> specification doesn't require a real tty for the user. If not set
|
<command>sudo</command> specification doesn't require a real tty for the user. If not set
|
||||||
this way, <command>repmgr</command> will fail to stop the primary.
|
this way, <command>repmgr</command> will fail to stop the primary.
|
||||||
</para>
|
</simpara>
|
||||||
<para>
|
|
||||||
See the <xref linkend="configuration-file-service-commands"/> documentation section for further details.
|
|
||||||
</para>
|
|
||||||
</note>
|
</note>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@@ -242,12 +239,21 @@
|
|||||||
</simpara>
|
</simpara>
|
||||||
</note>
|
</note>
|
||||||
<para>
|
<para>
|
||||||
For more details on <application>pg_rewind</application>, see section <xref linkend="repmgr-node-rejoin-pg-rewind"/>
|
For more details on <application>pg_rewind</application>, see:
|
||||||
in the <link linkend="repmgr-node-rejoin"><command>repmgr node rejoin</command></link> documentation and
|
|
||||||
the PostgreSQL documentation at
|
|
||||||
<ulink url="https://www.postgresql.org/docs/current/app-pgrewind.html">https://www.postgresql.org/docs/current/app-pgrewind.html</ulink>.
|
<ulink url="https://www.postgresql.org/docs/current/app-pgrewind.html">https://www.postgresql.org/docs/current/app-pgrewind.html</ulink>.
|
||||||
</para>
|
</para>
|
||||||
|
<para>
|
||||||
|
<application>pg_rewind</application> has been part of the core PostgreSQL distribution since
|
||||||
|
version 9.5. Users of PostgreSQL 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.4 version of <application>pg_rewind</application> requires the PostgreSQL
|
||||||
|
source code.
|
||||||
|
</para>
|
||||||
</sect2>
|
</sect2>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -71,12 +71,6 @@
|
|||||||
<secondary>minor release</secondary>
|
<secondary>minor release</secondary>
|
||||||
</indexterm>
|
</indexterm>
|
||||||
|
|
||||||
<para>
|
|
||||||
A minor release upgrade involves updating &repmgr; from one minor release to another
|
|
||||||
minor release within the same major release (e.g. <literal>5.3.1</literal> to <literal>5.3.2</literal>).
|
|
||||||
An upgrade between minor releases of differing major releases (e.g. <literal>5.2.1</literal> to <literal>5.3.2</literal>)
|
|
||||||
is a <link linkend="upgrading-major-version">major upgrade</link>.
|
|
||||||
</para>
|
|
||||||
<para>
|
<para>
|
||||||
The process for installing minor version upgrades is quite straightforward:
|
The process for installing minor version upgrades is quite straightforward:
|
||||||
|
|
||||||
@@ -111,17 +105,15 @@
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
A PostgreSQL restart is usually <emphasis>not</emphasis> required for minor version upgrades
|
A PostgreSQL restart is <emphasis>not</emphasis> required for minor version upgrades.
|
||||||
within the same major version (e.g. <literal>5.3.1</literal> to <literal>5.3.2</literal>).
|
|
||||||
Be sure to check the <link linkend="appendix-release-notes">release notes</link>.
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<note>
|
<note>
|
||||||
<para>
|
<para>
|
||||||
The same &repmgr; "major version" (e.g. <literal>5.3</literal>) must be
|
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
|
installed on all nodes in the replication cluster. While it's possible to have differing
|
||||||
&repmgr; "minor versions" (e.g. <literal>5.3.1</literal> and <literal>5.3.2</literal>)
|
&repmgr; "minor versions" (e.g. <literal>4.2.1</literal>) on different nodes,
|
||||||
on different nodes, we strongly recommend updating all nodes to the latest minor version.
|
we strongly recommend updating all nodes to the latest minor version.
|
||||||
</para>
|
</para>
|
||||||
</note>
|
</note>
|
||||||
|
|
||||||
@@ -490,7 +482,7 @@ ALTER EXTENSION repmgr UPDATE</programlisting>
|
|||||||
<simpara>
|
<simpara>
|
||||||
If you don't care about any data from the existing &repmgr; installation,
|
If you don't care about any data from the existing &repmgr; installation,
|
||||||
(e.g. the contents of the <structname>events</structname> and <structname>monitoring</structname>
|
(e.g. the contents of the <structname>events</structname> and <structname>monitoring</structname>
|
||||||
tables), the following steps can be skipped; proceed to <xref linkend="upgrade-reregister-nodes"/>.
|
tables), the follwing steps can be skipped; proceed to <xref linkend="upgrade-reregister-nodes"/>.
|
||||||
</simpara>
|
</simpara>
|
||||||
</tip>
|
</tip>
|
||||||
|
|
||||||
@@ -505,10 +497,10 @@ ALTER EXTENSION repmgr UPDATE</programlisting>
|
|||||||
<itemizedlist spacing="compact" mark="bullet">
|
<itemizedlist spacing="compact" mark="bullet">
|
||||||
<listitem>
|
<listitem>
|
||||||
<simpara>
|
<simpara>
|
||||||
<ulink url="https://raw.githubusercontent.com/EnterpriseDB/repmgr/REL3_3_STABLE/sql/repmgr3.0_repmgr3.1.sql">repmgr3.0_repmgr3.1.sql</ulink></simpara>
|
<ulink url="https://raw.githubusercontent.com/2ndQuadrant/repmgr/REL3_3_STABLE/sql/repmgr3.0_repmgr3.1.sql">repmgr3.0_repmgr3.1.sql</ulink></simpara>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<simpara><ulink url="https://raw.githubusercontent.com/EnterpriseDB/repmgr/REL3_3_STABLE/sql/repmgr3.1.1_repmgr3.1.2.sql">repmgr3.1.1_repmgr3.1.2.sql</ulink></simpara>
|
<simpara><ulink url="https://raw.githubusercontent.com/2ndQuadrant/repmgr/REL3_3_STABLE/sql/repmgr3.1.1_repmgr3.1.2.sql">repmgr3.1.1_repmgr3.1.2.sql</ulink></simpara>
|
||||||
</listitem>
|
</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</para>
|
</para>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* errcode.h
|
* errcode.h
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
* Copyright (c) 2ndQuadrant, 2010-2020
|
||||||
*
|
*
|
||||||
* 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
|
||||||
@@ -49,6 +49,5 @@
|
|||||||
#define ERR_NODE_STATUS 25
|
#define ERR_NODE_STATUS 25
|
||||||
#define ERR_REPMGRD_PAUSE 26
|
#define ERR_REPMGRD_PAUSE 26
|
||||||
#define ERR_REPMGRD_SERVICE 27
|
#define ERR_REPMGRD_SERVICE 27
|
||||||
#define ERR_PGBACKUPAPI_SERVICE 28
|
|
||||||
|
|
||||||
#endif /* _ERRCODE_H_ */
|
#endif /* _ERRCODE_H_ */
|
||||||
|
|||||||
2
log.c
2
log.c
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* log.c - Logging methods
|
* log.c - Logging methods
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
* Copyright (c) 2ndQuadrant, 2010-2020
|
||||||
*
|
*
|
||||||
* 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
|
||||||
|
|||||||
2
log.h
2
log.h
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* log.h
|
* log.h
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
* Copyright (c) 2ndQuadrant, 2010-2020
|
||||||
*
|
*
|
||||||
* 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
|
||||||
|
|||||||
147
pgbackupapi.c
147
pgbackupapi.c
@@ -1,147 +0,0 @@
|
|||||||
/*
|
|
||||||
* pgbackupapi.c
|
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
|
||||||
*
|
|
||||||
* 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 <string.h>
|
|
||||||
|
|
||||||
#include <curl/curl.h>
|
|
||||||
#include <json-c/json.h>
|
|
||||||
|
|
||||||
#include "repmgr.h"
|
|
||||||
#include "pgbackupapi.h"
|
|
||||||
|
|
||||||
|
|
||||||
size_t receive_operations_cb(void *content, size_t size, size_t nmemb, char *buffer) {
|
|
||||||
short int max_chars_to_copy = MAX_BUFFER_LENGTH -2;
|
|
||||||
short int i = 0;
|
|
||||||
int operation_length = 0;
|
|
||||||
json_object *value;
|
|
||||||
|
|
||||||
json_object *root = json_tokener_parse(content);
|
|
||||||
json_object *operations = json_object_object_get(root, "operations");
|
|
||||||
|
|
||||||
operation_length = strlen(json_object_get_string(operations));
|
|
||||||
if (operation_length < max_chars_to_copy) {
|
|
||||||
max_chars_to_copy = operation_length;
|
|
||||||
}
|
|
||||||
|
|
||||||
strncpy(buffer, json_object_get_string(operations), max_chars_to_copy);
|
|
||||||
|
|
||||||
fprintf(stdout, "Success! The following operations were found\n");
|
|
||||||
for (i=0; i<json_object_array_length(operations); i++) {
|
|
||||||
value = json_object_array_get_idx(operations, i);
|
|
||||||
printf("%s\n", json_object_get_string(value));
|
|
||||||
}
|
|
||||||
return size * nmemb;
|
|
||||||
}
|
|
||||||
|
|
||||||
char * define_base_url(operation_task *task) {
|
|
||||||
char *format = "http://%s:7480/servers/%s/operations";
|
|
||||||
char *url = malloc(MAX_BUFFER_LENGTH);
|
|
||||||
|
|
||||||
snprintf(url, MAX_BUFFER_LENGTH-1, format, task->host, task->node_name);
|
|
||||||
|
|
||||||
//`url` is freed on the function that called this
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
CURLcode get_operations_on_server(CURL *curl, operation_task *task) {
|
|
||||||
char buffer[MAX_BUFFER_LENGTH];
|
|
||||||
char *url = define_base_url(task);
|
|
||||||
CURLcode ret;
|
|
||||||
|
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, receive_operations_cb);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_URL, url);
|
|
||||||
|
|
||||||
ret = curl_easy_perform(curl);
|
|
||||||
free(url);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t receive_operation_id(void *content, size_t size, size_t nmemb, char *buffer) {
|
|
||||||
json_object *root = json_tokener_parse(content);
|
|
||||||
json_object *operation = json_object_object_get(root, "operation_id");
|
|
||||||
|
|
||||||
if (operation != NULL) {
|
|
||||||
strncpy(buffer, json_object_get_string(operation), MAX_BUFFER_LENGTH-2);
|
|
||||||
}
|
|
||||||
|
|
||||||
return size * nmemb;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
CURLcode create_new_task(CURL *curl, operation_task *task) {
|
|
||||||
PQExpBufferData payload;
|
|
||||||
char *url = define_base_url(task);
|
|
||||||
CURLcode ret;
|
|
||||||
json_object *root = json_object_new_object();
|
|
||||||
struct curl_slist *chunk = NULL;
|
|
||||||
|
|
||||||
json_object_object_add(root, "operation_type", json_object_new_string(task->operation_type));
|
|
||||||
json_object_object_add(root, "backup_id", json_object_new_string(task->backup_id));
|
|
||||||
json_object_object_add(root, "remote_ssh_command", json_object_new_string(task->remote_ssh_command));
|
|
||||||
json_object_object_add(root, "destination_directory", json_object_new_string(task->destination_directory));
|
|
||||||
|
|
||||||
initPQExpBuffer(&payload);
|
|
||||||
appendPQExpBufferStr(&payload, json_object_to_json_string(root));
|
|
||||||
|
|
||||||
chunk = curl_slist_append(chunk, "Content-type: application/json");
|
|
||||||
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_URL, url);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload.data);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
|
|
||||||
//curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, receive_operation_id);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, task->operation_id);
|
|
||||||
ret = curl_easy_perform(curl);
|
|
||||||
free(url);
|
|
||||||
termPQExpBuffer(&payload);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
size_t receive_operation_status(void *content, size_t size, size_t nmemb, char *buffer) {
|
|
||||||
json_object *root = json_tokener_parse(content);
|
|
||||||
json_object *status = json_object_object_get(root, "status");
|
|
||||||
if (status != NULL) {
|
|
||||||
strncpy(buffer, json_object_get_string(status), MAX_BUFFER_LENGTH-2);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
fprintf(stderr, "Incorrect reply received for that operation ID.\n");
|
|
||||||
strcpy(buffer, "\0");
|
|
||||||
}
|
|
||||||
return size * nmemb;
|
|
||||||
}
|
|
||||||
|
|
||||||
CURLcode get_status_of_operation(CURL *curl, operation_task *task) {
|
|
||||||
CURLcode ret;
|
|
||||||
char *url = define_base_url(task);
|
|
||||||
|
|
||||||
strcat(url, "/");
|
|
||||||
strcat(url, task->operation_id);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_URL, url);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, receive_operation_status);
|
|
||||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, task->operation_status);
|
|
||||||
|
|
||||||
ret = curl_easy_perform(curl);
|
|
||||||
free(url);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
/*
|
|
||||||
* pgbackupapi.h
|
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
|
||||||
*
|
|
||||||
* 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 <curl/curl.h>
|
|
||||||
#include <json-c/json.h>
|
|
||||||
|
|
||||||
typedef struct operation_task {
|
|
||||||
char *backup_id;
|
|
||||||
char *destination_directory;
|
|
||||||
char *operation_type;
|
|
||||||
char *operation_id;
|
|
||||||
char *operation_status;
|
|
||||||
char *remote_ssh_command;
|
|
||||||
char *host;
|
|
||||||
char *node_name;
|
|
||||||
} operation_task;
|
|
||||||
|
|
||||||
//Default simplebuffer size in most of operations
|
|
||||||
#define MAX_BUFFER_LENGTH 72
|
|
||||||
|
|
||||||
//Callbacks to send/receive data from pg-backup-api endpoints
|
|
||||||
size_t receive_operations_cb(void *content, size_t size, size_t nmemb, char *buffer);
|
|
||||||
size_t receive_operation_id(void *content, size_t size, size_t nmemb, char *buffer);
|
|
||||||
size_t receive_operation_status(void *content, size_t size, size_t nmemb, char *buffer);
|
|
||||||
|
|
||||||
//Functions that implement the logic and know what to do and how to comunnicate wuth the API
|
|
||||||
CURLcode get_operations_on_server(CURL *curl, operation_task *task);
|
|
||||||
CURLcode create_new_task(CURL *curl, operation_task *task);
|
|
||||||
CURLcode get_status_of_operation(CURL *curl, operation_task *task);
|
|
||||||
|
|
||||||
//Helper to make simpler to read the handler where we set the URL
|
|
||||||
char * define_base_url(operation_task *task);
|
|
||||||
@@ -1,10 +1,17 @@
|
|||||||
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
|
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||||
\echo Use "ALTER EXTENSION repmgr UPDATE" to load this file. \quit
|
\echo Use "CREATE EXTENSION repmgr" to load this file. \quit
|
||||||
|
|
||||||
-- This script is intentionally empty and exists to skip the CREATE FUNCTION
|
CREATE FUNCTION set_upstream_last_seen()
|
||||||
-- commands contained in the 4.2--4.3 and 4.3--4.4 extension upgrade scripts,
|
RETURNS VOID
|
||||||
-- which reference C functions which no longer exist in 5.3 and later.
|
AS 'MODULE_PATHNAME', 'set_upstream_last_seen'
|
||||||
--
|
LANGUAGE C STRICT;
|
||||||
-- These functions will be explicitly created in the 5.2--5.3 extension
|
|
||||||
-- upgrade step with the correct C function references.
|
|
||||||
|
|
||||||
|
CREATE FUNCTION get_upstream_last_seen()
|
||||||
|
RETURNS INT
|
||||||
|
AS 'MODULE_PATHNAME', 'get_upstream_last_seen'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION get_wal_receiver_pid()
|
||||||
|
RETURNS INT
|
||||||
|
AS 'MODULE_PATHNAME', 'get_wal_receiver_pid'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|||||||
@@ -1,9 +1,19 @@
|
|||||||
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
|
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
|
||||||
\echo Use "ALTER EXTENSION repmgr UPDATE" to load this file. \quit
|
\echo Use "CREATE EXTENSION repmgr" to load this file. \quit
|
||||||
|
|
||||||
-- This script is intentionally empty and exists to skip the CREATE FUNCTION
|
DROP FUNCTION set_upstream_last_seen();
|
||||||
-- commands contained in the 4.3--4.4 extension upgrade script, which reference
|
|
||||||
-- C functions which no longer exist in 5.3 and later.
|
CREATE FUNCTION set_upstream_last_seen(INT)
|
||||||
--
|
RETURNS VOID
|
||||||
-- These functions will be explicitly created in the 5.2--5.3 extension
|
AS 'MODULE_PATHNAME', 'set_upstream_last_seen'
|
||||||
-- upgrade step with the correct C function references.
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION get_upstream_node_id()
|
||||||
|
RETURNS INT
|
||||||
|
AS 'MODULE_PATHNAME', 'get_upstream_node_id'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
|
CREATE FUNCTION set_upstream_node_id(INT)
|
||||||
|
RETURNS VOID
|
||||||
|
AS 'MODULE_PATHNAME', 'set_upstream_node_id'
|
||||||
|
LANGUAGE C STRICT;
|
||||||
|
|||||||
@@ -1,64 +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 OR REPLACE FUNCTION set_local_node_id(INT)
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_set_local_node_id'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION repmgr.get_local_node_id()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_get_local_node_id'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION standby_set_last_updated()
|
|
||||||
RETURNS TIMESTAMP WITH TIME ZONE
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_standby_set_last_updated'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION standby_get_last_updated()
|
|
||||||
RETURNS TIMESTAMP WITH TIME ZONE
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_standby_get_last_updated'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION set_upstream_last_seen(INT)
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_set_upstream_last_seen'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION get_upstream_last_seen()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_get_upstream_last_seen'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION get_upstream_node_id()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_get_upstream_node_id'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION set_upstream_node_id(INT)
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_set_upstream_node_id'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
/* failover functions */
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION notify_follow_primary(INT)
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_notify_follow_primary'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION get_new_primary()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_get_new_primary'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION reset_voting_status()
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_reset_voting_status'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION get_wal_receiver_pid()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_get_wal_receiver_pid'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
-- complain if script is sourced in psql, rather than via CREAT EXTENSION
|
|
||||||
\echo Use "CREATE EXTENSION repmgr" to load this file. \quit
|
|
||||||
192
repmgr--5.3.sql
192
repmgr--5.3.sql
@@ -1,192 +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
|
|
||||||
);
|
|
||||||
|
|
||||||
SELECT pg_catalog.pg_extension_config_dump('repmgr.nodes', '');
|
|
||||||
|
|
||||||
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
|
|
||||||
);
|
|
||||||
|
|
||||||
SELECT pg_catalog.pg_extension_config_dump('repmgr.events', '');
|
|
||||||
|
|
||||||
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
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE INDEX idx_monitoring_history_time
|
|
||||||
ON repmgr.monitoring_history (last_monitor_time, standby_node_id);
|
|
||||||
|
|
||||||
SELECT pg_catalog.pg_extension_config_dump('repmgr.monitoring_history', '');
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
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', 'repmgr_set_local_node_id'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION get_local_node_id()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_get_local_node_id'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION standby_set_last_updated()
|
|
||||||
RETURNS TIMESTAMP WITH TIME ZONE
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_standby_set_last_updated'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION standby_get_last_updated()
|
|
||||||
RETURNS TIMESTAMP WITH TIME ZONE
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_standby_get_last_updated'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION set_upstream_last_seen(INT)
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_set_upstream_last_seen'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION get_upstream_last_seen()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_get_upstream_last_seen'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION get_upstream_node_id()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_get_upstream_node_id'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION set_upstream_node_id(INT)
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_set_upstream_node_id'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
/* failover functions */
|
|
||||||
|
|
||||||
CREATE FUNCTION notify_follow_primary(INT)
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_notify_follow_primary'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION get_new_primary()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_get_new_primary'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION reset_voting_status()
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_reset_voting_status'
|
|
||||||
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 CALLED ON NULL INPUT;
|
|
||||||
|
|
||||||
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 FUNCTION get_wal_receiver_pid()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_get_wal_receiver_pid'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* views */
|
|
||||||
|
|
||||||
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
|
|
||||||
);
|
|
||||||
|
|
||||||
192
repmgr--5.4.sql
192
repmgr--5.4.sql
@@ -1,192 +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
|
|
||||||
);
|
|
||||||
|
|
||||||
SELECT pg_catalog.pg_extension_config_dump('repmgr.nodes', '');
|
|
||||||
|
|
||||||
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
|
|
||||||
);
|
|
||||||
|
|
||||||
SELECT pg_catalog.pg_extension_config_dump('repmgr.events', '');
|
|
||||||
|
|
||||||
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
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE INDEX idx_monitoring_history_time
|
|
||||||
ON repmgr.monitoring_history (last_monitor_time, standby_node_id);
|
|
||||||
|
|
||||||
SELECT pg_catalog.pg_extension_config_dump('repmgr.monitoring_history', '');
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
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', 'repmgr_set_local_node_id'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION get_local_node_id()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_get_local_node_id'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION standby_set_last_updated()
|
|
||||||
RETURNS TIMESTAMP WITH TIME ZONE
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_standby_set_last_updated'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION standby_get_last_updated()
|
|
||||||
RETURNS TIMESTAMP WITH TIME ZONE
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_standby_get_last_updated'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION set_upstream_last_seen(INT)
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_set_upstream_last_seen'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION get_upstream_last_seen()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_get_upstream_last_seen'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION get_upstream_node_id()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_get_upstream_node_id'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION set_upstream_node_id(INT)
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_set_upstream_node_id'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
/* failover functions */
|
|
||||||
|
|
||||||
CREATE FUNCTION notify_follow_primary(INT)
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_notify_follow_primary'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION get_new_primary()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_get_new_primary'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION reset_voting_status()
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_reset_voting_status'
|
|
||||||
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 CALLED ON NULL INPUT;
|
|
||||||
|
|
||||||
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 FUNCTION get_wal_receiver_pid()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_get_wal_receiver_pid'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* views */
|
|
||||||
|
|
||||||
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
|
|
||||||
);
|
|
||||||
|
|
||||||
@@ -1,245 +0,0 @@
|
|||||||
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
|
|
||||||
\echo Use "CREATE EXTENSION repmgr" to load this file. \quit
|
|
||||||
|
|
||||||
-- extract the current schema name
|
|
||||||
-- NOTE: this assumes there will be only one schema matching 'repmgr_%';
|
|
||||||
-- user is responsible for ensuring this is the case
|
|
||||||
|
|
||||||
CREATE TEMPORARY TABLE repmgr_old_schema (schema_name TEXT);
|
|
||||||
INSERT INTO repmgr_old_schema (schema_name)
|
|
||||||
SELECT nspname AS schema_name
|
|
||||||
FROM pg_catalog.pg_namespace
|
|
||||||
WHERE nspname LIKE 'repmgr_%'
|
|
||||||
LIMIT 1;
|
|
||||||
|
|
||||||
-- move old objects into new schema
|
|
||||||
DO $repmgr$
|
|
||||||
DECLARE
|
|
||||||
old_schema TEXT;
|
|
||||||
BEGIN
|
|
||||||
SELECT schema_name FROM repmgr_old_schema
|
|
||||||
INTO old_schema;
|
|
||||||
EXECUTE format('ALTER TABLE %I.repl_nodes SET SCHEMA repmgr', old_schema);
|
|
||||||
EXECUTE format('ALTER TABLE %I.repl_events SET SCHEMA repmgr', old_schema);
|
|
||||||
EXECUTE format('ALTER TABLE %I.repl_monitor SET SCHEMA repmgr', old_schema);
|
|
||||||
EXECUTE format('DROP VIEW IF EXISTS %I.repl_show_nodes', old_schema);
|
|
||||||
EXECUTE format('DROP VIEW IF EXISTS %I.repl_status', old_schema);
|
|
||||||
END$repmgr$;
|
|
||||||
|
|
||||||
-- convert "repmgr_$cluster.repl_nodes" to "repmgr.nodes"
|
|
||||||
CREATE TABLE repmgr.nodes (
|
|
||||||
node_id INTEGER PRIMARY KEY,
|
|
||||||
upstream_node_id INTEGER NULL REFERENCES repmgr.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
|
|
||||||
);
|
|
||||||
|
|
||||||
INSERT INTO repmgr.nodes
|
|
||||||
(node_id, upstream_node_id, active, node_name, type, location, priority, conninfo, repluser, slot_name, config_file)
|
|
||||||
SELECT id, upstream_node_id, active, name,
|
|
||||||
CASE WHEN type = 'master' THEN 'primary' ELSE type END,
|
|
||||||
'default', priority, conninfo, 'unknown', slot_name, 'unknown'
|
|
||||||
FROM repmgr.repl_nodes
|
|
||||||
ORDER BY id;
|
|
||||||
|
|
||||||
|
|
||||||
-- convert "repmgr_$cluster.repl_event" to "event"
|
|
||||||
|
|
||||||
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
|
|
||||||
);
|
|
||||||
|
|
||||||
INSERT INTO repmgr.events
|
|
||||||
(node_id, event, successful, event_timestamp, details)
|
|
||||||
SELECT node_id, event, successful, event_timestamp, details
|
|
||||||
FROM repmgr.repl_events;
|
|
||||||
|
|
||||||
-- create new table "repmgr.voting_term"
|
|
||||||
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;
|
|
||||||
|
|
||||||
INSERT INTO repmgr.voting_term (term) VALUES (1);
|
|
||||||
|
|
||||||
-- convert "repmgr_$cluster.repl_monitor" to "monitoring_history"
|
|
||||||
|
|
||||||
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
|
|
||||||
);
|
|
||||||
|
|
||||||
INSERT INTO repmgr.monitoring_history
|
|
||||||
(primary_node_id, standby_node_id, last_monitor_time, last_apply_time, last_wal_primary_location, last_wal_standby_location, replication_lag, apply_lag)
|
|
||||||
SELECT primary_node, standby_node, last_monitor_time, last_apply_time, last_wal_primary_location::pg_lsn, last_wal_standby_location::pg_lsn, replication_lag, apply_lag
|
|
||||||
FROM repmgr.repl_monitor;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
|
|
||||||
/* ================= */
|
|
||||||
/* repmgrd functions */
|
|
||||||
/* ================= */
|
|
||||||
|
|
||||||
/* monitoring functions */
|
|
||||||
|
|
||||||
CREATE FUNCTION set_local_node_id(INT)
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_set_local_node_id'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION get_local_node_id()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_get_local_node_id'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION standby_set_last_updated()
|
|
||||||
RETURNS TIMESTAMP WITH TIME ZONE
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_standby_set_last_updated'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION standby_get_last_updated()
|
|
||||||
RETURNS TIMESTAMP WITH TIME ZONE
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_standby_get_last_updated'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION set_upstream_last_seen(INT)
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_set_upstream_last_seen'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION get_upstream_last_seen()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_get_upstream_last_seen'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION get_upstream_node_id()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_get_upstream_node_id'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION set_upstream_node_id(INT)
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_set_upstream_node_id'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
/* failover functions */
|
|
||||||
|
|
||||||
CREATE FUNCTION notify_follow_primary(INT)
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_notify_follow_primary'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION get_new_primary()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_get_new_primary'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
CREATE FUNCTION reset_voting_status()
|
|
||||||
RETURNS VOID
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_reset_voting_status'
|
|
||||||
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 CALLED ON NULL INPUT;
|
|
||||||
|
|
||||||
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 FUNCTION get_wal_receiver_pid()
|
|
||||||
RETURNS INT
|
|
||||||
AS 'MODULE_PATHNAME', 'repmgr_get_wal_receiver_pid'
|
|
||||||
LANGUAGE C STRICT;
|
|
||||||
|
|
||||||
|
|
||||||
/* views */
|
|
||||||
|
|
||||||
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
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* drop old tables */
|
|
||||||
DROP TABLE repmgr.repl_nodes;
|
|
||||||
DROP TABLE repmgr.repl_monitor;
|
|
||||||
DROP TABLE repmgr.repl_events;
|
|
||||||
|
|
||||||
-- remove temporary table
|
|
||||||
DROP TABLE repmgr_old_schema;
|
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Implements cluster information actions for the repmgr command line utility
|
* Implements cluster information actions for the repmgr command line utility
|
||||||
*
|
*
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
* Copyright (c) 2ndQuadrant, 2010-2020
|
||||||
*
|
*
|
||||||
* 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
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* repmgr-action-cluster.h
|
* repmgr-action-cluster.h
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
* Copyright (c) 2ndQuadrant, 2010-2020
|
||||||
*
|
*
|
||||||
* 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
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* repmgr-action-daemon.c
|
* repmgr-action-daemon.c
|
||||||
*
|
*
|
||||||
* Implements repmgrd actions for the repmgr command line utility
|
* Implements repmgrd actions for the repmgr command line utility
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
* Copyright (c) 2ndQuadrant, 2010-2020
|
||||||
*
|
*
|
||||||
* 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
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* repmgr-action-daemon.h
|
* repmgr-action-daemon.h
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
* Copyright (c) 2ndQuadrant, 2010-2020
|
||||||
*
|
*
|
||||||
* 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
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Implements actions available for any kind of node
|
* Implements actions available for any kind of node
|
||||||
*
|
*
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
* Copyright (c) 2ndQuadrant, 2010-2020
|
||||||
*
|
*
|
||||||
* 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
|
||||||
@@ -35,7 +35,6 @@
|
|||||||
static bool copy_file(const char *src_file, const char *dest_file);
|
static bool copy_file(const char *src_file, const char *dest_file);
|
||||||
static void format_archive_dir(PQExpBufferData *archive_dir);
|
static void format_archive_dir(PQExpBufferData *archive_dir);
|
||||||
static t_server_action parse_server_action(const char *action);
|
static t_server_action parse_server_action(const char *action);
|
||||||
static const char *output_repmgrd_status(CheckStatus status);
|
|
||||||
|
|
||||||
static void exit_optformat_error(const char *error, int errcode);
|
static void exit_optformat_error(const char *error, int errcode);
|
||||||
|
|
||||||
@@ -53,11 +52,9 @@ static CheckStatus do_node_check_role(PGconn *conn, OutputMode mode, t_node_info
|
|||||||
static CheckStatus do_node_check_slots(PGconn *conn, OutputMode mode, t_node_info *node_info, CheckStatusList *list_output);
|
static CheckStatus do_node_check_slots(PGconn *conn, OutputMode mode, t_node_info *node_info, CheckStatusList *list_output);
|
||||||
static CheckStatus do_node_check_missing_slots(PGconn *conn, OutputMode mode, t_node_info *node_info, CheckStatusList *list_output);
|
static CheckStatus do_node_check_missing_slots(PGconn *conn, OutputMode mode, t_node_info *node_info, CheckStatusList *list_output);
|
||||||
static CheckStatus do_node_check_data_directory(PGconn *conn, OutputMode mode, t_node_info *node_info, CheckStatusList *list_output);
|
static CheckStatus do_node_check_data_directory(PGconn *conn, OutputMode mode, t_node_info *node_info, CheckStatusList *list_output);
|
||||||
static CheckStatus do_node_check_repmgrd(PGconn *conn, OutputMode mode, t_node_info *node_info, CheckStatusList *list_output);
|
|
||||||
static CheckStatus do_node_check_replication_config_owner(PGconn *conn, OutputMode mode, t_node_info *node_info, CheckStatusList *list_output);
|
static CheckStatus do_node_check_replication_config_owner(PGconn *conn, OutputMode mode, t_node_info *node_info, CheckStatusList *list_output);
|
||||||
static CheckStatus do_node_check_db_connection(PGconn *conn, OutputMode mode);
|
static CheckStatus do_node_check_db_connection(PGconn *conn, OutputMode mode);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NODE STATUS
|
* NODE STATUS
|
||||||
*
|
*
|
||||||
@@ -944,16 +941,6 @@ do_node_check(void)
|
|||||||
exit(return_code);
|
exit(return_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (runtime_options.repmgrd == true)
|
|
||||||
{
|
|
||||||
return_code = do_node_check_repmgrd(conn,
|
|
||||||
runtime_options.output_mode,
|
|
||||||
&node_info,
|
|
||||||
NULL);
|
|
||||||
PQfinish(conn);
|
|
||||||
exit(return_code);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (runtime_options.replication_config_owner == true)
|
if (runtime_options.replication_config_owner == true)
|
||||||
{
|
{
|
||||||
return_code = do_node_check_replication_config_owner(conn,
|
return_code = do_node_check_replication_config_owner(conn,
|
||||||
@@ -1327,7 +1314,7 @@ do_node_check_downstream(PGconn *conn, OutputMode mode, t_node_info *node_info,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_downstream_node_attached_quiet(conn, cell->node_info->node_name, NULL) != NODE_ATTACHED)
|
if (is_downstream_node_attached(conn, cell->node_info->node_name, NULL) != NODE_ATTACHED)
|
||||||
{
|
{
|
||||||
missing_nodes_count++;
|
missing_nodes_count++;
|
||||||
item_list_append_format(&missing_nodes,
|
item_list_append_format(&missing_nodes,
|
||||||
@@ -1395,32 +1382,49 @@ do_node_check_downstream(PGconn *conn, OutputMode mode, t_node_info *node_info,
|
|||||||
{
|
{
|
||||||
case OM_NAGIOS:
|
case OM_NAGIOS:
|
||||||
{
|
{
|
||||||
|
printf("REPMGR_DOWNSTREAM_SERVERS %s: %s | ",
|
||||||
|
output_check_status(status),
|
||||||
|
details.data);
|
||||||
|
|
||||||
if (missing_nodes_count)
|
if (missing_nodes_count)
|
||||||
{
|
{
|
||||||
ItemListCell *missing_cell = NULL;
|
ItemListCell *missing_cell = NULL;
|
||||||
bool first = true;
|
bool first = true;
|
||||||
|
|
||||||
appendPQExpBufferStr(&details, " (missing: ");
|
printf("missing: ");
|
||||||
|
|
||||||
for (missing_cell = missing_nodes.head; missing_cell; missing_cell = missing_cell->next)
|
for (missing_cell = missing_nodes.head; missing_cell; missing_cell = missing_cell->next)
|
||||||
{
|
{
|
||||||
if (first == false)
|
if (first == false)
|
||||||
appendPQExpBufferStr(&details, ", ");
|
printf(", ");
|
||||||
else
|
else
|
||||||
first = false;
|
first = false;
|
||||||
|
|
||||||
if (first == false)
|
if (first == false)
|
||||||
appendPQExpBufferStr(&details, missing_cell->string);
|
printf("%s", missing_cell->string);
|
||||||
}
|
}
|
||||||
|
|
||||||
appendPQExpBufferChar(&details, ')');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("REPMGR_DOWNSTREAM_SERVERS %s: %s | attached=%i, missing=%i\n",
|
if (expected_nodes_count - missing_nodes_count)
|
||||||
output_check_status(status),
|
{
|
||||||
details.data,
|
ItemListCell *attached_cell = NULL;
|
||||||
expected_nodes_count - missing_nodes_count,
|
bool first = true;
|
||||||
missing_nodes_count);
|
|
||||||
|
if (missing_nodes_count)
|
||||||
|
printf("; ");
|
||||||
|
printf("attached: ");
|
||||||
|
for (attached_cell = attached_nodes.head; attached_cell; attached_cell = attached_cell->next)
|
||||||
|
{
|
||||||
|
if (first == false)
|
||||||
|
printf(", ");
|
||||||
|
else
|
||||||
|
first = false;
|
||||||
|
|
||||||
|
if (first == false)
|
||||||
|
printf("%s", attached_cell->string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OM_CSV:
|
case OM_CSV:
|
||||||
@@ -1518,7 +1522,7 @@ do_node_check_upstream(PGconn *conn, OutputMode mode, t_node_info *node_info, Ch
|
|||||||
{
|
{
|
||||||
case OM_NAGIOS:
|
case OM_NAGIOS:
|
||||||
{
|
{
|
||||||
printf("REPMGR_UPSTREAM_SERVER %s: %s\n",
|
printf("REPMGR_UPSTREAM_SERVER %s: %s | ",
|
||||||
output_check_status(status),
|
output_check_status(status),
|
||||||
details.data);
|
details.data);
|
||||||
}
|
}
|
||||||
@@ -2020,6 +2024,7 @@ do_node_check_missing_slots(PGconn *conn, OutputMode mode, t_node_info *node_inf
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CheckStatus
|
CheckStatus
|
||||||
do_node_check_data_directory(PGconn *conn, OutputMode mode, t_node_info *node_info, CheckStatusList *list_output)
|
do_node_check_data_directory(PGconn *conn, OutputMode mode, t_node_info *node_info, CheckStatusList *list_output)
|
||||||
{
|
{
|
||||||
@@ -2154,53 +2159,6 @@ do_node_check_data_directory(PGconn *conn, OutputMode mode, t_node_info *node_in
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
CheckStatus
|
|
||||||
do_node_check_repmgrd(PGconn *conn, OutputMode mode, t_node_info *node_info, CheckStatusList *list_output)
|
|
||||||
{
|
|
||||||
CheckStatus status = CHECK_STATUS_OK;
|
|
||||||
|
|
||||||
if (mode == OM_CSV && list_output == NULL)
|
|
||||||
{
|
|
||||||
log_error(_("--csv output not provided with --repmgrd option"));
|
|
||||||
PQfinish(conn);
|
|
||||||
exit(ERR_BAD_CONFIG);
|
|
||||||
}
|
|
||||||
|
|
||||||
status = get_repmgrd_status(conn);
|
|
||||||
switch (mode)
|
|
||||||
{
|
|
||||||
case OM_OPTFORMAT:
|
|
||||||
printf("--repmgrd=%s\n",
|
|
||||||
output_check_status(status));
|
|
||||||
break;
|
|
||||||
case OM_NAGIOS:
|
|
||||||
printf("REPMGRD %s: %s\n",
|
|
||||||
output_check_status(status),
|
|
||||||
output_repmgrd_status(status));
|
|
||||||
|
|
||||||
break;
|
|
||||||
case OM_CSV:
|
|
||||||
case OM_TEXT:
|
|
||||||
if (list_output != NULL)
|
|
||||||
{
|
|
||||||
check_status_list_set(list_output,
|
|
||||||
"repmgrd",
|
|
||||||
status,
|
|
||||||
output_repmgrd_status(status));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("%s (%s)\n",
|
|
||||||
output_check_status(status),
|
|
||||||
output_repmgrd_status(status));
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is not included in the general list output
|
* This is not included in the general list output
|
||||||
*/
|
*/
|
||||||
@@ -2654,13 +2612,6 @@ do_node_rejoin(void)
|
|||||||
exit(ERR_BAD_CONFIG);
|
exit(ERR_BAD_CONFIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Emit a notice about the identity of the rejoin target
|
|
||||||
*/
|
|
||||||
log_notice(_("rejoin target is node \"%s\" (ID: %i)"),
|
|
||||||
primary_node_record.node_name,
|
|
||||||
primary_node_record.node_id);
|
|
||||||
|
|
||||||
/* connect to registered primary and check it's not in recovery */
|
/* connect to registered primary and check it's not in recovery */
|
||||||
primary_conn = establish_db_connection(primary_node_record.conninfo, false);
|
primary_conn = establish_db_connection(primary_node_record.conninfo, false);
|
||||||
|
|
||||||
@@ -2862,8 +2813,7 @@ do_node_rejoin(void)
|
|||||||
log_notice(_("temporarily removing \"standby.signal\""));
|
log_notice(_("temporarily removing \"standby.signal\""));
|
||||||
log_detail(_("this is required so pg_rewind can fix the unclean shutdown"));
|
log_detail(_("this is required so pg_rewind can fix the unclean shutdown"));
|
||||||
|
|
||||||
make_standby_signal_path(config_file_options.data_directory,
|
make_standby_signal_path(standby_signal_file_path);
|
||||||
standby_signal_file_path);
|
|
||||||
|
|
||||||
if (unlink(standby_signal_file_path) < 0 && errno != ENOENT)
|
if (unlink(standby_signal_file_path) < 0 && errno != ENOENT)
|
||||||
{
|
{
|
||||||
@@ -2888,7 +2838,7 @@ do_node_rejoin(void)
|
|||||||
* of whether the pg_rewind operation failed.
|
* of whether the pg_rewind operation failed.
|
||||||
*/
|
*/
|
||||||
log_notice(_("recreating \"standby.signal\""));
|
log_notice(_("recreating \"standby.signal\""));
|
||||||
write_standby_signal(config_file_options.data_directory);
|
write_standby_signal();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret == false)
|
if (ret == false)
|
||||||
@@ -3612,25 +3562,6 @@ copy_file(const char *src_file, const char *dest_file)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static const char *
|
|
||||||
output_repmgrd_status(CheckStatus status)
|
|
||||||
{
|
|
||||||
switch (status)
|
|
||||||
{
|
|
||||||
case CHECK_STATUS_OK:
|
|
||||||
return "repmgrd running";
|
|
||||||
case CHECK_STATUS_WARNING:
|
|
||||||
return "repmgrd running but paused";
|
|
||||||
case CHECK_STATUS_CRITICAL:
|
|
||||||
return "repmgrd not running";
|
|
||||||
case CHECK_STATUS_UNKNOWN:
|
|
||||||
return "repmgrd status unknown";
|
|
||||||
}
|
|
||||||
|
|
||||||
return "UNKNOWN";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
do_node_help(void)
|
do_node_help(void)
|
||||||
{
|
{
|
||||||
@@ -3668,12 +3599,11 @@ do_node_help(void)
|
|||||||
printf(_(" Following options check an individual status:\n"));
|
printf(_(" Following options check an individual status:\n"));
|
||||||
printf(_(" --archive-ready number of WAL files ready for archiving\n"));
|
printf(_(" --archive-ready number of WAL files ready for archiving\n"));
|
||||||
printf(_(" --downstream whether all downstream nodes are connected\n"));
|
printf(_(" --downstream whether all downstream nodes are connected\n"));
|
||||||
printf(_(" --upstream whether the node is connected to its upstream\n"));
|
printf(_(" --uptream whether the node is connected to its upstream\n"));
|
||||||
printf(_(" --replication-lag replication lag in seconds (standbys only)\n"));
|
printf(_(" --replication-lag replication lag in seconds (standbys only)\n"));
|
||||||
printf(_(" --role check node has expected role\n"));
|
printf(_(" --role check node has expected role\n"));
|
||||||
printf(_(" --slots check for inactive replication slots\n"));
|
printf(_(" --slots check for inactive replication slots\n"));
|
||||||
printf(_(" --missing-slots check for missing replication slots\n"));
|
printf(_(" --missing-slots check for missing replication slots\n"));
|
||||||
printf(_(" --repmgrd check if repmgrd is running\n"));
|
|
||||||
printf(_(" --data-directory-config check repmgr's data directory configuration\n"));
|
printf(_(" --data-directory-config check repmgr's data directory configuration\n"));
|
||||||
|
|
||||||
puts("");
|
puts("");
|
||||||
@@ -3687,7 +3617,7 @@ do_node_help(void)
|
|||||||
printf(_(" --dry-run check that the prerequisites are met for rejoining the node\n" \
|
printf(_(" --dry-run check that the prerequisites are met for rejoining the node\n" \
|
||||||
" (including usability of \"pg_rewind\" if requested)\n"));
|
" (including usability of \"pg_rewind\" if requested)\n"));
|
||||||
printf(_(" --force-rewind[=VALUE] execute \"pg_rewind\" if necessary\n"));
|
printf(_(" --force-rewind[=VALUE] execute \"pg_rewind\" if necessary\n"));
|
||||||
printf(_(" (PostgreSQL 9.4 - provide full \"pg_rewind\" path)\n"));
|
printf(_(" (9.3 and 9.4 - provide full \"pg_rewind\" path)\n"));
|
||||||
|
|
||||||
printf(_(" --config-files comma-separated list of configuration files to retain\n" \
|
printf(_(" --config-files comma-separated list of configuration files to retain\n" \
|
||||||
" after executing \"pg_rewind\"\n"));
|
" after executing \"pg_rewind\"\n"));
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* repmgr-action-node.h
|
* repmgr-action-node.h
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
* Copyright (c) 2ndQuadrant, 2010-2020
|
||||||
*
|
*
|
||||||
* 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
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Implements primary actions for the repmgr command line utility
|
* Implements primary actions for the repmgr command line utility
|
||||||
*
|
*
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
* Copyright (c) 2ndQuadrant, 2010-2020
|
||||||
*
|
*
|
||||||
* 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
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* repmgr-action-primary.h
|
* repmgr-action-primary.h
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
* Copyright (c) 2ndQuadrant, 2010-2020
|
||||||
*
|
*
|
||||||
* 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
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* repmgr-action-service.c
|
* repmgr-action-service.c
|
||||||
*
|
*
|
||||||
* Implements repmgrd actions for the repmgr command line utility
|
* Implements repmgrd actions for the repmgr command line utility
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
* Copyright (c) 2ndQuadrant, 2010-2020
|
||||||
*
|
*
|
||||||
* 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
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* repmgr-action-service.h
|
* repmgr-action-service.h
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
* Copyright (c) 2ndQuadrant, 2010-2020
|
||||||
*
|
*
|
||||||
* 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
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Implements standby actions for the repmgr command line utility
|
* Implements standby actions for the repmgr command line utility
|
||||||
*
|
*
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
* Copyright (c) 2ndQuadrant, 2010-2020
|
||||||
*
|
*
|
||||||
* 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
|
||||||
@@ -20,8 +20,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <time.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include "repmgr.h"
|
#include "repmgr.h"
|
||||||
#include "dirutil.h"
|
#include "dirutil.h"
|
||||||
@@ -30,7 +28,7 @@
|
|||||||
|
|
||||||
#include "repmgr-client-global.h"
|
#include "repmgr-client-global.h"
|
||||||
#include "repmgr-action-standby.h"
|
#include "repmgr-action-standby.h"
|
||||||
#include "pgbackupapi.h"
|
|
||||||
|
|
||||||
typedef struct TablespaceDataListCell
|
typedef struct TablespaceDataListCell
|
||||||
{
|
{
|
||||||
@@ -96,8 +94,6 @@ static char barman_command_buf[MAXLEN] = "";
|
|||||||
* be run and which of the available users, which will be one
|
* be run and which of the available users, which will be one
|
||||||
* of the repmgr user, the replication user (if available) or
|
* of the repmgr user, the replication user (if available) or
|
||||||
* the superuser (if available).
|
* the superuser (if available).
|
||||||
*
|
|
||||||
* This is determined in check_source_server().
|
|
||||||
*/
|
*/
|
||||||
static t_user_type SettingsUser = REPMGR_USER;
|
static t_user_type SettingsUser = REPMGR_USER;
|
||||||
|
|
||||||
@@ -114,7 +110,6 @@ static void check_recovery_type(PGconn *conn);
|
|||||||
static void initialise_direct_clone(t_node_info *local_node_record, t_node_info *upstream_node_record);
|
static void initialise_direct_clone(t_node_info *local_node_record, t_node_info *upstream_node_record);
|
||||||
static int run_basebackup(t_node_info *node_record);
|
static int run_basebackup(t_node_info *node_record);
|
||||||
static int run_file_backup(t_node_info *node_record);
|
static int run_file_backup(t_node_info *node_record);
|
||||||
static int run_pg_backupapi(t_node_info *node_record);
|
|
||||||
|
|
||||||
static void copy_configuration_files(bool delete_after_copy);
|
static void copy_configuration_files(bool delete_after_copy);
|
||||||
|
|
||||||
@@ -178,6 +173,21 @@ do_standby_clone(void)
|
|||||||
|
|
||||||
initialize_conninfo_params(&recovery_conninfo, false);
|
initialize_conninfo_params(&recovery_conninfo, false);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* --replication-conf-only provided - we'll handle that separately
|
||||||
|
*/
|
||||||
|
if (runtime_options.replication_conf_only == true)
|
||||||
|
{
|
||||||
|
return _do_create_replication_conf();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* conninfo params for the actual upstream node (which might be different
|
||||||
|
* to the node we're cloning from) to write to recovery.conf
|
||||||
|
*/
|
||||||
|
|
||||||
|
mode = get_standby_clone_mode();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copy the provided data directory; if a configuration file was provided,
|
* Copy the provided data directory; if a configuration file was provided,
|
||||||
* use the (mandatory) value from that; if -D/--pgdata was provided, use
|
* use the (mandatory) value from that; if -D/--pgdata was provided, use
|
||||||
@@ -205,19 +215,6 @@ do_standby_clone(void)
|
|||||||
exit(ERR_BAD_CONFIG);
|
exit(ERR_BAD_CONFIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* --replication-conf-only provided - we'll handle that separately
|
|
||||||
*/
|
|
||||||
if (runtime_options.replication_conf_only == true)
|
|
||||||
{
|
|
||||||
return _do_create_replication_conf();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* conninfo params for the actual upstream node (which might be different
|
|
||||||
* to the node we're cloning from) to write to recovery.conf
|
|
||||||
*/
|
|
||||||
mode = get_standby_clone_mode();
|
|
||||||
|
|
||||||
if (mode == barman)
|
if (mode == barman)
|
||||||
{
|
{
|
||||||
@@ -673,15 +670,6 @@ do_standby_clone(void)
|
|||||||
log_hint(_("consider using the -c/--fast-checkpoint option"));
|
log_hint(_("consider using the -c/--fast-checkpoint option"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode == pg_basebackup)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* In --dry-run mode, this will just output the pg_basebackup command which
|
|
||||||
* would be executed.
|
|
||||||
*/
|
|
||||||
run_basebackup(&local_node_record);
|
|
||||||
}
|
|
||||||
|
|
||||||
PQfinish(source_conn);
|
PQfinish(source_conn);
|
||||||
|
|
||||||
log_info(_("all prerequisites for \"standby clone\" are met"));
|
log_info(_("all prerequisites for \"standby clone\" are met"));
|
||||||
@@ -689,18 +677,19 @@ do_standby_clone(void)
|
|||||||
exit(SUCCESS);
|
exit(SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mode != barman)
|
||||||
|
{
|
||||||
|
initialise_direct_clone(&local_node_record, &upstream_node_record);
|
||||||
|
}
|
||||||
|
|
||||||
switch (mode)
|
switch (mode)
|
||||||
{
|
{
|
||||||
case pg_basebackup:
|
case pg_basebackup:
|
||||||
initialise_direct_clone(&local_node_record, &upstream_node_record);
|
|
||||||
log_notice(_("starting backup (using pg_basebackup)..."));
|
log_notice(_("starting backup (using pg_basebackup)..."));
|
||||||
break;
|
break;
|
||||||
case barman:
|
case barman:
|
||||||
log_notice(_("retrieving backup from Barman..."));
|
log_notice(_("retrieving backup from Barman..."));
|
||||||
break;
|
break;
|
||||||
case pg_backupapi:
|
|
||||||
log_notice(_("starting backup (using pg_backupapi)..."));
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
/* should never reach here */
|
/* should never reach here */
|
||||||
log_error(_("unknown clone mode"));
|
log_error(_("unknown clone mode"));
|
||||||
@@ -722,9 +711,6 @@ do_standby_clone(void)
|
|||||||
case barman:
|
case barman:
|
||||||
r = run_file_backup(&local_node_record);
|
r = run_file_backup(&local_node_record);
|
||||||
break;
|
break;
|
||||||
case pg_backupapi:
|
|
||||||
r = run_pg_backupapi(&local_node_record);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
/* should never reach here */
|
/* should never reach here */
|
||||||
log_error(_("unknown clone mode"));
|
log_error(_("unknown clone mode"));
|
||||||
@@ -818,6 +804,7 @@ do_standby_clone(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Write the recovery.conf file */
|
/* Write the recovery.conf file */
|
||||||
|
|
||||||
if (create_recovery_file(&local_node_record,
|
if (create_recovery_file(&local_node_record,
|
||||||
&recovery_conninfo,
|
&recovery_conninfo,
|
||||||
source_server_version_num,
|
source_server_version_num,
|
||||||
@@ -849,9 +836,6 @@ do_standby_clone(void)
|
|||||||
case barman:
|
case barman:
|
||||||
log_notice(_("standby clone (from Barman) complete"));
|
log_notice(_("standby clone (from Barman) complete"));
|
||||||
break;
|
break;
|
||||||
case pg_backupapi:
|
|
||||||
log_notice(_("standby clone (from pg_backupapi) complete"));
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -943,9 +927,6 @@ do_standby_clone(void)
|
|||||||
case barman:
|
case barman:
|
||||||
appendPQExpBufferStr(&event_details, "barman");
|
appendPQExpBufferStr(&event_details, "barman");
|
||||||
break;
|
break;
|
||||||
case pg_backupapi:
|
|
||||||
appendPQExpBufferStr(&event_details, "pg_backupapi");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
appendPQExpBuffer(&event_details,
|
appendPQExpBuffer(&event_details,
|
||||||
@@ -1319,64 +1300,6 @@ _do_create_replication_conf(void)
|
|||||||
PQExpBufferData msg;
|
PQExpBufferData msg;
|
||||||
t_replication_slot slot_info = T_REPLICATION_SLOT_INITIALIZER;
|
t_replication_slot slot_info = T_REPLICATION_SLOT_INITIALIZER;
|
||||||
|
|
||||||
/*
|
|
||||||
* Check the node record has slot_name set; if not we'll need to
|
|
||||||
* update it.
|
|
||||||
*/
|
|
||||||
if (local_node_record.slot_name[0] == '\0')
|
|
||||||
{
|
|
||||||
PGconn *primary_conn = NULL;
|
|
||||||
|
|
||||||
create_slot_name(local_node_record.slot_name, local_node_record.node_id);
|
|
||||||
|
|
||||||
/* Check we can connect to the primary so we can update the record */
|
|
||||||
|
|
||||||
if (get_recovery_type(upstream_conn) == RECTYPE_PRIMARY)
|
|
||||||
{
|
|
||||||
primary_conn = upstream_conn;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
primary_conn = establish_primary_db_connection(upstream_conn, false);
|
|
||||||
|
|
||||||
if (primary_conn == NULL)
|
|
||||||
{
|
|
||||||
log_error(_("unable to connect to primary to update slot name for node \"%s\" (ID: %i)"),
|
|
||||||
local_node_record.node_name,
|
|
||||||
local_node_record.node_id);
|
|
||||||
PQfinish(upstream_conn);
|
|
||||||
termPQExpBuffer(&msg);
|
|
||||||
exit(ERR_BAD_CONFIG);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (runtime_options.dry_run == true)
|
|
||||||
{
|
|
||||||
log_info(_("would set \"slot_name\" for node \"%s\" (ID: %i) to \"%s\""),
|
|
||||||
local_node_record.node_name,
|
|
||||||
local_node_record.node_id,
|
|
||||||
local_node_record.slot_name);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bool success = update_node_record_slot_name(primary_conn,
|
|
||||||
local_node_record.node_id,
|
|
||||||
local_node_record.slot_name);
|
|
||||||
|
|
||||||
if (primary_conn != upstream_conn)
|
|
||||||
PQfinish(primary_conn);
|
|
||||||
|
|
||||||
if (success == false)
|
|
||||||
{
|
|
||||||
log_error(_("unable to update slot name for node \"%s\" (ID: %i)"),
|
|
||||||
local_node_record.node_name,
|
|
||||||
local_node_record.node_id);
|
|
||||||
PQfinish(upstream_conn);
|
|
||||||
exit(ERR_BAD_CONFIG);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
record_status = get_slot_record(upstream_conn, local_node_record.slot_name, &slot_info);
|
record_status = get_slot_record(upstream_conn, local_node_record.slot_name, &slot_info);
|
||||||
|
|
||||||
/* check if replication slot exists*/
|
/* check if replication slot exists*/
|
||||||
@@ -1557,7 +1480,7 @@ _do_create_replication_conf(void)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (write_standby_signal(local_data_directory) == false)
|
if (write_standby_signal() == false)
|
||||||
{
|
{
|
||||||
log_error(_("unable to write \"standby.signal\" file"));
|
log_error(_("unable to write \"standby.signal\" file"));
|
||||||
}
|
}
|
||||||
@@ -2009,7 +1932,7 @@ do_standby_register(void)
|
|||||||
/*
|
/*
|
||||||
* If --upstream-node-id not provided, we're defaulting to the primary as
|
* If --upstream-node-id not provided, we're defaulting to the primary as
|
||||||
* upstream node. If local node is available, double-check that it's attached
|
* upstream node. If local node is available, double-check that it's attached
|
||||||
* to the primary, in case --upstream-node-id was an accidental omission.
|
* to the primary, in case --upstream-node-id was an accidental ommission.
|
||||||
*
|
*
|
||||||
* Currently we'll only do this for newly registered nodes.
|
* Currently we'll only do this for newly registered nodes.
|
||||||
*/
|
*/
|
||||||
@@ -2018,7 +1941,7 @@ do_standby_register(void)
|
|||||||
/* only do this if record does not exist */
|
/* only do this if record does not exist */
|
||||||
if (record_status != RECORD_FOUND)
|
if (record_status != RECORD_FOUND)
|
||||||
{
|
{
|
||||||
log_warning(_("--upstream-node-id not supplied, assuming upstream node is primary (node ID: %i)"),
|
log_warning(_("--upstream-node-id not supplied, assuming upstream node is primary (node ID %i)"),
|
||||||
primary_node_id);
|
primary_node_id);
|
||||||
|
|
||||||
/* check our standby is connected */
|
/* check our standby is connected */
|
||||||
@@ -3357,9 +3280,10 @@ do_standby_follow_internal(PGconn *primary_conn, PGconn *follow_target_conn, t_n
|
|||||||
update_node_record_slot_name(primary_conn, config_file_options.node_id, local_node_record.slot_name);
|
update_node_record_slot_name(primary_conn, config_file_options.node_id, local_node_record.slot_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (create_replication_slot(follow_target_conn,
|
if (create_replication_slot(follow_target_conn,
|
||||||
local_node_record.slot_name,
|
local_node_record.slot_name,
|
||||||
follow_target_node_record,
|
NULL,
|
||||||
output) == false)
|
output) == false)
|
||||||
{
|
{
|
||||||
log_error("%s", output->data);
|
log_error("%s", output->data);
|
||||||
@@ -3471,7 +3395,7 @@ do_standby_follow_internal(PGconn *primary_conn, PGconn *follow_target_conn, t_n
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* In the unlikely event that fails, we'll fall back to a restart */
|
/* In the unlikley event that fails, we'll fall back to a restart */
|
||||||
log_warning(_("unable to reload server configuration"));
|
log_warning(_("unable to reload server configuration"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3662,9 +3586,8 @@ do_standby_switchover(void)
|
|||||||
PQExpBufferData remote_command_str;
|
PQExpBufferData remote_command_str;
|
||||||
PQExpBufferData command_output;
|
PQExpBufferData command_output;
|
||||||
PQExpBufferData node_rejoin_options;
|
PQExpBufferData node_rejoin_options;
|
||||||
PQExpBufferData logmsg;
|
PQExpBufferData errmsg;
|
||||||
PQExpBufferData detailmsg;
|
PQExpBufferData detailmsg;
|
||||||
PQExpBufferData event_details;
|
|
||||||
|
|
||||||
int r,
|
int r,
|
||||||
i;
|
i;
|
||||||
@@ -3681,9 +3604,6 @@ do_standby_switchover(void)
|
|||||||
/* store list of configuration files on the demotion candidate */
|
/* store list of configuration files on the demotion candidate */
|
||||||
KeyValueList remote_config_files = {NULL, NULL};
|
KeyValueList remote_config_files = {NULL, NULL};
|
||||||
|
|
||||||
/* temporary log file for "repmgr node rejoin" on the demotion candidate */
|
|
||||||
char node_rejoin_log[MAXPGPATH] = "";
|
|
||||||
|
|
||||||
NodeInfoList sibling_nodes = T_NODE_INFO_LIST_INITIALIZER;
|
NodeInfoList sibling_nodes = T_NODE_INFO_LIST_INITIALIZER;
|
||||||
SiblingNodeStats sibling_nodes_stats = T_SIBLING_NODES_STATS_INITIALIZER;
|
SiblingNodeStats sibling_nodes_stats = T_SIBLING_NODES_STATS_INITIALIZER;
|
||||||
|
|
||||||
@@ -3706,7 +3626,7 @@ do_standby_switchover(void)
|
|||||||
* SANITY CHECKS
|
* SANITY CHECKS
|
||||||
*
|
*
|
||||||
* We'll be doing a bunch of operations on the remote server (primary to
|
* We'll be doing a bunch of operations on the remote server (primary to
|
||||||
* be demoted) - careful checks needed before proceeding.
|
* be demoted) - careful checks needed before proceding.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
local_conn = establish_db_connection(config_file_options.conninfo, true);
|
local_conn = establish_db_connection(config_file_options.conninfo, true);
|
||||||
@@ -3826,24 +3746,24 @@ do_standby_switchover(void)
|
|||||||
* the demotion candidate as the rejoin will fail if we are unable to to write to that.
|
* the demotion candidate as the rejoin will fail if we are unable to to write to that.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
initPQExpBuffer(&logmsg);
|
initPQExpBuffer(&errmsg);
|
||||||
initPQExpBuffer(&detailmsg);
|
initPQExpBuffer(&detailmsg);
|
||||||
|
|
||||||
if (check_replication_config_owner(PQserverVersion(local_conn),
|
if (check_replication_config_owner(PQserverVersion(local_conn),
|
||||||
config_file_options.data_directory,
|
config_file_options.data_directory,
|
||||||
&logmsg, &detailmsg) == false)
|
&errmsg, &detailmsg) == false)
|
||||||
{
|
{
|
||||||
log_error("%s", logmsg.data);
|
log_error("%s", errmsg.data);
|
||||||
log_detail("%s", detailmsg.data);
|
log_detail("%s", detailmsg.data);
|
||||||
|
|
||||||
termPQExpBuffer(&logmsg);
|
termPQExpBuffer(&errmsg);
|
||||||
termPQExpBuffer(&detailmsg);
|
termPQExpBuffer(&detailmsg);
|
||||||
|
|
||||||
PQfinish(local_conn);
|
PQfinish(local_conn);
|
||||||
exit(ERR_BAD_CONFIG);
|
exit(ERR_BAD_CONFIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
termPQExpBuffer(&logmsg);
|
termPQExpBuffer(&errmsg);
|
||||||
termPQExpBuffer(&detailmsg);
|
termPQExpBuffer(&detailmsg);
|
||||||
|
|
||||||
/* check remote server connection and retrieve its record */
|
/* check remote server connection and retrieve its record */
|
||||||
@@ -4188,7 +4108,7 @@ do_standby_switchover(void)
|
|||||||
|
|
||||||
if (command_success == false || command_output.data[0] == '0')
|
if (command_success == false || command_output.data[0] == '0')
|
||||||
{
|
{
|
||||||
log_error(_("expected configuration file not found on the demotion candidate \"%s\" (ID: %i)"),
|
log_error(_("expected configuration file not found on the demotion candiate \"%s\" (ID: %i)"),
|
||||||
remote_node_record.node_name,
|
remote_node_record.node_name,
|
||||||
remote_node_record.node_id);
|
remote_node_record.node_id);
|
||||||
log_detail(_("registered configuration file is \"%s\""),
|
log_detail(_("registered configuration file is \"%s\""),
|
||||||
@@ -4288,7 +4208,7 @@ do_standby_switchover(void)
|
|||||||
else if (remote_error == REMOTE_ERROR_CONNINFO_PARSE)
|
else if (remote_error == REMOTE_ERROR_CONNINFO_PARSE)
|
||||||
{
|
{
|
||||||
/* highly unlikely */
|
/* highly unlikely */
|
||||||
log_detail(_("an error was encountered when parsing the \"conninfo\" parameter in \"repmgr.conf\" on node \"%s\" (ID: %i)"),
|
log_detail(_("an error was encountered when parsing the \"conninfo\" parameter in \"rempgr.conf\" on node \"%s\" (ID: %i)"),
|
||||||
remote_node_record.node_name,
|
remote_node_record.node_name,
|
||||||
remote_node_record.node_id);
|
remote_node_record.node_id);
|
||||||
}
|
}
|
||||||
@@ -4791,7 +4711,6 @@ do_standby_switchover(void)
|
|||||||
|
|
||||||
repmgrd_info = (RepmgrdInfo **) pg_malloc0(sizeof(RepmgrdInfo *) * all_nodes.node_count);
|
repmgrd_info = (RepmgrdInfo **) pg_malloc0(sizeof(RepmgrdInfo *) * all_nodes.node_count);
|
||||||
|
|
||||||
log_notice(_("attempting to pause repmgrd on %i nodes"), all_nodes.node_count);
|
|
||||||
for (cell = all_nodes.head; cell; cell = cell->next)
|
for (cell = all_nodes.head; cell; cell = cell->next)
|
||||||
{
|
{
|
||||||
repmgrd_info[i] = pg_malloc0(sizeof(RepmgrdInfo));
|
repmgrd_info[i] = pg_malloc0(sizeof(RepmgrdInfo));
|
||||||
@@ -4820,7 +4739,7 @@ do_standby_switchover(void)
|
|||||||
unreachable_node_count++;
|
unreachable_node_count++;
|
||||||
|
|
||||||
item_list_append_format(&repmgrd_connection_errors,
|
item_list_append_format(&repmgrd_connection_errors,
|
||||||
_("unable to connect to node \"%s\" (ID: %i):\n%s"),
|
_("unable to connect to node \"%s\" (ID %i):\n%s"),
|
||||||
cell->node_info->node_name,
|
cell->node_info->node_name,
|
||||||
cell->node_info->node_id,
|
cell->node_info->node_id,
|
||||||
PQerrorMessage(cell->node_info->conn));
|
PQerrorMessage(cell->node_info->conn));
|
||||||
@@ -4851,9 +4770,8 @@ do_standby_switchover(void)
|
|||||||
|
|
||||||
initPQExpBuffer(&msg);
|
initPQExpBuffer(&msg);
|
||||||
appendPQExpBuffer(&msg,
|
appendPQExpBuffer(&msg,
|
||||||
_("unable to connect to %i of %i node(s), unable to pause all repmgrd instances"),
|
_("unable to connect to %i node(s), unable to pause all repmgrd instances"),
|
||||||
unreachable_node_count,
|
unreachable_node_count);
|
||||||
all_nodes.node_count);
|
|
||||||
|
|
||||||
initPQExpBuffer(&detail);
|
initPQExpBuffer(&detail);
|
||||||
|
|
||||||
@@ -4904,7 +4822,7 @@ do_standby_switchover(void)
|
|||||||
*/
|
*/
|
||||||
if (repmgrd_info[i]->pg_running == false)
|
if (repmgrd_info[i]->pg_running == false)
|
||||||
{
|
{
|
||||||
log_warning(_("node \"%s\" (ID: %i) unreachable, unable to pause repmgrd"),
|
log_warning(_("node \"%s\" (ID %i) unreachable, unable to pause repmgrd"),
|
||||||
cell->node_info->node_name,
|
cell->node_info->node_name,
|
||||||
cell->node_info->node_id);
|
cell->node_info->node_id);
|
||||||
i++;
|
i++;
|
||||||
@@ -4917,7 +4835,7 @@ do_standby_switchover(void)
|
|||||||
*/
|
*/
|
||||||
if (repmgrd_info[i]->running == false)
|
if (repmgrd_info[i]->running == false)
|
||||||
{
|
{
|
||||||
log_notice(_("repmgrd not running on node \"%s\" (ID: %i), not pausing"),
|
log_warning(_("repmgrd not running on node \"%s\" (ID %i)"),
|
||||||
cell->node_info->node_name,
|
cell->node_info->node_name,
|
||||||
cell->node_info->node_id);
|
cell->node_info->node_id);
|
||||||
i++;
|
i++;
|
||||||
@@ -4938,14 +4856,14 @@ do_standby_switchover(void)
|
|||||||
|
|
||||||
if (runtime_options.dry_run == true)
|
if (runtime_options.dry_run == true)
|
||||||
{
|
{
|
||||||
log_info(_("would pause repmgrd on node \"%s\" (ID: %i)"),
|
log_info(_("would pause repmgrd on node \"%s\" (ID %i)"),
|
||||||
cell->node_info->node_name,
|
cell->node_info->node_name,
|
||||||
cell->node_info->node_id);
|
cell->node_info->node_id);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* XXX check result */
|
/* XXX check result */
|
||||||
log_debug("pausing repmgrd on node \"%s\" (ID: %i)",
|
log_debug("pausing repmgrd on node \"%s\" (ID %i)",
|
||||||
cell->node_info->node_name,
|
cell->node_info->node_name,
|
||||||
cell->node_info->node_id);
|
cell->node_info->node_id);
|
||||||
|
|
||||||
@@ -5245,18 +5163,6 @@ do_standby_switchover(void)
|
|||||||
format_lsn(replication_info.last_wal_receive_lsn),
|
format_lsn(replication_info.last_wal_receive_lsn),
|
||||||
format_lsn(remote_last_checkpoint_lsn));
|
format_lsn(remote_last_checkpoint_lsn));
|
||||||
|
|
||||||
/*
|
|
||||||
* optionally add a delay before promoting the standby; this is mainly
|
|
||||||
* useful for testing (e.g. for reappearance of the original primary) and
|
|
||||||
* is not documented.
|
|
||||||
*/
|
|
||||||
if (config_file_options.promote_delay > 0)
|
|
||||||
{
|
|
||||||
log_debug("sleeping %i seconds before promoting standby",
|
|
||||||
config_file_options.promote_delay);
|
|
||||||
sleep(config_file_options.promote_delay);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Promote standby (local node).
|
* Promote standby (local node).
|
||||||
*
|
*
|
||||||
@@ -5382,21 +5288,6 @@ do_standby_switchover(void)
|
|||||||
pfree(conninfo_normalized);
|
pfree(conninfo_normalized);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* */
|
|
||||||
snprintf(node_rejoin_log, MAXPGPATH,
|
|
||||||
#if defined(__i386__) || defined(__i386)
|
|
||||||
"/tmp/node-rejoin.%u.log",
|
|
||||||
(unsigned)time(NULL)
|
|
||||||
#else
|
|
||||||
"/tmp/node-rejoin.%lu.log",
|
|
||||||
(unsigned long)time(NULL)
|
|
||||||
#endif
|
|
||||||
);
|
|
||||||
|
|
||||||
appendPQExpBuffer(&remote_command_str,
|
|
||||||
" > %s 2>&1 && echo \"1\" || echo \"0\"",
|
|
||||||
node_rejoin_log);
|
|
||||||
|
|
||||||
termPQExpBuffer(&node_rejoin_options);
|
termPQExpBuffer(&node_rejoin_options);
|
||||||
|
|
||||||
log_debug("executing:\n %s", remote_command_str.data);
|
log_debug("executing:\n %s", remote_command_str.data);
|
||||||
@@ -5410,161 +5301,78 @@ do_standby_switchover(void)
|
|||||||
|
|
||||||
termPQExpBuffer(&remote_command_str);
|
termPQExpBuffer(&remote_command_str);
|
||||||
|
|
||||||
initPQExpBuffer(&logmsg);
|
/* TODO: verify this node's record was updated correctly */
|
||||||
initPQExpBuffer(&detailmsg);
|
|
||||||
|
|
||||||
/* This is failure to execute the ssh command */
|
|
||||||
if (command_success == false)
|
if (command_success == false)
|
||||||
{
|
{
|
||||||
log_error(_("rejoin failed with error code %i"), r);
|
log_error(_("rejoin failed with error code %i"), r);
|
||||||
switchover_success = false;
|
|
||||||
|
|
||||||
appendPQExpBuffer(&logmsg,
|
|
||||||
_("unable to execute \"repmgr node rejoin\" on demotion candidate \"%s\" (ID: %i)"),
|
|
||||||
remote_node_record.node_name,
|
|
||||||
remote_node_record.node_id);
|
|
||||||
appendPQExpBufferStr(&detailmsg,
|
|
||||||
command_output.data);
|
|
||||||
|
|
||||||
|
create_event_notification_extended(local_conn,
|
||||||
|
&config_file_options,
|
||||||
|
config_file_options.node_id,
|
||||||
|
"standby_switchover",
|
||||||
|
false,
|
||||||
|
command_output.data,
|
||||||
|
&event_info);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
standy_join_status join_success = JOIN_UNKNOWN;
|
PQExpBufferData event_details;
|
||||||
|
standy_join_status join_success = check_standby_join(local_conn,
|
||||||
|
&local_node_record,
|
||||||
|
&remote_node_record);
|
||||||
|
|
||||||
/* "rempgr node rejoin" failed on the demotion candidate */
|
initPQExpBuffer(&event_details);
|
||||||
if (command_output.data[0] == '0')
|
|
||||||
|
switch (join_success) {
|
||||||
|
case JOIN_FAIL_NO_PING:
|
||||||
|
appendPQExpBuffer(&event_details,
|
||||||
|
_("node \"%s\" (ID: %i) promoted to primary, but demote node \"%s\" (ID: %i) did not beome available"),
|
||||||
|
config_file_options.node_name,
|
||||||
|
config_file_options.node_id,
|
||||||
|
remote_node_record.node_name,
|
||||||
|
remote_node_record.node_id);
|
||||||
|
switchover_success = false;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case JOIN_FAIL_NO_REPLICATION:
|
||||||
|
appendPQExpBuffer(&event_details,
|
||||||
|
_("node \"%s\" (ID: %i) promoted to primary, but demote node \"%s\" (ID: %i) did not connect to the new primary"),
|
||||||
|
config_file_options.node_name,
|
||||||
|
config_file_options.node_id,
|
||||||
|
remote_node_record.node_name,
|
||||||
|
remote_node_record.node_id);
|
||||||
|
switchover_success = false;
|
||||||
|
break;
|
||||||
|
case JOIN_SUCCESS:
|
||||||
|
appendPQExpBuffer(&event_details,
|
||||||
|
_("node \"%s\" (ID: %i) promoted to primary, node \"%s\" (ID: %i) demoted to standby"),
|
||||||
|
config_file_options.node_name,
|
||||||
|
config_file_options.node_id,
|
||||||
|
remote_node_record.node_name,
|
||||||
|
remote_node_record.node_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
create_event_notification_extended(local_conn,
|
||||||
|
&config_file_options,
|
||||||
|
config_file_options.node_id,
|
||||||
|
"standby_switchover",
|
||||||
|
switchover_success,
|
||||||
|
event_details.data,
|
||||||
|
&event_info);
|
||||||
|
if (switchover_success == true)
|
||||||
{
|
{
|
||||||
appendPQExpBuffer(&logmsg,
|
log_notice("%s", event_details.data);
|
||||||
_("execution of \"repmgr node rejoin\" on demotion candidate \"%s\" (ID: %i) failed"),
|
|
||||||
remote_node_record.node_name,
|
|
||||||
remote_node_record.node_id);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Speculatively check if the demotion candidate has been restarted, e.g. by
|
|
||||||
* an external watchdog process which isn't aware a switchover is happening.
|
|
||||||
* This falls into the category "thing outside of our control which shouldn't
|
|
||||||
* happen, but if it does, make it easier to find out what happened".
|
|
||||||
*/
|
|
||||||
remote_conn = establish_db_connection(remote_node_record.conninfo, false);
|
|
||||||
|
|
||||||
if (PQstatus(remote_conn) == CONNECTION_OK)
|
|
||||||
{
|
|
||||||
if (get_recovery_type(remote_conn) == RECTYPE_PRIMARY)
|
|
||||||
{
|
|
||||||
appendPQExpBuffer(&detailmsg,
|
|
||||||
_("PostgreSQL instance on demotion candidate \"%s\" (ID: %i) is running as a primary\n"),
|
|
||||||
remote_node_record.node_name,
|
|
||||||
remote_node_record.node_id);
|
|
||||||
log_warning("%s", detailmsg.data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PQfinish(remote_conn);
|
|
||||||
|
|
||||||
appendPQExpBuffer(&detailmsg,
|
|
||||||
"check log file \"%s\" on \"%s\" for details",
|
|
||||||
node_rejoin_log,
|
|
||||||
remote_node_record.node_name);
|
|
||||||
|
|
||||||
switchover_success = false;
|
|
||||||
join_success = JOIN_COMMAND_FAIL;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
join_success = check_standby_join(local_conn,
|
log_error("%s", event_details.data);
|
||||||
&local_node_record,
|
|
||||||
&remote_node_record);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
switch (join_success) {
|
|
||||||
case JOIN_FAIL_NO_PING:
|
|
||||||
appendPQExpBuffer(&logmsg,
|
|
||||||
_("node \"%s\" (ID: %i) promoted to primary, but demotion candidate \"%s\" (ID: %i) did not become available"),
|
|
||||||
config_file_options.node_name,
|
|
||||||
config_file_options.node_id,
|
|
||||||
remote_node_record.node_name,
|
|
||||||
remote_node_record.node_id);
|
|
||||||
|
|
||||||
switchover_success = false;
|
|
||||||
|
|
||||||
break;
|
|
||||||
case JOIN_FAIL_NO_REPLICATION:
|
|
||||||
appendPQExpBuffer(&logmsg,
|
|
||||||
_("node \"%s\" (ID: %i) promoted to primary, but demotion candidate \"%s\" (ID: %i) did not connect to the new primary"),
|
|
||||||
config_file_options.node_name,
|
|
||||||
config_file_options.node_id,
|
|
||||||
remote_node_record.node_name,
|
|
||||||
remote_node_record.node_id);
|
|
||||||
switchover_success = false;
|
|
||||||
break;
|
|
||||||
case JOIN_SUCCESS:
|
|
||||||
appendPQExpBuffer(&logmsg,
|
|
||||||
_("node \"%s\" (ID: %i) promoted to primary, node \"%s\" (ID: %i) demoted to standby"),
|
|
||||||
config_file_options.node_name,
|
|
||||||
config_file_options.node_id,
|
|
||||||
remote_node_record.node_name,
|
|
||||||
remote_node_record.node_id);
|
|
||||||
break;
|
|
||||||
/* check_standby_join() does not return this */
|
|
||||||
case JOIN_COMMAND_FAIL:
|
|
||||||
break;
|
|
||||||
/* should never happen*/
|
|
||||||
case JOIN_UNKNOWN:
|
|
||||||
appendPQExpBuffer(&logmsg,
|
|
||||||
"unable to determine success of node rejoin action for demotion candidate \"%s\" (ID: %i)",
|
|
||||||
remote_node_record.node_name,
|
|
||||||
remote_node_record.node_id);
|
|
||||||
switchover_success = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (switchover_success == false)
|
|
||||||
{
|
|
||||||
appendPQExpBuffer(&detailmsg,
|
|
||||||
"check the PostgreSQL log file on demotion candidate \"%s\" (ID: %i)",
|
|
||||||
remote_node_record.node_name,
|
|
||||||
remote_node_record.node_id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
termPQExpBuffer(&event_details);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (switchover_success == true)
|
|
||||||
{
|
|
||||||
/* TODO: verify demotion candidates's node record was updated correctly */
|
|
||||||
|
|
||||||
log_notice("%s", logmsg.data);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
log_error("%s", logmsg.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
initPQExpBuffer(&event_details);
|
|
||||||
|
|
||||||
appendPQExpBufferStr(&event_details, logmsg.data);
|
|
||||||
|
|
||||||
if (detailmsg.data[0] != '\0')
|
|
||||||
{
|
|
||||||
log_detail("%s", detailmsg.data);
|
|
||||||
appendPQExpBuffer(&event_details, "\n%s",
|
|
||||||
detailmsg.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
create_event_notification_extended(local_conn,
|
|
||||||
&config_file_options,
|
|
||||||
config_file_options.node_id,
|
|
||||||
"standby_switchover",
|
|
||||||
switchover_success,
|
|
||||||
event_details.data,
|
|
||||||
&event_info);
|
|
||||||
|
|
||||||
termPQExpBuffer(&event_details);
|
|
||||||
termPQExpBuffer(&logmsg);
|
|
||||||
termPQExpBuffer(&detailmsg);
|
|
||||||
termPQExpBuffer(&command_output);
|
termPQExpBuffer(&command_output);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If --siblings-follow specified, attempt to make them follow the new
|
* If --siblings-follow specified, attempt to make them follow the new
|
||||||
* primary
|
* primary
|
||||||
@@ -5677,7 +5485,7 @@ do_standby_switchover(void)
|
|||||||
|
|
||||||
if (repmgrd_info[i]->paused == true && runtime_options.repmgrd_force_unpause == false)
|
if (repmgrd_info[i]->paused == true && runtime_options.repmgrd_force_unpause == false)
|
||||||
{
|
{
|
||||||
log_debug("repmgrd on node \"%s\" (ID: %i) paused before switchover, --repmgrd-force-unpause not provided, not unpausing",
|
log_debug("repmgrd on node \"%s\" (ID %i) paused before switchover, --repmgrd-force-unpause not provided, not unpausing",
|
||||||
cell->node_info->node_name,
|
cell->node_info->node_name,
|
||||||
cell->node_info->node_id);
|
cell->node_info->node_id);
|
||||||
|
|
||||||
@@ -5685,7 +5493,7 @@ do_standby_switchover(void)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
log_debug("unpausing repmgrd on node \"%s\" (ID: %i)",
|
log_debug("unpausing repmgrd on node \"%s\" (ID %i)",
|
||||||
cell->node_info->node_name,
|
cell->node_info->node_name,
|
||||||
cell->node_info->node_id);
|
cell->node_info->node_id);
|
||||||
|
|
||||||
@@ -5696,7 +5504,7 @@ do_standby_switchover(void)
|
|||||||
if (repmgrd_pause(cell->node_info->conn, false) == false)
|
if (repmgrd_pause(cell->node_info->conn, false) == false)
|
||||||
{
|
{
|
||||||
item_list_append_format(&repmgrd_unpause_errors,
|
item_list_append_format(&repmgrd_unpause_errors,
|
||||||
_("unable to unpause node \"%s\" (ID: %i)"),
|
_("unable to unpause node \"%s\" (ID %i)"),
|
||||||
cell->node_info->node_name,
|
cell->node_info->node_name,
|
||||||
cell->node_info->node_id);
|
cell->node_info->node_id);
|
||||||
error_node_count++;
|
error_node_count++;
|
||||||
@@ -5705,7 +5513,7 @@ do_standby_switchover(void)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
item_list_append_format(&repmgrd_unpause_errors,
|
item_list_append_format(&repmgrd_unpause_errors,
|
||||||
_("unable to connect to node \"%s\" (ID: %i):\n%s"),
|
_("unable to connect to node \"%s\" (ID %i):\n%s"),
|
||||||
cell->node_info->node_name,
|
cell->node_info->node_name,
|
||||||
cell->node_info->node_id,
|
cell->node_info->node_id,
|
||||||
PQerrorMessage(cell->node_info->conn));
|
PQerrorMessage(cell->node_info->conn));
|
||||||
@@ -5793,18 +5601,20 @@ check_source_server()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The server version check will also serve as a sanity-check that we can
|
* If a connection was established, perform some sanity checks on the
|
||||||
* actually execute queries on this connection.
|
* provided upstream connection.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
source_server_version_num = check_server_version(source_conn, "primary", true, NULL);
|
source_server_version_num = check_server_version(source_conn, "primary", true, NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The cluster size is nice to have, but not essential to know, so only display
|
* It's not essential to know the cluster size, but useful to sanity-check
|
||||||
* something if the user has sufficient permissions to retrieve the size of
|
* we can actually run a query before going any further.
|
||||||
* all databases.
|
|
||||||
*/
|
*/
|
||||||
if (get_cluster_size(source_conn, cluster_size) == true)
|
if (get_cluster_size(source_conn, cluster_size) == false)
|
||||||
log_detail(_("current installation size is %s"),
|
exit(ERR_DB_QUERY);
|
||||||
|
|
||||||
|
log_detail(_("current installation size is %s"),
|
||||||
cluster_size);
|
cluster_size);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -6987,13 +6797,6 @@ run_basebackup(t_node_info *node_record)
|
|||||||
|
|
||||||
termPQExpBuffer(¶ms);
|
termPQExpBuffer(¶ms);
|
||||||
|
|
||||||
if (runtime_options.dry_run == true)
|
|
||||||
{
|
|
||||||
log_info(_("would execute:\n %s"), script.data);
|
|
||||||
termPQExpBuffer(&script);
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
log_info(_("executing:\n %s"), script.data);
|
log_info(_("executing:\n %s"), script.data);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -7727,7 +7530,7 @@ stop_backup:
|
|||||||
if (record_status == RECORD_FOUND)
|
if (record_status == RECORD_FOUND)
|
||||||
{
|
{
|
||||||
log_verbose(LOG_INFO,
|
log_verbose(LOG_INFO,
|
||||||
_("replication slot \"%s\" already exists on upstream node %i"),
|
_("replication slot \"%s\" aleady exists on upstream node %i"),
|
||||||
local_node_record->slot_name,
|
local_node_record->slot_name,
|
||||||
upstream_node_id);
|
upstream_node_id);
|
||||||
}
|
}
|
||||||
@@ -7779,117 +7582,6 @@ stop_backup:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Perform a call to pg_backupapi endpoint to ask barman to write the backup
|
|
||||||
* for us. This will ensure that no matter the format on-disk of new backups,
|
|
||||||
* barman will always find a way how to read and write them.
|
|
||||||
* From repmgr 4 this is only used for Barman backups.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
run_pg_backupapi(t_node_info *local_node_record)
|
|
||||||
{
|
|
||||||
int r = ERR_PGBACKUPAPI_SERVICE;
|
|
||||||
long http_return_code = 0;
|
|
||||||
short seconds_to_sleep = 3;
|
|
||||||
operation_task *task = malloc(sizeof(operation_task));
|
|
||||||
CURL *curl = curl_easy_init();
|
|
||||||
CURLcode ret;
|
|
||||||
|
|
||||||
check_pg_backupapi_standby_clone_options();
|
|
||||||
|
|
||||||
task->host = malloc(strlen(config_file_options.pg_backupapi_host)+1);
|
|
||||||
task->remote_ssh_command = malloc(strlen(config_file_options.pg_backupapi_remote_ssh_command)+1);
|
|
||||||
task->node_name = malloc(strlen(config_file_options.pg_backupapi_node_name)+1);
|
|
||||||
task->operation_type = malloc(strlen(DEFAULT_STANDBY_PG_BACKUPAPI_OP_TYPE)+1);
|
|
||||||
task->backup_id = malloc(strlen(config_file_options.pg_backupapi_backup_id)+1);
|
|
||||||
task->destination_directory = malloc(strlen(local_data_directory)+1);
|
|
||||||
|
|
||||||
task->operation_id = malloc(MAX_BUFFER_LENGTH);
|
|
||||||
task->operation_status = malloc(MAX_BUFFER_LENGTH);
|
|
||||||
|
|
||||||
strcpy(task->host, config_file_options.pg_backupapi_host);
|
|
||||||
strcpy(task->remote_ssh_command, config_file_options.pg_backupapi_remote_ssh_command);
|
|
||||||
strcpy(task->node_name, config_file_options.pg_backupapi_node_name);
|
|
||||||
strcpy(task->operation_type, DEFAULT_STANDBY_PG_BACKUPAPI_OP_TYPE);
|
|
||||||
strcpy(task->backup_id, config_file_options.pg_backupapi_backup_id);
|
|
||||||
strcpy(task->destination_directory, local_data_directory);
|
|
||||||
strcpy(task->operation_id, "\0");
|
|
||||||
|
|
||||||
ret = create_new_task(curl, task);
|
|
||||||
|
|
||||||
if ((ret != CURLE_OK) || (strlen(task->operation_id) == 0)) {
|
|
||||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_return_code);
|
|
||||||
if (499 > http_return_code && http_return_code >= 400) {
|
|
||||||
log_error("Cannot find backup '%s' for node '%s'.", task->backup_id, task->node_name);
|
|
||||||
} else {
|
|
||||||
log_error("whilst reaching out pg_backup service: %s\n", curl_easy_strerror(ret));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
log_info("Success creating the task: operation id '%s'", task->operation_id);
|
|
||||||
|
|
||||||
//We call init again because previous call included POST calls
|
|
||||||
curl_easy_cleanup(curl);
|
|
||||||
curl = curl_easy_init();
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
ret = get_status_of_operation(curl, task);
|
|
||||||
if (strlen(task->operation_status) == 0) {
|
|
||||||
log_info("Retrying...");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
log_info("status %s", task->operation_status);
|
|
||||||
}
|
|
||||||
if (strcmp(task->operation_status, "FAILED") == 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (strcmp(task->operation_status, "DONE") == 0) {
|
|
||||||
r = SUCCESS;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
sleep(seconds_to_sleep);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
curl_easy_cleanup(curl);
|
|
||||||
free(task);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* pg_backupapi mode is enabled when config_file_options.pg_backupapi_host is set hence, we
|
|
||||||
* should also check the other required variables too.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void check_pg_backupapi_standby_clone_options() {
|
|
||||||
|
|
||||||
bool error = false;
|
|
||||||
|
|
||||||
if (*config_file_options.pg_backupapi_remote_ssh_command == '\0') {
|
|
||||||
log_hint("Check config: remote ssh command is required");
|
|
||||||
error = true;
|
|
||||||
}
|
|
||||||
if (*config_file_options.pg_backupapi_node_name == '\0') {
|
|
||||||
log_hint("Check config: node name is required");
|
|
||||||
error = true;
|
|
||||||
}
|
|
||||||
if (*config_file_options.pg_backupapi_backup_id == '\0') {
|
|
||||||
log_hint("Check config: backup_id is required");
|
|
||||||
error = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error == true) {
|
|
||||||
log_error("Please fix the errors and try again");
|
|
||||||
exit(ERR_BAD_CONFIG);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
make_barman_ssh_command(char *buf)
|
make_barman_ssh_command(char *buf)
|
||||||
{
|
{
|
||||||
@@ -8268,9 +7960,9 @@ create_recovery_file(t_node_info *node_record, t_conninfo_param_list *primary_co
|
|||||||
free(escaped);
|
free(escaped);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Caller requests the generated file to be written into a buffer
|
|
||||||
*/
|
|
||||||
if (as_file == false)
|
if (as_file == false)
|
||||||
{
|
{
|
||||||
/* create file in buffer */
|
/* create file in buffer */
|
||||||
@@ -8290,17 +7982,20 @@ create_recovery_file(t_node_info *node_record, t_conninfo_param_list *primary_co
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PostgreSQL 12 and later: modify postgresql.auto.conf
|
* PostgreSQL 12 and later: modify postgresql.auto.conf
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
if (server_version_num >= 120000)
|
if (server_version_num >= 120000)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (modify_auto_conf(dest, &recovery_config) == false)
|
if (modify_auto_conf(dest, &recovery_config) == false)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (write_standby_signal(dest) == false)
|
if (write_standby_signal() == false)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -9293,7 +8988,7 @@ do_standby_help(void)
|
|||||||
printf(_(" --dry-run perform checks etc. but don't actually execute switchover\n"));
|
printf(_(" --dry-run perform checks etc. but don't actually execute switchover\n"));
|
||||||
printf(_(" -F, --force ignore warnings and continue anyway\n"));
|
printf(_(" -F, --force ignore warnings and continue anyway\n"));
|
||||||
printf(_(" --force-rewind[=VALUE] use \"pg_rewind\" to reintegrate the old primary if necessary\n"));
|
printf(_(" --force-rewind[=VALUE] use \"pg_rewind\" to reintegrate the old primary if necessary\n"));
|
||||||
printf(_(" (PostgreSQL 9.4 - provide \"pg_rewind\" path)\n"));
|
printf(_(" (9.3 and 9.4 - provide \"pg_rewind\" path)\n"));
|
||||||
|
|
||||||
printf(_(" -R, --remote-user=USERNAME database server username for SSH operations (default: \"%s\")\n"), runtime_options.username);
|
printf(_(" -R, --remote-user=USERNAME database server username for SSH operations (default: \"%s\")\n"), runtime_options.username);
|
||||||
printf(_(" -S, --superuser=USERNAME superuser to use, if repmgr user is not superuser\n"));
|
printf(_(" -S, --superuser=USERNAME superuser to use, if repmgr user is not superuser\n"));
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* repmgr-action-standby.h
|
* repmgr-action-standby.h
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
* Copyright (c) 2ndQuadrant, 2010-2020
|
||||||
*
|
*
|
||||||
* 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
|
||||||
@@ -30,6 +30,6 @@ extern void do_standby_help(void);
|
|||||||
|
|
||||||
extern bool do_standby_follow_internal(PGconn *primary_conn, PGconn *follow_target_conn, t_node_info *follow_target_node_record, PQExpBufferData *output, int general_error_code, int *error_code);
|
extern bool do_standby_follow_internal(PGconn *primary_conn, PGconn *follow_target_conn, t_node_info *follow_target_node_record, PQExpBufferData *output, int general_error_code, int *error_code);
|
||||||
|
|
||||||
void check_pg_backupapi_standby_clone_options(void);
|
|
||||||
|
|
||||||
#endif /* _REPMGR_ACTION_STANDBY_H_ */
|
#endif /* _REPMGR_ACTION_STANDBY_H_ */
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Implements witness actions for the repmgr command line utility
|
* Implements witness actions for the repmgr command line utility
|
||||||
*
|
*
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
* Copyright (c) 2ndQuadrant, 2010-2020
|
||||||
*
|
*
|
||||||
* 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
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* repmgr-action-witness.h
|
* repmgr-action-witness.h
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
* Copyright (c) 2ndQuadrant, 2010-2020
|
||||||
*
|
*
|
||||||
* 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
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* repmgr-client-global.h
|
* repmgr-client-global.h
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
* Copyright (c) 2ndQuadrant, 2010-2020
|
||||||
*
|
*
|
||||||
* 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
|
||||||
@@ -120,7 +120,6 @@ typedef struct
|
|||||||
bool missing_slots;
|
bool missing_slots;
|
||||||
bool has_passfile;
|
bool has_passfile;
|
||||||
bool replication_connection;
|
bool replication_connection;
|
||||||
bool repmgrd;
|
|
||||||
bool data_directory_config;
|
bool data_directory_config;
|
||||||
bool replication_config_owner;
|
bool replication_config_owner;
|
||||||
bool db_connection;
|
bool db_connection;
|
||||||
@@ -176,7 +175,7 @@ typedef struct
|
|||||||
/* "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, false, false, false, false, false, false, false, false, false, false, \
|
||||||
/* "node rejoin" options */ \
|
/* "node rejoin" options */ \
|
||||||
"", \
|
"", \
|
||||||
/* "node service" options */ \
|
/* "node service" options */ \
|
||||||
@@ -193,8 +192,7 @@ typedef struct
|
|||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
barman,
|
barman,
|
||||||
pg_basebackup,
|
pg_basebackup
|
||||||
pg_backupapi
|
|
||||||
} standy_clone_mode;
|
} standy_clone_mode;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
@@ -221,9 +219,7 @@ typedef enum
|
|||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
JOIN_UNKNOWN = -1,
|
|
||||||
JOIN_SUCCESS,
|
JOIN_SUCCESS,
|
||||||
JOIN_COMMAND_FAIL,
|
|
||||||
JOIN_FAIL_NO_PING,
|
JOIN_FAIL_NO_PING,
|
||||||
JOIN_FAIL_NO_REPLICATION
|
JOIN_FAIL_NO_REPLICATION
|
||||||
} standy_join_status;
|
} standy_join_status;
|
||||||
@@ -286,8 +282,8 @@ 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 bool can_use_pg_rewind(PGconn *conn, const char *data_directory, PQExpBufferData *reason);
|
||||||
extern void make_standby_signal_path(const char *data_dir, char *buf);
|
extern void make_standby_signal_path(char *buf);
|
||||||
extern bool write_standby_signal(const char *data_dir);
|
extern bool write_standby_signal(void);
|
||||||
|
|
||||||
extern bool create_replication_slot(PGconn *conn, char *slot_name, t_node_info *upstream_node_record, PQExpBufferData *error_msg);
|
extern bool create_replication_slot(PGconn *conn, char *slot_name, t_node_info *upstream_node_record, PQExpBufferData *error_msg);
|
||||||
extern bool drop_replication_slot_if_exists(PGconn *conn, int node_id, char *slot_name);
|
extern bool drop_replication_slot_if_exists(PGconn *conn, int node_id, char *slot_name);
|
||||||
|
|||||||
249
repmgr-client.c
249
repmgr-client.c
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* repmgr-client.c - Command interpreter for the repmgr package
|
* repmgr-client.c - Command interpreter for the repmgr package
|
||||||
*
|
*
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
* Copyright (c) 2ndQuadrant, 2010-2020
|
||||||
*
|
*
|
||||||
* This module is a command-line utility to easily setup a cluster of
|
* This module is a command-line utility to easily setup a cluster of
|
||||||
* hot standby servers for an HA environment
|
* hot standby servers for an HA environment
|
||||||
@@ -51,7 +51,6 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <pwd.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
@@ -90,22 +89,17 @@ char pg_bindir[MAXPGPATH] = "";
|
|||||||
*/
|
*/
|
||||||
t_node_info target_node_info = T_NODE_INFO_INITIALIZER;
|
t_node_info target_node_info = T_NODE_INFO_INITIALIZER;
|
||||||
|
|
||||||
/* set by the first call to _determine_replication_slot_user() */
|
/* used by create_replication_slot() */
|
||||||
static t_user_type ReplicationSlotUser = USER_TYPE_UNKNOWN;
|
static t_user_type ReplicationSlotUser = USER_TYPE_UNKNOWN;
|
||||||
|
|
||||||
/* Collate command line errors and warnings here for friendlier reporting */
|
/* Collate command line errors and warnings here for friendlier reporting */
|
||||||
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 void _determine_replication_slot_user(PGconn *conn,
|
static void _determine_replication_slot_user(PGconn *conn,
|
||||||
t_node_info *upstream_node_record,
|
t_node_info *upstream_node_record,
|
||||||
char **replication_user);
|
char **replication_user);
|
||||||
|
|
||||||
static PGconn *_get_replication_slot_connection(PGconn *conn,
|
|
||||||
char *replication_user,
|
|
||||||
bool *use_replication_protocol);
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int argc, char **argv)
|
main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
@@ -128,7 +122,7 @@ main(int argc, char **argv)
|
|||||||
/*
|
/*
|
||||||
* Tell the logger we're a command-line program - this will ensure any
|
* Tell the logger we're a command-line program - this will ensure any
|
||||||
* output logged before the logger is initialized will be formatted
|
* output logged before the logger is initialized will be formatted
|
||||||
* correctly. Can be overridden with "--log-to-file".
|
* correctly. Can be overriden with "--log-to-file".
|
||||||
*/
|
*/
|
||||||
logger_output_mode = OM_COMMAND_LINE;
|
logger_output_mode = OM_COMMAND_LINE;
|
||||||
|
|
||||||
@@ -555,10 +549,6 @@ main(int argc, char **argv)
|
|||||||
runtime_options.data_directory_config = true;
|
runtime_options.data_directory_config = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OPT_REPMGRD:
|
|
||||||
runtime_options.repmgrd = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OPT_REPLICATION_CONFIG_OWNER:
|
case OPT_REPLICATION_CONFIG_OWNER:
|
||||||
runtime_options.replication_config_owner = true;
|
runtime_options.replication_config_owner = true;
|
||||||
break;
|
break;
|
||||||
@@ -2745,7 +2735,7 @@ do_help(void)
|
|||||||
*
|
*
|
||||||
* Note:
|
* Note:
|
||||||
* This is one of two places where superuser rights are required.
|
* This is one of two places where superuser rights are required.
|
||||||
* We should also consider possible scenarios where a non-superuser
|
* We should also consider possible scenarious where a non-superuser
|
||||||
* has sufficient privileges to install the extension.
|
* has sufficient privileges to install the extension.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -2780,7 +2770,7 @@ create_repmgr_extension(PGconn *conn)
|
|||||||
log_detail(_("version %s is installed but newer version %s is available"),
|
log_detail(_("version %s is installed but newer version %s is available"),
|
||||||
extversions.installed_version,
|
extversions.installed_version,
|
||||||
extversions.default_version);
|
extversions.default_version);
|
||||||
log_hint(_("update the installed extension version by executing \"ALTER EXTENSION repmgr UPDATE\" in the repmgr database"));
|
log_hint(_("update the installed extension version by executing \"ALTER EXTENSION repmgr UPDATE\""));
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
case REPMGR_INSTALLED:
|
case REPMGR_INSTALLED:
|
||||||
@@ -2946,7 +2936,7 @@ check_server_version(PGconn *conn, char *server_type, bool exit_on_error, char *
|
|||||||
* PostgreSQL from a particular PostgreSQL release onwards (e.g. 4.4 with PostgreSQL
|
* PostgreSQL from a particular PostgreSQL release onwards (e.g. 4.4 with PostgreSQL
|
||||||
* 12 and later due to recovery.conf removal), set MAX_UNSUPPORTED_VERSION and
|
* 12 and later due to recovery.conf removal), set MAX_UNSUPPORTED_VERSION and
|
||||||
* MAX_UNSUPPORTED_VERSION_NUM in "repmgr.h" to define the first PostgreSQL
|
* MAX_UNSUPPORTED_VERSION_NUM in "repmgr.h" to define the first PostgreSQL
|
||||||
* version which can't be supported.
|
* version which can't be suppored.
|
||||||
*/
|
*/
|
||||||
#ifdef MAX_UNSUPPORTED_VERSION_NUM
|
#ifdef MAX_UNSUPPORTED_VERSION_NUM
|
||||||
if (conn_server_version_num >= MAX_UNSUPPORTED_VERSION_NUM)
|
if (conn_server_version_num >= MAX_UNSUPPORTED_VERSION_NUM)
|
||||||
@@ -3096,14 +3086,9 @@ get_standby_clone_mode(void)
|
|||||||
|
|
||||||
if (*config_file_options.barman_host != '\0' && runtime_options.without_barman == false)
|
if (*config_file_options.barman_host != '\0' && runtime_options.without_barman == false)
|
||||||
mode = barman;
|
mode = barman;
|
||||||
else {
|
else
|
||||||
if (*config_file_options.pg_backupapi_host != '\0') {
|
mode = pg_basebackup;
|
||||||
log_info("Attempting to use `pg_backupapi` new restore mode");
|
|
||||||
mode = pg_backupapi;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
mode = pg_basebackup;
|
|
||||||
}
|
|
||||||
return mode;
|
return mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3197,11 +3182,6 @@ copy_remote_files(char *host, char *remote_user, char *remote_path,
|
|||||||
" --exclude=pg_xlog/* --exclude=pg_log/*");
|
" --exclude=pg_xlog/* --exclude=pg_log/*");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* From PostgreSQL 15, the core server no longer uses pg_stat_tmp,
|
|
||||||
* but some extensions (e.g. pg_stat_statements) may still do, so
|
|
||||||
* keep excluding it.
|
|
||||||
*/
|
|
||||||
appendPQExpBufferStr(&rsync_flags,
|
appendPQExpBufferStr(&rsync_flags,
|
||||||
" --exclude=pg_stat_tmp/*");
|
" --exclude=pg_stat_tmp/*");
|
||||||
|
|
||||||
@@ -3639,8 +3619,8 @@ can_use_pg_rewind(PGconn *conn, const char *data_directory, PQExpBufferData *rea
|
|||||||
/* "full_page_writes" must be on in any case */
|
/* "full_page_writes" must be on in any case */
|
||||||
if (guc_set(conn, "full_page_writes", "=", "off"))
|
if (guc_set(conn, "full_page_writes", "=", "off"))
|
||||||
{
|
{
|
||||||
appendPQExpBufferStr(reason,
|
appendPQExpBuffer(reason,
|
||||||
_("\"full_page_writes\" must be set to \"on\""));
|
_("\"full_page_writes\" must be set to \"on\""));
|
||||||
|
|
||||||
can_use = false;
|
can_use = false;
|
||||||
}
|
}
|
||||||
@@ -3658,18 +3638,18 @@ can_use_pg_rewind(PGconn *conn, const char *data_directory, PQExpBufferData *rea
|
|||||||
if (data_checksum_version == UNKNOWN_DATA_CHECKSUM_VERSION)
|
if (data_checksum_version == UNKNOWN_DATA_CHECKSUM_VERSION)
|
||||||
{
|
{
|
||||||
if (can_use == false)
|
if (can_use == false)
|
||||||
appendPQExpBufferStr(reason, "; ");
|
appendPQExpBuffer(reason, "; ");
|
||||||
|
|
||||||
appendPQExpBufferStr(reason,
|
appendPQExpBuffer(reason,
|
||||||
_("\"wal_log_hints\" is set to \"off\" but unable to determine data checksum version"));
|
_("\"wal_log_hints\" is set to \"off\" but unable to determine data checksum version"));
|
||||||
can_use = false;
|
can_use = false;
|
||||||
}
|
}
|
||||||
else if (data_checksum_version == 0)
|
else if (data_checksum_version == 0)
|
||||||
{
|
{
|
||||||
if (can_use == false)
|
if (can_use == false)
|
||||||
appendPQExpBufferStr(reason, "; ");
|
appendPQExpBuffer(reason, "; ");
|
||||||
|
|
||||||
appendPQExpBufferStr(reason,
|
appendPQExpBuffer(reason,
|
||||||
_("\"wal_log_hints\" is set to \"off\" and data checksums are disabled"));
|
_("\"wal_log_hints\" is set to \"off\" and data checksums are disabled"));
|
||||||
|
|
||||||
can_use = false;
|
can_use = false;
|
||||||
@@ -3681,11 +3661,11 @@ can_use_pg_rewind(PGconn *conn, const char *data_directory, PQExpBufferData *rea
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
make_standby_signal_path(const char *data_dir, char *buf)
|
make_standby_signal_path(char *buf)
|
||||||
{
|
{
|
||||||
snprintf(buf, MAXPGPATH,
|
snprintf(buf, MAXPGPATH,
|
||||||
"%s/%s",
|
"%s/%s",
|
||||||
data_dir,
|
config_file_options.data_directory,
|
||||||
STANDBY_SIGNAL_FILE);
|
STANDBY_SIGNAL_FILE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3693,15 +3673,13 @@ make_standby_signal_path(const char *data_dir, char *buf)
|
|||||||
* create standby.signal (PostgreSQL 12 and later)
|
* create standby.signal (PostgreSQL 12 and later)
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
write_standby_signal(const char *data_dir)
|
write_standby_signal(void)
|
||||||
{
|
{
|
||||||
char standby_signal_file_path[MAXPGPATH] = "";
|
char standby_signal_file_path[MAXPGPATH] = "";
|
||||||
FILE *file;
|
FILE *file;
|
||||||
mode_t um;
|
mode_t um;
|
||||||
|
|
||||||
Assert(data_dir != NULL);
|
make_standby_signal_path(standby_signal_file_path);
|
||||||
|
|
||||||
make_standby_signal_path(data_dir, standby_signal_file_path);
|
|
||||||
|
|
||||||
/* Set umask to 0600 */
|
/* Set umask to 0600 */
|
||||||
um = umask((~(S_IRUSR | S_IWUSR)) & (S_IRWXG | S_IRWXO));
|
um = umask((~(S_IRUSR | S_IWUSR)) & (S_IRWXG | S_IRWXO));
|
||||||
@@ -3749,7 +3727,6 @@ create_replication_slot(PGconn *conn, char *slot_name, t_node_info *upstream_nod
|
|||||||
char *replication_user = NULL;
|
char *replication_user = NULL;
|
||||||
|
|
||||||
_determine_replication_slot_user(conn, upstream_node_record, &replication_user);
|
_determine_replication_slot_user(conn, upstream_node_record, &replication_user);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If called in --dry-run context, if the replication slot user is not the
|
* If called in --dry-run context, if the replication slot user is not the
|
||||||
* repmgr user, attempt to validate the connection.
|
* repmgr user, attempt to validate the connection.
|
||||||
@@ -3761,7 +3738,7 @@ create_replication_slot(PGconn *conn, char *slot_name, t_node_info *upstream_nod
|
|||||||
case USER_TYPE_UNKNOWN:
|
case USER_TYPE_UNKNOWN:
|
||||||
log_error("unable to determine user for replication slot creation");
|
log_error("unable to determine user for replication slot creation");
|
||||||
return false;
|
return false;
|
||||||
case REPMGR_USER:
|
case REPMGR_USER:
|
||||||
log_info(_("replication slots will be created by user \"%s\""),
|
log_info(_("replication slots will be created by user \"%s\""),
|
||||||
PQuser(conn));
|
PQuser(conn));
|
||||||
return true;
|
return true;
|
||||||
@@ -3807,12 +3784,65 @@ create_replication_slot(PGconn *conn, char *slot_name, t_node_info *upstream_nod
|
|||||||
PQfinish(superuser_conn);
|
PQfinish(superuser_conn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
slot_conn = _get_replication_slot_connection(conn, replication_user, &use_replication_protocol);
|
/*
|
||||||
|
* If we can't create a replication slot with the connection provided to
|
||||||
|
* the function, create an connection with appropriate permissions.
|
||||||
|
*/
|
||||||
|
switch (ReplicationSlotUser)
|
||||||
|
{
|
||||||
|
case USER_TYPE_UNKNOWN:
|
||||||
|
log_error("unable to determine user for replication slot creation");
|
||||||
|
return false;
|
||||||
|
case REPMGR_USER:
|
||||||
|
slot_conn = conn;
|
||||||
|
log_info(_("creating replication slot as user \"%s\""),
|
||||||
|
PQuser(conn));
|
||||||
|
break;
|
||||||
|
|
||||||
if (slot_conn == NULL)
|
case REPLICATION_USER_NODE:
|
||||||
return false;
|
case REPLICATION_USER_OPT:
|
||||||
|
{
|
||||||
|
slot_conn = duplicate_connection(conn,
|
||||||
|
replication_user,
|
||||||
|
true);
|
||||||
|
if (slot_conn == NULL || PQstatus(slot_conn) != CONNECTION_OK)
|
||||||
|
{
|
||||||
|
log_error(_("unable to create replication connection as user \"%s\""),
|
||||||
|
runtime_options.replication_user);
|
||||||
|
log_detail("%s", PQerrorMessage(slot_conn));
|
||||||
|
|
||||||
|
PQfinish(slot_conn);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
use_replication_protocol = true;
|
||||||
|
log_info(_("creating replication slot as replication user \"%s\""),
|
||||||
|
replication_user);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SUPERUSER:
|
||||||
|
{
|
||||||
|
slot_conn = duplicate_connection(conn,
|
||||||
|
runtime_options.superuser,
|
||||||
|
false);
|
||||||
|
if (slot_conn == NULL || PQstatus(slot_conn )!= CONNECTION_OK)
|
||||||
|
{
|
||||||
|
log_error(_("unable to create super connection as user \"%s\""),
|
||||||
|
runtime_options.superuser);
|
||||||
|
log_detail("%s", PQerrorMessage(slot_conn));
|
||||||
|
|
||||||
|
PQfinish(slot_conn);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
log_info(_("creating replication slot as superuser \"%s\""),
|
||||||
|
runtime_options.superuser);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (use_replication_protocol == true)
|
if (use_replication_protocol == true)
|
||||||
{
|
{
|
||||||
@@ -3855,53 +3885,34 @@ drop_replication_slot_if_exists(PGconn *conn, int node_id, char *slot_name)
|
|||||||
|
|
||||||
if (record_status != RECORD_FOUND)
|
if (record_status != RECORD_FOUND)
|
||||||
{
|
{
|
||||||
/* no slot, no problem */
|
/* this is not a bad good thing */
|
||||||
log_verbose(LOG_INFO,
|
log_verbose(LOG_INFO,
|
||||||
_("slot \"%s\" does not exist on node %i, nothing to remove"),
|
_("slot \"%s\" does not exist on node %i, nothing to remove"),
|
||||||
slot_name, node_id);
|
slot_name, node_id);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (slot_info.active == true)
|
if (slot_info.active == false)
|
||||||
{
|
{
|
||||||
/*
|
if (drop_replication_slot_sql(conn, slot_name) == true)
|
||||||
* If an active replication slot exists, bail out as we have a problem
|
|
||||||
* we can't solve here.
|
|
||||||
*/
|
|
||||||
log_warning(_("replication slot \"%s\" is still active on node %i"), slot_name, node_id);
|
|
||||||
success = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Create the appropriate connection with which to drop the slot
|
|
||||||
*/
|
|
||||||
|
|
||||||
bool use_replication_protocol = false;
|
|
||||||
PGconn *slot_conn = _get_replication_slot_connection(conn,
|
|
||||||
replication_user,
|
|
||||||
&use_replication_protocol);
|
|
||||||
|
|
||||||
if (use_replication_protocol == true)
|
|
||||||
{
|
|
||||||
success = drop_replication_slot_replprot(slot_conn, slot_name);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
success = drop_replication_slot_sql(slot_conn, slot_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (success == true)
|
|
||||||
{
|
{
|
||||||
log_notice(_("replication slot \"%s\" deleted on node %i"), slot_name, node_id);
|
log_notice(_("replication slot \"%s\" deleted on node %i"), slot_name, node_id);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
log_error(_("unable to delete replication slot \"%s\" on node %i"), slot_name, node_id);
|
log_error(_("unable to delete replication slot \"%s\" on node %i"), slot_name, node_id);
|
||||||
|
success = false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (slot_conn != conn)
|
/*
|
||||||
PQfinish(slot_conn);
|
* If an 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);
|
||||||
|
success = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
@@ -3963,88 +3974,10 @@ _determine_replication_slot_user(PGconn *conn, t_node_info *upstream_node_record
|
|||||||
ReplicationSlotUser = REPLICATION_USER_NODE;
|
ReplicationSlotUser = REPLICATION_USER_NODE;
|
||||||
*replication_user = upstream_node_record->repluser;
|
*replication_user = upstream_node_record->repluser;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
/* This should never happen */
|
|
||||||
log_error("unable to determine replication slot user");
|
|
||||||
if (upstream_node_record != NULL)
|
|
||||||
{
|
|
||||||
log_debug("%i %s %s", upstream_node_record->node_id, upstream_node_record->repluser, PQuser(conn));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
log_debug("upstream_node_record not provided");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static PGconn *
|
|
||||||
_get_replication_slot_connection(PGconn *conn, char *replication_user, bool *use_replication_protocol)
|
|
||||||
{
|
|
||||||
PGconn *slot_conn = NULL;
|
|
||||||
/*
|
|
||||||
* If we can't create a replication slot with the connection provided to
|
|
||||||
* the function, create an connection with appropriate permissions.
|
|
||||||
*/
|
|
||||||
switch (ReplicationSlotUser)
|
|
||||||
{
|
|
||||||
case USER_TYPE_UNKNOWN:
|
|
||||||
log_error("unable to determine user for managing replication slots");
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
case REPMGR_USER:
|
|
||||||
slot_conn = conn;
|
|
||||||
log_verbose(LOG_INFO, _("managing replication slot as user \"%s\""),
|
|
||||||
PQuser(conn));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case REPLICATION_USER_NODE:
|
|
||||||
case REPLICATION_USER_OPT:
|
|
||||||
{
|
|
||||||
slot_conn = duplicate_connection(conn,
|
|
||||||
replication_user,
|
|
||||||
true);
|
|
||||||
if (slot_conn == NULL || PQstatus(slot_conn) != CONNECTION_OK)
|
|
||||||
{
|
|
||||||
log_error(_("unable to manage replication connection as replication user \"%s\""),
|
|
||||||
runtime_options.replication_user);
|
|
||||||
log_detail("%s", PQerrorMessage(slot_conn));
|
|
||||||
|
|
||||||
PQfinish(slot_conn);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
*use_replication_protocol = true;
|
|
||||||
log_verbose(LOG_INFO, _("managing replication slot as replication user \"%s\""),
|
|
||||||
replication_user);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SUPERUSER:
|
|
||||||
{
|
|
||||||
slot_conn = duplicate_connection(conn,
|
|
||||||
runtime_options.superuser,
|
|
||||||
false);
|
|
||||||
if (slot_conn == NULL || PQstatus(slot_conn )!= CONNECTION_OK)
|
|
||||||
{
|
|
||||||
log_error(_("unable to create superuser connection as user \"%s\""),
|
|
||||||
runtime_options.superuser);
|
|
||||||
log_detail("%s", PQerrorMessage(slot_conn));
|
|
||||||
|
|
||||||
PQfinish(slot_conn);
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
log_verbose(LOG_INFO, _("creating replication slot as superuser \"%s\""),
|
|
||||||
runtime_options.superuser);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return slot_conn;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
check_replication_slots_available(int node_id, PGconn* conn)
|
check_replication_slots_available(int node_id, PGconn* conn)
|
||||||
{
|
{
|
||||||
@@ -4153,7 +4086,7 @@ check_standby_join(PGconn *upstream_conn, t_node_info *upstream_node_record, t_n
|
|||||||
|
|
||||||
if (node_attached == NODE_NOT_ATTACHED)
|
if (node_attached == NODE_NOT_ATTACHED)
|
||||||
{
|
{
|
||||||
log_detail(_("node \"%s\" (ID: %i) is currently attached to its upstream node in state \"%s\""),
|
log_detail(_("node \"%s\" (ID: %i) is currrently attached to its upstream node in state \"%s\""),
|
||||||
upstream_node_record->node_name,
|
upstream_node_record->node_name,
|
||||||
standby_node_record->node_id,
|
standby_node_record->node_id,
|
||||||
node_state);
|
node_state);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* repmgr-client.h
|
* repmgr-client.h
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
* Copyright (c) 2ndQuadrant, 2010-2020
|
||||||
*
|
*
|
||||||
* 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
|
||||||
@@ -100,7 +100,6 @@
|
|||||||
#define OPT_DB_CONNECTION 1047
|
#define OPT_DB_CONNECTION 1047
|
||||||
#define OPT_VERIFY_BACKUP 1048
|
#define OPT_VERIFY_BACKUP 1048
|
||||||
#define OPT_RECOVERY_MIN_APPLY_DELAY 1049
|
#define OPT_RECOVERY_MIN_APPLY_DELAY 1049
|
||||||
#define OPT_REPMGRD 1050
|
|
||||||
|
|
||||||
/* These options are for internal use only */
|
/* These options are for internal use only */
|
||||||
#define OPT_CONFIG_ARCHIVE_DIR 2001
|
#define OPT_CONFIG_ARCHIVE_DIR 2001
|
||||||
@@ -194,7 +193,6 @@ static struct option long_options[] =
|
|||||||
{"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},
|
{"missing-slots", no_argument, NULL, OPT_MISSING_SLOTS},
|
||||||
{"repmgrd", no_argument, NULL, OPT_REPMGRD},
|
|
||||||
{"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},
|
||||||
{"data-directory-config", no_argument, NULL, OPT_DATA_DIRECTORY_CONFIG},
|
{"data-directory-config", no_argument, NULL, OPT_DATA_DIRECTORY_CONFIG},
|
||||||
|
|||||||
125
repmgr.c
125
repmgr.c
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* repmgr.c - repmgr extension
|
* repmgr.c - repmgr extension
|
||||||
*
|
*
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
* Copyright (c) 2ndQuadrant, 2010-2020
|
||||||
*
|
*
|
||||||
* This is the actual extension code; see repmgr-client.c for the code which
|
* This is the actual extension code; see repmgr-client.c for the code which
|
||||||
* generates the repmgr binary
|
* generates the repmgr binary
|
||||||
@@ -80,36 +80,67 @@ typedef struct repmgrdSharedState
|
|||||||
|
|
||||||
static repmgrdSharedState *shared_state = NULL;
|
static repmgrdSharedState *shared_state = NULL;
|
||||||
|
|
||||||
#if (PG_VERSION_NUM >= 150000)
|
|
||||||
static shmem_request_hook_type prev_shmem_request_hook = NULL;
|
|
||||||
#endif
|
|
||||||
static shmem_startup_hook_type prev_shmem_startup_hook = NULL;
|
static shmem_startup_hook_type prev_shmem_startup_hook = NULL;
|
||||||
|
|
||||||
void _PG_init(void);
|
|
||||||
|
|
||||||
#if (PG_VERSION_NUM >= 150000)
|
void _PG_init(void);
|
||||||
static void repmgr_shmem_request(void);
|
void _PG_fini(void);
|
||||||
#endif
|
|
||||||
static void repmgr_shmem_startup(void);
|
static void repmgr_shmem_startup(void);
|
||||||
|
|
||||||
PG_FUNCTION_INFO_V1(repmgr_set_local_node_id);
|
Datum set_local_node_id(PG_FUNCTION_ARGS);
|
||||||
PG_FUNCTION_INFO_V1(repmgr_get_local_node_id);
|
PG_FUNCTION_INFO_V1(set_local_node_id);
|
||||||
PG_FUNCTION_INFO_V1(repmgr_standby_set_last_updated);
|
|
||||||
PG_FUNCTION_INFO_V1(repmgr_standby_get_last_updated);
|
Datum get_local_node_id(PG_FUNCTION_ARGS);
|
||||||
PG_FUNCTION_INFO_V1(repmgr_set_upstream_last_seen);
|
PG_FUNCTION_INFO_V1(get_local_node_id);
|
||||||
PG_FUNCTION_INFO_V1(repmgr_get_upstream_last_seen);
|
|
||||||
PG_FUNCTION_INFO_V1(repmgr_get_upstream_node_id);
|
Datum standby_set_last_updated(PG_FUNCTION_ARGS);
|
||||||
PG_FUNCTION_INFO_V1(repmgr_set_upstream_node_id);
|
PG_FUNCTION_INFO_V1(standby_set_last_updated);
|
||||||
PG_FUNCTION_INFO_V1(repmgr_notify_follow_primary);
|
|
||||||
PG_FUNCTION_INFO_V1(repmgr_get_new_primary);
|
Datum standby_get_last_updated(PG_FUNCTION_ARGS);
|
||||||
PG_FUNCTION_INFO_V1(repmgr_reset_voting_status);
|
PG_FUNCTION_INFO_V1(standby_get_last_updated);
|
||||||
|
|
||||||
|
Datum set_upstream_last_seen(PG_FUNCTION_ARGS);
|
||||||
|
PG_FUNCTION_INFO_V1(set_upstream_last_seen);
|
||||||
|
|
||||||
|
Datum get_upstream_last_seen(PG_FUNCTION_ARGS);
|
||||||
|
PG_FUNCTION_INFO_V1(get_upstream_last_seen);
|
||||||
|
|
||||||
|
Datum get_upstream_node_id(PG_FUNCTION_ARGS);
|
||||||
|
PG_FUNCTION_INFO_V1(get_upstream_node_id);
|
||||||
|
|
||||||
|
Datum set_upstream_node_id(PG_FUNCTION_ARGS);
|
||||||
|
PG_FUNCTION_INFO_V1(set_upstream_node_id);
|
||||||
|
|
||||||
|
Datum notify_follow_primary(PG_FUNCTION_ARGS);
|
||||||
|
PG_FUNCTION_INFO_V1(notify_follow_primary);
|
||||||
|
|
||||||
|
Datum get_new_primary(PG_FUNCTION_ARGS);
|
||||||
|
PG_FUNCTION_INFO_V1(get_new_primary);
|
||||||
|
|
||||||
|
Datum reset_voting_status(PG_FUNCTION_ARGS);
|
||||||
|
PG_FUNCTION_INFO_V1(reset_voting_status);
|
||||||
|
|
||||||
|
Datum set_repmgrd_pid(PG_FUNCTION_ARGS);
|
||||||
PG_FUNCTION_INFO_V1(set_repmgrd_pid);
|
PG_FUNCTION_INFO_V1(set_repmgrd_pid);
|
||||||
|
|
||||||
|
Datum get_repmgrd_pid(PG_FUNCTION_ARGS);
|
||||||
PG_FUNCTION_INFO_V1(get_repmgrd_pid);
|
PG_FUNCTION_INFO_V1(get_repmgrd_pid);
|
||||||
|
|
||||||
|
Datum get_repmgrd_pidfile(PG_FUNCTION_ARGS);
|
||||||
PG_FUNCTION_INFO_V1(get_repmgrd_pidfile);
|
PG_FUNCTION_INFO_V1(get_repmgrd_pidfile);
|
||||||
|
|
||||||
|
Datum repmgrd_is_running(PG_FUNCTION_ARGS);
|
||||||
PG_FUNCTION_INFO_V1(repmgrd_is_running);
|
PG_FUNCTION_INFO_V1(repmgrd_is_running);
|
||||||
|
|
||||||
|
Datum repmgrd_pause(PG_FUNCTION_ARGS);
|
||||||
PG_FUNCTION_INFO_V1(repmgrd_pause);
|
PG_FUNCTION_INFO_V1(repmgrd_pause);
|
||||||
|
|
||||||
|
Datum repmgrd_is_paused(PG_FUNCTION_ARGS);
|
||||||
PG_FUNCTION_INFO_V1(repmgrd_is_paused);
|
PG_FUNCTION_INFO_V1(repmgrd_is_paused);
|
||||||
PG_FUNCTION_INFO_V1(repmgr_get_wal_receiver_pid);
|
|
||||||
|
Datum get_wal_receiver_pid(PG_FUNCTION_ARGS);
|
||||||
|
PG_FUNCTION_INFO_V1(get_wal_receiver_pid);
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -121,47 +152,35 @@ _PG_init(void)
|
|||||||
if (!process_shared_preload_libraries_in_progress)
|
if (!process_shared_preload_libraries_in_progress)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#if (PG_VERSION_NUM < 150000)
|
|
||||||
RequestAddinShmemSpace(MAXALIGN(sizeof(repmgrdSharedState)));
|
RequestAddinShmemSpace(MAXALIGN(sizeof(repmgrdSharedState)));
|
||||||
|
|
||||||
#if (PG_VERSION_NUM >= 90600)
|
#if (PG_VERSION_NUM >= 90600)
|
||||||
RequestNamedLWLockTranche(TRANCHE_NAME, 1);
|
RequestNamedLWLockTranche(TRANCHE_NAME, 1);
|
||||||
#else
|
#else
|
||||||
RequestAddinLWLocks(1);
|
RequestAddinLWLocks(1);
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Install hooks.
|
* Install hooks.
|
||||||
*/
|
*/
|
||||||
#if (PG_VERSION_NUM >= 150000)
|
|
||||||
prev_shmem_request_hook = shmem_request_hook;
|
|
||||||
shmem_request_hook = repmgr_shmem_request;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
prev_shmem_startup_hook = shmem_startup_hook;
|
prev_shmem_startup_hook = shmem_startup_hook;
|
||||||
shmem_startup_hook = repmgr_shmem_startup;
|
shmem_startup_hook = repmgr_shmem_startup;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (PG_VERSION_NUM >= 150000)
|
|
||||||
/*
|
/*
|
||||||
* shmem_requst_hook: request shared memory
|
* Module unload callback
|
||||||
*/
|
*/
|
||||||
static void
|
void
|
||||||
repmgr_shmem_request(void)
|
_PG_fini(void)
|
||||||
{
|
{
|
||||||
if (prev_shmem_request_hook)
|
/* Uninstall hook */
|
||||||
prev_shmem_request_hook();
|
shmem_startup_hook = prev_shmem_startup_hook;
|
||||||
|
|
||||||
RequestAddinShmemSpace(MAXALIGN(sizeof(repmgrdSharedState)));
|
|
||||||
|
|
||||||
RequestNamedLWLockTranche(TRANCHE_NAME, 1);
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* shmem_startup hook: allocate or attach to shared memory
|
* shmem_startup hook: allocate or attach to shared memory,
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
repmgr_shmem_startup(void)
|
repmgr_shmem_startup(void)
|
||||||
@@ -175,7 +194,7 @@ repmgr_shmem_startup(void)
|
|||||||
shared_state = NULL;
|
shared_state = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create or attach to the shared memory state
|
* Create or attach to the shared memory state, including hash table
|
||||||
*/
|
*/
|
||||||
LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE);
|
LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE);
|
||||||
|
|
||||||
@@ -214,7 +233,7 @@ repmgr_shmem_startup(void)
|
|||||||
/* ==================== */
|
/* ==================== */
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
repmgr_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 stored_node_id = UNKNOWN_NODE_ID;
|
||||||
@@ -284,7 +303,7 @@ repmgr_set_local_node_id(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
repmgr_get_local_node_id(PG_FUNCTION_ARGS)
|
get_local_node_id(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
int local_node_id = UNKNOWN_NODE_ID;
|
int local_node_id = UNKNOWN_NODE_ID;
|
||||||
|
|
||||||
@@ -301,7 +320,7 @@ repmgr_get_local_node_id(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
/* update and return last updated with current timestamp */
|
/* update and return last updated with current timestamp */
|
||||||
Datum
|
Datum
|
||||||
repmgr_standby_set_last_updated(PG_FUNCTION_ARGS)
|
standby_set_last_updated(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
TimestampTz last_updated = GetCurrentTimestamp();
|
TimestampTz last_updated = GetCurrentTimestamp();
|
||||||
|
|
||||||
@@ -318,7 +337,7 @@ repmgr_standby_set_last_updated(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
/* get last updated timestamp */
|
/* get last updated timestamp */
|
||||||
Datum
|
Datum
|
||||||
repmgr_standby_get_last_updated(PG_FUNCTION_ARGS)
|
standby_get_last_updated(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
TimestampTz last_updated;
|
TimestampTz last_updated;
|
||||||
|
|
||||||
@@ -335,7 +354,7 @@ repmgr_standby_get_last_updated(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
repmgr_set_upstream_last_seen(PG_FUNCTION_ARGS)
|
set_upstream_last_seen(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
int upstream_node_id = UNKNOWN_NODE_ID;
|
int upstream_node_id = UNKNOWN_NODE_ID;
|
||||||
|
|
||||||
@@ -358,7 +377,7 @@ repmgr_set_upstream_last_seen(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
repmgr_get_upstream_last_seen(PG_FUNCTION_ARGS)
|
get_upstream_last_seen(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
long secs;
|
long secs;
|
||||||
int microsecs;
|
int microsecs;
|
||||||
@@ -392,7 +411,7 @@ repmgr_get_upstream_last_seen(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
repmgr_get_upstream_node_id(PG_FUNCTION_ARGS)
|
get_upstream_node_id(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
int upstream_node_id = UNKNOWN_NODE_ID;
|
int upstream_node_id = UNKNOWN_NODE_ID;
|
||||||
|
|
||||||
@@ -407,7 +426,7 @@ repmgr_get_upstream_node_id(PG_FUNCTION_ARGS)
|
|||||||
}
|
}
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
repmgr_set_upstream_node_id(PG_FUNCTION_ARGS)
|
set_upstream_node_id(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
int upstream_node_id = UNKNOWN_NODE_ID;
|
int upstream_node_id = UNKNOWN_NODE_ID;
|
||||||
int local_node_id = UNKNOWN_NODE_ID;
|
int local_node_id = UNKNOWN_NODE_ID;
|
||||||
@@ -443,7 +462,7 @@ repmgr_set_upstream_node_id(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
repmgr_notify_follow_primary(PG_FUNCTION_ARGS)
|
notify_follow_primary(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
int primary_node_id = UNKNOWN_NODE_ID;
|
int primary_node_id = UNKNOWN_NODE_ID;
|
||||||
|
|
||||||
@@ -486,7 +505,7 @@ repmgr_notify_follow_primary(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
repmgr_get_new_primary(PG_FUNCTION_ARGS)
|
get_new_primary(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
int new_primary_node_id = UNKNOWN_NODE_ID;
|
int new_primary_node_id = UNKNOWN_NODE_ID;
|
||||||
|
|
||||||
@@ -508,7 +527,7 @@ repmgr_get_new_primary(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
repmgr_reset_voting_status(PG_FUNCTION_ARGS)
|
reset_voting_status(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
if (!shared_state)
|
if (!shared_state)
|
||||||
PG_RETURN_NULL();
|
PG_RETURN_NULL();
|
||||||
@@ -716,7 +735,7 @@ repmgrd_is_paused(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
|
|
||||||
Datum
|
Datum
|
||||||
repmgr_get_wal_receiver_pid(PG_FUNCTION_ARGS)
|
get_wal_receiver_pid(PG_FUNCTION_ARGS)
|
||||||
{
|
{
|
||||||
int wal_receiver_pid;
|
int wal_receiver_pid;
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,7 @@
|
|||||||
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
||||||
|
|
||||||
#replication_user='repmgr' # User to make replication connections with, if not set
|
#replication_user='repmgr' # User to make replication connections with, if not set
|
||||||
# defaults to the user defined in "conninfo".
|
# defaults to the user defined in "conninfo".
|
||||||
|
|
||||||
#replication_type='physical' # Must "physical" (the default).
|
#replication_type='physical' # Must "physical" (the default).
|
||||||
|
|
||||||
@@ -238,7 +238,7 @@ ssh_options='-q -o ConnectTimeout=10' # Options to append to "ssh"
|
|||||||
|
|
||||||
#primary_follow_timeout=60 # The max length of time (in seconds) to wait
|
#primary_follow_timeout=60 # The max length of time (in seconds) to wait
|
||||||
# for the new primary to become available
|
# for the new primary to become available
|
||||||
#standby_follow_timeout=30 # The max length of time (in seconds) to wait
|
#standby_follow_timeout=15 # The max length of time (in seconds) to wait
|
||||||
# for the standby to connect to the primary
|
# for the standby to connect to the primary
|
||||||
#standby_follow_restart=false # Restart the standby instead of sending a SIGHUP
|
#standby_follow_restart=false # Restart the standby instead of sending a SIGHUP
|
||||||
# (only for PostgreSQL 13 and later)
|
# (only for PostgreSQL 13 and later)
|
||||||
@@ -301,7 +301,7 @@ ssh_options='-q -o ConnectTimeout=10' # Options to append to "ssh"
|
|||||||
|
|
||||||
#connection_check_type=ping # How to check availability of the upstream node; valid options:
|
#connection_check_type=ping # How to check availability of the upstream node; valid options:
|
||||||
# 'ping': use PQping() to check if the node is accepting connections
|
# 'ping': use PQping() to check if the node is accepting connections
|
||||||
# 'connection': attempt to make a new connection to the node
|
# 'connection': execute a throwaway query on the current connection
|
||||||
# 'query': execute an SQL statement on the node via the existing connection
|
# 'query': execute an SQL statement on the node via the existing connection
|
||||||
#reconnect_attempts=6 # Number of attempts which will be made to reconnect to an unreachable
|
#reconnect_attempts=6 # Number of attempts which will be made to reconnect to an unreachable
|
||||||
# primary (or other upstream node)
|
# primary (or other upstream node)
|
||||||
@@ -314,7 +314,7 @@ ssh_options='-q -o ConnectTimeout=10' # Options to append to "ssh"
|
|||||||
#follow_command='' # command repmgrd executes when instructing a standby to follow a new primary;
|
#follow_command='' # command repmgrd executes when instructing a standby to follow a new primary;
|
||||||
# use something like:
|
# use something like:
|
||||||
#
|
#
|
||||||
# repmgr standby follow -f /etc/repmgr.conf --upstream-node-id=%n
|
# repmgr standby follow -f /etc/repmgr.conf -W --upstream-node-id=%n
|
||||||
#
|
#
|
||||||
#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,
|
||||||
@@ -323,7 +323,7 @@ ssh_options='-q -o ConnectTimeout=10' # Options to append to "ssh"
|
|||||||
# for the the local node to restart and become ready to accept connections after
|
# for the the local node to restart and become ready to accept connections after
|
||||||
# executing "follow_command" (defaults to the value set in "standby_reconnect_timeout")
|
# executing "follow_command" (defaults to the value set in "standby_reconnect_timeout")
|
||||||
|
|
||||||
#monitoring_history=no # Whether to write monitoring data to the "monitoring_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
|
||||||
#degraded_monitoring_timeout=-1 # Interval (in seconds) after which repmgrd will terminate if the
|
#degraded_monitoring_timeout=-1 # Interval (in seconds) after which repmgrd will terminate if the
|
||||||
# server(s) being monitored are no longer available. -1 (default)
|
# server(s) being monitored are no longer available. -1 (default)
|
||||||
@@ -337,7 +337,6 @@ ssh_options='-q -o ConnectTimeout=10' # Options to append to "ssh"
|
|||||||
# "--no-pid-file" will force PID file creation to be skipped.
|
# "--no-pid-file" will force PID file creation to be skipped.
|
||||||
# Note: there is normally no need to set this, particularly if
|
# Note: there is normally no need to set this, particularly if
|
||||||
# repmgr was installed from packages.
|
# repmgr was installed from packages.
|
||||||
#repmgrd_exit_on_inactive_node=false # If "true", and the node record is marked as "inactive", abort repmgrd startup
|
|
||||||
#standby_disconnect_on_failover=false # If "true", in a failover situation wait for all standbys to
|
#standby_disconnect_on_failover=false # If "true", in a failover situation wait for all standbys to
|
||||||
# disconnect their WAL receivers before electing a new primary
|
# disconnect their WAL receivers before electing a new primary
|
||||||
# (PostgreSQL 9.5 and later only; repmgr user must be a superuser for this)
|
# (PostgreSQL 9.5 and later only; repmgr user must be a superuser for this)
|
||||||
@@ -398,7 +397,7 @@ ssh_options='-q -o ConnectTimeout=10' # Options to append to "ssh"
|
|||||||
#
|
#
|
||||||
# Debian/Ubuntu users: use "sudo pg_ctlcluster" to execute service control commands.
|
# Debian/Ubuntu users: use "sudo pg_ctlcluster" to execute service control commands.
|
||||||
#
|
#
|
||||||
# For more details, see: https://repmgr.org/docs/current/configuration-file-service-commands.html
|
# For more details, see: https://repmgr.org/docs/current/configuration-service-commands.html
|
||||||
|
|
||||||
#service_start_command = ''
|
#service_start_command = ''
|
||||||
#service_stop_command = ''
|
#service_stop_command = ''
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
# repmgr extension
|
# repmgr extension
|
||||||
comment = 'Replication manager for PostgreSQL'
|
comment = 'Replication manager for PostgreSQL'
|
||||||
default_version = '5.4'
|
default_version = '5.2'
|
||||||
module_pathname = '$libdir/repmgr'
|
module_pathname = '$libdir/repmgr'
|
||||||
relocatable = false
|
relocatable = false
|
||||||
schema = repmgr
|
schema = repmgr
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
4
repmgr.h
4
repmgr.h
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* repmgr.h
|
* repmgr.h
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
* Copyright (c) 2ndQuadrant, 2010-2020
|
||||||
*
|
*
|
||||||
* 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
|
||||||
@@ -116,7 +116,6 @@
|
|||||||
#define DEFAULT_STANDBY_FOLLOW_TIMEOUT 30 /* seconds */
|
#define DEFAULT_STANDBY_FOLLOW_TIMEOUT 30 /* seconds */
|
||||||
#define DEFAULT_STANDBY_FOLLOW_RESTART false
|
#define DEFAULT_STANDBY_FOLLOW_RESTART false
|
||||||
#define DEFAULT_SHUTDOWN_CHECK_TIMEOUT 60 /* seconds */
|
#define DEFAULT_SHUTDOWN_CHECK_TIMEOUT 60 /* seconds */
|
||||||
#define DEFAULT_STANDBY_PG_BACKUPAPI_OP_TYPE "recovery"
|
|
||||||
#define DEFAULT_STANDBY_RECONNECT_TIMEOUT 60 /* seconds */
|
#define DEFAULT_STANDBY_RECONNECT_TIMEOUT 60 /* seconds */
|
||||||
#define DEFAULT_NODE_REJOIN_TIMEOUT 60 /* seconds */
|
#define DEFAULT_NODE_REJOIN_TIMEOUT 60 /* seconds */
|
||||||
#define DEFAULT_ARCHIVE_READY_WARNING 16 /* WAL files */
|
#define DEFAULT_ARCHIVE_READY_WARNING 16 /* WAL files */
|
||||||
@@ -136,7 +135,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_REPMGRD_STANDBY_STARTUP_TIMEOUT -1 /*seconds */
|
#define DEFAULT_REPMGRD_STANDBY_STARTUP_TIMEOUT -1 /*seconds */
|
||||||
#define DEFAULT_REPMGRD_EXIT_ON_INACTIVE_NODE false,
|
|
||||||
#define DEFAULT_STANDBY_DISCONNECT_ON_FAILOVER false
|
#define DEFAULT_STANDBY_DISCONNECT_ON_FAILOVER false
|
||||||
#define DEFAULT_SIBLING_NODES_DISCONNECT_TIMEOUT 30 /* seconds */
|
#define DEFAULT_SIBLING_NODES_DISCONNECT_TIMEOUT 30 /* seconds */
|
||||||
#define DEFAULT_CONNECTION_CHECK_TYPE CHECK_PING
|
#define DEFAULT_CONNECTION_CHECK_TYPE CHECK_PING
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
#define REPMGR_VERSION_DATE ""
|
#define REPMGR_VERSION_DATE ""
|
||||||
#define REPMGR_VERSION "5.4.1"
|
#define REPMGR_VERSION "5.2.1"
|
||||||
#define REPMGR_VERSION_NUM 50401
|
#define REPMGR_VERSION_NUM 50201
|
||||||
#define REPMGR_EXTENSION_VERSION "5.4"
|
#define REPMGR_RELEASE_DATE "2020-12-07"
|
||||||
#define REPMGR_EXTENSION_NUM 50400
|
|
||||||
#define REPMGR_RELEASE_DATE "2023-07-04"
|
|
||||||
#define PG_ACTUAL_VERSION_NUM
|
#define PG_ACTUAL_VERSION_NUM
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* repmgrd-physical.c - physical (streaming) replication functionality for repmgrd
|
* repmgrd-physical.c - physical (streaming) replication functionality for repmgrd
|
||||||
*
|
*
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
* Copyright (c) 2ndQuadrant, 2010-2020
|
||||||
*
|
*
|
||||||
* 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
|
||||||
@@ -169,126 +169,45 @@ handle_sigint_physical(SIGNAL_ARGS)
|
|||||||
/* perform some sanity checks on the node's configuration */
|
/* perform some sanity checks on the node's configuration */
|
||||||
|
|
||||||
void
|
void
|
||||||
do_physical_node_check(PGconn *conn)
|
do_physical_node_check(void)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* If node record is "inactive"; if not, attempt to set it to "active".
|
* Check if node record is active - if not, and `failover=automatic`, the
|
||||||
|
* node won't be considered as a promotion candidate; this often happens
|
||||||
|
* when a failed primary is recloned and the node was not re-registered,
|
||||||
|
* giving the impression failover capability is there when it's not. In
|
||||||
|
* this case abort with an error and a hint about registering.
|
||||||
*
|
*
|
||||||
* Usually it will have become inactive due to e.g. a standby being shut down
|
* If `failover=manual`, repmgrd can continue to passively monitor the
|
||||||
* while repmgrd was running in an unpaused state. In this case it's
|
* node, but we should nevertheless issue a warning and the same hint.
|
||||||
* perfectly reasonable to automatically mark the node as "active".
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (local_node_info.active == false)
|
if (local_node_info.active == false)
|
||||||
{
|
{
|
||||||
char *hint = "Check that \"repmgr (primary|standby) register\" was executed for this node";
|
char *hint = "Check that \"repmgr (primary|standby) register\" was executed for this node";
|
||||||
RecoveryType recovery_type = get_recovery_type(conn);
|
|
||||||
|
|
||||||
/*
|
switch (config_file_options.failover)
|
||||||
* If the local node's recovery status is incompatible with its registered
|
|
||||||
* status, e.g. registered as primary but running as a standby, refuse to start.
|
|
||||||
*
|
|
||||||
* This typically happens when a failed primary is recloned but the node was not
|
|
||||||
* re-registered, leaving the cluster in a potentially ambiguous state. In
|
|
||||||
* this case it would not be possible or desirable to attempt to set the
|
|
||||||
* node to active; the user should ensure the cluster is in the correct state.
|
|
||||||
*/
|
|
||||||
if (recovery_type != RECTYPE_UNKNOWN && local_node_info.type != UNKNOWN)
|
|
||||||
{
|
{
|
||||||
bool require_reregister = false;
|
/* "failover" is an enum, all values should be covered here */
|
||||||
PQExpBufferData event_details;
|
|
||||||
initPQExpBuffer(&event_details);
|
|
||||||
|
|
||||||
if (recovery_type == RECTYPE_STANDBY && local_node_info.type != STANDBY)
|
case FAILOVER_AUTOMATIC:
|
||||||
{
|
log_error(_("this node is marked as inactive and cannot be used as a failover target"));
|
||||||
appendPQExpBuffer(&event_details,
|
|
||||||
_("node is registered as a %s but running as a standby"),
|
|
||||||
get_node_type_string(local_node_info.type));
|
|
||||||
|
|
||||||
require_reregister = true;
|
|
||||||
}
|
|
||||||
else if (recovery_type == RECTYPE_PRIMARY && local_node_info.type == STANDBY)
|
|
||||||
{
|
|
||||||
log_error(_("node is registered as a standby but running as a %s"), get_node_type_string(local_node_info.type));
|
|
||||||
require_reregister = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (require_reregister == true)
|
|
||||||
{
|
|
||||||
log_error("%s", event_details.data);
|
|
||||||
log_hint(_("%s"), hint);
|
log_hint(_("%s"), hint);
|
||||||
|
|
||||||
create_event_notification(NULL,
|
create_event_notification(NULL,
|
||||||
&config_file_options,
|
&config_file_options,
|
||||||
config_file_options.node_id,
|
config_file_options.node_id,
|
||||||
"repmgrd_start",
|
"repmgrd_shutdown",
|
||||||
false,
|
false,
|
||||||
event_details.data);
|
"node is inactive and cannot be used as a failover target");
|
||||||
|
|
||||||
termPQExpBuffer(&event_details);
|
|
||||||
terminate(ERR_BAD_CONFIG);
|
terminate(ERR_BAD_CONFIG);
|
||||||
}
|
break;
|
||||||
|
|
||||||
termPQExpBuffer(&event_details);
|
case FAILOVER_MANUAL:
|
||||||
}
|
log_warning(_("this node is marked as inactive and will be passively monitored only"));
|
||||||
|
log_hint(_("%s"), hint);
|
||||||
/*
|
break;
|
||||||
* Attempt to set node record active (unless explicitly configured not to)
|
|
||||||
*/
|
|
||||||
log_notice(_("setting node record for node \"%s\" (ID: %i) to \"active\""),
|
|
||||||
local_node_info.node_name,
|
|
||||||
local_node_info.node_id);
|
|
||||||
|
|
||||||
if (config_file_options.repmgrd_exit_on_inactive_node == false)
|
|
||||||
{
|
|
||||||
PGconn *primary_conn = get_primary_connection(conn, NULL, NULL);
|
|
||||||
bool success = true;
|
|
||||||
|
|
||||||
if (PQstatus(primary_conn) != CONNECTION_OK)
|
|
||||||
{
|
|
||||||
log_error(_("unable to connect to the primary node to activate the node record"));
|
|
||||||
success = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
success = update_node_record_set_active(primary_conn, local_node_info.node_id, true);
|
|
||||||
PQfinish(primary_conn);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (success == true)
|
|
||||||
{
|
|
||||||
local_node_info.active = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Corner-case where it was not possible to set the node to "active"
|
|
||||||
*/
|
|
||||||
if (local_node_info.active == false)
|
|
||||||
{
|
|
||||||
switch (config_file_options.failover)
|
|
||||||
{
|
|
||||||
/* "failover" is an enum, all values should be covered here */
|
|
||||||
|
|
||||||
case FAILOVER_AUTOMATIC:
|
|
||||||
log_error(_("this node is marked as inactive and cannot be used as a failover target"));
|
|
||||||
log_hint(_("%s"), hint);
|
|
||||||
|
|
||||||
create_event_notification(NULL,
|
|
||||||
&config_file_options,
|
|
||||||
config_file_options.node_id,
|
|
||||||
"repmgrd_start",
|
|
||||||
false,
|
|
||||||
"node is inactive and cannot be used as a failover target");
|
|
||||||
|
|
||||||
terminate(ERR_BAD_CONFIG);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FAILOVER_MANUAL:
|
|
||||||
log_warning(_("this node is marked as inactive and will be passively monitored only"));
|
|
||||||
log_hint(_("%s"), hint);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -585,7 +504,6 @@ monitor_streaming_primary(void)
|
|||||||
|
|
||||||
if (is_server_available(local_node_info.conninfo) == true)
|
if (is_server_available(local_node_info.conninfo) == true)
|
||||||
{
|
{
|
||||||
close_connection(&local_conn);
|
|
||||||
local_conn = establish_db_connection(local_node_info.conninfo, false);
|
local_conn = establish_db_connection(local_node_info.conninfo, false);
|
||||||
|
|
||||||
if (PQstatus(local_conn) != CONNECTION_OK)
|
if (PQstatus(local_conn) != CONNECTION_OK)
|
||||||
@@ -819,7 +737,7 @@ check_primary_status(int degraded_monitoring_elapsed)
|
|||||||
/* refresh our copy of the node record from the primary */
|
/* refresh our copy of the node record from the primary */
|
||||||
record_status = get_node_record(new_primary_conn, config_file_options.node_id, &local_node_info);
|
record_status = get_node_record(new_primary_conn, config_file_options.node_id, &local_node_info);
|
||||||
|
|
||||||
/* this is unlikely to happen */
|
/* this is unlikley to happen */
|
||||||
if (record_status != RECORD_FOUND)
|
if (record_status != RECORD_FOUND)
|
||||||
{
|
{
|
||||||
log_warning(_("unable to retrieve local node record from primary node %i"), primary_node_id);
|
log_warning(_("unable to retrieve local node record from primary node %i"), primary_node_id);
|
||||||
@@ -1193,7 +1111,7 @@ execute_child_nodes_disconnect_command(NodeInfoList *db_child_node_records, t_ch
|
|||||||
/* calculate number of connected child nodes */
|
/* calculate number of connected child nodes */
|
||||||
for (cell = db_child_node_records->head; cell; cell = cell->next)
|
for (cell = db_child_node_records->head; cell; cell = cell->next)
|
||||||
{
|
{
|
||||||
/* exclude witness server from total, if necessary */
|
/* exclude witness server from total, if necessay */
|
||||||
if (config_file_options.child_nodes_connected_include_witness == false &&
|
if (config_file_options.child_nodes_connected_include_witness == false &&
|
||||||
cell->node_info->type == WITNESS)
|
cell->node_info->type == WITNESS)
|
||||||
continue;
|
continue;
|
||||||
@@ -1231,7 +1149,7 @@ execute_child_nodes_disconnect_command(NodeInfoList *db_child_node_records, t_ch
|
|||||||
instr_time current_time = current_time_base;
|
instr_time current_time = current_time_base;
|
||||||
int seconds_since_detached;
|
int seconds_since_detached;
|
||||||
|
|
||||||
/* exclude witness server from calculation, if requested */
|
/* exclude witness server from calculatin if neccessary */
|
||||||
if (config_file_options.child_nodes_connected_include_witness == false &&
|
if (config_file_options.child_nodes_connected_include_witness == false &&
|
||||||
child_node_rec->type == WITNESS)
|
child_node_rec->type == WITNESS)
|
||||||
continue;
|
continue;
|
||||||
@@ -1587,22 +1505,22 @@ monitor_streaming_standby(void)
|
|||||||
/* TODO: possibly add pre-action event here */
|
/* TODO: possibly add pre-action event here */
|
||||||
if (upstream_node_info.type == STANDBY)
|
if (upstream_node_info.type == STANDBY)
|
||||||
{
|
{
|
||||||
create_event_notification(primary_conn,
|
create_event_record(primary_conn,
|
||||||
&config_file_options,
|
&config_file_options,
|
||||||
config_file_options.node_id,
|
config_file_options.node_id,
|
||||||
"repmgrd_upstream_disconnect",
|
"repmgrd_upstream_disconnect",
|
||||||
true,
|
true,
|
||||||
event_details.data);
|
event_details.data);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* primary connection lost - script notification only */
|
/* primary connection lost - script notification only */
|
||||||
create_event_notification(NULL,
|
create_event_record(NULL,
|
||||||
&config_file_options,
|
&config_file_options,
|
||||||
config_file_options.node_id,
|
config_file_options.node_id,
|
||||||
"repmgrd_upstream_disconnect",
|
"repmgrd_upstream_disconnect",
|
||||||
true,
|
true,
|
||||||
event_details.data);
|
event_details.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
log_warning("%s", event_details.data);
|
log_warning("%s", event_details.data);
|
||||||
@@ -1814,10 +1732,7 @@ monitor_streaming_standby(void)
|
|||||||
if (upstream_check_result == true)
|
if (upstream_check_result == true)
|
||||||
{
|
{
|
||||||
if (config_file_options.connection_check_type != CHECK_QUERY)
|
if (config_file_options.connection_check_type != CHECK_QUERY)
|
||||||
{
|
|
||||||
close_connection(&upstream_conn);
|
|
||||||
upstream_conn = establish_db_connection(upstream_node_info.conninfo, false);
|
upstream_conn = establish_db_connection(upstream_node_info.conninfo, false);
|
||||||
}
|
|
||||||
|
|
||||||
if (PQstatus(upstream_conn) == CONNECTION_OK)
|
if (PQstatus(upstream_conn) == CONNECTION_OK)
|
||||||
{
|
{
|
||||||
@@ -1898,7 +1813,6 @@ monitor_streaming_standby(void)
|
|||||||
int former_upstream_node_id = local_node_info.upstream_node_id;
|
int former_upstream_node_id = local_node_info.upstream_node_id;
|
||||||
NodeInfoList sibling_nodes = T_NODE_INFO_LIST_INITIALIZER;
|
NodeInfoList sibling_nodes = T_NODE_INFO_LIST_INITIALIZER;
|
||||||
PQExpBufferData event_details;
|
PQExpBufferData event_details;
|
||||||
t_event_info event_info = T_EVENT_INFO_INITIALIZER;
|
|
||||||
|
|
||||||
update_node_record_set_primary(local_conn, local_node_info.node_id);
|
update_node_record_set_primary(local_conn, local_node_info.node_id);
|
||||||
record_status = get_node_record(local_conn, local_node_info.node_id, &local_node_info);
|
record_status = get_node_record(local_conn, local_node_info.node_id, &local_node_info);
|
||||||
@@ -1911,16 +1825,12 @@ monitor_streaming_standby(void)
|
|||||||
initPQExpBuffer(&event_details);
|
initPQExpBuffer(&event_details);
|
||||||
appendPQExpBufferStr(&event_details,
|
appendPQExpBufferStr(&event_details,
|
||||||
_("promotion command failed but promotion completed successfully"));
|
_("promotion command failed but promotion completed successfully"));
|
||||||
|
create_event_notification(local_conn,
|
||||||
event_info.node_id = former_upstream_node_id;
|
&config_file_options,
|
||||||
|
local_node_info.node_id,
|
||||||
create_event_notification_extended(local_conn,
|
"repmgrd_failover_promote",
|
||||||
&config_file_options,
|
true,
|
||||||
local_node_info.node_id,
|
event_details.data);
|
||||||
"repmgrd_failover_promote",
|
|
||||||
true,
|
|
||||||
event_details.data,
|
|
||||||
&event_info);
|
|
||||||
|
|
||||||
termPQExpBuffer(&event_details);
|
termPQExpBuffer(&event_details);
|
||||||
|
|
||||||
@@ -2382,29 +2292,6 @@ monitor_streaming_witness(void)
|
|||||||
log_warning(_("unable to retrieve node record from primary"));
|
log_warning(_("unable to retrieve node record from primary"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* refresh local node record from the primary */
|
|
||||||
record_status = get_node_record(primary_conn, config_file_options.node_id, &local_node_info);
|
|
||||||
|
|
||||||
if (record_status != RECORD_FOUND)
|
|
||||||
{
|
|
||||||
log_error(_("no metadata record found for this node on the current primary - terminating"));
|
|
||||||
log_hint(_("check that 'repmgr witness register' was executed for this node"));
|
|
||||||
close_connection(&primary_conn);
|
|
||||||
close_connection(&local_conn);
|
|
||||||
terminate(ERR_BAD_CONFIG);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* It's possible that the primary changed while the witness repmgrd was not
|
|
||||||
* running. This does not affect the functionality of the witness repmgrd, but
|
|
||||||
* does mean outdated node metadata will be displayed, so update that.
|
|
||||||
*/
|
|
||||||
if (local_node_info.upstream_node_id != primary_node_id)
|
|
||||||
{
|
|
||||||
update_node_record_set_upstream(primary_conn, local_node_info.node_id, primary_node_id);
|
|
||||||
local_node_info.upstream_node_id = primary_node_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
initPQExpBuffer(&event_details);
|
initPQExpBuffer(&event_details);
|
||||||
|
|
||||||
appendPQExpBuffer(&event_details,
|
appendPQExpBuffer(&event_details,
|
||||||
@@ -2493,12 +2380,12 @@ monitor_streaming_witness(void)
|
|||||||
_("unable to connect to primary node \"%s\" (ID: %i)"),
|
_("unable to connect to primary node \"%s\" (ID: %i)"),
|
||||||
upstream_node_info.node_name, upstream_node_info.node_id);
|
upstream_node_info.node_name, upstream_node_info.node_id);
|
||||||
|
|
||||||
create_event_notification(NULL,
|
create_event_record(NULL,
|
||||||
&config_file_options,
|
&config_file_options,
|
||||||
config_file_options.node_id,
|
config_file_options.node_id,
|
||||||
"repmgrd_upstream_disconnect",
|
"repmgrd_upstream_disconnect",
|
||||||
true,
|
true,
|
||||||
event_details.data);
|
event_details.data);
|
||||||
termPQExpBuffer(&event_details);
|
termPQExpBuffer(&event_details);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2573,10 +2460,8 @@ monitor_streaming_witness(void)
|
|||||||
if (check_upstream_connection(&primary_conn, upstream_node_info.conninfo, NULL) == true)
|
if (check_upstream_connection(&primary_conn, upstream_node_info.conninfo, NULL) == true)
|
||||||
{
|
{
|
||||||
if (config_file_options.connection_check_type != CHECK_QUERY)
|
if (config_file_options.connection_check_type != CHECK_QUERY)
|
||||||
{
|
|
||||||
close_connection(&primary_conn);
|
|
||||||
primary_conn = establish_db_connection(upstream_node_info.conninfo, false);
|
primary_conn = establish_db_connection(upstream_node_info.conninfo, false);
|
||||||
}
|
|
||||||
if (PQstatus(primary_conn) == CONNECTION_OK)
|
if (PQstatus(primary_conn) == CONNECTION_OK)
|
||||||
{
|
{
|
||||||
PQExpBufferData event_details;
|
PQExpBufferData event_details;
|
||||||
@@ -2873,7 +2758,6 @@ do_primary_failover(void)
|
|||||||
bool final_result = false;
|
bool final_result = false;
|
||||||
NodeInfoList sibling_nodes = T_NODE_INFO_LIST_INITIALIZER;
|
NodeInfoList sibling_nodes = T_NODE_INFO_LIST_INITIALIZER;
|
||||||
int new_primary_id = UNKNOWN_NODE_ID;
|
int new_primary_id = UNKNOWN_NODE_ID;
|
||||||
bool standby_disconnect_on_failover = false;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Double-check status of the local connection
|
* Double-check status of the local connection
|
||||||
@@ -2886,20 +2770,20 @@ do_primary_failover(void)
|
|||||||
*/
|
*/
|
||||||
if (config_file_options.standby_disconnect_on_failover == true)
|
if (config_file_options.standby_disconnect_on_failover == true)
|
||||||
{
|
{
|
||||||
/*
|
NodeInfoListCell *cell = NULL;
|
||||||
* Determine whether we can actually disable the walsender; this depends
|
NodeInfoList check_sibling_nodes = T_NODE_INFO_LIST_INITIALIZER;
|
||||||
* on PostgreSQL version and user permissions.
|
int i;
|
||||||
*/
|
|
||||||
standby_disconnect_on_failover = can_disable_walsender(local_conn);
|
|
||||||
|
|
||||||
if (standby_disconnect_on_failover == true)
|
bool sibling_node_wal_receiver_connected = false;
|
||||||
|
|
||||||
|
if (PQserverVersion(local_conn) < 90500)
|
||||||
|
{
|
||||||
|
log_warning(_("\"standby_disconnect_on_failover\" specified, but not available for this PostgreSQL version"));
|
||||||
|
/* TODO: format server version */
|
||||||
|
log_detail(_("available from PostgreSQL 9.5, this PostgreSQL version is %i"), PQserverVersion(local_conn));
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
NodeInfoListCell *cell = NULL;
|
|
||||||
NodeInfoList check_sibling_nodes = T_NODE_INFO_LIST_INITIALIZER;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
bool sibling_node_wal_receiver_connected = false;
|
|
||||||
|
|
||||||
disable_wal_receiver(local_conn);
|
disable_wal_receiver(local_conn);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2983,7 +2867,7 @@ do_primary_failover(void)
|
|||||||
log_debug("election result: %s", _print_election_result(election_result));
|
log_debug("election result: %s", _print_election_result(election_result));
|
||||||
|
|
||||||
/* Reenable WAL receiver, if disabled */
|
/* Reenable WAL receiver, if disabled */
|
||||||
if (standby_disconnect_on_failover == true)
|
if (config_file_options.standby_disconnect_on_failover == true)
|
||||||
{
|
{
|
||||||
/* adjust "wal_retrieve_retry_interval" but don't wait for WAL receiver to start */
|
/* adjust "wal_retrieve_retry_interval" but don't wait for WAL receiver to start */
|
||||||
enable_wal_receiver(local_conn, false);
|
enable_wal_receiver(local_conn, false);
|
||||||
@@ -3091,6 +2975,7 @@ do_primary_failover(void)
|
|||||||
|
|
||||||
t_node_info new_primary = T_NODE_INFO_INITIALIZER;
|
t_node_info new_primary = T_NODE_INFO_INITIALIZER;
|
||||||
RecordStatus record_status = RECORD_NOT_FOUND;
|
RecordStatus record_status = RECORD_NOT_FOUND;
|
||||||
|
PGconn *new_primary_conn;
|
||||||
|
|
||||||
record_status = get_node_record(local_conn, new_primary_id, &new_primary);
|
record_status = get_node_record(local_conn, new_primary_id, &new_primary);
|
||||||
|
|
||||||
@@ -3102,7 +2987,6 @@ do_primary_failover(void)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
PQExpBufferData event_details;
|
PQExpBufferData event_details;
|
||||||
PGconn *new_primary_conn;
|
|
||||||
|
|
||||||
initPQExpBuffer(&event_details);
|
initPQExpBuffer(&event_details);
|
||||||
appendPQExpBuffer(&event_details,
|
appendPQExpBuffer(&event_details,
|
||||||
@@ -3123,6 +3007,7 @@ do_primary_failover(void)
|
|||||||
event_details.data);
|
event_details.data);
|
||||||
close_connection(&new_primary_conn);
|
close_connection(&new_primary_conn);
|
||||||
termPQExpBuffer(&event_details);
|
termPQExpBuffer(&event_details);
|
||||||
|
|
||||||
}
|
}
|
||||||
failover_state = FAILOVER_STATE_REQUIRES_MANUAL_FAILOVER;
|
failover_state = FAILOVER_STATE_REQUIRES_MANUAL_FAILOVER;
|
||||||
}
|
}
|
||||||
@@ -3369,7 +3254,7 @@ update_monitoring_history(void)
|
|||||||
*
|
*
|
||||||
* Attach cascaded standby to another node, currently the primary.
|
* Attach cascaded standby to another node, currently the primary.
|
||||||
*
|
*
|
||||||
* Note that in contrast to a primary failover, where one of the downstream
|
* Note that in contrast to a primary failover, where one of the downstrean
|
||||||
* standby nodes will become a primary, a cascaded standby failover (where the
|
* standby nodes will become a primary, a cascaded standby failover (where the
|
||||||
* upstream standby has gone away) is "just" a case of attaching the standby to
|
* upstream standby has gone away) is "just" a case of attaching the standby to
|
||||||
* another node.
|
* another node.
|
||||||
@@ -3789,7 +3674,6 @@ promote_self(void)
|
|||||||
|
|
||||||
{
|
{
|
||||||
PQExpBufferData event_details;
|
PQExpBufferData event_details;
|
||||||
t_event_info event_info = T_EVENT_INFO_INITIALIZER;
|
|
||||||
|
|
||||||
/* update own internal node record */
|
/* update own internal node record */
|
||||||
record_status = get_node_record(local_conn, local_node_info.node_id, &local_node_info);
|
record_status = get_node_record(local_conn, local_node_info.node_id, &local_node_info);
|
||||||
@@ -3806,16 +3690,13 @@ promote_self(void)
|
|||||||
failed_primary.node_name,
|
failed_primary.node_name,
|
||||||
failed_primary.node_id);
|
failed_primary.node_id);
|
||||||
|
|
||||||
event_info.node_id = failed_primary.node_id;
|
|
||||||
|
|
||||||
/* local_conn is now the primary connection */
|
/* local_conn is now the primary connection */
|
||||||
create_event_notification_extended(local_conn,
|
create_event_notification(local_conn,
|
||||||
&config_file_options,
|
&config_file_options,
|
||||||
local_node_info.node_id,
|
local_node_info.node_id,
|
||||||
"repmgrd_failover_promote",
|
"repmgrd_failover_promote",
|
||||||
true,
|
true,
|
||||||
event_details.data,
|
event_details.data);
|
||||||
&event_info);
|
|
||||||
|
|
||||||
termPQExpBuffer(&event_details);
|
termPQExpBuffer(&event_details);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* repmgrd-physical.h
|
* repmgrd-physical.h
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
* Copyright (c) 2ndQuadrant, 2010-2020
|
||||||
*
|
*
|
||||||
* 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
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
#ifndef _REPMGRD_PHYSICAL_H_
|
#ifndef _REPMGRD_PHYSICAL_H_
|
||||||
#define _REPMGRD_PHYSICAL_H_
|
#define _REPMGRD_PHYSICAL_H_
|
||||||
|
|
||||||
void do_physical_node_check(PGconn *conn);
|
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);
|
||||||
|
|||||||
28
repmgrd.c
28
repmgrd.c
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* repmgrd.c - Replication manager daemon
|
* repmgrd.c - Replication manager daemon
|
||||||
*
|
*
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
* Copyright (c) 2ndQuadrant, 2010-2020
|
||||||
*
|
*
|
||||||
* 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
|
||||||
@@ -131,7 +131,7 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
memset(pid_file, 0, MAXPGPATH);
|
memset(pid_file, 0, MAXPGPATH);
|
||||||
|
|
||||||
while ((c = getopt_long(argc, argv, "?Vf:L:vdp:sm", long_options, &optindex)) != -1)
|
while ((c = getopt_long(argc, argv, "?Vf:L:vdp:m", long_options, &optindex)) != -1)
|
||||||
{
|
{
|
||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
@@ -249,7 +249,7 @@ main(int argc, char **argv)
|
|||||||
/*
|
/*
|
||||||
* Parse the configuration file, if provided (if no configuration file was
|
* Parse the configuration file, if provided (if no configuration file was
|
||||||
* provided, an attempt will be made to find one in one of the default
|
* provided, an attempt will be made to find one in one of the default
|
||||||
* locations). If no configuration file is available, or it can't be parsed
|
* locations). If no conifguration file is available, or it can't be parsed
|
||||||
* parse_config() will abort anyway, with an appropriate message.
|
* parse_config() will abort anyway, with an appropriate message.
|
||||||
*/
|
*/
|
||||||
load_config(config_file, verbose, false, argv[0]);
|
load_config(config_file, verbose, false, argv[0]);
|
||||||
@@ -307,7 +307,7 @@ main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Some configuration file items can be overridden by command line options */
|
/* Some configuration file items can be overriden by command line options */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Command-line parameter -L/--log-level overrides any setting in config
|
* Command-line parameter -L/--log-level overrides any setting in config
|
||||||
@@ -396,14 +396,13 @@ main(int argc, char **argv)
|
|||||||
* extension is the latest available according to "pg_available_extensions" -
|
* extension is the latest available according to "pg_available_extensions" -
|
||||||
* - does our (major) version match that?
|
* - does our (major) version match that?
|
||||||
*/
|
*/
|
||||||
log_verbose(LOG_DEBUG, "expected extension version: %i; extension version: %i",
|
log_verbose(LOG_DEBUG, "binary version: %i; extension version: %i",
|
||||||
REPMGR_EXTENSION_NUM, extversions.installed_version_num);
|
REPMGR_VERSION_NUM, extversions.installed_version_num);
|
||||||
if ((REPMGR_EXTENSION_NUM/100) < (extversions.installed_version_num / 100))
|
if ((REPMGR_VERSION_NUM/100) < (extversions.installed_version_num / 100))
|
||||||
{
|
{
|
||||||
log_error(_("this \"repmgr\" version is older than the installed \"repmgr\" extension version"));
|
log_error(_("this \"repmgr\" version is older than the installed \"repmgr\" extension version"));
|
||||||
log_detail(_("\"repmgr\" version %s providing extension version %s is installed but extension is version %s"),
|
log_detail(_("\"repmgr\" version %s is installed but extension is version %s"),
|
||||||
REPMGR_VERSION,
|
REPMGR_VERSION,
|
||||||
REPMGR_EXTENSION_VERSION,
|
|
||||||
extversions.installed_version);
|
extversions.installed_version);
|
||||||
log_hint(_("update the repmgr binaries to match the installed extension version"));
|
log_hint(_("update the repmgr binaries to match the installed extension version"));
|
||||||
|
|
||||||
@@ -411,14 +410,13 @@ main(int argc, char **argv)
|
|||||||
exit(ERR_BAD_CONFIG);
|
exit(ERR_BAD_CONFIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((REPMGR_EXTENSION_NUM/100) > (extversions.installed_version_num / 100))
|
if ((REPMGR_VERSION_NUM/100) > (extversions.installed_version_num / 100))
|
||||||
{
|
{
|
||||||
log_error(_("this \"repmgr\" version is newer than the installed \"repmgr\" extension version"));
|
log_error(_("this \"repmgr\" version is newer than the installed \"repmgr\" extension version"));
|
||||||
log_detail(_("\"repmgr\" version %s providing extension version %s is installed but extension is version %s"),
|
log_detail(_("\"repmgr\" version %s is installed but extension is version %s"),
|
||||||
REPMGR_VERSION,
|
REPMGR_VERSION,
|
||||||
REPMGR_EXTENSION_VERSION,
|
|
||||||
extversions.installed_version);
|
extversions.installed_version);
|
||||||
log_hint(_("update the installed extension version by executing \"ALTER EXTENSION repmgr UPDATE\" in the repmgr database"));
|
log_hint(_("update the installed extension version by executing \"ALTER EXTENSION repmgr UPDATE\""));
|
||||||
|
|
||||||
close_connection(&local_conn);
|
close_connection(&local_conn);
|
||||||
exit(ERR_BAD_CONFIG);
|
exit(ERR_BAD_CONFIG);
|
||||||
@@ -479,7 +477,7 @@ main(int argc, char **argv)
|
|||||||
switch (config_file_options.replication_type)
|
switch (config_file_options.replication_type)
|
||||||
{
|
{
|
||||||
case REPLICATION_TYPE_PHYSICAL:
|
case REPLICATION_TYPE_PHYSICAL:
|
||||||
log_hint(_("check that 'repmgr (primary|standby|witness) register' was executed for this node"));
|
log_hint(_("check that 'repmgr (primary|standby) register' was executed for this node"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -512,7 +510,7 @@ main(int argc, char **argv)
|
|||||||
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);
|
||||||
do_physical_node_check(local_conn);
|
do_physical_node_check();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (daemonize == true)
|
if (daemonize == true)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* repmgrd.h
|
* repmgrd.h
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
* Copyright (c) 2ndQuadrant, 2010-2020
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* strutil.c
|
* strutil.c
|
||||||
*
|
*
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
* Copyright (c) 2ndQuadrant, 2010-2020
|
||||||
*
|
*
|
||||||
* 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
|
||||||
@@ -369,6 +369,7 @@ check_status_list_free(CheckStatusList *list)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
output_check_status(CheckStatus status)
|
output_check_status(CheckStatus status)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* strutil.h
|
* strutil.h
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
* Copyright (c) 2ndQuadrant, 2010-2020
|
||||||
*
|
*
|
||||||
* 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
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* Functions which need to be executed on the local system.
|
* Functions which need to be executed on the local system.
|
||||||
*
|
*
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
* Copyright (c) 2ndQuadrant, 2010-2020
|
||||||
*
|
*
|
||||||
* 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
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* sysutils.h
|
* sysutils.h
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
* Copyright (c) 2ndQuadrant, 2010-2020
|
||||||
*
|
*
|
||||||
* 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
|
||||||
|
|||||||
2
voting.h
2
voting.h
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* voting.h
|
* voting.h
|
||||||
* Copyright (c) EnterpriseDB Corporation, 2010-2021
|
* Copyright (c) 2ndQuadrant, 2010-2020
|
||||||
*
|
*
|
||||||
* 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
|
||||||
|
|||||||
Reference in New Issue
Block a user