mirror of
https://github.com/EnterpriseDB/repmgr.git
synced 2026-03-22 22:56:29 +00:00
Add sanity check for extension version
This should cover the cases where the "repmgr" extension was installed manually but not updated, or an upgrade was not fully completed.
This commit is contained in:
3
HISTORY
3
HISTORY
@@ -1,3 +1,6 @@
|
||||
4.2.1 2018-??-??
|
||||
repmgr: add sanity check for correct extension version (Ian)
|
||||
|
||||
4.2 2018-10-24
|
||||
repmgr: add parameter "shutdown_check_timeout" for use by "standby switchover";
|
||||
GitHub #504 (Ian)
|
||||
|
||||
27
dbutils.c
27
dbutils.c
@@ -1834,7 +1834,7 @@ atobool(const char *value)
|
||||
/* =================== */
|
||||
|
||||
ExtensionStatus
|
||||
get_repmgr_extension_status(PGconn *conn)
|
||||
get_repmgr_extension_status(PGconn *conn, t_extension_versions *extversions)
|
||||
{
|
||||
PQExpBufferData query;
|
||||
PGresult *res = NULL;
|
||||
@@ -1845,7 +1845,11 @@ get_repmgr_extension_status(PGconn *conn)
|
||||
initPQExpBuffer(&query);
|
||||
|
||||
appendPQExpBufferStr(&query,
|
||||
" SELECT ae.name, e.extname "
|
||||
" SELECT ae.name, e.extname, "
|
||||
" ae.default_version, "
|
||||
" (ae.default_version::numeric * 10)::INT AS available, "
|
||||
" ae.installed_version, "
|
||||
" (ae.installed_version::numeric * 10)::INT AS installed "
|
||||
" FROM pg_catalog.pg_available_extensions ae "
|
||||
"LEFT JOIN pg_catalog.pg_extension e "
|
||||
" ON e.extname=ae.name "
|
||||
@@ -1868,7 +1872,24 @@ get_repmgr_extension_status(PGconn *conn)
|
||||
/* 2. Check if extension installed */
|
||||
else if (PQgetisnull(res, 0, 1) == 0)
|
||||
{
|
||||
status = REPMGR_INSTALLED;
|
||||
int available_version = atoi(PQgetvalue(res, 0, 3));
|
||||
int installed_version = atoi(PQgetvalue(res, 0, 5));
|
||||
|
||||
/* caller wants to know which versions are installed/available */
|
||||
if (extversions != NULL)
|
||||
{
|
||||
strncpy(extversions->default_version, PQgetvalue(res, 0, 2), 7);
|
||||
strncpy(extversions->installed_version, PQgetvalue(res, 0, 4), 7);
|
||||
}
|
||||
|
||||
if (available_version > installed_version)
|
||||
{
|
||||
status = REPMGR_OLD_VERSION_INSTALLED;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = REPMGR_INSTALLED;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
17
dbutils.h
17
dbutils.h
@@ -47,6 +47,7 @@ typedef enum
|
||||
typedef enum
|
||||
{
|
||||
REPMGR_INSTALLED = 0,
|
||||
REPMGR_OLD_VERSION_INSTALLED,
|
||||
REPMGR_AVAILABLE,
|
||||
REPMGR_UNAVAILABLE,
|
||||
REPMGR_UNKNOWN
|
||||
@@ -104,6 +105,20 @@ typedef enum
|
||||
} BackupState;
|
||||
|
||||
|
||||
/*
|
||||
* Struct to store extension version information
|
||||
*/
|
||||
|
||||
typedef struct s_extension_versions {
|
||||
char default_version[8];
|
||||
char installed_version[8];
|
||||
} t_extension_versions;
|
||||
|
||||
#define T_EXTENSION_VERSIONS_INITIALIZER { \
|
||||
"", \
|
||||
"", \
|
||||
}
|
||||
|
||||
/*
|
||||
* Struct to store node information
|
||||
*/
|
||||
@@ -419,7 +434,7 @@ bool repmgrd_is_paused(PGconn *conn);
|
||||
bool repmgrd_pause(PGconn *conn, bool pause);
|
||||
|
||||
/* extension functions */
|
||||
ExtensionStatus get_repmgr_extension_status(PGconn *conn);
|
||||
ExtensionStatus get_repmgr_extension_status(PGconn *conn, t_extension_versions *extversions);
|
||||
|
||||
/* node management functions */
|
||||
void checkpoint(PGconn *conn);
|
||||
|
||||
@@ -126,7 +126,7 @@ do_bdr_register(void)
|
||||
}
|
||||
|
||||
/* check whether repmgr extension exists, and there are no non-BDR nodes registered */
|
||||
extension_status = get_repmgr_extension_status(conn);
|
||||
extension_status = get_repmgr_extension_status(conn, NULL);
|
||||
|
||||
if (extension_status == REPMGR_UNKNOWN)
|
||||
{
|
||||
@@ -232,7 +232,7 @@ do_bdr_register(void)
|
||||
}
|
||||
|
||||
/* check repmgr schema exists, skip if not */
|
||||
other_node_extension_status = get_repmgr_extension_status(bdr_node_conn);
|
||||
other_node_extension_status = get_repmgr_extension_status(bdr_node_conn, NULL);
|
||||
|
||||
if (other_node_extension_status != REPMGR_INSTALLED)
|
||||
{
|
||||
@@ -442,7 +442,7 @@ do_bdr_unregister(void)
|
||||
exit(ERR_BAD_CONFIG);
|
||||
}
|
||||
|
||||
extension_status = get_repmgr_extension_status(conn);
|
||||
extension_status = get_repmgr_extension_status(conn, NULL);
|
||||
if (extension_status != REPMGR_INSTALLED)
|
||||
{
|
||||
log_error(_("repmgr is not installed on database \"%s\""), dbname);
|
||||
|
||||
@@ -4395,7 +4395,7 @@ check_source_server()
|
||||
* to be used as a standalone clone tool)
|
||||
*/
|
||||
|
||||
extension_status = get_repmgr_extension_status(primary_conn);
|
||||
extension_status = get_repmgr_extension_status(primary_conn, NULL);
|
||||
|
||||
if (extension_status != REPMGR_INSTALLED)
|
||||
{
|
||||
|
||||
@@ -2080,8 +2080,9 @@ create_repmgr_extension(PGconn *conn)
|
||||
bool is_superuser = false;
|
||||
PGconn *superuser_conn = NULL;
|
||||
PGconn *schema_create_conn = NULL;
|
||||
t_extension_versions extversions = T_EXTENSION_VERSIONS_INITIALIZER;
|
||||
|
||||
extension_status = get_repmgr_extension_status(conn);
|
||||
extension_status = get_repmgr_extension_status(conn, &extversions);
|
||||
|
||||
switch (extension_status)
|
||||
{
|
||||
@@ -2093,8 +2094,15 @@ create_repmgr_extension(PGconn *conn)
|
||||
log_error(_("\"repmgr\" extension is not available"));
|
||||
return false;
|
||||
|
||||
case REPMGR_OLD_VERSION_INSTALLED:
|
||||
log_error(_("an older version of the \"repmgr\" extension is installed"));
|
||||
log_detail(_("version %s is installed but newer version %s is available"),
|
||||
extversions.installed_version,
|
||||
extversions.default_version);
|
||||
log_hint(_("execute \"ALTER EXTENSION repmgr UPGRADE\""));
|
||||
return false;
|
||||
|
||||
case REPMGR_INSTALLED:
|
||||
/* TODO: check version */
|
||||
log_info(_("\"repmgr\" extension is already installed"));
|
||||
return true;
|
||||
|
||||
|
||||
32
repmgrd.c
32
repmgrd.c
@@ -88,6 +88,7 @@ main(int argc, char **argv)
|
||||
|
||||
RecordStatus record_status;
|
||||
ExtensionStatus extension_status = REPMGR_UNKNOWN;
|
||||
t_extension_versions extversions = T_EXTENSION_VERSIONS_INITIALIZER;
|
||||
|
||||
FILE *fd;
|
||||
|
||||
@@ -389,7 +390,7 @@ main(int argc, char **argv)
|
||||
*/
|
||||
|
||||
/* Check "repmgr" the extension is installed */
|
||||
extension_status = get_repmgr_extension_status(local_conn);
|
||||
extension_status = get_repmgr_extension_status(local_conn, &extversions);
|
||||
|
||||
if (extension_status != REPMGR_INSTALLED)
|
||||
{
|
||||
@@ -402,19 +403,32 @@ main(int argc, char **argv)
|
||||
exit(ERR_DB_QUERY);
|
||||
}
|
||||
|
||||
log_error(_("repmgr extension not found on this node"));
|
||||
if (extension_status == REPMGR_OLD_VERSION_INSTALLED)
|
||||
{
|
||||
log_error(_("an older version of the \"repmgr\" extension is installed"));
|
||||
log_detail(_("version %s is installed but newer version %s is available"),
|
||||
extversions.installed_version,
|
||||
extversions.default_version);
|
||||
log_hint(_("verify the repmgr installation is updated properly before continuing"));
|
||||
|
||||
if (extension_status == REPMGR_AVAILABLE)
|
||||
{
|
||||
log_detail(_("repmgr extension is available but not installed in database \"%s\""),
|
||||
PQdb(local_conn));
|
||||
}
|
||||
else if (extension_status == REPMGR_UNAVAILABLE)
|
||||
else
|
||||
{
|
||||
log_detail(_("repmgr extension is not available on this node"));
|
||||
log_error(_("repmgr extension not found on this node"));
|
||||
|
||||
if (extension_status == REPMGR_AVAILABLE)
|
||||
{
|
||||
log_detail(_("repmgr extension is available but not installed in database \"%s\""),
|
||||
PQdb(local_conn));
|
||||
}
|
||||
else if (extension_status == REPMGR_UNAVAILABLE)
|
||||
{
|
||||
log_detail(_("repmgr extension is not available on this node"));
|
||||
}
|
||||
|
||||
log_hint(_("check that this node is part of a repmgr cluster"));
|
||||
}
|
||||
|
||||
log_hint(_("check that this node is part of a repmgr cluster"));
|
||||
close_connection(&local_conn);
|
||||
exit(ERR_BAD_CONFIG);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user