mirror of
https://github.com/EnterpriseDB/repmgr.git
synced 2026-03-22 22:56:29 +00:00
Compare commits
27 Commits
dev/standb
...
v5.3.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
78cc278639 | ||
|
|
ceb65027c6 | ||
|
|
e6caa14ea2 | ||
|
|
88a11f36ca | ||
|
|
7f371b11a5 | ||
|
|
349eacd4b7 | ||
|
|
9f2afe9643 | ||
|
|
356f65531f | ||
|
|
2a7579c770 | ||
|
|
820d972d41 | ||
|
|
d0add49c84 | ||
|
|
9a84fa84f9 | ||
|
|
ff2c56f5cb | ||
|
|
3b860bad80 | ||
|
|
70c79aeaec | ||
|
|
afd876377c | ||
|
|
277910cb31 | ||
|
|
9554154677 | ||
|
|
2bbfb5daa0 | ||
|
|
82b0e85a66 | ||
|
|
3320eb0983 | ||
|
|
7862941300 | ||
|
|
f152fc3016 | ||
|
|
9c260e605d | ||
|
|
7ad06530e4 | ||
|
|
c787273f91 | ||
|
|
d40055c8dd |
37
.github/workflows/sonarqube-scan.yml
vendored
37
.github/workflows/sonarqube-scan.yml
vendored
@@ -1,37 +0,0 @@
|
||||
name: SonarQube Scan
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches: [ master ]
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
sonarQube:
|
||||
name: SonarQube-Job
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
- name: Checkout source repo
|
||||
uses: actions/checkout@v1
|
||||
with:
|
||||
ref: '${{ github.head_ref }}'
|
||||
|
||||
- name: Checkout GitHub Action Repo
|
||||
uses: actions/checkout@master
|
||||
with:
|
||||
repository: EnterpriseDB/edb-github-actions.git
|
||||
ref: master
|
||||
token: ${{ secrets.GH_SLONIK }}
|
||||
path: .github/actions/edb-github-actions
|
||||
|
||||
- name: SonarQube Scan
|
||||
uses: ./.github/actions/edb-github-actions/sonarqube
|
||||
with:
|
||||
REPO_NAME: '${{github.event.repository.name}}'
|
||||
SONAR_PROJECT_KEY: EnterpriseDB_repmgr
|
||||
SONAR_URL: '${{secrets.SONARQUBE_URL}}'
|
||||
SONAR_LOGIN: '${{secrets.SONARQUBE_LOGIN}}'
|
||||
PULL_REQUEST_KEY: '${{github.event.number}}'
|
||||
PULL_REQUEST_BRANCH: '${{github.head_ref}}'
|
||||
PULL_REQUEST_BASE_BRANCH: '${{github.base_ref}}'
|
||||
REPO_DEFAULT_BRANCH: '${{github.event.repository.default_branch}}'
|
||||
REPO_EXCLUDE_FILES: '*properties*,**/src/test/**/*,**/*.sql,**/docs/**/*,**/*/*.java'
|
||||
18
.github/workflows/sonarqube/configure-env.sh
vendored
18
.github/workflows/sonarqube/configure-env.sh
vendored
@@ -1,18 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
DEBIAN_FRONTEND=noninteractive sudo apt-get -y install debhelper curl autoconf zlib1g-dev \
|
||||
libedit-dev libxml2-dev libxslt1-dev libkrb5-dev libssl-dev libpam0g-dev systemtap-sdt-dev \
|
||||
libselinux1-dev build-essential bison apt-utils lsb-release devscripts \
|
||||
software-properties-common git shellcheck flex
|
||||
|
||||
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
|
||||
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
|
||||
sudo apt-get update
|
||||
|
||||
sudo apt-get -y install libpq-dev postgresql-13 postgresql-server-dev-13
|
||||
|
||||
./configure
|
||||
|
||||
export PG_CONFIG=/usr/bin/pg_config
|
||||
|
||||
/home/buildfarm/sonar/depends/build-wrapper-linux-x86/build-wrapper-linux-x86-64 --out-dir build_wrapper_output_directory make
|
||||
9
HISTORY
9
HISTORY
@@ -1,12 +1,5 @@
|
||||
5.3.2 2022-??-??
|
||||
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)
|
||||
|
||||
5.3.1 2022-02-15
|
||||
5.3.1 2022-??-??
|
||||
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)
|
||||
|
||||
@@ -30,9 +30,7 @@ DATA = \
|
||||
repmgr--5.1--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
|
||||
repmgr--5.3.sql
|
||||
|
||||
REGRESS = repmgr_extension
|
||||
|
||||
|
||||
18
configure
vendored
18
configure
vendored
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.69 for repmgr 5.4.0.
|
||||
# Generated by GNU Autoconf 2.69 for repmgr 5.3.0.
|
||||
#
|
||||
# Report bugs to <repmgr@googlegroups.com>.
|
||||
#
|
||||
@@ -582,8 +582,8 @@ MAKEFLAGS=
|
||||
# Identity of this package.
|
||||
PACKAGE_NAME='repmgr'
|
||||
PACKAGE_TARNAME='repmgr'
|
||||
PACKAGE_VERSION='5.4.0'
|
||||
PACKAGE_STRING='repmgr 5.4.0'
|
||||
PACKAGE_VERSION='5.3.0'
|
||||
PACKAGE_STRING='repmgr 5.3.0'
|
||||
PACKAGE_BUGREPORT='repmgr@googlegroups.com'
|
||||
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.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
cat <<_ACEOF
|
||||
\`configure' configures repmgr 5.4.0 to adapt to many kinds of systems.
|
||||
\`configure' configures repmgr 5.3.0 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@@ -1242,7 +1242,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of repmgr 5.4.0:";;
|
||||
short | recursive ) echo "Configuration of repmgr 5.3.0:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@@ -1316,7 +1316,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
repmgr configure 5.4.0
|
||||
repmgr configure 5.3.0
|
||||
generated by GNU Autoconf 2.69
|
||||
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
@@ -1335,7 +1335,7 @@ cat >config.log <<_ACEOF
|
||||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by repmgr $as_me 5.4.0, which was
|
||||
It was created by repmgr $as_me 5.3.0, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
@@ -2487,7 +2487,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
||||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by repmgr $as_me 5.4.0, which was
|
||||
This file was extended by repmgr $as_me 5.3.0, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@@ -2550,7 +2550,7 @@ _ACEOF
|
||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||
ac_cs_version="\\
|
||||
repmgr config.status 5.4.0
|
||||
repmgr config.status 5.3.0
|
||||
configured by $0, generated by GNU Autoconf 2.69,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
AC_INIT([repmgr], [5.4.0], [repmgr@googlegroups.com], [repmgr], [https://repmgr.org/])
|
||||
AC_INIT([repmgr], [5.3.1], [repmgr@googlegroups.com], [repmgr], [https://repmgr.org/])
|
||||
|
||||
AC_COPYRIGHT([Copyright (c) 2010-2021, EnterpriseDB Corporation])
|
||||
|
||||
|
||||
134
dbutils.c
134
dbutils.c
@@ -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 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
|
||||
* that the provided PGconn can be a normal or a replication connection;
|
||||
@@ -1291,16 +1289,21 @@ get_cluster_size(PGconn *conn, char *size)
|
||||
initPQExpBuffer(&query);
|
||||
appendPQExpBufferStr(&query,
|
||||
"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);
|
||||
|
||||
res = PQexec(conn, query.data);
|
||||
|
||||
if (PQresultStatus(res) != PGRES_TUPLES_OK)
|
||||
{
|
||||
log_db_error(conn, query.data, _("get_cluster_size(): unable to execute query"));
|
||||
success = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(size, MAXLEN, "%s", PQgetvalue(res, 0, 0));
|
||||
}
|
||||
|
||||
termPQExpBuffer(&query);
|
||||
PQclear(res);
|
||||
@@ -1823,30 +1826,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 */
|
||||
/* =============================== */
|
||||
@@ -1888,42 +1867,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
|
||||
* a member of the "pg_monitor" default role, or optionally one
|
||||
@@ -2139,13 +2082,7 @@ server_in_exclusive_backup_mode(PGconn *conn)
|
||||
{
|
||||
BackupState backup_state = BACKUP_STATE_UNKNOWN;
|
||||
const char *sqlquery = "SELECT pg_catalog.pg_is_in_backup()";
|
||||
PGresult *res = NULL;
|
||||
|
||||
/* Exclusive backup removed from PostgreSQL 15 */
|
||||
if (PQserverVersion(conn) >= 150000)
|
||||
return BACKUP_STATE_NO_BACKUP;
|
||||
|
||||
res = PQexec(conn, sqlquery);
|
||||
PGresult *res = PQexec(conn, sqlquery);
|
||||
|
||||
if (PQresultStatus(res) != PGRES_TUPLES_OK)
|
||||
{
|
||||
@@ -2309,6 +2246,29 @@ repmgrd_pause(PGconn *conn, bool pause)
|
||||
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
|
||||
repmgrd_get_upstream_node_id(PGconn *conn)
|
||||
@@ -5744,7 +5704,7 @@ get_node_timeline(PGconn *conn, char *timeline_id_str)
|
||||
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)
|
||||
{
|
||||
@@ -5832,19 +5792,6 @@ get_node_replication_stats(PGconn *conn, t_node_info *node_info)
|
||||
NodeAttached
|
||||
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;
|
||||
PGresult *res = NULL;
|
||||
|
||||
@@ -5879,12 +5826,9 @@ _is_downstream_node_attached(PGconn *conn, char *node_name, char **node_state, b
|
||||
*/
|
||||
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_hint(_("verify that a unique node name is configured for each node"));
|
||||
}
|
||||
log_error(_("multiple entries with \"application_name\" set to \"%s\" found in \"pg_stat_replication\""),
|
||||
node_name);
|
||||
log_hint(_("verify that a unique node name is configured for each node"));
|
||||
|
||||
PQclear(res);
|
||||
|
||||
@@ -5893,8 +5837,7 @@ _is_downstream_node_attached(PGconn *conn, char *node_name, char **node_state, b
|
||||
|
||||
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);
|
||||
|
||||
@@ -5920,10 +5863,9 @@ _is_downstream_node_attached(PGconn *conn, char *node_name, char **node_state, b
|
||||
|
||||
if (strcmp(state, "streaming") != 0)
|
||||
{
|
||||
if (quiet == false)
|
||||
log_warning(_("node \"%s\" attached in state \"%s\""),
|
||||
node_name,
|
||||
state);
|
||||
log_warning(_("node \"%s\" attached in state \"%s\""),
|
||||
node_name,
|
||||
state);
|
||||
|
||||
PQclear(res);
|
||||
|
||||
|
||||
@@ -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);
|
||||
uint64 system_identifier(PGconn *conn);
|
||||
TimeLineHistoryEntry *get_timeline_history(PGconn *repl_conn, TimeLineID tli);
|
||||
pid_t get_wal_receiver_pid(PGconn *conn);
|
||||
|
||||
/* user/role information functions */
|
||||
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 is_replication_role(PGconn *conn, char *rolname);
|
||||
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_paused(PGconn *conn);
|
||||
bool repmgrd_pause(PGconn *conn, bool pause);
|
||||
pid_t get_wal_receiver_pid(PGconn *conn);
|
||||
int repmgrd_get_upstream_node_id(PGconn *conn);
|
||||
bool repmgrd_set_upstream_node_id(PGconn *conn, int node_id);
|
||||
|
||||
@@ -598,7 +597,6 @@ int get_replication_lag_seconds(PGconn *conn);
|
||||
TimeLineID get_node_timeline(PGconn *conn, char *timeline_id_str);
|
||||
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_quiet(PGconn *conn, char *node_name, char **node_state);
|
||||
void set_upstream_last_seen(PGconn *conn, int upstream_node_id);
|
||||
int get_upstream_last_seen(PGconn *conn, t_server_type node_type);
|
||||
|
||||
|
||||
@@ -249,16 +249,16 @@
|
||||
For a standby which has been manually cloned or recovered from an external
|
||||
backup manager such as Barman, the 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,
|
||||
<link linkend="repmgr-standby-register">register the node</link> as usual.
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
<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>
|
||||
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>
|
||||
</sect2>
|
||||
|
||||
@@ -366,11 +366,11 @@
|
||||
</para>
|
||||
</sect2>
|
||||
|
||||
<sect2 id="faq-repmgr-recovery-conf-quoted-values" xreflabel="Quoted values in replication.conf">
|
||||
<title>Why are some values in <filename>recovery.conf</filename> (PostgreSQL 11 and earlier) surrounded by pairs of single quotes?</title>
|
||||
<sect2 id="faq-repmgr-recovery-conf-quoted-values" xreflabel="Quoted values in recovery.conf">
|
||||
<title>Why are some values in <filename>recovery.conf</filename> surrounded by pairs of single quotes?</title>
|
||||
<para>
|
||||
This is to ensure that user-supplied values which are written as parameter values in <filename>recovery.conf</filename>
|
||||
are escaped correctly and do not cause errors when the file is parsed.
|
||||
are escaped correctly and do not cause errors when <filename>recovery.conf</filename> is parsed.
|
||||
</para>
|
||||
<para>
|
||||
The escaping is performed by an internal PostgreSQL routine, which leaves strings consisting
|
||||
@@ -419,9 +419,9 @@
|
||||
<para>
|
||||
&repmgrd; can monitor delayed standbys - those set up with
|
||||
<varname>recovery_min_apply_delay</varname> set to a non-zero value
|
||||
in the replication configuration. However &repmgrd; does not currently
|
||||
consider this setting, and therefore may not be able to properly evaluate
|
||||
the node as a promotion candidate.
|
||||
in <filename>recovery.conf</filename> - but as it's not currently possible
|
||||
to directly examine the value applied to the standby, &repmgrd;
|
||||
may not be able to properly evaluate the node as a promotion candidate.
|
||||
</para>
|
||||
<para>
|
||||
We recommend that delayed standbys are explicitly excluded from promotion
|
||||
|
||||
@@ -50,18 +50,18 @@
|
||||
<title>CentOS repositories</title>
|
||||
|
||||
<para>
|
||||
&repmgr; packages are available from the public EDB repository, and also the
|
||||
PostgreSQL community repository. The EDB repository is updated immediately
|
||||
&repmgr; packages are available from the public 2ndQuadrant repository, and also the
|
||||
PostgreSQL community repository. The 2ndQuadrant repository is updated immediately
|
||||
after each &repmgr; release.
|
||||
</para>
|
||||
|
||||
<table id="centos-2ndquadrant-repository">
|
||||
<title>EDB public repository</title>
|
||||
<title>2ndQuadrant public repository</title>
|
||||
<tgroup cols="2">
|
||||
<tbody>
|
||||
<row>
|
||||
<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>
|
||||
<entry>Repository documentation:</entry>
|
||||
@@ -252,7 +252,7 @@
|
||||
</indexterm>
|
||||
|
||||
<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 version, currently supported Debian releases, and currently supported
|
||||
Ubuntu LTS releases.
|
||||
@@ -262,12 +262,12 @@
|
||||
<title>APT repositories</title>
|
||||
|
||||
<table id="apt-2ndquadrant-repository">
|
||||
<title>EDB public repository</title>
|
||||
<title>2ndQuadrant public repository</title>
|
||||
<tgroup cols="2">
|
||||
<tbody>
|
||||
<row>
|
||||
<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>
|
||||
<entry>Repository documentation:</entry>
|
||||
@@ -401,7 +401,7 @@
|
||||
</indexterm>
|
||||
|
||||
<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
|
||||
are built from the &repmgr; source at a particular point in time, and are not formal
|
||||
releases.
|
||||
@@ -413,22 +413,22 @@
|
||||
</para>
|
||||
</note>
|
||||
<para>
|
||||
To install a snapshot package, it's necessary to install the EDB 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>
|
||||
To install a snapshot package, it's necessary to install the 2ndQuadrant public snapshot repository,
|
||||
following the instructions here: <ulink url="https://dl.2ndquadrant.com/default/release/site/">https://dl.2ndquadrant.com/default/release/site/</ulink> but replace <literal>release</literal> with <literal>snapshot</literal>
|
||||
in the appropriate URL.
|
||||
</para>
|
||||
<para>
|
||||
For example, to install the snapshot RPM repository for PostgreSQL 9.6, execute (as <literal>root</literal>):
|
||||
<programlisting>
|
||||
curl https://dl.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:
|
||||
<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>
|
||||
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>
|
||||
Once the repository is installed, installing or updating &repmgr; will result in the latest snapshot
|
||||
@@ -493,6 +493,32 @@ repmgr96-4.1.1-0.0git320.g5113ab0.1.el7.x86_64.rpm</programlisting>
|
||||
yum install repmgr96-4.0.6-1.rhel6</programlisting>
|
||||
</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>
|
||||
</sect1>
|
||||
|
||||
|
||||
@@ -14,69 +14,14 @@
|
||||
<para>
|
||||
See also: <xref linkend="upgrading-repmgr"/>
|
||||
</para>
|
||||
<sect1 id="release-5.3.2">
|
||||
<title id="release-current">Release 5.3.2</title>
|
||||
<para><emphasis>??? ??? ???, 2022</emphasis></para>
|
||||
<para>
|
||||
&repmgr; 5.3.2 is a minor release.
|
||||
</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>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
</sect2>
|
||||
</sect1>
|
||||
|
||||
<!-- remember to update the release date in ../repmgr_version.h.in -->
|
||||
<sect1 id="release-5.3.1">
|
||||
<title>Release 5.3.1</title>
|
||||
<title id="release-current">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>
|
||||
@@ -111,11 +56,6 @@
|
||||
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>
|
||||
@@ -202,7 +142,8 @@
|
||||
risk of clashes with other shared libraries.
|
||||
</para>
|
||||
<para>
|
||||
This does not affect user-facing SQL functions. Howe
|
||||
This does not affect user-facing SQL functions. However an upgrade
|
||||
of the installed extension version is required.
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
|
||||
@@ -7,13 +7,13 @@
|
||||
</indexterm>
|
||||
|
||||
<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
|
||||
products, including configuration assistance, installation
|
||||
verification and training for running a robust replication cluster.
|
||||
</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>
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
<para>
|
||||
<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
|
||||
to clone a standby (and also as a fallback source for WAL files).
|
||||
</para>
|
||||
@@ -197,7 +197,7 @@ description = "Main cluster"
|
||||
<para>
|
||||
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
|
||||
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.
|
||||
</para>
|
||||
<para>
|
||||
@@ -299,7 +299,7 @@ description = "Main cluster"
|
||||
build up indefinitely, possibly leading to server failure.
|
||||
</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
|
||||
slot for each individual standby to reserve WAL. See section <xref linkend="cloning-from-barman"/>
|
||||
for more details on using &repmgr; together with Barman.
|
||||
@@ -328,9 +328,9 @@ description = "Main cluster"
|
||||
&repmgr; supports cascading replication. When cloning a standby,
|
||||
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
|
||||
&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,
|
||||
&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.
|
||||
</para>
|
||||
<para>
|
||||
@@ -392,7 +392,7 @@ description = "Main cluster"
|
||||
does not yet exist. In this case you can clone from the primary (or
|
||||
another upstream node); provide the parameter <literal>--upstream-conninfo</literal>
|
||||
to explicitly set the upstream's <varname>primary_conninfo</varname> string
|
||||
in the replication configuration.
|
||||
in <filename>recovery.conf</filename>.
|
||||
</simpara>
|
||||
</tip>
|
||||
</sect1>
|
||||
@@ -491,12 +491,12 @@ description = "Main cluster"
|
||||
</note>
|
||||
|
||||
<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
|
||||
<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>
|
||||
string in the replication configuration. Note that <varname>PGPASSWORD</varname>
|
||||
will need to be set during any action which causes the replication configuration file to be
|
||||
string in <filename>recovery.conf</filename>. Note that <varname>PGPASSWORD</varname>
|
||||
will need to be set during any action which causes <filename>recovery.conf</filename> to be
|
||||
rewritten, e.g. <xref linkend="repmgr-standby-follow"/>.
|
||||
</para>
|
||||
</sect2>
|
||||
@@ -508,7 +508,7 @@ description = "Main cluster"
|
||||
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
|
||||
<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>
|
||||
table for each node; it no longer needs to be explicitly specified when
|
||||
cloning a node or executing <xref linkend="repmgr-standby-follow"/>.
|
||||
|
||||
@@ -164,7 +164,7 @@ conninfo='host=node1 user=repmgr dbname=repmgr connect_timeout=2'</programlistin
|
||||
</para>
|
||||
<para>
|
||||
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>
|
||||
For &repmgrd;-specific settings, see <xref linkend="repmgrd-configuration"/>.
|
||||
|
||||
@@ -7,186 +7,19 @@
|
||||
</indexterm>
|
||||
|
||||
<para>
|
||||
If the &repmgr; database user (the PostgreSQL user defined in the
|
||||
<varname>conninfo</varname> setting is a superuser, no further user permissions need
|
||||
to be granted.
|
||||
&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>
|
||||
|
||||
<sect2 id="configuration-permissions-no-superuser" xreflabel="Non-super user permissions">
|
||||
<title>repmgr user as a non-superuser</title>
|
||||
<para>
|
||||
In principle the &repmgr; database user does not need to be a superuser.
|
||||
In this case the &repmgr; will need to be granted execution permissions on certain
|
||||
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>
|
||||
<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>
|
||||
</sect1>
|
||||
|
||||
@@ -22,15 +22,16 @@
|
||||
|
||||
<para>
|
||||
&repmgr; RPM packages for RedHat/CentOS variants and Fedora are available from the
|
||||
<ulink url="https://www.enterprisedb.com">EDB</ulink>
|
||||
<ulink url="https://dl.enterprisedb.com/">public repository</ulink>; see following
|
||||
<ulink url="https://2ndquadrant.com">2ndQuadrant</ulink>
|
||||
<ulink url="https://dl.2ndquadrant.com/">public repository</ulink>; see following
|
||||
section for details.
|
||||
</para>
|
||||
<note>
|
||||
<para>
|
||||
Currently the <ulink url="https://www.enterprisedb.com">EDB</ulink>
|
||||
<ulink url="https://dl.enterprisedb.com/">public repository</ulink> provides
|
||||
support for RedHat/CentOS versions 6,7 and 8.
|
||||
Currently the <ulink url="https://2ndquadrant.com">2ndQuadrant</ulink>
|
||||
<ulink url="https://dl.2ndquadrant.com/">public repository</ulink> provides
|
||||
support for RedHat/CentOS versions 5, 6 and 7. Support for version 8 is
|
||||
available via the PGDG repository; see below for details.
|
||||
</para>
|
||||
</note>
|
||||
<para>
|
||||
@@ -44,7 +45,7 @@
|
||||
<note>
|
||||
<para>
|
||||
&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
|
||||
customers, as the PostgreSQL filesystem layout may be different to the community RPMs.
|
||||
Please contact your support vendor for assistance.
|
||||
@@ -63,16 +64,16 @@
|
||||
|
||||
|
||||
<sect3 id="installation-packages-redhat-2ndq">
|
||||
<title>EDB public RPM yum repository</title>
|
||||
<title>2ndQuadrant public RPM yum repository</title>
|
||||
|
||||
<para>
|
||||
<ulink url="https://www.enterprisedb.com/">EDB</ulink> provides a dedicated <literal>yum</literal>
|
||||
<ulink url="https://dl.enterprisedb.com/">public repository</ulink> for EDB software,
|
||||
<ulink url="https://2ndquadrant.com/">2ndQuadrant</ulink> provides a dedicated <literal>yum</literal>
|
||||
<ulink url="https://dl.2ndquadrant.com/">public repository</ulink> for 2ndQuadrant software,
|
||||
including &repmgr;. We recommend using this for all future &repmgr; releases.
|
||||
</para>
|
||||
<para>
|
||||
General instructions for using this repository can be found on its
|
||||
<ulink url="https://dl.enterprisedb.com/">homepage</ulink>. Specific instructions
|
||||
<ulink url="https://dl.2ndquadrant.com/">homepage</ulink>. Specific instructions
|
||||
for installing &repmgr; follow below.
|
||||
</para>
|
||||
<para>
|
||||
@@ -82,46 +83,57 @@
|
||||
<listitem>
|
||||
<para>
|
||||
Locate the repository RPM for your PostgreSQL version from the list at:
|
||||
<ulink url="https://dl.enterprisedb.com/">https://dl.enterprisedb.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>
|
||||
<ulink url="https://dl.2ndquadrant.com/">https://dl.2ndquadrant.com/</ulink>
|
||||
</para>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<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>
|
||||
sudo dnf install repmgr14</programlisting>
|
||||
sudo yum install repmgr11</programlisting>
|
||||
</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>
|
||||
<para>
|
||||
To determine the names of available packages, execute:
|
||||
<programlisting>
|
||||
dnf search repmgr</programlisting>
|
||||
</para>
|
||||
<para>
|
||||
In CentOS 7 and earlier, use <literal>yum</literal> instead of <literal>dnf</literal>.
|
||||
yum search repmgr</programlisting>
|
||||
</para>
|
||||
</tip>
|
||||
|
||||
@@ -133,7 +145,7 @@ dnf search repmgr</programlisting>
|
||||
<emphasis>Compatibility with PGDG Repositories</emphasis>
|
||||
</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.
|
||||
</para>
|
||||
<para>
|
||||
@@ -142,42 +154,36 @@ dnf search repmgr</programlisting>
|
||||
the packages are installed from.
|
||||
</para>
|
||||
<para>
|
||||
To ensure the EDB repository is always prioritised, set the <literal>priority</literal> option
|
||||
in the repository configuration file (e.g. <filename>/etc/yum.repos.d/2ndquadrant-dl-default-release-pg14.repo</filename>
|
||||
accordingly.
|
||||
To ensure the 2ndQuadrant repository is always prioritised, install <literal>yum-plugin-priorities</literal>
|
||||
and set the repository priorities accordingly.
|
||||
</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>
|
||||
<emphasis>Installing a specific package version</emphasis>
|
||||
</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:
|
||||
<programlisting>
|
||||
[root@localhost ~]# dnf --showduplicates list repmgr10
|
||||
Last metadata expiration check: 0:09:15 ago on Fri 11 Mar 2022 01:09:19 AM UTC.
|
||||
[root@localhost ~]# yum --showduplicates list repmgr11
|
||||
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
|
||||
repmgr10.x86_64 5.3.1-1.el8 @2ndquadrant-dl-default-release-pg10
|
||||
repmgr11.x86_64 4.4.0-1.rhel7 @pgdg11
|
||||
Available Packages
|
||||
repmgr10.x86_64 5.0.0-1.rhel8 pgdg10
|
||||
repmgr10.x86_64 5.1.0-1.el8 2ndquadrant-dl-default-release-pg10
|
||||
repmgr10.x86_64 5.1.0-1.rhel8 pgdg10
|
||||
repmgr10.x86_64 5.1.0-2.el8 2ndquadrant-dl-default-release-pg10
|
||||
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>
|
||||
repmgr11.x86_64 4.2-1.el7 2ndquadrant-dl-default-release-pg11
|
||||
repmgr11.x86_64 4.2-2.el7 2ndquadrant-dl-default-release-pg11
|
||||
repmgr11.x86_64 4.3-1.el7 2ndquadrant-dl-default-release-pg11
|
||||
repmgr11.x86_64 4.4-1.el7 2ndquadrant-dl-default-release-pg11</programlisting>
|
||||
then append the appropriate version number to the package name with a hyphen, e.g.:
|
||||
<programlisting>
|
||||
[root@localhost ~]# dnf install repmgr10-5.3.0-1.el8</programlisting>
|
||||
[root@localhost ~]# yum install repmgr11-4.3-1.el7</programlisting>
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<emphasis>Installing old packages</emphasis>
|
||||
</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>
|
||||
for details on how to retrieve older package versions.
|
||||
</para>
|
||||
|
||||
</sect3>
|
||||
|
||||
</sect2>
|
||||
@@ -210,16 +217,16 @@ repmgr10.x86_64 5.3.1-1.el8
|
||||
</para>
|
||||
|
||||
<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>
|
||||
<ulink url="https://www.enterprisedb.com/">EDB</ulink> provides a
|
||||
<ulink url="https://dl.enterprisedb.com/">public apt repository</ulink> for EDB software,
|
||||
<ulink url="https://2ndquadrant.com/">2ndQuadrant</ulink> provides a
|
||||
<ulink url="https://dl.2ndquadrant.com/">public apt repository</ulink> for 2ndQuadrant software,
|
||||
including &repmgr;.
|
||||
</para>
|
||||
<para>
|
||||
General instructions for using this repository can be found on its
|
||||
<ulink url="https://dl.enterprisedb.com/">homepage</ulink>. Specific instructions
|
||||
<ulink url="https://dl.2ndquadrant.com/">homepage</ulink>. Specific instructions
|
||||
for installing &repmgr; follow below.
|
||||
</para>
|
||||
|
||||
@@ -232,9 +239,9 @@ repmgr10.x86_64 5.3.1-1.el8
|
||||
<listitem>
|
||||
<para>
|
||||
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>
|
||||
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>
|
||||
<note>
|
||||
<para>
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
<!-- doc/legal.xml -->
|
||||
|
||||
<date>2022</date>
|
||||
<date>2017</date>
|
||||
|
||||
<copyright>
|
||||
<year>2010-2022</year>
|
||||
<holder>EDB</holder>
|
||||
<year>2010-2021</year>
|
||||
<holder>EnterpriseDB Corporation</holder>
|
||||
</copyright>
|
||||
|
||||
<legalnotice id="legalnotice">
|
||||
<title>Legal Notice</title>
|
||||
|
||||
<para>
|
||||
<productname>repmgr</productname> is Copyright © 2010-2022
|
||||
by EDB All rights reserved.
|
||||
<productname>repmgr</productname> is Copyright © 2010-2021
|
||||
by EnterpriseDB Corporation All rights reserved.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
|
||||
@@ -405,10 +405,9 @@
|
||||
</programlisting>
|
||||
<para>
|
||||
This has cloned the PostgreSQL data directory files from the primary <literal>node1</literal>
|
||||
using PostgreSQL's <command>pg_basebackup</command> utility. Replication configuration
|
||||
containing the correct parameters to start streaming from this primary server will be
|
||||
automatically appended to <filename>postgresql.auto.conf</filename>. (In PostgreSQL 11
|
||||
and earlier the file <filename>recovery.conf</filename> will be created).
|
||||
using PostgreSQL's <command>pg_basebackup</command> utility. A <filename>recovery.conf</filename>
|
||||
file containing the correct parameters to start streaming from this primary server will be created
|
||||
automatically.
|
||||
</para>
|
||||
<note>
|
||||
<simpara>
|
||||
@@ -482,10 +481,9 @@
|
||||
sender_port | 5432
|
||||
conninfo | user=repmgr dbname=replication host=node1 application_name=node2
|
||||
</programlisting>
|
||||
Note that the <varname>conninfo</varname> value is that generated in <filename>postgresql.auto.conf</filename>
|
||||
(PostgreSQL 11 and earlier: <filename>recovery.conf</filename>) and will differ slightly from the primary's
|
||||
<varname>conninfo</varname> as set in <filename>repmgr.conf</filename> - among others it will contain the
|
||||
connecting node's name as <varname>application_name</varname>.
|
||||
Note that the <varname>conninfo</varname> value is that generated in <filename>recovery.conf</filename>
|
||||
and will differ slightly from the primary's <varname>conninfo</varname> as set in <filename>repmgr.conf</filename> -
|
||||
among others it will contain the connecting node's name as <varname>application_name</varname>.
|
||||
</para>
|
||||
</sect1>
|
||||
|
||||
|
||||
@@ -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
|
||||
PostgreSQL data directory.
|
||||
</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>
|
||||
</varlistentry>
|
||||
|
||||
@@ -405,15 +399,11 @@ pg_basebackup_options='--waldir=/path/to/wal-directory'</programlisting>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>-S</option>/<option>--superuser</option></term>
|
||||
<term><option>--superuser</option></term>
|
||||
<listitem>
|
||||
<para>
|
||||
The name of a valid PostgreSQL superuser can be provided with this option.
|
||||
</para>
|
||||
<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.
|
||||
If the &repmgr; user is not a superuser, the name of a valid superuser must
|
||||
be provided with this option.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
@@ -64,13 +64,6 @@
|
||||
|
||||
<refsect1>
|
||||
<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>
|
||||
&repmgr; executes <command>CHECKPOINT</command> on the demotion candidate as part of the shutdown
|
||||
@@ -79,7 +72,7 @@
|
||||
<para>
|
||||
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
|
||||
provided with the <option>-S</option>/<option>--superuser</option> option.
|
||||
provided with the <option>-S</option>/<option>--superuser</option>.
|
||||
</para>
|
||||
<para>
|
||||
If &repmgr; is unable to execute the <command>CHECKPOINT</command> command, the switchover
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<title>repmgr &repmgrversion; Documentation</title>
|
||||
|
||||
<bookinfo>
|
||||
<corpauthor>EDB</corpauthor>
|
||||
<corpauthor>EnterpriseDB Corporation</corpauthor>
|
||||
<productname>repmgr</productname>
|
||||
<productnumber>&repmgrversion;</productnumber>
|
||||
&legal;
|
||||
@@ -38,18 +38,19 @@
|
||||
|
||||
<para>
|
||||
&repmgr; is developed by
|
||||
<ulink url="https://www.enterprisedb.com/">EDB</ulink>
|
||||
<ulink url="https://2ndquadrant.com">2ndQuadrant (EDB)</ulink>
|
||||
along with contributions from other individuals and organisations.
|
||||
Contributions from the community are appreciated and welcome - get
|
||||
in touch via <ulink url="https://github.com/EnterpriseDB/repmgr">github</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 (EDB) customers contribute funding
|
||||
to make repmgr development possible.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
&repmgr; is fully supported by EDB's
|
||||
<ulink url="https://www.enterprisedb.com/support/postgresql-support-overview-get-the-most-out-of-postgresql">24/7 Production Support</ulink>.
|
||||
EDB, a Major Sponsor of the PostgreSQL project, continues to maintain &repmgr;.
|
||||
&repmgr; is fully supported by 2ndQuadrant (EDB)'s
|
||||
<ulink url="https://www.2ndquadrant.com/en/support/support-postgresql/">24/7 Production Support</ulink>.
|
||||
EnterpriseDB Corporation, a Major Sponsor of the PostgreSQL project, continues to maintain &repmgr;.
|
||||
We welcome participation from other organisations and individual developers.
|
||||
</para>
|
||||
</abstract>
|
||||
|
||||
@@ -81,15 +81,11 @@
|
||||
</para>
|
||||
<note>
|
||||
<simpara>
|
||||
A PostgreSQL instance can only accommodate a single witness server.
|
||||
</simpara>
|
||||
<simpara>
|
||||
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.
|
||||
&repmgr; 3.3 and earlier provided a <command>repmgr create witness</command>
|
||||
command, which would automatically create a PostgreSQL instance. However
|
||||
this often resulted in an unsatisfactory, hard-to-customise instance.
|
||||
</simpara>
|
||||
</note>
|
||||
|
||||
<para>
|
||||
The witness server should be configured in the same way as a normal
|
||||
&repmgr; node; see section <xref linkend="configuration"/>.
|
||||
|
||||
@@ -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.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
|
||||
);
|
||||
|
||||
@@ -1327,7 +1327,7 @@ do_node_check_downstream(PGconn *conn, OutputMode mode, t_node_info *node_info,
|
||||
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++;
|
||||
item_list_append_format(&missing_nodes,
|
||||
@@ -1395,32 +1395,49 @@ do_node_check_downstream(PGconn *conn, OutputMode mode, t_node_info *node_info,
|
||||
{
|
||||
case OM_NAGIOS:
|
||||
{
|
||||
printf("REPMGR_DOWNSTREAM_SERVERS %s: %s | ",
|
||||
output_check_status(status),
|
||||
details.data);
|
||||
|
||||
if (missing_nodes_count)
|
||||
{
|
||||
ItemListCell *missing_cell = NULL;
|
||||
bool first = true;
|
||||
|
||||
appendPQExpBufferStr(&details, " (missing: ");
|
||||
|
||||
printf("missing: ");
|
||||
for (missing_cell = missing_nodes.head; missing_cell; missing_cell = missing_cell->next)
|
||||
{
|
||||
if (first == false)
|
||||
appendPQExpBufferStr(&details, ", ");
|
||||
printf(", ");
|
||||
else
|
||||
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",
|
||||
output_check_status(status),
|
||||
details.data,
|
||||
expected_nodes_count - missing_nodes_count,
|
||||
missing_nodes_count);
|
||||
if (expected_nodes_count - missing_nodes_count)
|
||||
{
|
||||
ItemListCell *attached_cell = NULL;
|
||||
bool first = true;
|
||||
|
||||
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;
|
||||
case OM_CSV:
|
||||
@@ -1518,7 +1535,7 @@ do_node_check_upstream(PGconn *conn, OutputMode mode, t_node_info *node_info, Ch
|
||||
{
|
||||
case OM_NAGIOS:
|
||||
{
|
||||
printf("REPMGR_UPSTREAM_SERVER %s: %s\n",
|
||||
printf("REPMGR_UPSTREAM_SERVER %s: %s | ",
|
||||
output_check_status(status),
|
||||
details.data);
|
||||
}
|
||||
|
||||
@@ -95,8 +95,6 @@ static char barman_command_buf[MAXLEN] = "";
|
||||
* be run and which of the available users, which will be one
|
||||
* of the repmgr user, the replication user (if available) or
|
||||
* the superuser (if available).
|
||||
*
|
||||
* This is determined in check_source_server().
|
||||
*/
|
||||
static t_user_type SettingsUser = REPMGR_USER;
|
||||
|
||||
@@ -5785,18 +5783,20 @@ check_source_server()
|
||||
}
|
||||
|
||||
/*
|
||||
* The server version check will also serve as a sanity-check that we can
|
||||
* actually execute queries on this connection.
|
||||
* If a connection was established, perform some sanity checks on the
|
||||
* provided upstream connection.
|
||||
*/
|
||||
|
||||
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
|
||||
* something if the user has sufficient permissions to retrieve the size of
|
||||
* all databases.
|
||||
* It's not essential to know the cluster size, but useful to sanity-check
|
||||
* we can actually run a query before going any further.
|
||||
*/
|
||||
if (get_cluster_size(source_conn, cluster_size) == true)
|
||||
log_detail(_("current installation size is %s"),
|
||||
if (get_cluster_size(source_conn, cluster_size) == false)
|
||||
exit(ERR_DB_QUERY);
|
||||
|
||||
log_detail(_("current installation size is %s"),
|
||||
cluster_size);
|
||||
|
||||
/*
|
||||
|
||||
@@ -3187,11 +3187,6 @@ copy_remote_files(char *host, char *remote_user, char *remote_path,
|
||||
" --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,
|
||||
" --exclude=pg_stat_tmp/*");
|
||||
|
||||
|
||||
36
repmgr.c
36
repmgr.c
@@ -80,17 +80,12 @@ typedef struct repmgrdSharedState
|
||||
|
||||
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;
|
||||
|
||||
|
||||
void _PG_init(void);
|
||||
void _PG_fini(void);
|
||||
|
||||
#if (PG_VERSION_NUM >= 150000)
|
||||
static void repmgr_shmem_request(void);
|
||||
#endif
|
||||
static void repmgr_shmem_startup(void);
|
||||
|
||||
PG_FUNCTION_INFO_V1(repmgr_set_local_node_id);
|
||||
@@ -122,27 +117,19 @@ _PG_init(void)
|
||||
if (!process_shared_preload_libraries_in_progress)
|
||||
return;
|
||||
|
||||
#if (PG_VERSION_NUM < 150000)
|
||||
RequestAddinShmemSpace(MAXALIGN(sizeof(repmgrdSharedState)));
|
||||
|
||||
#if (PG_VERSION_NUM >= 90600)
|
||||
RequestNamedLWLockTranche(TRANCHE_NAME, 1);
|
||||
#else
|
||||
RequestAddinLWLocks(1);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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;
|
||||
shmem_startup_hook = repmgr_shmem_startup;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -153,31 +140,12 @@ void
|
||||
_PG_fini(void)
|
||||
{
|
||||
/* Uninstall hook */
|
||||
#if (PG_VERSION_NUM >= 150000)
|
||||
shmem_request_hook = prev_shmem_request_hook;
|
||||
#endif
|
||||
|
||||
shmem_startup_hook = prev_shmem_startup_hook;
|
||||
}
|
||||
|
||||
#if (PG_VERSION_NUM >= 150000)
|
||||
/*
|
||||
* shmem_requst_hook: request shared memory
|
||||
*/
|
||||
static void
|
||||
repmgr_shmem_request(void)
|
||||
{
|
||||
if (prev_shmem_request_hook)
|
||||
prev_shmem_request_hook();
|
||||
|
||||
RequestAddinShmemSpace(MAXALIGN(sizeof(repmgrdSharedState)));
|
||||
|
||||
RequestNamedLWLockTranche(TRANCHE_NAME, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* shmem_ hook: allocate or attach to shared memory,
|
||||
* shmem_startup hook: allocate or attach to shared memory,
|
||||
*/
|
||||
static void
|
||||
repmgr_shmem_startup(void)
|
||||
|
||||
@@ -398,7 +398,7 @@ ssh_options='-q -o ConnectTimeout=10' # Options to append to "ssh"
|
||||
#
|
||||
# Debian/Ubuntu users: use "sudo pg_ctlcluster" to execute service control commands.
|
||||
#
|
||||
# For more details, see: https://repmgr.org/docs/current/configuration-file-service-commands.html
|
||||
# For more details, see: https://repmgr.org/docs/current/configuration-service-commands.html
|
||||
|
||||
#service_start_command = ''
|
||||
#service_stop_command = ''
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# repmgr extension
|
||||
comment = 'Replication manager for PostgreSQL'
|
||||
default_version = '5.4'
|
||||
default_version = '5.3'
|
||||
module_pathname = '$libdir/repmgr'
|
||||
relocatable = false
|
||||
schema = repmgr
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#define REPMGR_VERSION_DATE ""
|
||||
#define REPMGR_VERSION "5.4dev"
|
||||
#define REPMGR_VERSION_NUM 50400
|
||||
#define REPMGR_EXTENSION_VERSION "5.4"
|
||||
#define REPMGR_EXTENSION_NUM 50400
|
||||
#define REPMGR_RELEASE_DATE "2022-XX-XX"
|
||||
#define REPMGR_VERSION "5.3.1"
|
||||
#define REPMGR_VERSION_NUM 50301
|
||||
#define REPMGR_EXTENSION_VERSION "5.3"
|
||||
#define REPMGR_EXTENSION_NUM 50300
|
||||
#define REPMGR_RELEASE_DATE "2022-02-15"
|
||||
#define PG_ACTUAL_VERSION_NUM
|
||||
|
||||
@@ -2382,18 +2382,6 @@ monitor_streaming_witness(void)
|
||||
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);
|
||||
}
|
||||
|
||||
initPQExpBuffer(&event_details);
|
||||
|
||||
appendPQExpBuffer(&event_details,
|
||||
@@ -2862,7 +2850,6 @@ do_primary_failover(void)
|
||||
bool final_result = false;
|
||||
NodeInfoList sibling_nodes = T_NODE_INFO_LIST_INITIALIZER;
|
||||
int new_primary_id = UNKNOWN_NODE_ID;
|
||||
bool standby_disconnect_on_failover = false;
|
||||
|
||||
/*
|
||||
* Double-check status of the local connection
|
||||
@@ -2875,20 +2862,20 @@ do_primary_failover(void)
|
||||
*/
|
||||
if (config_file_options.standby_disconnect_on_failover == true)
|
||||
{
|
||||
/*
|
||||
* Determine whether we can actually disable the walsender; this depends
|
||||
* on PostgreSQL version and user permissions.
|
||||
*/
|
||||
standby_disconnect_on_failover = can_disable_walsender(local_conn);
|
||||
NodeInfoListCell *cell = NULL;
|
||||
NodeInfoList check_sibling_nodes = T_NODE_INFO_LIST_INITIALIZER;
|
||||
int i;
|
||||
|
||||
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);
|
||||
|
||||
/*
|
||||
@@ -2972,7 +2959,7 @@ do_primary_failover(void)
|
||||
log_debug("election result: %s", _print_election_result(election_result));
|
||||
|
||||
/* 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 */
|
||||
enable_wal_receiver(local_conn, false);
|
||||
|
||||
@@ -479,7 +479,7 @@ main(int argc, char **argv)
|
||||
switch (config_file_options.replication_type)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user