diff --git a/HISTORY b/HISTORY index c8f670a8..82055fc7 100644 --- a/HISTORY +++ b/HISTORY @@ -18,6 +18,8 @@ GitHub #451 (Ian) repmgr: fix "primary_slot_name" when using "standby clone" with --recovery-conf-only; GitHub #474 (Ian) + repmgr: don't perform a switchover if an exclusive backup is running; + GitHub #476 (Martín) repmgr: enable "witness unregister" to be run on any node; GitHub #472 (Ian) repmgrd: create a PID file by default; GitHub #457 (Ian) repmgrd: daemonize process by default; GitHub #458 (Ian) diff --git a/dbutils.c b/dbutils.c index 607821df..0a52c377 100644 --- a/dbutils.c +++ b/dbutils.c @@ -1601,6 +1601,39 @@ repmgrd_get_local_node_id(PGconn *conn) } +/* + * Function that checks if the primary is in exclusive backup mode. + * We'll use this when executing an action can conflict with an exclusive + * backup. + */ +BackupState +server_in_exclusive_backup_mode(PGconn *conn) +{ + BackupState backup_state = BACKUP_STATE_UNKNOWN; + PGresult *res = PQexec(conn, "SELECT pg_catalog.pg_is_in_backup()"); + + if (PQresultStatus(res) != PGRES_TUPLES_OK) + { + log_error(_("unable to retrieve information regarding backup mode of node")); + log_detail("%s", PQerrorMessage(conn)); + PQclear(res); + return BACKUP_STATE_UNKNOWN; + } + + if (atobool(PQgetvalue(res, 0, 0)) == true) + { + backup_state = BACKUP_STATE_IN_BACKUP; + } + else + { + backup_state = BACKUP_STATE_NO_BACKUP; + } + + PQclear(res); + + return backup_state; +} + /* ================ */ /* result functions */ @@ -3953,31 +3986,7 @@ connection_ping(PGconn *conn) return; } -/* - * Function that checks if the primary is in exclusive backup mode. - * We'll use this when executing an action can conflict with an exclusive - * backup. - */ -bool -server_not_in_exclusive_backup_mode(PGconn *conn) -{ - PGresult *res = PQexec(conn, "SELECT pg_is_in_backup()"); - if (PQresultStatus(res) != PGRES_TUPLES_OK) - { - log_error(_("unable to retrieve information regarding backup mode of node")); - log_detail("%s", PQerrorMessage(conn)); - PQclear(res); - return false; - } - - if (strcmp(PQgetvalue(res, 0, 0), "t") == 0) - { - log_warning(_("node is in exclusive backup mode")); - return false; - } - return true; -} /* ==================== */ /* monitoring functions */ diff --git a/dbutils.h b/dbutils.h index 3b765acb..1978a577 100644 --- a/dbutils.h +++ b/dbutils.h @@ -96,6 +96,14 @@ typedef enum SLOT_ACTIVE } ReplSlotStatus; +typedef enum +{ + BACKUP_STATE_UNKNOWN = -1, + BACKUP_STATE_IN_BACKUP, + BACKUP_STATE_NO_BACKUP +} BackupState; + + /* * Struct to store node information */ @@ -390,6 +398,7 @@ int get_ready_archive_files(PGconn *conn, const char *data_directory); bool identify_system(PGconn *repl_conn, t_system_identification *identification); bool repmgrd_set_local_node_id(PGconn *conn, int local_node_id); int repmgrd_get_local_node_id(PGconn *conn); +BackupState server_in_exclusive_backup_mode(PGconn *conn); /* extension functions */ ExtensionStatus get_repmgr_extension_status(PGconn *conn); @@ -467,7 +476,6 @@ int wait_connection_availability(PGconn *conn, long long timeout); bool is_server_available(const char *conninfo); bool is_server_available_params(t_conninfo_param_list *param_list); void connection_ping(PGconn *conn); -bool server_not_in_exclusive_backup_mode(PGconn *conn); /* monitoring functions */ void diff --git a/doc/appendix-release-notes.sgml b/doc/appendix-release-notes.sgml index f3e5e22a..d5b63789 100644 --- a/doc/appendix-release-notes.sgml +++ b/doc/appendix-release-notes.sgml @@ -106,6 +106,14 @@ + + + repmgr standby switchover + will refuse to run if an exclusive backup is taking place on the current primary. + (GitHub #476). + + + diff --git a/doc/repmgr-standby-switchover.sgml b/doc/repmgr-standby-switchover.sgml index 81b06450..ebaa2d87 100644 --- a/doc/repmgr-standby-switchover.sgml +++ b/doc/repmgr-standby-switchover.sgml @@ -46,6 +46,9 @@ repmgrd should not be active on any nodes while a switchover is being executed. This restriction may be lifted in a later version. + + &repmgr; will not perform the switchover if an exclusive backup is running on the current primary. + diff --git a/doc/switchover.sgml b/doc/switchover.sgml index 000d3e8c..69119ca3 100644 --- a/doc/switchover.sgml +++ b/doc/switchover.sgml @@ -57,7 +57,7 @@ As mentioned in the previous section, success of the switchover operation depends on - &repmgr; being able to shut down the current primary server quickly and cleanly. + &repmgr; being able to shut down the current primary server quickly and cleanly. @@ -121,15 +121,21 @@ - - Check that access from applications is minimalized or preferably blocked - completely, so applications are not unexpectedly interrupted. + Check that access from applications is minimalized or preferably blocked + completely, so applications are not unexpectedly interrupted. + + + + + If an exclusive backup is running on the current primary, &repmgr; will not perform the + switchover. + - Check there is no significant replication lag on standbys attached to the - current primary. + Check there is no significant replication lag on standbys attached to the + current primary. @@ -147,6 +153,7 @@ + Finally, consider executing repmgr standby switchover with the --dry-run option; this will perform any necessary checks and inform you about diff --git a/repmgr-action-standby.c b/repmgr-action-standby.c index d778a075..16465521 100644 --- a/repmgr-action-standby.c +++ b/repmgr-action-standby.c @@ -2919,11 +2919,12 @@ do_standby_switchover(void) * If the DBA wants to do the switchover anyway, he should first stop the * backup that's running. */ - if (!server_not_in_exclusive_backup_mode(remote_conn)) + if (server_in_exclusive_backup_mode(remote_conn) != BACKUP_STATE_NO_BACKUP) { - log_error(_("can't perform a switchover while primary server is in exclusive backup mode")); + log_error(_("unable to perform a switchover while primary server is in exclusive backup mode")); log_hint(_("stop backup before attempting the switchover")); + PQfinish(local_conn); PQfinish(remote_conn); exit(ERR_SWITCHOVER_FAIL);