From 594e9e50079623214535ecea59a27220ade1120e Mon Sep 17 00:00:00 2001 From: Ian Barwick Date: Thu, 17 Aug 2017 23:37:31 +0900 Subject: [PATCH] Document upgrade process from repmgr3 Also provide unpackaged extension upgrade SQL, and a script to assist converting repmgr.conf files. --- README.md | 17 ++--- configfile.c | 2 +- contrib/convert-config.pl | 88 ++++++++++++++++++++++++ doc/upgrading-from-repmgr3.md | 122 ++++++++++++++++++++++++++++++++++ repmgr--unpackaged--4.0.sql | 28 +++++--- repmgr-action-standby.c | 1 + repmgr-client.c | 16 ++++- 7 files changed, 252 insertions(+), 22 deletions(-) create mode 100755 contrib/convert-config.pl create mode 100644 doc/upgrading-from-repmgr3.md diff --git a/README.md b/README.md index 9bf835b5..4abd97b8 100644 --- a/README.md +++ b/README.md @@ -26,14 +26,6 @@ objects used by repmgr are stored in a dedicated `repmgr` schema, rather than `repmgr_$cluster_name`. Note there is no need to install the extension, this will be done automatically by `repmgr primary register`. -Metadata tables have been revised and are not backwards-compatible with repmgr 3.x, -however future DDL updates will be easier as they can be carried out via the -`ALTER EXTENSION` mechanism. - -An extension upgrade script will be provided for pre-4.0 installations; -note this will require the existing `repmgr_$cluster_name` schema to -be renamed to `repmgr` beforehand. - Some configuration items have had their names changed for consistency and clarity e.g. `node` => `node_id`. `repmgr` will issue a warning about deprecated/altered options. @@ -44,6 +36,12 @@ upstream ID, which might change over time. See file `doc/changes-in-repmgr4.md` for more details. +To upgrade from repmgr 3.x, both the `repmgr` metadatabase and all +repmgr configuration files need to be converted. This is quite +straightforward and scripts are provided to assist with this. +See document `docs/upgrading-from-repmgr3.md` for further details. + + Overview -------- @@ -148,6 +146,9 @@ UNIX-like system supported by PostgreSQL itself. `repmgr 4` supports PostgreSQL from version 9.5. If you need to using `repmgr` on earlier versions of PostgreSQL 9.3 or 9.4, please use `repmgr 3.3`. +If upgrading from `repmgr 3`, please see the separate upgrade guide +`docs/upgrading-from-repmgr3.md`. + All servers in the replication cluster must be running the same major version of PostgreSQL, and we recommend that they also run the same minor version. diff --git a/configfile.c b/configfile.c index 34cc3fdb..3b0be4af 100644 --- a/configfile.c +++ b/configfile.c @@ -528,7 +528,7 @@ _parse_config(t_configuration_options *options, ItemList *error_list, ItemList * _("parameter \"master_reponse_timeout\" has been removed; use \"async_query_timeout\" instead")); known_parameter = false; } - else if (strcmp(name, "master_reponse_timeout") == 0) + else if (strcmp(name, "retry_promote_interval_secs") == 0) { item_list_append(warning_list, _("parameter \"retry_promote_interval_secs\" has been removed; use \"primary_notification_timeout\" instead")); diff --git a/contrib/convert-config.pl b/contrib/convert-config.pl new file mode 100755 index 00000000..e1786f83 --- /dev/null +++ b/contrib/convert-config.pl @@ -0,0 +1,88 @@ +#!/usr/bin/env perl + +use strict; +use warnings; + + +if (scalar @ARGV < 1) { + print qq|Please provide path to the repmgr.conf file as first parameter\n|; + exit(1); +} + +my $file = $ARGV[0]; + +if (!-e $file) { + print qq|Provide file "$file" does not exist\n|; + exit(1); +} + +if (!-f $file) { + print qq|Provide path "$file" does not point to a file\n|; + exit(1); +} + +my @outp = (); +my $fh = undef; + +if (!open ($fh, $file)){ + print qq|Unable to open "$file"\n|; + exit(1); +} + +my $data_directory_found = 0; + +while(<$fh>) { + my $line = $_; + chomp $line; + if ($line =~ m|\s*#|) { + push @outp, $line; + continue; + } + + if ($line !~ m|\s*(\S+?)\s*=(.+?)$|) { + push @outp, $line; + continue; + } + + my $param = $1; + my $value = $2; + + # These parameters can be removed: + next if ($param eq 'cluster'); + + # These parameters can be renamed: + if ($param eq 'node') { + push @outp, qq|node_id=${value}|; + } + elsif ($param eq 'failover') { + push @outp, qq|failover_mode=${value}|; + } + elsif ($param eq 'loglevel') { + push @outp, qq|log_level=${value}|; + } + elsif ($param eq 'logfacility') { + push @outp, qq|log_facility=${value}|; + } + elsif ($param eq 'logfile') { + push @outp, qq|log_file=${value}|; + } + elsif ($param eq 'master_reponse_timeout') { + push @outp, qq|async_query_timeout=${value}|; + } + else { + if ($param eq 'data_directory') { + $data_directory_found = 1; + } + push @outp, $line; + } +} + +close $fh; + +print join("\n", @outp); +print "\n"; + +if ($data_directory_found == 0) { + print "data_directory=\n"; +} + diff --git a/doc/upgrading-from-repmgr3.md b/doc/upgrading-from-repmgr3.md new file mode 100644 index 00000000..54c02129 --- /dev/null +++ b/doc/upgrading-from-repmgr3.md @@ -0,0 +1,122 @@ +Upgrading from repmgr 3 +======================= + +The upgrade process consists of two steps: + + 1) converting the repmgr.conf configuration files + 2) upgrading the repmgr schema. + +Scripts are provided to assist both with converting repmgr.conf +and upgrading the schema. + +Converting repmgr.conf configuration files +------------------------------------------ + +With a completely new repmgr version, we've taken the opportunity +to rename some configuration items have had their names changed for +clarity and consistency, both between the configuration file and +the column names in `repmgr.nodes` (e.g. `node` → `node_id`), and +also for consistency with PostgreSQL naming conventions +(e.g. `loglevel` → `log_level`). + +Other configuration items have been changed to command line options, +and vice-versa, e.g. to avoid hard-coding items such as a a node's +upstream ID, which might change oer time. + +`repmgr` will issue a warning about deprecated/altered options. + + +### Changed parameters + +Following parameters have been added: + + - `data_directory`: this is mandatory and must contain the path + to the node's data directory + - `monitoring_history`: this replaces the `repmgrd` command line + option `--monitoring-history` + +Following parameters have been renamed: + + - `failover` → `failover_mode` + - `node` → `node_id` + - `loglevel` → `log_level` + - `logfacility` → `log_facility` + - `logfile` → `log_file` + - `master_reponse_timeout` → `async_query_timeout` + +Following parameters have been removed: + + - `cluster` is no longer required and will be ignored. + - `upstream_node_id` is replaced by the command-line parameter + `--upstream-node-id` + +### Conversion script + +To assist with conversion of `repmgr.conf` files, a Perl script +is provided in `contrib/convert-config.pl`. Use like this: + + $ ./convert-config.pl /etc/repmgr.conf + node_id=2 + node_name=node2 + conninfo=host=localhost dbname=repmgr user=repmgr port=5602 + pg_ctl_options='-l /tmp/postgres.5602.log' + pg_bindir=/home/barwick/devel/builds/HEAD/bin + rsync_options=--exclude=postgresql.local.conf --archive + log_level=DEBUG + pg_basebackup_options=--no-slot + data_directory= + +The converted file is printed to `STDOUT` and the original file is not +changed. + +Please note that the parameter `data_directory` *must* be provided; +if not already present, the conversion script will add an empty +placeholder parameter. + + +Upgrading the repmgr schema +--------------------------- + +Ensure `repmgrd` is not running, or any cronjobs which execute the +`repmgr` binary. + +Install `repmgr4`; any `repmgr3` packages should be uninstalled +(if not automatically installed already). + +### Manually create the repmgr extension + +In the database used by the existing `repmgr` configuration, execute: + + CREATE EXTENSION repmgr FROM unpackaged; + +This will move and convert all objects from the existing schema +into the new, standard `repmgr` schema. + +> *NOTE* there must be only one schema matching 'repmgr_%' in the +> database, otherwise this step may not work. + +### Re-register each node + +This is necessary to update the `repmgr` metadata with some additional items. + +On the primary node, execute e.g. + + repmgr primary register -f /etc/repmgr.conf --force + +On each standby node, execute e.g. + + repmgr standby register -f /etc/repmgr.conf --force + +Check the data is updated as expected by examining the `repmgr.nodes` table; +restart `repmgrd` if required. + +The original `repmgr_$cluster` schema can be dropped at any time. + +* * * + +> *TIP* If you don't care about any data from the existing `repmgr` installation, +> (e.g. the contents of the `events` and `monitoring` tables), the manual +> "CREATE EXTENSION" step can be skipped; just re-register each node, starting +> with the primary node, and the `repmgr` extension will be automatically created. + +* * * diff --git a/repmgr--unpackaged--4.0.sql b/repmgr--unpackaged--4.0.sql index b52c6c7a..9b947557 100644 --- a/repmgr--unpackaged--4.0.sql +++ b/repmgr--unpackaged--4.0.sql @@ -1,5 +1,5 @@ -- complain if script is sourced in psql, rather than via CREATE EXTENSION --- \echo Use "CREATE EXTENSION repmgr" to load this file. \quit +\echo Use "CREATE EXTENSION repmgr" to load this file. \quit -- extract the current schema name -- NOTE: this assumes there will be only one schema matching 'repmgr_%'; @@ -12,18 +12,24 @@ SELECT nspname AS old_schema WHERE nspname LIKE 'repmgr_%' LIMIT 1; -DO $$ +-- move old objects into new schema +DO $repmgr$ DECLARE - old_schema TEXT; + schema TEXT; BEGIN - old_schema := SELECT old_schema FROM repmgr_old_schema; - ALTER SCHEMA RENAME TO repmgr; -END$$; + SELECT old_schema FROM repmgr_old_schema + INTO schema; + EXECUTE format('ALTER TABLE %I.repl_nodes SET SCHEMA repmgr', schema); + EXECUTE format('ALTER TABLE %I.repl_events SET SCHEMA repmgr', schema); + EXECUTE format('ALTER TABLE %I.repl_monitor SET SCHEMA repmgr', schema); + EXECUTE format('ALTER VIEW %I.repl_show_nodes SET SCHEMA repmgr', schema); + EXECUTE format('ALTER VIEW %I.repl_status SET SCHEMA repmgr', schema); +END$repmgr$; -- convert "repmgr_$cluster.repl_nodes" to "repmgr.nodes" CREATE TABLE nodes ( node_id INTEGER PRIMARY KEY, - upstream_node_id INTEGER NULL REFERENCES nodes (node_id) DEFERRABLE, + upstream_node_id INTEGER NULL REFERENCES repmgr.nodes (node_id) DEFERRABLE, active BOOLEAN NOT NULL DEFAULT TRUE, node_name TEXT NOT NULL, type TEXT NOT NULL CHECK (type IN('primary','standby','bdr')), @@ -44,11 +50,11 @@ SELECT id, upstream_node_id, active, name, ORDER BY id; --- convert "repmgr_$cluster.repl_event" to "repmgr.event" +-- convert "repmgr_$cluster.repl_event" to "event" -ALTER TABLE repl_events RENAME TO event; +ALTER TABLE repl_events RENAME TO events; --- convert "repmgr_$cluster.repl_monitor" to "repmgr.monitor" +-- convert "repmgr_$cluster.repl_monitor" to "monitor" ALTER TABLE repl_monitor RENAME TO monitor; @@ -125,3 +131,5 @@ CREATE FUNCTION unset_bdr_failover_handler() AS '$libdir/repmgr', 'unset_bdr_failover_handler' LANGUAGE C STRICT; +-- remove temporary table +DROP TABLE repmgr_old_schema; diff --git a/repmgr-action-standby.c b/repmgr-action-standby.c index efe79683..707d1bbd 100644 --- a/repmgr-action-standby.c +++ b/repmgr-action-standby.c @@ -571,6 +571,7 @@ check_barman_config(void) * Event(s): * - standby_register */ +// XXX check --upstream-node-id works when re-registering void do_standby_register(void) diff --git a/repmgr-client.c b/repmgr-client.c index 4dfa2357..08b6b9b8 100644 --- a/repmgr-client.c +++ b/repmgr-client.c @@ -3034,11 +3034,16 @@ init_node_record(t_node_info *node_record) node_record->priority = config_file_options.priority; node_record->active = true; - strncpy(node_record->location, config_file_options.location, MAXLEN); + + if (config_file_options.location[0] != '\0') + strncpy(node_record->location, config_file_options.location, MAXLEN); + else + strncpy(node_record->location, "default", MAXLEN); + strncpy(node_record->node_name, config_file_options.node_name, MAXLEN); strncpy(node_record->conninfo, config_file_options.conninfo, MAXLEN); - strncpy(node_record->config_file, config_file_path, MAXLEN); + strncpy(node_record->config_file, config_file_path, MAXPGPATH); if (config_file_options.replication_user[0] != '\0') { @@ -3048,11 +3053,16 @@ init_node_record(t_node_info *node_record) else { /* use the "user" value from "conninfo" */ - (void)get_conninfo_value(config_file_options.conninfo, "user", node_record->repluser); + char repluser[MAXLEN] = ""; + + (void)get_conninfo_value(config_file_options.conninfo, "user", repluser); + strncpy(node_record->repluser, repluser, NAMEDATALEN); } if (config_file_options.use_replication_slots == true) { maxlen_snprintf(node_record->slot_name, "repmgr_slot_%i", config_file_options.node_id); } + + }