diff --git a/HISTORY b/HISTORY index 5f8dcde9d52ebaba148802ea71b022a6781052ec..c8ef1e92242bd38bb77ec08c31c042efea5959b9 100644 --- a/HISTORY +++ b/HISTORY @@ -1,5 +1,14 @@ -5.3.1 2022-??-?? +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) + 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) diff --git a/configure.in b/configure.in index 21fa4fa396e7c06c7d047c5d6d00e1b7866d4cd8..7b9cd03cff89b9eb2264dbb009b8d5dcd3ff96bd 100644 --- a/configure.in +++ b/configure.in @@ -1,6 +1,6 @@ -AC_INIT([repmgr], [5.3.1], [repmgr@googlegroups.com], [repmgr], [https://repmgr.org/]) +AC_INIT([repmgr], [5.3.2], [repmgr@googlegroups.com], [repmgr], [https://repmgr.org/]) -AC_COPYRIGHT([Copyright (c) 2010-2021, EnterpriseDB Corporation]) +AC_COPYRIGHT([Copyright (c) 2010-2022, EnterpriseDB Corporation]) AC_CONFIG_HEADER(config.h) diff --git a/dbutils.c b/dbutils.c index 22ab1b8509238336ba407bff545e50128fa1c7da..791d7d7c78b4e99f488e70d3dd1f8ce1abd12e71 100644 --- a/dbutils.c +++ b/dbutils.c @@ -61,6 +61,8 @@ 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; @@ -1289,21 +1291,16 @@ 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); @@ -1826,6 +1823,30 @@ 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 */ /* =============================== */ @@ -1867,6 +1888,42 @@ 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 @@ -2246,29 +2303,6 @@ 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) @@ -4576,17 +4610,17 @@ drop_replication_slot_replprot(PGconn *repl_conn, char *slot_name) initPQExpBuffer(&query); appendPQExpBuffer(&query, - "DROP_REPLICATION_SLOT %s", + "DROP_REPLICATION_SLOT %s;", slot_name); log_verbose(LOG_DEBUG, "drop_replication_slot_replprot():\n %s", query.data); res = PQexec(repl_conn, query.data); - if (PQresultStatus(res) != PGRES_TUPLES_OK) + if (PQresultStatus(res) != PGRES_TUPLES_OK || !PQntuples(res)) { log_db_error(repl_conn, query.data, - _("drop_replication_slot_sql(): unable to drop replication slot \"%s\""), + _("drop_replication_slot_replprot(): unable to drop replication slot \"%s\""), slot_name); success = false; @@ -5704,7 +5738,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) { @@ -5792,6 +5826,19 @@ 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; @@ -5826,9 +5873,12 @@ is_downstream_node_attached(PGconn *conn, char *node_name, char **node_state) */ if (PQntuples(res) > 1) { - 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")); + 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")); + } PQclear(res); @@ -5837,7 +5887,8 @@ is_downstream_node_attached(PGconn *conn, char *node_name, char **node_state) if (PQntuples(res) == 0) { - log_warning(_("node \"%s\" not found in \"pg_stat_replication\""), node_name); + if (quiet == false) + log_warning(_("node \"%s\" not found in \"pg_stat_replication\""), node_name); PQclear(res); @@ -5863,9 +5914,10 @@ is_downstream_node_attached(PGconn *conn, char *node_name, char **node_state) if (strcmp(state, "streaming") != 0) { - log_warning(_("node \"%s\" attached in state \"%s\""), - node_name, - state); + if (quiet == false) + log_warning(_("node \"%s\" attached in state \"%s\""), + node_name, + state); PQclear(res); diff --git a/dbutils.h b/dbutils.h index e2783cea13fa524cb229561a71283590f9279fb4..23bfff2912f738ab8495ab5bf10108ab11d5a8e0 100644 --- a/dbutils.h +++ b/dbutils.h @@ -450,9 +450,11 @@ 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); @@ -467,7 +469,6 @@ 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); @@ -597,6 +598,7 @@ 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); diff --git a/doc/appendix-faq.xml b/doc/appendix-faq.xml index 6248d43f49f4753c0b5fe45d15478171838c555c..49bc738ca6df4045ab10a66a9fcc2b1b85d1b074 100644 --- a/doc/appendix-faq.xml +++ b/doc/appendix-faq.xml @@ -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 <filename>recovery.conf</filename> file for + can be used to create the correct replication configuration 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 <filename>recovery.conf</filename>, and what options can be set there?</title> + <title>What does &repmgr; write in the replication configuration, and what options can be set there?</title> <para> - See section <link linkend="repmgr-standby-clone-recovery-conf">Customising recovery.conf</link>. + See section <link linkend="repmgr-standby-clone-recovery-conf">Customising replication configuration</link>. </para> </sect2> @@ -366,11 +366,11 @@ </para> </sect2> - <sect2 id="faq-repmgr-recovery-conf-quoted-values" xreflabel="Quoted values in recovery.conf"> - <title>Why are some values in <filename>recovery.conf</filename> surrounded by pairs of single quotes?</title> + <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> <para> This is to ensure that user-supplied values which are written as parameter values in <filename>recovery.conf</filename> - are escaped correctly and do not cause errors when <filename>recovery.conf</filename> is parsed. + are escaped correctly and do not cause errors when the file 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 <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. + 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. </para> <para> We recommend that delayed standbys are explicitly excluded from promotion diff --git a/doc/appendix-packages.xml b/doc/appendix-packages.xml index a96f8b747a7b988f5bccdf4caf63fde2186b0b86..eedfef31b2af787d6036cb564b49afe8d0e2a0ab 100644 --- a/doc/appendix-packages.xml +++ b/doc/appendix-packages.xml @@ -50,18 +50,18 @@ <title>CentOS repositories</title> <para> - &repmgr; packages are available from the public 2ndQuadrant repository, and also the - PostgreSQL community repository. The 2ndQuadrant repository is updated immediately + &repmgr; packages are available from the public EDB repository, and also the + PostgreSQL community repository. The EDB repository is updated immediately after each &repmgr; release. </para> <table id="centos-2ndquadrant-repository"> - <title>2ndQuadrant public repository</title> + <title>EDB public repository</title> <tgroup cols="2"> <tbody> <row> <entry>Repository URL:</entry> - <entry><ulink url="https://dl.2ndquadrant.com/">https://dl.2ndquadrant.com/</ulink></entry> + <entry><ulink url="https://dl.enterprisedb.com/">https://dl.enterprisedb.com/</ulink></entry> </row> <row> <entry>Repository documentation:</entry> @@ -252,7 +252,7 @@ </indexterm> <para> - &repmgr; <literal>.deb</literal> packages are provided by 2ndQuadrant as well as the + &repmgr; <literal>.deb</literal> packages are provided by EDB 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>2ndQuadrant public repository</title> + <title>EDB public repository</title> <tgroup cols="2"> <tbody> <row> <entry>Repository URL:</entry> - <entry><ulink url="https://dl.2ndquadrant.com/">https://dl.2ndquadrant.com/</ulink></entry> + <entry><ulink url="https://dl.enterprisedb.com/">https://dl.enterprisedb.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 2ndQuadrant provides + For testing new features and bug fixes, from time to time EDB 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 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> + 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> in the appropriate URL. </para> <para> For example, to install the snapshot RPM repository for PostgreSQL 9.6, execute (as <literal>root</literal>): <programlisting> -curl https://dl.2ndquadrant.com/default/snapshot/get/9.6/rpm | bash</programlisting> +curl https://dl.enterprisedb.com/default/snapshot/get/9.6/rpm | bash</programlisting> or as a normal user with root sudo access: <programlisting> -curl https://dl.2ndquadrant.com/default/snapshot/get/9.6/rpm | sudo bash</programlisting> +curl https://dl.enterprisedb.com/default/snapshot/get/9.6/rpm | sudo bash</programlisting> </para> <para> Alternatively you can browse the repository here: - <ulink url="https://dl.2ndquadrant.com/default/snapshot/browse/">https://dl.2ndquadrant.com/default/snapshot/browse/</ulink>. + <ulink url="https://dl.enterprisedb.com/default/snapshot/browse/">https://dl.enterprisedb.com/default/snapshot/browse/</ulink>. </para> <para> Once the repository is installed, installing or updating &repmgr; will result in the latest snapshot @@ -493,32 +493,6 @@ 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> diff --git a/doc/appendix-release-notes.xml b/doc/appendix-release-notes.xml index 347c0564f51704b06a0a3b1babdb454823469759..8f3f6e8ec433deed8ac5f03e8a5b7ddc9a07f816 100644 --- a/doc/appendix-release-notes.xml +++ b/doc/appendix-release-notes.xml @@ -15,13 +15,79 @@ See also: <xref linkend="upgrading-repmgr"/> </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.3.2"> + <title id="release-current">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 id="release-current">Release 5.3.1</title> + <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> @@ -56,6 +122,11 @@ 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> diff --git a/doc/appendix-support.xml b/doc/appendix-support.xml index 4dee47e3bcefa468d63e9f08a592b1cef482277d..2c4408d2ea343cd550dc97c391b595af3e02ce96 100644 --- a/doc/appendix-support.xml +++ b/doc/appendix-support.xml @@ -7,13 +7,13 @@ </indexterm> <para> - <ulink url="https://2ndquadrant.com/">2ndQuadrant</ulink> provides 24x7 + <ulink url="https://www.enterprisedb.com/">EDB</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://2ndquadrant.com/en/support/">https://2ndquadrant.com/en/support/</ulink> + For further details see: <ulink url="https://www.enterprisedb.com/support/postgresql-support-overview-get-the-most-out-of-postgresql">Support Center</ulink> </para> <para> diff --git a/doc/cloning-standbys.xml b/doc/cloning-standbys.xml index eca50feefa9aa53f5bfcf8829cc27b9b04980a15..fc5a18abeecb017cb45a9171454dced3aef3a106 100644 --- a/doc/cloning-standbys.xml +++ b/doc/cloning-standbys.xml @@ -15,7 +15,7 @@ <para> <xref linkend="repmgr-standby-clone"/> can use - <ulink url="https://www.2ndquadrant.com/">2ndQuadrant</ulink>'s + <ulink url="https://www.enterprisedb.com/">EDB</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 <filename>recovery.conf</filename> to + setting <varname>restore_command</varname> in the replication configuration 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 2ndQuadrant's <ulink url="https://www.pgbarman.org/">Barman</ulink>, + As an alternative we recommend using EDB'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 <filename>recovery.conf</filename> to point to it. Note + &repmgr; will create a replication configuration file to point to it. Note that if <literal>--upstream-node-id</literal> is not explicitly provided, - &repmgr; will set the standby's <filename>recovery.conf</filename> to + &repmgr; will set the standby's replication configuration 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 <filename>recovery.conf</filename>. + in the replication configuration. </simpara> </tip> </sect1> @@ -491,12 +491,12 @@ description = "Main cluster" </note> <para> - If, for whatever reason, you wish to include the password in <filename>recovery.conf</filename>, + If, for whatever reason, you wish to include the password in the replication configuration file, 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 <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 + 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 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 <filename>recovery.conf</filename>. This + replication connections and generating the replication configuration. 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"/>. diff --git a/doc/configuration-file.xml b/doc/configuration-file.xml index 9bb4795e7815fb0ef34c7f773e9c9b20def52c80..fccdc89f7e5f48b00a0180a8ee007515a8f6253b 100644 --- a/doc/configuration-file.xml +++ b/doc/configuration-file.xml @@ -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/2ndQuadrant/repmgr/master/repmgr.conf.sample">repmgr.conf.sample</ulink>. + <ulink url="https://raw.githubusercontent.com/EnterpriseDB/repmgr/master/repmgr.conf.sample">repmgr.conf.sample</ulink>. </para> <para> For &repmgrd;-specific settings, see <xref linkend="repmgrd-configuration"/>. diff --git a/doc/configuration-permissions.xml b/doc/configuration-permissions.xml index fb0038c478d6db7be2c761e66dc7f2a9ac4e6836..d3977404371c7af307164c3c72fddb794f2315ee 100644 --- a/doc/configuration-permissions.xml +++ b/doc/configuration-permissions.xml @@ -7,19 +7,186 @@ </indexterm> <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. + 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. </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> + <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> </sect1> diff --git a/doc/install-packages.xml b/doc/install-packages.xml index 371fae317b81b60e074b3e9de3e2ef9acc7e77e1..2c4d67df90541f46bb92dd456451af2bbb59f8c3 100644 --- a/doc/install-packages.xml +++ b/doc/install-packages.xml @@ -22,16 +22,15 @@ <para> &repmgr; RPM packages for RedHat/CentOS variants and Fedora are available from the - <ulink url="https://2ndquadrant.com">2ndQuadrant</ulink> - <ulink url="https://dl.2ndquadrant.com/">public repository</ulink>; see following + <ulink url="https://www.enterprisedb.com">EDB</ulink> + <ulink url="https://dl.enterprisedb.com/">public repository</ulink>; see following section for details. </para> <note> <para> - 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. + 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. </para> </note> <para> @@ -45,7 +44,7 @@ <note> <para> &repmgr; RPM packages are designed to be compatible with the community-provided PostgreSQL packages - and 2ndQuadrant's <ulink url="https://www.2ndquadrant.com/en/resources/2ndqpostgres/">2ndQPostgres</ulink>. + and EDB's PostgreSQL Extended Server (formerly 2ndQPostgres). 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. @@ -64,16 +63,16 @@ <sect3 id="installation-packages-redhat-2ndq"> - <title>2ndQuadrant public RPM yum repository</title> + <title>EDB public RPM yum repository</title> <para> - <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, + <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, including &repmgr;. We recommend using this for all future &repmgr; releases. </para> <para> General instructions for using this repository can be found on its - <ulink url="https://dl.2ndquadrant.com/">homepage</ulink>. Specific instructions + <ulink url="https://dl.enterprisedb.com/">homepage</ulink>. Specific instructions for installing &repmgr; follow below. </para> <para> @@ -83,57 +82,46 @@ <listitem> <para> Locate the repository RPM for your PostgreSQL version from the list at: - <ulink url="https://dl.2ndquadrant.com/">https://dl.2ndquadrant.com/</ulink> + <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 2ndQuadrant repository as a source of &repmgr; packages). + <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 11 on CentOS, execute: + For example, for PostgreSQL 14 on Rocky Linux 8, execute: <programlisting> -curl https://dl.2ndquadrant.com/default/release/get/11/rpm | sudo bash</programlisting> +curl https://dl.enterprisedb.com/default/release/get/14/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> +sudo dnf 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> +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> </listitem> <listitem> <para> - Install the &repmgr; version appropriate for your PostgreSQL version (e.g. <literal>repmgr10</literal>): + Install the &repmgr; version appropriate for your PostgreSQL version (e.g. <literal>repmgr14</literal>): <programlisting> -sudo yum install repmgr11</programlisting> +sudo dnf install repmgr14</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> -yum search repmgr</programlisting> +dnf search repmgr</programlisting> + </para> + <para> + In CentOS 7 and earlier, use <literal>yum</literal> instead of <literal>dnf</literal>. </para> </tip> @@ -145,7 +133,7 @@ yum search repmgr</programlisting> <emphasis>Compatibility with PGDG Repositories</emphasis> </para> <para> - The 2ndQuadrant &repmgr; yum repository packages use the same definitions and file system layout as the + The EDB &repmgr; yum repository packages use the same definitions and file system layout as the main PGDG repository. </para> <para> @@ -154,36 +142,42 @@ yum search repmgr</programlisting> the packages are installed from. </para> <para> - To ensure the 2ndQuadrant repository is always prioritised, install <literal>yum-plugin-priorities</literal> - and set the repository priorities accordingly. + 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. </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>yum --showduplicates list</command> + To install a specific package version, execute <command>dnf --showduplicates list</command> for the package in question: <programlisting> -[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 +[root@localhost ~]# dnf --showduplicates list repmgr10 +Last metadata expiration check: 0:09:15 ago on Fri 11 Mar 2022 01:09:19 AM UTC. Installed Packages -repmgr11.x86_64 4.4.0-1.rhel7 @pgdg11 +repmgr10.x86_64 5.3.1-1.el8 @2ndquadrant-dl-default-release-pg10 Available Packages -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> +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> then append the appropriate version number to the package name with a hyphen, e.g.: <programlisting> -[root@localhost ~]# yum install repmgr11-4.3-1.el7</programlisting> +[root@localhost ~]# dnf install repmgr10-5.3.0-1.el8</programlisting> </para> - <para> <emphasis>Installing old packages</emphasis> </para> @@ -191,7 +185,6 @@ repmgr11.x86_64 4.4-1.el7 2nd 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> @@ -217,16 +210,16 @@ repmgr11.x86_64 4.4-1.el7 2nd </para> <sect3 id="installation-packages-debian-ubuntu-2ndq"> - <title>2ndQuadrant public apt repository for Debian/Ubuntu</title> + <title>EDB public apt repository for Debian/Ubuntu</title> <para> - <ulink url="https://2ndquadrant.com/">2ndQuadrant</ulink> provides a - <ulink url="https://dl.2ndquadrant.com/">public apt repository</ulink> for 2ndQuadrant software, + <ulink url="https://www.enterprisedb.com/">EDB</ulink> provides a + <ulink url="https://dl.enterprisedb.com/">public apt repository</ulink> for EDB software, including &repmgr;. </para> <para> General instructions for using this repository can be found on its - <ulink url="https://dl.2ndquadrant.com/">homepage</ulink>. Specific instructions + <ulink url="https://dl.enterprisedb.com/">homepage</ulink>. Specific instructions for installing &repmgr; follow below. </para> @@ -239,9 +232,9 @@ repmgr11.x86_64 4.4-1.el7 2nd <listitem> <para> Install the repository definition for your distribution and PostgreSQL version - (this enables the 2ndQuadrant repository as a source of &repmgr; packages) by executing: + (this enables the EDB repository as a source of &repmgr; packages) by executing: <programlisting> - curl https://dl.2ndquadrant.com/default/release/get/deb | sudo bash</programlisting> + curl https://dl.enterprisedb.com/default/release/get/deb | sudo bash</programlisting> </para> <note> <para> diff --git a/doc/legal.xml b/doc/legal.xml index d1c50ef95903d49f15d21a23e558ab8626fbd8e1..f6e06aa21eeec930502e6413d6d7c42dedc9574d 100644 --- a/doc/legal.xml +++ b/doc/legal.xml @@ -1,18 +1,18 @@ <!-- doc/legal.xml --> -<date>2017</date> +<date>2022</date> <copyright> - <year>2010-2021</year> - <holder>EnterpriseDB Corporation</holder> + <year>2010-2022</year> + <holder>EDB</holder> </copyright> <legalnotice id="legalnotice"> <title>Legal Notice</title> <para> - <productname>repmgr</productname> is Copyright © 2010-2021 - by EnterpriseDB Corporation All rights reserved. + <productname>repmgr</productname> is Copyright © 2010-2022 + by EDB All rights reserved. </para> <para> diff --git a/doc/quickstart.xml b/doc/quickstart.xml index b7c5d056177ea76bb98f6ff7deb68567dd018b17..08c77474bf88b3ec076906166791a97a6d882415 100644 --- a/doc/quickstart.xml +++ b/doc/quickstart.xml @@ -405,9 +405,10 @@ </programlisting> <para> This has cloned the PostgreSQL data directory files from the primary <literal>node1</literal> - 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. + 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). </para> <note> <simpara> @@ -481,9 +482,10 @@ 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>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>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>. </para> </sect1> diff --git a/doc/repmgr-standby-clone.xml b/doc/repmgr-standby-clone.xml index ad7470c7dd3eca0a326b450272db060c7d471adb..eac759717c0be0a35f13db4543988d904578e821 100644 --- a/doc/repmgr-standby-clone.xml +++ b/doc/repmgr-standby-clone.xml @@ -332,6 +332,12 @@ 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> @@ -399,11 +405,15 @@ pg_basebackup_options='--waldir=/path/to/wal-directory'</programlisting> </varlistentry> <varlistentry> - <term><option>--superuser</option></term> + <term><option>-S</option>/<option>--superuser</option></term> <listitem> <para> - If the &repmgr; user is not a superuser, the name of a valid superuser must - be provided with this option. + 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. </para> </listitem> </varlistentry> diff --git a/doc/repmgr-standby-switchover.xml b/doc/repmgr-standby-switchover.xml index 8ae0043595c2e4946ae04fe8e3ae593c67ce3019..90deb15c64ee1ba8f3aae1b277a1e857869ab45f 100644 --- a/doc/repmgr-standby-switchover.xml +++ b/doc/repmgr-standby-switchover.xml @@ -64,6 +64,13 @@ <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 @@ -72,7 +79,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>. + provided with the <option>-S</option>/<option>--superuser</option> option. </para> <para> If &repmgr; is unable to execute the <command>CHECKPOINT</command> command, the switchover diff --git a/doc/repmgr.xml b/doc/repmgr.xml index 5713e4bee70c0695d9d807c2d39498a5d720b155..10618dda1d7eec38f51a91d6d0531ca77ec87fe9 100644 --- a/doc/repmgr.xml +++ b/doc/repmgr.xml @@ -18,7 +18,7 @@ <title>repmgr &repmgrversion; Documentation</title> <bookinfo> - <corpauthor>EnterpriseDB Corporation</corpauthor> + <corpauthor>EDB</corpauthor> <productname>repmgr</productname> <productnumber>&repmgrversion;</productnumber> &legal; @@ -38,19 +38,18 @@ <para> &repmgr; is developed by - <ulink url="https://2ndquadrant.com">2ndQuadrant (EDB)</ulink> + <ulink url="https://www.enterprisedb.com/">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 2ndQuadrant (EDB) customers contribute funding - to make repmgr development possible. + Multiple EDB customers contribute funding to make &repmgr; development possible. </para> <para> - &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;. + &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;. We welcome participation from other organisations and individual developers. </para> </abstract> diff --git a/doc/repmgrd-automatic-failover.xml b/doc/repmgrd-automatic-failover.xml index 795afc615359c4edfc86267c51c1d20f074b20db..5c58890be96eb1ec348dc219f7a5d9bfb9e3d900 100644 --- a/doc/repmgrd-automatic-failover.xml +++ b/doc/repmgrd-automatic-failover.xml @@ -81,11 +81,15 @@ </para> <note> <simpara> - &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. + 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. </simpara> </note> + <para> The witness server should be configured in the same way as a normal &repmgr; node; see section <xref linkend="configuration"/>. diff --git a/repmgr-action-node.c b/repmgr-action-node.c index f709ca63064df64fd64ae68326d4b1bb95f7e181..ac476172724d6526a24daa0a21ed0ed525347e60 100644 --- a/repmgr-action-node.c +++ b/repmgr-action-node.c @@ -1327,7 +1327,7 @@ do_node_check_downstream(PGconn *conn, OutputMode mode, t_node_info *node_info, continue; } - if (is_downstream_node_attached(conn, cell->node_info->node_name, NULL) != NODE_ATTACHED) + if (is_downstream_node_attached_quiet(conn, cell->node_info->node_name, NULL) != NODE_ATTACHED) { missing_nodes_count++; item_list_append_format(&missing_nodes, @@ -1395,49 +1395,32 @@ 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; - printf("missing: "); + appendPQExpBufferStr(&details, " (missing: "); + for (missing_cell = missing_nodes.head; missing_cell; missing_cell = missing_cell->next) { if (first == false) - printf(", "); + appendPQExpBufferStr(&details, ", "); else first = false; if (first == false) - printf("%s", missing_cell->string); + appendPQExpBufferStr(&details, missing_cell->string); } - } - - 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); - } + appendPQExpBufferChar(&details, ')'); } - printf("\n"); + 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); } break; case OM_CSV: @@ -1535,7 +1518,7 @@ do_node_check_upstream(PGconn *conn, OutputMode mode, t_node_info *node_info, Ch { case OM_NAGIOS: { - printf("REPMGR_UPSTREAM_SERVER %s: %s | ", + printf("REPMGR_UPSTREAM_SERVER %s: %s\n", output_check_status(status), details.data); } diff --git a/repmgr-action-standby.c b/repmgr-action-standby.c index 6e10f152ebf7773900fd76f36e49560d2466df4f..cc9829c1c0512692c9e5bc3098e60853c129e251 100644 --- a/repmgr-action-standby.c +++ b/repmgr-action-standby.c @@ -95,6 +95,8 @@ 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; @@ -3346,10 +3348,9 @@ 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); } - if (create_replication_slot(follow_target_conn, local_node_record.slot_name, - NULL, + follow_target_node_record, output) == false) { log_error("%s", output->data); @@ -5783,20 +5784,18 @@ check_source_server() } /* - * If a connection was established, perform some sanity checks on the - * provided upstream connection. + * The server version check will also serve as a sanity-check that we can + * actually execute queries on this connection. */ - source_server_version_num = check_server_version(source_conn, "primary", true, NULL); /* - * It's not essential to know the cluster size, but useful to sanity-check - * we can actually run a query before going any further. + * 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. */ - if (get_cluster_size(source_conn, cluster_size) == false) - exit(ERR_DB_QUERY); - - log_detail(_("current installation size is %s"), + if (get_cluster_size(source_conn, cluster_size) == true) + log_detail(_("current installation size is %s"), cluster_size); /* diff --git a/repmgr-client.c b/repmgr-client.c index 6115a61e06f399ff922c1409064c2bc2aa90b62f..395d1590f0140aaf65495db50722ccb8c485d18d 100644 --- a/repmgr-client.c +++ b/repmgr-client.c @@ -90,17 +90,22 @@ char pg_bindir[MAXPGPATH] = ""; */ t_node_info target_node_info = T_NODE_INFO_INITIALIZER; -/* used by create_replication_slot() */ +/* set by the first call to _determine_replication_slot_user() */ static t_user_type ReplicationSlotUser = USER_TYPE_UNKNOWN; /* Collate command line errors and warnings here for friendlier reporting */ static ItemList cli_errors = {NULL, NULL}; static ItemList cli_warnings = {NULL, NULL}; + static void _determine_replication_slot_user(PGconn *conn, t_node_info *upstream_node_record, char **replication_user); +static PGconn *_get_replication_slot_connection(PGconn *conn, + char *replication_user, + bool *use_replication_protocol); + int main(int argc, char **argv) { @@ -3734,6 +3739,7 @@ create_replication_slot(PGconn *conn, char *slot_name, t_node_info *upstream_nod char *replication_user = NULL; _determine_replication_slot_user(conn, upstream_node_record, &replication_user); + /* * If called in --dry-run context, if the replication slot user is not the * repmgr user, attempt to validate the connection. @@ -3745,7 +3751,7 @@ create_replication_slot(PGconn *conn, char *slot_name, t_node_info *upstream_nod case USER_TYPE_UNKNOWN: log_error("unable to determine user for replication slot creation"); return false; - case REPMGR_USER: + case REPMGR_USER: log_info(_("replication slots will be created by user \"%s\""), PQuser(conn)); return true; @@ -3791,65 +3797,12 @@ create_replication_slot(PGconn *conn, char *slot_name, t_node_info *upstream_nod PQfinish(superuser_conn); } } - } - /* - * 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; - - 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 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; + slot_conn = _get_replication_slot_connection(conn, replication_user, &use_replication_protocol); - 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 (slot_conn == NULL) + return false; if (use_replication_protocol == true) { @@ -3892,34 +3845,53 @@ drop_replication_slot_if_exists(PGconn *conn, int node_id, char *slot_name) if (record_status != RECORD_FOUND) { - /* this is not a bad good thing */ + /* no slot, no problem */ log_verbose(LOG_INFO, _("slot \"%s\" does not exist on node %i, nothing to remove"), slot_name, node_id); return true; } - if (slot_info.active == false) + if (slot_info.active == true) { - 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); } else { log_error(_("unable to delete replication slot \"%s\" on node %i"), slot_name, node_id); - success = false; } - } - /* - * 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; + if (slot_conn != conn) + PQfinish(slot_conn); } return success; @@ -3981,10 +3953,88 @@ _determine_replication_slot_user(PGconn *conn, t_node_info *upstream_node_record ReplicationSlotUser = REPLICATION_USER_NODE; *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 check_replication_slots_available(int node_id, PGconn* conn) { diff --git a/repmgr.c b/repmgr.c index 16a21b8245ce573ee6cc0d252d86c9f1cf464bd2..299cc00de522f3b271873f63e07b8eb6bc504440 100644 --- a/repmgr.c +++ b/repmgr.c @@ -84,7 +84,6 @@ static shmem_startup_hook_type prev_shmem_startup_hook = NULL; void _PG_init(void); -void _PG_fini(void); static void repmgr_shmem_startup(void); @@ -133,17 +132,6 @@ _PG_init(void) } -/* - * Module unload callback - */ -void -_PG_fini(void) -{ - /* Uninstall hook */ - shmem_startup_hook = prev_shmem_startup_hook; -} - - /* * shmem_startup hook: allocate or attach to shared memory, */ diff --git a/repmgr.conf.sample b/repmgr.conf.sample index 01d69f4182a8e25250f2bc021d833065ad743650..2c1e808c12f7165b3b48fa4e39cc8f1744c4158d 100644 --- a/repmgr.conf.sample +++ b/repmgr.conf.sample @@ -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-service-commands.html +# For more details, see: https://repmgr.org/docs/current/configuration-file-service-commands.html #service_start_command = '' #service_stop_command = '' diff --git a/repmgr_version.h.in b/repmgr_version.h.in index 823e4b87a46ad87f7bed68a6cfd98364c9f1c762..2cb3fc893054c03216a522eb4336a2823347126d 100644 --- a/repmgr_version.h.in +++ b/repmgr_version.h.in @@ -1,7 +1,7 @@ #define REPMGR_VERSION_DATE "" -#define REPMGR_VERSION "5.3.1" -#define REPMGR_VERSION_NUM 50301 +#define REPMGR_VERSION "5.3.2" +#define REPMGR_VERSION_NUM 50302 #define REPMGR_EXTENSION_VERSION "5.3" #define REPMGR_EXTENSION_NUM 50300 -#define REPMGR_RELEASE_DATE "2022-02-15" +#define REPMGR_RELEASE_DATE "2022-05-25" #define PG_ACTUAL_VERSION_NUM diff --git a/repmgrd-physical.c b/repmgrd-physical.c index 9a2624d40bba4de66af35f53b26b3d643685e04a..f20f9b4331446578d3a8c035a79e37bcb513ff9b 100644 --- a/repmgrd-physical.c +++ b/repmgrd-physical.c @@ -2382,6 +2382,18 @@ 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, @@ -2850,6 +2862,7 @@ 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 @@ -2862,20 +2875,20 @@ do_primary_failover(void) */ if (config_file_options.standby_disconnect_on_failover == true) { - NodeInfoListCell *cell = NULL; - NodeInfoList check_sibling_nodes = T_NODE_INFO_LIST_INITIALIZER; - int i; - - bool sibling_node_wal_receiver_connected = false; + /* + * 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); - 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 + if (standby_disconnect_on_failover == true) { + 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); /* @@ -2959,7 +2972,7 @@ do_primary_failover(void) log_debug("election result: %s", _print_election_result(election_result)); /* Reenable WAL receiver, if disabled */ - if (config_file_options.standby_disconnect_on_failover == true) + if (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); diff --git a/repmgrd.c b/repmgrd.c index 94be8d6a0fa631f88e6a9a0420065a1293850581..2369859434ee77b8c5717a3c265b0bbd072fd16b 100644 --- a/repmgrd.c +++ b/repmgrd.c @@ -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) register' was executed for this node")); + log_hint(_("check that 'repmgr (primary|standby|witness) register' was executed for this node")); break; }