From 40408a173441830e112d15a843236158cb236054 Mon Sep 17 00:00:00 2001 From: Ian Barwick Date: Tue, 18 Dec 2018 10:34:01 +0900 Subject: [PATCH] repmgrd: check binary and extension major versions match repmgr requires that the same "major version" (e.g. 4.3) is present on all nodes, otherwise - particularly in the case of repmgrd - it's highly likely things won't work as expected. Implements part of GitHub #515. --- HISTORY | 3 +++ dbutils.c | 6 ++++-- dbutils.h | 4 ++++ repmgr_version.h.in | 1 + repmgrd.c | 37 ++++++++++++++++++++++++++++++++++--- 5 files changed, 46 insertions(+), 5 deletions(-) diff --git a/HISTORY b/HISTORY index 01324836..6cee602b 100644 --- a/HISTORY +++ b/HISTORY @@ -1,3 +1,6 @@ +4.3 2019-?? + repmgrd: check binary and extension major versions match; GitHub #515 (Ian) + 4.2.1 2018-??-?? repmgr: add sanity check for correct extension version (Ian) repmgr: ensure "witness register --dry-run" does not attempt to read node diff --git a/dbutils.c b/dbutils.c index 6faeba36..712988e7 100644 --- a/dbutils.c +++ b/dbutils.c @@ -1904,9 +1904,9 @@ get_repmgr_extension_status(PGconn *conn, t_extension_versions *extversions) appendPQExpBufferStr(&query, " SELECT ae.name, e.extname, " " ae.default_version, " - " (ae.default_version::numeric * 10)::INT AS available, " + " (((ae.default_version::NUMERIC::INT) * 10000) + (ae.default_version::NUMERIC - ae.default_version::NUMERIC::INT) * 1000)::INT AS available, " " ae.installed_version, " - " (ae.installed_version::numeric * 10)::INT AS installed " + " (((ae.installed_version::NUMERIC::INT) * 10000) + (ae.installed_version::NUMERIC - ae.installed_version::NUMERIC::INT) * 1000)::INT AS installed " " FROM pg_catalog.pg_available_extensions ae " "LEFT JOIN pg_catalog.pg_extension e " " ON e.extname=ae.name " @@ -1936,7 +1936,9 @@ get_repmgr_extension_status(PGconn *conn, t_extension_versions *extversions) if (extversions != NULL) { strncpy(extversions->default_version, PQgetvalue(res, 0, 2), 7); + extversions->default_version_num = available_version; strncpy(extversions->installed_version, PQgetvalue(res, 0, 4), 7); + extversions->installed_version_num = installed_version; } if (available_version > installed_version) diff --git a/dbutils.h b/dbutils.h index 0cfb2bb3..e34a70e1 100644 --- a/dbutils.h +++ b/dbutils.h @@ -112,12 +112,16 @@ typedef enum typedef struct s_extension_versions { char default_version[8]; + int default_version_num; char installed_version[8]; + int installed_version_num; } t_extension_versions; #define T_EXTENSION_VERSIONS_INITIALIZER { \ "", \ + UNKNOWN_SERVER_VERSION_NUM, \ "", \ + UNKNOWN_SERVER_VERSION_NUM \ } /* diff --git a/repmgr_version.h.in b/repmgr_version.h.in index 8fe5025e..43354433 100644 --- a/repmgr_version.h.in +++ b/repmgr_version.h.in @@ -1,2 +1,3 @@ #define REPMGR_VERSION_DATE "" #define REPMGR_VERSION "4.3dev" +#define REPMGR_VERSION_NUM 40300 diff --git a/repmgrd.c b/repmgrd.c index 46498332..515758d9 100644 --- a/repmgrd.c +++ b/repmgrd.c @@ -386,7 +386,39 @@ main(int argc, char **argv) /* Check "repmgr" the extension is installed */ extension_status = get_repmgr_extension_status(local_conn, &extversions); - if (extension_status != REPMGR_INSTALLED) + if (extension_status == REPMGR_INSTALLED) + { + /* + * extension is the latest available according to "pg_available_extensions" - + * - does our (major) version match that? + */ + log_verbose(LOG_DEBUG, "binary version: %i; extension version: %i", + REPMGR_VERSION_NUM, extversions.installed_version_num); + if ((REPMGR_VERSION_NUM/100) < (extversions.installed_version_num / 100)) + { + log_error(_("this \"repmgr\" version is older than the installed \"repmgr\" extension version")); + log_detail(_("\"repmgr\" version %s is installed but extension is version %s"), + REPMGR_VERSION, + extversions.installed_version); + + log_hint(_("verify the repmgr installation on this server is updated properly before continuing")); + close_connection(&local_conn); + exit(ERR_BAD_CONFIG); + } + + if ((REPMGR_VERSION_NUM/100) > (extversions.installed_version_num / 100)) + { + log_error(_("this \"repmgr\" version is newer than the installed \"repmgr\" extension version")); + log_detail(_("\"repmgr\" version %s is installed but extension is version %s"), + REPMGR_VERSION, + extversions.installed_version); + + log_hint(_("verify the repmgr extension is updated properly before continuing")); + close_connection(&local_conn); + exit(ERR_BAD_CONFIG); + } + } + else { /* this is unlikely to happen */ if (extension_status == REPMGR_UNKNOWN) @@ -400,11 +432,10 @@ main(int argc, char **argv) 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"), + log_detail(_("extension 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")); - } else {