Compare commits

..

67 Commits

Author SHA1 Message Date
Ian Barwick
48099e9c5f Clean up whitespace 2015-07-22 16:18:04 +09:00
Marco Nenciarini
e7ca8c369f Allow repmgr to be compiled with a libpq newer than PostgreSQL
Fixes #44
2015-04-29 17:57:51 +02:00
Ian Barwick
782fae6239 Fix typo 2015-04-20 08:31:37 +09:00
Ian Barwick
a492745db1 Update version number for minor release 2.0.3 2015-04-16 11:14:04 +09:00
Ian Barwick
9ac066db51 Add 2.0.3 HISTORY file items 2015-04-16 11:01:31 +09:00
Ian Barwick
20db2f52b1 Clean up indentation, trailing whitespace 2015-04-16 08:47:05 +09:00
Ian Barwick
341831ad69 Change '-X/--fast-checkpoint' option to '-c/--fast-checkpoint'
Make consistent with same option added in 3.0. '-c' is similar to
pg_basebackup's '-c, --checkpoint=fast|spread' option; we may also
want to use -X for something more pg_xlog-related in future.

Also add missing 'break' statement
2015-04-16 08:24:29 +09:00
Ian Barwick
e8bc5521a5 Add option "--initdb-no-pwprompt"
Previously repmgr passed the -W flag to initdb, which forced
manual input of a password; this option removes the -W flag
to make repetitive testing easier.

Conflicts:
	repmgr.c
	repmgr.h
2015-04-16 07:58:41 +09:00
Ian Barwick
1d9aacfed9 Add -S/--superuser option for witness database creation
Previously the witness database creation code was hard-coding the
username 'postgres' when accessing the previously initialised database.
However initdb was not passed any explicit username, meaning the
default database superuser name was the same as the user running
repmgr.

With this patch, a superuser user name (default: postgres) will
be passed to initdb.

Per report by eggyknap [1]

[1] https://github.com/2ndQuadrant/repmgr/issues/38

Conflicts:
	repmgr.c
	repmgr.h
2015-04-15 08:10:58 +09:00
Ian Barwick
e39ec70ef0 Prevent compiler warnings with 9.0
PG_PRINTF_ATTRIBUTE was introduced with 9.1.
2015-04-14 20:21:54 +09:00
Christoph Monech-Tegeder
196585c78a optional fast checkpointing
commandline -X/--fast-checkpoint
2015-04-08 23:09:12 +02:00
Martín Marqués
79728ba6dd Updated RHEL files. 2015-03-30 11:07:11 -03:00
Martín Marqués
c4a47c467f Add check for wal_level = logical so we don't fail on 9.4
On 9.4 we have logical decoding, which introduced a new wal_level called
logical. This level includes all the previous ones, so you can run a
hot_standby if wal_level = logical, because the relevant information for
hot_standby will be there, plus other information needed for logical
decoding.

We fix this be adding a second check when wal_level is not hot_standby.
2015-03-30 10:47:17 -03:00
Ian Barwick
36e5944b2c Add items for future 2.0.3 release 2015-03-27 11:12:11 +09:00
John Galt
097bbdebfd Fixed typo 2015-03-24 10:47:48 +09:00
Germ van Ek
4fa75afa26 Added postgresql-9.4 to debian control file 2015-03-24 10:03:38 +09:00
Ian Barwick
0aae96008f Parse config file before daemonizing
Daemonizing changes the current working directory to '/',
which breaks configuration file parsing if the file is in
the previous working directory and provided without an
explicit path.

Also it makes general sense to parse the configuration file
before daemonizing.
2015-03-09 08:26:59 +09:00
Ian Barwick
2349e182d2 Prevent trim() from segfaulting on an empty string 2015-03-07 23:48:14 +09:00
Ian Barwick
03a8f2eaba Clarify repmgr.conf usage 2015-02-27 10:02:30 +09:00
Ian Barwick
b6a263a40e Update QUICKSTART.md 2015-02-24 08:52:36 +09:00
Magnus Hagander
81050899e8 Fix markup
This was broken in commit  8faf41dd94,
most likely because of a runaway search/replace.
2015-02-24 08:49:55 +09:00
Ian Barwick
51aa63c8f9 Update version and history for minor release 2.0.2 2015-02-17 16:06:00 +09:00
Ian Barwick
e53162deb8 Fix master port check
Check introduced in dc0dfe9b56
was comparing the provided database name instead of the port.
2015-02-12 14:43:53 +09:00
Jaime Casanova
6a8336b880 Add "--checksum" in rsync when using "--force"
If the user don't put that option in rsync_options using of "--force"
could be unsafe.
While the probability of failures because of this are low they aren't
zero.
2015-02-10 20:28:17 -05:00
Marco Nenciarini
4a445e7f8a Fix syntax errors in repmgr.c 2014-11-10 12:38:18 -05:00
Jaime Casanova
3c1d72a5ea Code review: Do not use psql on do_witness_create,
use createdb and createuser binaries instead
2014-11-10 12:37:10 -05:00
Martín Marqués
d4b9a32a86 errcode.h is a local header. 2014-11-10 12:36:17 -05:00
Martín Marqués
07a216ca25 If the user doesn't pass the port on which the primary server is listening
we have to assume it's the DEFAULT_MASTER_PORT.

This was not done, so we added a check to see if it has a value that is
usable, else we use DEFAULT_MASTER_PORT.
2014-11-10 12:34:30 -05:00
Ian Barwick
d3c067f1bd Clarify repmgr database role
Conflicts:
	QUICKSTART.md
2014-11-10 12:33:26 -05:00
Ian Barwick
e6caf11bf2 Fix pg_hba.conf example
Conflicts:
	QUICKSTART.md
2014-11-10 12:30:33 -05:00
Ian Barwick
9909881d81 Update HISTORY for minor release 2.0.1 2014-11-10 12:27:07 -05:00
Ian Barwick
8073a294f0 Formatting fixes
Conflicts:
	QUICKSTART.md
2014-11-10 12:26:28 -05:00
Ian Barwick
bf5e0b9b48 Correct year in specfile changelog 2014-11-10 12:21:49 -05:00
Ian Barwick
2e9f4aa30f Convert QUICKSTART file to markdown format
Less effort for more consistent formatting (at least the way
github renders it).
2014-11-10 12:12:25 -05:00
Ian Barwick
0dcacc3a70 Formatting fixes 2014-11-10 12:11:42 -05:00
Ian Barwick
65120c47cf Fix formatting 2014-11-10 12:10:47 -05:00
Ian Barwick
f9397c0f06 Add a "quickstart" guide
Provides a succinct overview of the steps needed to get repmgr
up and running as.
2014-11-10 12:04:02 -05:00
Ian Barwick
af3c865b05 Fix log messages in do_standby_promote()
Initial connection is to current standby, before attempting to
connect to old master.
2014-11-10 10:44:55 -05:00
Ian Barwick
112a11a311 Typo fixes 2014-11-10 10:42:39 -05:00
Ian Barwick
7b87b5eddd Change successful standby promotion message to log level 'NOTICE'
Was previously 'ERROR'.
2014-11-10 10:40:31 -05:00
Ian Barwick
1aa36ca1c1 Properly specify rsync --exclude directories
Using '--exclude=dirname/*' to explicitly specify directories whose contents
should not be copied. This will result in empty directories being created
on the destination if they exist on the source, but that's not a problem as
they are needed anyway.

Previously the generated rsync command contained '--exclude=pg_log*', which
will break replication on 9.5 as the wildcard expansion prevents the
'pg_logical' directory from being copied.
2014-11-09 18:16:08 -05:00
Ian Barwick
a7eff1f39e Typo fixes and minor wording tweaks for clarity 2014-11-09 17:25:47 -05:00
Riegie Godwin Jeyaranchen
e64e230559 Update README.rst
Fixing a grammar mistake.
2014-11-09 17:15:42 -05:00
Nathan Van Overloop
bba167db9e init script: make status call return proper return code 2014-11-09 11:13:47 -05:00
Nathan Van Overloop
2676adcaed re-add comment full debug of log.c 2014-11-09 11:04:39 -05:00
Nathan Van Overloop
5a27d5e57b on init of witness server create db and user to avoid using postgres 2014-11-09 10:55:09 -05:00
Nathan Van Overloop
4071589ba5 adapt makefile for RHEL + RHEL specific files 2014-11-09 10:51:40 -05:00
brynhood
6cb2376974 Makefile: create bindir before instal + force dir
in order to facilitate building of an rpm I've added an / to the end of the dirs.
2014-11-07 15:25:45 -05:00
PriceChild
235c98a0b5 Typo in example command. 2014-11-07 15:13:23 -05:00
Warren Moore
16da2f48c2 keep naming consistent 2014-11-07 15:12:49 -05:00
Warren Moore
c23e5858f2 fix: witness creation and monitoring
While reading node entries from master use a separate PGresult when inserting into witness.
Witness monitoring supplies a null value for 'last_apply_time'.
2014-11-07 15:09:05 -05:00
József Kószó
30ccee43d9 debian init script and config file documentation fixes 2014-11-07 15:02:27 -05:00
József Kószó
9357f89d12 debian init script and config file documentation fixes 2014-11-07 15:02:03 -05:00
József Kószó
48da11acfd debian init script and config file documentation fixes 2014-11-07 14:40:53 -05:00
Christian Kruse
07c54c296c removed old comment 2014-11-07 13:49:13 -05:00
Christian Kruse
8f0b9592e8 no longer use global variable for SQL query buffer 2014-11-07 13:47:58 -05:00
Christian Kruse
b35bf3f91d removed no-longer used variable 2014-11-07 13:47:18 -05:00
Christian Kruse
04c101c5f0 rather big refactoring: use a naming scheme
In the past naming of functions, variables and such didn't really have a
naming scheme. Now they should have.

This is backpatched from master (2.1dev) just because it will be easier
to backpatch other fixes.
2014-11-07 13:46:04 -05:00
Christian Kruse
65989840d2 avoid usage of snprintf()
We have a nice little abstraction for snprintf with covering the case
that a string is too big for the target buffer – let's use that!
2014-11-07 13:44:23 -05:00
Christian Kruse
24bd4e7a3f completely avoid usage of strnlen() 2014-11-07 13:40:20 -05:00
Christian Kruse
1c67e105ff pg_indent'ing all files…
Conflicts:
	version.h
2014-11-07 13:32:29 -05:00
Christian Kruse
069f9ff2ed version push 2014-03-17 14:26:56 +01:00
Christian Kruse
b8ade8e908 fixing some documentation errors 2014-03-10 15:51:55 +01:00
Christian Kruse
c0abb3be31 Merge branch 'master' into REL2_0_STABLE 2014-03-06 15:23:52 +01:00
Christian Kruse
0a71123920 Merge branch 'master' into REL2_0_STABLE 2014-03-03 09:25:08 +01:00
Christian Kruse
a72c2296e9 Merge branch 'master' into REL2_0_STABLE 2014-02-11 09:28:40 +01:00
Christian Kruse
9c3d79147b now version.h contains the right version 2014-02-07 21:47:39 +01:00
16 changed files with 403 additions and 235 deletions

28
HISTORY
View File

@@ -1,10 +1,22 @@
2.0.1 2014-07-16 2.0.3 2015-04-16
Documentation fixes and new QUICKSTART file (Ian) Add -S/--superuser option for witness database creation (Ian)
Explicitly specify directories to ignore when cloning (Ian) Add -c/--fast-checkpoint option for cloning (Christoph)
Fix log level for some log messages (Ian) Add option "--initdb-no-pwprompt" (Ian)
RHEL/CentOS specfile, init script and Makefile fixes (Nathan Van Overloop)
2.0.2 2015-02-17
Add "--checksum" in rsync when using "--force" (Jaime)
Use createdb/createuser instead of psql (Jaime)
Fixes to witness creation and monitoring (wamonite)
Use default master port if none supplied (Martín)
Documentation fixes and improvements (Ian)
2.0.1 2014-07-16
Documentation fixes and new QUICKSTART file (Ian)
Explicitly specify directories to ignore when cloning (Ian)
Fix log level for some log messages (Ian)
RHEL/CentOS specfile, init script and Makefile fixes (Nathan Van Overloop)
Debian init script and config file documentation fixes (József Kószó) Debian init script and config file documentation fixes (József Kószó)
Typo fixes (Riegie Godwin Jeyaranchen, PriceChild) Typo fixes (Riegie Godwin Jeyaranchen, PriceChild)
2.0stable 2014-01-30 2.0stable 2014-01-30
Documentation fixes (Christian) Documentation fixes (Christian)
@@ -25,7 +37,7 @@
Add a ssh_options parameter (Jay Taylor) Add a ssh_options parameter (Jay Taylor)
2.0beta1 2012-07-27 2.0beta1 2012-07-27
Make CLONE command try to make an exact copy including $PGDATA location (Cedric) Make CLONE command try to make an exact copy including $PGDATA location (Cedric)
Add detection of master failure (Jaime) Add detection of master failure (Jaime)
Add the notion of a witness server (Jaime) Add the notion of a witness server (Jaime)
Add autofailover capabilities (Jaime) Add autofailover capabilities (Jaime)
@@ -52,7 +64,7 @@
1.1.0 2011-03-09 1.1.0 2011-03-09
Make options -U, -R and -p not mandatory (Jaime) Make options -U, -R and -p not mandatory (Jaime)
1.1.0b1 2011-02-24 1.1.0b1 2011-02-24
Fix missing "--force" option in help (Greg Smith) Fix missing "--force" option in help (Greg Smith)
Correct warning message for wal_keep_segments (Bas van Oostveen) Correct warning message for wal_keep_segments (Bas van Oostveen)
Add Debian build/usage docs (Bas, Hannu Krosing, Cedric Villemain) Add Debian build/usage docs (Bas, Hannu Krosing, Cedric Villemain)

View File

@@ -1,7 +1,7 @@
repmgr: Quickstart guide repmgr: Quickstart guide
======================== ========================
repmgr is an open-source tool suite for mananaging replication and failover `repmgr` is an open-source tool suite for mananaging replication and failover
among multiple PostgreSQL server nodes. It enhances PostgreSQL's built-in among multiple PostgreSQL server nodes. It enhances PostgreSQL's built-in
hot-standby capabilities with a set of administration tools for monitoring hot-standby capabilities with a set of administration tools for monitoring
replication, setting up standby servers and performing failover/switchover replication, setting up standby servers and performing failover/switchover
@@ -14,14 +14,14 @@ covering setup on a variety of different systems, see the README.rst file.
Conceptual Overview Conceptual Overview
------------------- -------------------
repmgr provides two binaries: `repmgr` provides two binaries:
- `repmgr`: a command-line client to manage replication and repmgr configuration - `repmgr`: a command-line client to manage replication and `repmgr` configuration
- `repmgrd`: an optional daemon process which runs on standby nodes to monitor - `repmgrd`: an optional daemon process which runs on standby nodes to monitor
replication and node status replication and node status
Each PostgreSQL node requires a repmgr configuration file; additionally Each PostgreSQL node requires a `repmgr.conf` configuration file; additionally
it must be "registered" using the repmgr command-line client. repmgr stores it must be "registered" using the `repmgr` command-line client. `repmgr` stores
information about managed nodes in a custom schema on the node's current master information about managed nodes in a custom schema on the node's current master
database. database.
@@ -29,31 +29,31 @@ database.
Requirements Requirements
------------ ------------
repmgr works with PostgreSQL 9.0 and later. All server nodes must be running the `repmgr` works with PostgreSQL 9.0 and later. All server nodes must be running the
same PostgreSQL major version, and preferably should be running the same minor same PostgreSQL major version, and preferably should be running the same minor
version. version.
repmgr will work on any Linux or UNIX-like environment capable of running `repmgr` will work on any Linux or UNIX-like environment capable of running
PostgreSQL. `rsync` must also be installed. PostgreSQL. `rsync` must also be installed.
Installation Installation
------------ ------------
repmgr must be installed on each PostgreSQL server node. `repmgr` must be installed on each PostgreSQL server node.
* Packages * Packages
- RPM packages for RedHat-based distributions are available from PGDG - RPM packages for RedHat-based distributions are available from PGDG
- Debian/Ubuntu provide .deb packages. - Debian/Ubuntu provide .deb packages.
It is also possible to build .deb packages directly from the repmgr source; It is also possible to build .deb packages directly from the `repmgr` source;
see README.rst for further details. see README.rst for further details.
* Source installation * Source installation
- repmgr source code is hosted at github (https://github.com/2ndQuadrant/repmgr); - `repmgr` source code is hosted at github (https://github.com/2ndQuadrant/repmgr);
tar.gz files can be downloaded from https://github.com/2ndQuadrant/repmgr/releases . tar.gz files can be downloaded from https://github.com/2ndQuadrant/repmgr/releases .
repmgr can be built easily using PGXS: `repmgr` can be built easily using PGXS:
sudo make USE_PGXS=1 install sudo make USE_PGXS=1 install
@@ -64,7 +64,7 @@ Configuration
### Server configuration ### Server configuration
Password-less SSH logins must be enabled for the database system user (typically `postgres`) Password-less SSH logins must be enabled for the database system user (typically `postgres`)
between all server nodes to enable repmgr to copy required files. between all server nodes to enable `repmgr` to copy required files.
### PostgreSQL configuration ### PostgreSQL configuration
@@ -78,18 +78,21 @@ following settings:
wal_keep_segments = 5000 # in logfile segments, 16MB each; 0 disables wal_keep_segments = 5000 # in logfile segments, 16MB each; 0 disables
hot_standby = on # "on" allows queries during recovery hot_standby = on # "on" allows queries during recovery
Note that repmgr expects a default of 5000 wal_keep_segments, although this Note that `repmgr` expects a default of 5000 wal_keep_segments, although this
value can be overridden when executing the `repmgr` client. value can be overridden when executing the `repmgr` client.
Additionally, repmgr requires a dedicated PostgreSQL superuser account Additionally, `repmgr` requires a dedicated PostgreSQL superuser account
and a database in which to store monitoring and replication data. The and a database in which to store monitoring and replication data. The `repmgr`
database can in principle be any database, including the default postgres user account will also be used for replication connections from the standby,
one, however it's probably advisable to create a dedicated repmgr database. so a seperate replication user with the `REPLICATION` privilege is not required.
The database can in principle be any database, including the default `postgres`
one, however it's probably advisable to create a dedicated database for `repmgr`
usage.
### repmgr configuration ### repmgr configuration
Each PostgreSQL node requires a repmgr configuration file containing Each PostgreSQL node requires a `repmgr.conf` configuration file containing
identification and database connection information: identification and database connection information:
cluster=test cluster=test
@@ -108,11 +111,14 @@ identification and database connection information:
* `pg_bindir`: (optional) location of PostgreSQL binaries, if not in the default $PATH * `pg_bindir`: (optional) location of PostgreSQL binaries, if not in the default $PATH
Note that the configuration file should *not* be stored inside the PostgreSQL Note that the configuration file should *not* be stored inside the PostgreSQL
data directory. data directory. The configuration file can be specified with the
`-f, --config-file=PATH` option and can have any arbitrary name. If no
configuration file is specified, `repmgr` will search for `repmgr.conf`
in the current working directory.
Each node configuration needs to be registered with repmgr, either using the Each node configuration needs to be registered with `repmgr`, either using the
`repmgr` command line tool, or the `repmgrd` daemon; for details see below. Details `repmgr` command line tool, or the `repmgrd` daemon; for details see below. Details
about each node are inserted into the repmgr database (for details see below). about each node are inserted into the `repmgr` database (for details see below).
Replication setup and monitoring Replication setup and monitoring
@@ -138,17 +144,17 @@ Master setup
CREATE DATABASE repmgr_db OWNER repmgr_usr; CREATE DATABASE repmgr_db OWNER repmgr_usr;
``` ```
- configure postgresql.conf for replication (see above) - configure `postgresql.conf` for replication (see above)
- update pg_hba.conf: - update `pg_hba.conf`, e.g.:
``` ```
host repmgr_usr repmgr_db 192.168.1.0/24 trust host repmgr_db repmgr_usr 192.168.1.0/24 trust
host replication all 192.168.1.0/24 trust host replication repmgr_usr 192.168.1.0/24 trust
``` ```
Restart the PostgreSQL server after making these changes. Restart the PostgreSQL server after making these changes.
2. Create the repmgr configuration file: 2. Create the `repmgr` configuration file:
$ cat $HOME/repmgr/repmgr.conf $ cat $HOME/repmgr/repmgr.conf
cluster=test cluster=test
@@ -157,7 +163,10 @@ Master setup
conninfo='host=repmgr_node1 user=repmgr_usr dbname=repmgr_db' conninfo='host=repmgr_node1 user=repmgr_usr dbname=repmgr_db'
pg_bindir=/path/to/postgres/bin pg_bindir=/path/to/postgres/bin
3. Register the master node with repmgr: (For an annotated `repmgr.conf` file, see `repmgr.conf.sample` in the
repository's root directory).
3. Register the master node with `repmgr`:
$ repmgr -f $HOME/repmgr/repmgr.conf --verbose master register $ repmgr -f $HOME/repmgr/repmgr.conf --verbose master register
[2014-07-04 10:43:42] [INFO] repmgr mgr connecting to master database [2014-07-04 10:43:42] [INFO] repmgr mgr connecting to master database
@@ -169,9 +178,9 @@ Master setup
Slave/standby setup Slave/standby setup
------------------- -------------------
1. Use repmgr to clone the master: 1. Use `repmgr` to clone the master:
$ repmgr -f $HOME/repmgr/repmgr.conf -D $PGDATA -d repmgr_db -U repmgr_usr -R postgres --verbose standby clone 192.168.1.2 $ repmgr -D $PGDATA -d repmgr_db -U repmgr_usr -R postgres --verbose standby clone 192.168.1.2
Opening configuration file: ./repmgr.conf Opening configuration file: ./repmgr.conf
[2014-07-04 10:49:00] [ERROR] Did not find the configuration file './repmgr.conf', continuing [2014-07-04 10:49:00] [ERROR] Did not find the configuration file './repmgr.conf', continuing
[2014-07-04 10:49:00] [INFO] repmgr connecting to master database [2014-07-04 10:49:00] [INFO] repmgr connecting to master database
@@ -190,12 +199,14 @@ Slave/standby setup
-R is the database system user on the master node. At this point it does not matter -R is the database system user on the master node. At this point it does not matter
if the `repmgr.conf` file is not found. if the `repmgr.conf` file is not found.
This will clone the PostgreSQL database files from the master, and additionally This will clone the PostgreSQL database files from the master, including its
create an appropriate `recovery.conf` file. `postgresql.conf` and `pg_hba.conf` files, and additionally automatically create
the `recovery.conf` file containing the correct parameters to start streaming
from the primary node.
2. Start the PostgreSQL server 2. Start the PostgreSQL server
3. Create the repmgr configuration file: 3. Create the `repmgr` configuration file:
$ cat $HOME/repmgr/repmgr.conf $ cat $HOME/repmgr/repmgr.conf
cluster=test cluster=test
@@ -204,7 +215,7 @@ Slave/standby setup
conninfo='host=repmgr_node2 user=repmgr_usr dbname=repmgr_db' conninfo='host=repmgr_node2 user=repmgr_usr dbname=repmgr_db'
pg_bindir=/path/to/postgres/bin pg_bindir=/path/to/postgres/bin
4. Register the master node with repmgr: 4. Register the master node with `repmgr`:
$ repmgr -f $HOME/repmgr/repmgr.conf --verbose standby register $ repmgr -f $HOME/repmgr/repmgr.conf --verbose standby register
Opening configuration file: /path/to/repmgr/repmgr.conf Opening configuration file: /path/to/repmgr/repmgr.conf
@@ -253,8 +264,8 @@ To promote a standby to master, on the standby execute e.g.:
repmgr -f $HOME/repmgr/repmgr.conf --verbose standby promote repmgr -f $HOME/repmgr/repmgr.conf --verbose standby promote
repmgr will attempt to connect to the current master to verify that it `repmgr` will attempt to connect to the current master to verify that it
is not available (if it is, repmgr will not promote the standby). is not available (if it is, `repmgr` will not promote the standby).
Other standby servers need to be told to follow the new master with: Other standby servers need to be told to follow the new master with:
@@ -267,7 +278,7 @@ automated failover.
repmgr database schema repmgr database schema
---------------------- ----------------------
repmgr creates a small schema for its own use in the database specified in `repmgr` creates a small schema for its own use in the database specified in
each node's conninfo configuration parameter. This database can in principle each node's conninfo configuration parameter. This database can in principle
be any database. The schema name is the global `cluster` name prefixed be any database. The schema name is the global `cluster` name prefixed
with `repmgr_`, so for the example setup above the schema name is with `repmgr_`, so for the example setup above the schema name is
@@ -284,3 +295,10 @@ and one view, `repl_status`, which summarizes the latest monitoring information
for each node. for each node.
Further reading
---------------
* http://blog.2ndquadrant.com/announcing-repmgr-2-0/
* http://blog.2ndquadrant.com/managing-useful-clusters-repmgr/
* http://blog.2ndquadrant.com/easier_postgresql_90_clusters/

View File

@@ -427,7 +427,7 @@ system you already have superuser access to.
Clearing the PostgreSQL installation on the Standby Clearing the PostgreSQL installation on the Standby
--------------------------------------------------- ---------------------------------------------------
To setup a new streaming replica, startin by removing any PostgreSQL To setup a new streaming replica, start by removing any PostgreSQL
installation on the existing standby nodes. installation on the existing standby nodes.
* Stop any server on "node2" and "node3". You can confirm the database * Stop any server on "node2" and "node3". You can confirm the database

View File

@@ -4,7 +4,7 @@ Version: 2.0
Release: 2 Release: 2
License: GPLv3 License: GPLv3
Group: System Environment/Daemons Group: System Environment/Daemons
URL: http://repmgr.org URL: http://repmgr.org
Packager: Nathan Van Overloop <nathan.van.overloop@nexperteam.be> Packager: Nathan Van Overloop <nathan.van.overloop@nexperteam.be>
Vendor: 2ndQuadrant Limited Vendor: 2ndQuadrant Limited
Distribution: centos Distribution: centos
@@ -32,7 +32,7 @@ export PATH=$PATH:/usr/pgsql-9.3/bin/
%clean %clean
[ "%{buildroot}" != "/" ] && %{__rm} -rf %{buildroot} [ "%{buildroot}" != "/" ] && %{__rm} -rf %{buildroot}
%files %files
%defattr(-,root,root) %defattr(-,root,root)
@@ -45,7 +45,7 @@ export PATH=$PATH:/usr/pgsql-9.3/bin/
/usr/pgsql-9.3/share/contrib/repmgr_funcs.sql /usr/pgsql-9.3/share/contrib/repmgr_funcs.sql
/usr/pgsql-9.3/share/contrib/uninstall_repmgr.sql /usr/pgsql-9.3/share/contrib/uninstall_repmgr.sql
/usr/pgsql-9.3/share/contrib/uninstall_repmgr_funcs.sql /usr/pgsql-9.3/share/contrib/uninstall_repmgr_funcs.sql
%attr(0755,root,root)/etc/init.d/repmgrd %attr(0755,root,root)/etc/init.d/repmgrd
%attr(0644,root,root)/etc/sysconfig/repmgrd %attr(0644,root,root)/etc/sysconfig/repmgrd
%attr(0644,root,root)/etc/repmgr/repmgr.conf.sample %attr(0644,root,root)/etc/repmgr/repmgr.conf.sample
@@ -54,4 +54,3 @@ export PATH=$PATH:/usr/pgsql-9.3/bin/
- fix witness creation to create db and user if needed - fix witness creation to create db and user if needed
* Fri Apr 04 2014 Nathan Van Overloop <nathan.van.overloop@nexperteam.be> 2.0.1 * Fri Apr 04 2014 Nathan Van Overloop <nathan.van.overloop@nexperteam.be> 2.0.1
- initial build for RHEL6 - initial build for RHEL6

View File

@@ -1,89 +1,114 @@
#!/bin/bash #!/bin/sh
# #
# repmgrd Start up the repmgrd daemon # chkconfig: - 75 16
# repmrgd (replication manager daemon) # description: Enable repmgrd replication management and monitoring daemon for PostgreSQL
# # processname: repmgrd
# chkconfig: - 75 16 # pidfile="/var/run/${NAME}.pid"
# description: repmgrd is the repliation manager daemon \
# The repmgrd replication management and monitoring daemon for PostgreSQL.
### BEGIN INIT INFO
# Provides: repmgrd
# Required-Start: $local_fs $remote_fs $network $syslog postgresql
# Required-Stop: $local_fs $remote_fs $network $syslog postgresql
# Should-Start: $syslog postgresql-9.3
# Should-Stop: $syslog postgresql-9.3
# Short-Description: start and stop repmrgd
# Description: Enable repmgrd replication management and monitoring daemon for PostgreSQL
# this is used to monitor a postgresql cluster.
### END INIT INFO
# Source function library. # Source function library.
. /etc/init.d/functions INITD=/etc/rc.d/init.d
. $INITD/functions
# Source networking configuration. # Get function listing for cross-distribution logic.
TYPESET=`typeset -f|grep "declare"`
# Get network config.
. /etc/sysconfig/network . /etc/sysconfig/network
prog=repmgrd DESC="PostgreSQL replication management and monitoring daemon"
REPMGRD_ENABLED=yes NAME=repmgrd
REPMGRD_ENABLED=no
REPMGRD_OPTS= REPMGRD_OPTS=
REPMGRD_USER=postgres REPMGRD_USER=postgres
DAEMONIZE="-d" REPMGRD_BIN=/usr/pgsql-9.3/bin/repmgrd
REPMGRD_PIDFILE=/var/run/repmgrd.pid
REPMGRD_LOCK=/var/lock/subsys/${NAME}
REPMGRD_LOG=/var/lib/pgsql/9.3/data/pg_log/repmgrd.log
# pull in sysconfig settings # Read configuration variable file if it is present
[ -f /etc/sysconfig/repmgrd ] && . /etc/sysconfig/repmgrd [ -r /etc/sysconfig/$NAME ] && . /etc/sysconfig/$NAME
LOCKFILE=/var/lock/subsys/$prog # For SELinux we need to use 'runuser' not 'su'
RETVAL=0 if [ -x /sbin/runuser ]
then
SU=runuser
else
SU=su
fi
test -x $REPMGRD_BIN || exit 0
case "$REPMGRD_ENABLED" in case "$REPMGRD_ENABLED" in
[Yy]*) [Yy]*)
#nothing to do here break
;; ;;
*) *)
exit 2 exit 0
;; ;;
esac esac
if [ -z "$REPMGRD_OPTS" ] if [ -z "${REPMGRD_OPTS}" ]
then then
echo "Not starting $prog, REPMGRD_OPTS not set in /etc/sysconfig/$prog" echo "Not starting ${NAME}, REPMGRD_OPTS not set in /etc/sysconfig/${NAME}"
exit 2 exit 0
fi fi
start() { start()
[ "$EUID" != "0" ] && exit 4 {
[ "$NETWORKING" = "no" ] && exit 1 REPMGRD_START=$"Starting ${NAME} service: "
# Start daemons. # Make sure startup-time log file is valid
echo -n $"Starting $prog: " if [ ! -e "${REPMGRD_LOG}" -a ! -h "${REPMGRD_LOG}" ]
daemon --user $REPMGRD_USER $prog $DAEMONIZE $REPMGRD_OPTS then
RETVAL=$? touch "${REPMGRD_LOG}" || exit 1
chown ${REPMGRD_USER}:postgres "${REPMGRD_LOG}"
chmod go-rwx "${REPMGRD_LOG}"
[ -x /sbin/restorecon ] && /sbin/restorecon "${REPMGRD_LOG}"
fi
echo -n "${REPMGRD_START}"
$SU -l $REPMGRD_USER -c "${REPMGRD_BIN} ${REPMGRD_OPTS} -p ${REPMGRD_PIDFILE} &" >> "${REPMGRD_LOG}" 2>&1 < /dev/null
sleep 2
pid=`head -n 1 "${REPMGRD_PIDFILE}" 2>/dev/null`
if [ "x${pid}" != "x" ]
then
success "${REPMGRD_START}"
touch "${REPMGRD_LOCK}"
echo $pid > "${REPMGRD_PIDFILE}"
echo echo
[ $RETVAL -eq 0 ] && touch $LOCKFILE else
return $RETVAL failure "${REPMGRD_START}"
echo
script_result=1
fi
} }
stop() { stop()
[ "$EUID" != "0" ] && exit 4 {
echo -n $"Shutting down $prog: " echo -n $"Stopping ${NAME} service: "
killproc $prog if [ -e "${REPMGRD_LOCK}" ]
RETVAL=$? then
echo killproc ${NAME}
[ $RETVAL -eq 0 ] && rm -f $LOCKFILE ret=$?
return $RETVAL if [ $ret -eq 0 ]
} then
status() { echo_success
if [ -f "$LOCKFILE" ]; then rm -f "${REPMGRD_PIDFILE}"
echo "$prog is running" rm -f "${REPMGRD_LOCK}"
else else
RETVAL=3 echo_failure
echo "$prog is stopped" script_result=1
fi fi
return $RETVAL else
# not running; per LSB standards this is "ok"
echo_success
fi
echo
} }
# See how we were called. # See how we were called.
case "$1" in case "$1" in
start) start)
@@ -93,22 +118,16 @@ case "$1" in
stop stop
;; ;;
status) status)
status $prog status -p $REPMGRD_PIDFILE $NAME
script_result=$?
;; ;;
restart|force-reload) restart)
stop stop
start start
;;
try-restart|condrestart)
if status $prog > /dev/null; then
stop
start
fi
;;
reload)
exit 3
;; ;;
*) *)
echo $"Usage: $0 {start|stop|status|restart|try-restart|force-reload}" echo $"Usage: $0 {start|stop|status|restart}"
exit 2 exit 2
esac esac
exit $script_result

View File

@@ -1,4 +1,21 @@
#default sysconfig file for repmrgd # default settings for repmgrd. This file is source by /bin/sh from
#custom overrides can be placed here # /etc/init.d/repmgrd
REPMGRD_OPTS="-f /etc/repmgr/repmgr.conf" # disable repmgrd by default so it won't get started upon installation
# valid values: yes/no
REPMGRD_ENABLED=no
# Options for repmgrd (required)
#REPMGRD_OPTS="--verbose -d -f /var/lib/pgsql/repmgr/repmgr.conf"
# User to run repmgrd as
#REPMGRD_USER=postgres
# repmgrd binary
#REPMGRD_BIN=/usr/bin/repmgr
# pid file
#REPMGRD_PIDFILE=/var/lib/pgsql/repmgr/repmgrd.pid
# log file
#REPMGRD_LOG=/var/lib/pgsql/repmgr/repmgrd.log

View File

@@ -25,7 +25,8 @@
#include <string.h> #include <string.h>
/* NB: postgres_fe must be included BEFORE check_dir */ /* NB: postgres_fe must be included BEFORE check_dir */
#include "postgres_fe.h" #include <libpq-fe.h>
#include <postgres_fe.h>
#include "check_dir.h" #include "check_dir.h"
#include "strutil.h" #include "strutil.h"

View File

@@ -185,6 +185,10 @@ trim(char *s)
char *s1 = s, char *s1 = s,
*s2 = &s[strlen(s) - 1]; *s2 = &s[strlen(s) - 1];
/* If string is empty, no action needed */
if(s2 < s1)
return s;
/* Trim and delimit right side */ /* Trim and delimit right side */
while ((isspace(*s2)) && (s2 >= s1)) while ((isspace(*s2)) && (s2 >= s1))
--s2; --s2;

View File

@@ -3,7 +3,7 @@ Version: 2.0beta2
Section: database Section: database
Priority: optional Priority: optional
Architecture: all Architecture: all
Depends: rsync, postgresql-9.0 | postgresql-9.1 | postgresql-9.2 | postgresql-9.3 Depends: rsync, postgresql-9.0 | postgresql-9.1 | postgresql-9.2 | postgresql-9.3 | postgresql-9.4
Maintainer: Jaime Casanova <jaime@2ndQuadrant.com> Maintainer: Jaime Casanova <jaime@2ndQuadrant.com>
Description: PostgreSQL replication setup, magament and monitoring Description: PostgreSQL replication setup, magament and monitoring
has two main executables has two main executables

6
log.h
View File

@@ -25,9 +25,15 @@
#define REPMGR_SYSLOG 1 #define REPMGR_SYSLOG 1
#define REPMGR_STDERR 2 #define REPMGR_STDERR 2
#if (PG_VERSION_NUM >= 90100)
void void
stderr_log_with_level(const char *level_name, int level, const char *fmt,...) stderr_log_with_level(const char *level_name, int level, const char *fmt,...)
__attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 4))); __attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 4)));
#else
void
stderr_log_with_level(const char *level_name, int level, const char *fmt,...)
__attribute__((format(printf, 3, 4)));
#endif
/* Standard error logging */ /* Standard error logging */
#define stderr_log_debug(...) stderr_log_with_level("DEBUG", LOG_DEBUG, __VA_ARGS__) #define stderr_log_debug(...) stderr_log_with_level("DEBUG", LOG_DEBUG, __VA_ARGS__)

253
repmgr.c
View File

@@ -100,6 +100,7 @@ main(int argc, char **argv)
{"host", required_argument, NULL, 'h'}, {"host", required_argument, NULL, 'h'},
{"port", required_argument, NULL, 'p'}, {"port", required_argument, NULL, 'p'},
{"username", required_argument, NULL, 'U'}, {"username", required_argument, NULL, 'U'},
{"superuser", required_argument, NULL, 'S'},
{"dest-dir", required_argument, NULL, 'D'}, {"dest-dir", required_argument, NULL, 'D'},
{"local-port", required_argument, NULL, 'l'}, {"local-port", required_argument, NULL, 'l'},
{"config-file", required_argument, NULL, 'f'}, {"config-file", required_argument, NULL, 'f'},
@@ -109,15 +110,15 @@ main(int argc, char **argv)
{"force", no_argument, NULL, 'F'}, {"force", no_argument, NULL, 'F'},
{"wait", no_argument, NULL, 'W'}, {"wait", no_argument, NULL, 'W'},
{"ignore-rsync-warning", no_argument, NULL, 'I'}, {"ignore-rsync-warning", no_argument, NULL, 'I'},
{"min-recovery-apply-delay", required_argument, NULL, 'r'},
{"verbose", no_argument, NULL, 'v'}, {"verbose", no_argument, NULL, 'v'},
{"fast-checkpoint", no_argument, NULL, 'c'},
{"initdb-no-pwprompt", no_argument, NULL, 1},
{NULL, 0, NULL, 0} {NULL, 0, NULL, 0}
}; };
int optindex; int optindex;
int c, targ; int c;
int action = NO_ACTION; int action = NO_ACTION;
char *ptr = NULL;
progname = get_progname(argv[0]); progname = get_progname(argv[0]);
@@ -136,7 +137,7 @@ main(int argc, char **argv)
} }
while ((c = getopt_long(argc, argv, "d:h:p:U:D:l:f:R:w:k:FWIvr:", long_options, while ((c = getopt_long(argc, argv, "d:h:p:U:S:D:l:f:R:w:k:FWIvc", long_options,
&optindex)) != -1) &optindex)) != -1)
{ {
switch (c) switch (c)
@@ -154,6 +155,9 @@ main(int argc, char **argv)
case 'U': case 'U':
strncpy(runtime_options.username, optarg, MAXLEN); strncpy(runtime_options.username, optarg, MAXLEN);
break; break;
case 'S':
strncpy(runtime_options.superuser, optarg, MAXLEN);
break;
case 'D': case 'D':
strncpy(runtime_options.dest_dir, optarg, MAXFILENAME); strncpy(runtime_options.dest_dir, optarg, MAXFILENAME);
break; break;
@@ -186,28 +190,15 @@ main(int argc, char **argv)
case 'I': case 'I':
runtime_options.ignore_rsync_warn = true; runtime_options.ignore_rsync_warn = true;
break; break;
case 'r':
targ = strtol(optarg, &ptr, 10);
if(targ < 0) {
usage();
exit(ERR_BAD_CONFIG);
}
if(ptr && *ptr) {
if(strcmp(ptr, "ms") != 0 && strcmp(ptr, "s") != 0 &&
strcmp(ptr, "min") != 0 && strcmp(ptr, "h") != 0 &&
strcmp(ptr, "d") != 0)
{
usage();
exit(ERR_BAD_CONFIG);
}
}
strncpy(runtime_options.min_recovery_apply_delay, optarg, MAXLEN);
break;
case 'v': case 'v':
runtime_options.verbose = true; runtime_options.verbose = true;
break; break;
case 'c':
runtime_options.fast_checkpoint = true;
break;
case 1:
runtime_options.initdb_no_pwprompt = true;
break;
default: default:
usage(); usage();
exit(ERR_BAD_CONFIG); exit(ERR_BAD_CONFIG);
@@ -309,6 +300,12 @@ main(int argc, char **argv)
strncpy(runtime_options.dbname, DEFAULT_DBNAME, MAXLEN); strncpy(runtime_options.dbname, DEFAULT_DBNAME, MAXLEN);
} }
/* We check that port number is not null */
if (!runtime_options.masterport[0])
{
strncpy(runtime_options.masterport, DEFAULT_MASTER_PORT, MAXLEN);
}
/* Read the configuration file, normally repmgr.conf */ /* Read the configuration file, normally repmgr.conf */
if (!runtime_options.config_file[0]) if (!runtime_options.config_file[0])
strncpy(runtime_options.config_file, DEFAULT_CONFIG_FILE, MAXLEN); strncpy(runtime_options.config_file, DEFAULT_CONFIG_FILE, MAXLEN);
@@ -827,7 +824,7 @@ do_standby_clone(void)
int r = 0, int r = 0,
retval = SUCCESS; retval = SUCCESS;
int i, int i,j,
is_standby_retval; is_standby_retval;
bool flag_success = false; bool flag_success = false;
bool test_mode = false; bool test_mode = false;
@@ -905,11 +902,30 @@ do_standby_clone(void)
i = guc_set(conn, "wal_level", "=", "hot_standby"); i = guc_set(conn, "wal_level", "=", "hot_standby");
if (i == 0 || i == -1) if (i == 0 || i == -1)
{ {
PQfinish(conn);
if (i == 0) if (i == 0)
log_err(_("%s needs parameter 'wal_level' to be set to 'hot_standby'\n"), {
progname); /* We could be using PG 9.4 with log_level logical, which is good enough for
exit(ERR_BAD_CONFIG); hot standby replication.
We should check if the wal_level is set to that value, in which case we are
good to proceed.
No need to check if we are in 9.4 first, as the query used in guc_set will just
return zero rows if on < 9.4, and so will work anyway.
*/
j = guc_set(conn, "wal_level", "=", "logical");
if (j == 0 || j == -1)
{
PQfinish(conn);
if (j == 0)
log_err(_("%s needs parameter 'wal_level' to be set to at least 'hot_standby'\n"),
progname);
exit(ERR_BAD_CONFIG);
}
}
else if (i == -1)
{
PQfinish(conn);
exit(ERR_BAD_CONFIG);
}
} }
i = guc_set_typed(conn, "wal_keep_segments", ">=", i = guc_set_typed(conn, "wal_keep_segments", ">=",
@@ -1102,8 +1118,9 @@ do_standby_clone(void)
*/ */
sqlquery_snprintf( sqlquery_snprintf(
sqlquery, sqlquery,
"SELECT pg_xlogfile_name(pg_start_backup('repmgr_standby_clone_%ld'))", "SELECT pg_xlogfile_name(pg_start_backup('repmgr_standby_clone_%ld', %s))",
time(NULL)); time(NULL),
runtime_options.fast_checkpoint ? "TRUE" : "FALSE");
log_debug(_("standby clone: %s\n"), sqlquery); log_debug(_("standby clone: %s\n"), sqlquery);
res = PQexec(conn, sqlquery); res = PQexec(conn, sqlquery);
if (PQresultStatus(res) != PGRES_TUPLES_OK) if (PQresultStatus(res) != PGRES_TUPLES_OK)
@@ -1703,8 +1720,13 @@ do_witness_create(void)
*/ */
/* Create the cluster for witness */ /* Create the cluster for witness */
sprintf(script, "%s/pg_ctl %s -D %s init -o \"-W\"", options.pg_bindir, if (!runtime_options.superuser[0])
options.pgctl_options, runtime_options.dest_dir); strncpy(runtime_options.superuser, "postgres", MAXLEN);
sprintf(script, "%s/pg_ctl %s -D %s init -o \"%s-U %s\"", options.pg_bindir,
options.pgctl_options, runtime_options.dest_dir,
runtime_options.initdb_no_pwprompt ? "" : "-W ",
runtime_options.superuser);
log_info("Initialize cluster for witness: %s.\n", script); log_info("Initialize cluster for witness: %s.\n", script);
r = system(script); r = system(script);
@@ -1745,6 +1767,53 @@ do_witness_create(void)
fclose(pg_conf); fclose(pg_conf);
/* start new instance */
sprintf(script, "%s/pg_ctl %s -w -D %s start", options.pg_bindir,
options.pgctl_options, runtime_options.dest_dir);
log_info(_("Start cluster for witness: %s"), script);
r = system(script);
if (r != 0)
{
log_err(_("Can't start cluster for witness server\n"));
PQfinish(masterconn);
exit(ERR_BAD_CONFIG);
}
/* check if we need to create a user */
if (runtime_options.username[0] && runtime_options.localport[0] && strcmp(runtime_options.username,"postgres")!=0 )
{
/* create required user needs to be superuser to create untrusted language function in c */
sprintf(script, "%s/createuser -p %s --superuser --login -U %s %s", options.pg_bindir,
runtime_options.localport, runtime_options.superuser, runtime_options.username);
log_info("Create user for witness db: %s.\n", script);
r = system(script);
if (r != 0)
{
log_err("Can't create user for witness server\n");
PQfinish(masterconn);
exit(ERR_BAD_CONFIG);
}
}
/* check if we need to create a database */
if(runtime_options.dbname[0] && strcmp(runtime_options.dbname,"postgres")!=0 && runtime_options.localport[0])
{
/* create required db */
sprintf(script, "%s/createdb -p %s -U %s --owner=%s %s",
options.pg_bindir, runtime_options.localport, runtime_options.superuser, runtime_options.username, runtime_options.dbname);
log_info("Create database for witness db: %s.\n", script);
r = system(script);
if (r != 0)
{
log_err("Can't create database for witness server\n");
PQfinish(masterconn);
exit(ERR_BAD_CONFIG);
}
}
/* Get the pg_hba.conf full path */ /* Get the pg_hba.conf full path */
sqlquery_snprintf(sqlquery, "SELECT name, setting " sqlquery_snprintf(sqlquery, "SELECT name, setting "
" FROM pg_settings " " FROM pg_settings "
@@ -1778,18 +1847,19 @@ do_witness_create(void)
exit(ERR_BAD_CONFIG); exit(ERR_BAD_CONFIG);
} }
/* start new instance */ /* reload to adapt for changed pg_hba.conf */
sprintf(script, "%s/pg_ctl %s -w -D %s start", options.pg_bindir, sprintf(script, "%s/pg_ctl %s -w -D %s reload", options.pg_bindir,
options.pgctl_options, runtime_options.dest_dir); options.pgctl_options, runtime_options.dest_dir);
log_info(_("Start cluster for witness: %s"), script); log_info(_("Reload cluster config for witness: %s"), script);
r = system(script); r = system(script);
if (r != 0) if (r != 0)
{ {
log_err(_("Can't start cluster for witness server\n")); log_err(_("Can't reload cluster for witness server\n"));
PQfinish(masterconn); PQfinish(masterconn);
exit(ERR_BAD_CONFIG); exit(ERR_BAD_CONFIG);
} }
/* register ourselves in the master */ /* register ourselves in the master */
sqlquery_snprintf(sqlquery, "INSERT INTO %s.repl_nodes(id, cluster, name, conninfo, priority, witness) " sqlquery_snprintf(sqlquery, "INSERT INTO %s.repl_nodes(id, cluster, name, conninfo, priority, witness) "
"VALUES (%d, '%s', '%s', '%s', %d, true)", "VALUES (%d, '%s', '%s', '%s', %d, true)",
@@ -1825,6 +1895,24 @@ do_witness_create(void)
PQfinish(witnessconn); PQfinish(witnessconn);
exit(ERR_BAD_CONFIG); exit(ERR_BAD_CONFIG);
} }
/* drop superuser powers if needed */
if (runtime_options.username[0] && runtime_options.localport[0] && strcmp(runtime_options.username,"postgres")!=0 )
{
sqlquery_snprintf(sqlquery, "ALTER ROLE %s NOSUPERUSER", runtime_options.username);
log_info("Drop superuser powers on user for witness db: %s.\n", sqlquery);
log_debug(_("witness create: %s"), sqlquery);
res = PQexec(witnessconn, sqlquery);
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
{
log_err(_("Cannot alter user privileges, %s\n"),
PQerrorMessage(witnessconn));
PQfinish(masterconn);
PQfinish(witnessconn);
exit(ERR_DB_QUERY);
}
}
PQfinish(masterconn); PQfinish(masterconn);
PQfinish(witnessconn); PQfinish(witnessconn);
@@ -1866,6 +1954,8 @@ help(const char *progname)
printf(_(" -l, --local-port=PORT standby or witness server local port\n")); printf(_(" -l, --local-port=PORT standby or witness server local port\n"));
printf(_(" -f, --config-file=PATH path to the configuration file\n")); printf(_(" -f, --config-file=PATH path to the configuration file\n"));
printf(_(" -R, --remote-user=USERNAME database server username for rsync\n")); printf(_(" -R, --remote-user=USERNAME database server username for rsync\n"));
printf(_(" -S, --superuser=USERNAME superuser username for witness database\n" \
" (default: postgres)\n"));
printf(_(" -w, --wal-keep-segments=VALUE minimum value for the GUC\n" \ printf(_(" -w, --wal-keep-segments=VALUE minimum value for the GUC\n" \
" wal_keep_segments (default: 5000)\n")); " wal_keep_segments (default: 5000)\n"));
printf(_(" -I, --ignore-rsync-warning ignore rsync partial transfer warning\n")); printf(_(" -I, --ignore-rsync-warning ignore rsync partial transfer warning\n"));
@@ -1874,8 +1964,8 @@ help(const char *progname)
printf(_(" -F, --force force potentially dangerous operations\n" \ printf(_(" -F, --force force potentially dangerous operations\n" \
" to happen\n")); " to happen\n"));
printf(_(" -W, --wait wait for a master to appear\n")); printf(_(" -W, --wait wait for a master to appear\n"));
printf(_(" -r, --min-recovery-apply-delay=VALUE enable recovery time delay, value has to be a valid time atom (e.g. 5min)")); printf(_(" -c, --fast-checkpoint force fast checkpoint when cloning a standby\n"));
printf(_(" --initdb-no-pwprompt don't require superuser password when running initdb\n"));
printf(_("\n%s performs some tasks like clone a node, promote it or making follow\n"), progname); printf(_("\n%s performs some tasks like clone a node, promote it or making follow\n"), progname);
printf(_("another node and then exits.\n\n")); printf(_("another node and then exits.\n\n"));
printf(_("COMMANDS:\n")); printf(_("COMMANDS:\n"));
@@ -1927,19 +2017,6 @@ create_recovery_file(const char *data_dir)
return false; return false;
} }
if(*runtime_options.min_recovery_apply_delay)
{
maxlen_snprintf(line, "\nmin_recovery_apply_delay = %s\n",
runtime_options.min_recovery_apply_delay);
if (fputs(line, recovery_file) == EOF)
{
log_err(_("recovery file could not be written, it could be necessary to create it manually\n"));
fclose(recovery_file);
return false;
}
}
/* FreeFile(recovery_file); */ /* FreeFile(recovery_file); */
fclose(recovery_file); fclose(recovery_file);
@@ -1950,34 +2027,25 @@ static int
test_ssh_connection(char *host, char *remote_user) test_ssh_connection(char *host, char *remote_user)
{ {
char script[MAXLEN]; char script[MAXLEN];
int r = 1, i; int r;
/* On some OS, true is located in a different place than in Linux /* On some OS, true is located in a different place than in Linux */
* we have to try them all until all alternatives are gone or we #ifdef __FreeBSD__
* found `true' because the target OS may differ from the source #define TRUEBIN_PATH "/usr/bin/true"
* OS #else
*/ #define TRUEBIN_PATH "/bin/true"
const char *truebin_pathes[] = { #endif
"/bin/true",
"/usr/bin/true",
NULL
};
/* Check if we have ssh connectivity to host before trying to rsync */ /* Check if we have ssh connectivity to host before trying to rsync */
for(i = 0; truebin_pathes[i] && r != 0; ++i) if (!remote_user[0])
{ maxlen_snprintf(script, "ssh -o Batchmode=yes %s %s %s",
if (!remote_user[0]) options.ssh_options, host, TRUEBIN_PATH);
maxlen_snprintf(script, "ssh -o Batchmode=yes %s %s %s", else
options.ssh_options, host, truebin_pathes[i]); maxlen_snprintf(script, "ssh -o Batchmode=yes %s %s -l %s %s",
else options.ssh_options, host, remote_user, TRUEBIN_PATH);
maxlen_snprintf(script, "ssh -o Batchmode=yes %s %s -l %s %s",
options.ssh_options, host, remote_user,
truebin_pathes[i]);
log_debug(_("command is: %s\n"), script);
r = system(script);
}
log_debug(_("command is: %s\n"), script);
r = system(script);
if (r != 0) if (r != 0)
log_info(_("Can not connect to the remote host (%s)\n"), host); log_info(_("Can not connect to the remote host (%s)\n"), host);
return r; return r;
@@ -2000,7 +2068,7 @@ copy_remote_files(char *host, char *remote_user, char *remote_path,
maxlen_snprintf(rsync_flags, "%s", options.rsync_options); maxlen_snprintf(rsync_flags, "%s", options.rsync_options);
if (runtime_options.force) if (runtime_options.force)
strcat(rsync_flags, " --delete"); strcat(rsync_flags, " --delete --checksum");
if (!remote_user[0]) if (!remote_user[0])
{ {
@@ -2368,13 +2436,14 @@ static bool
copy_configuration(PGconn *masterconn, PGconn *witnessconn) copy_configuration(PGconn *masterconn, PGconn *witnessconn)
{ {
char sqlquery[MAXLEN]; char sqlquery[MAXLEN];
PGresult *res; PGresult *res1;
PGresult *res2;
int i; int i;
sqlquery_snprintf(sqlquery, "TRUNCATE TABLE %s.repl_nodes", repmgr_schema); sqlquery_snprintf(sqlquery, "TRUNCATE TABLE %s.repl_nodes", repmgr_schema);
log_debug("copy_configuration: %s\n", sqlquery); log_debug("copy_configuration: %s\n", sqlquery);
res = PQexec(witnessconn, sqlquery); res1 = PQexec(witnessconn, sqlquery);
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) if (!res1 || PQresultStatus(res1) != PGRES_COMMAND_OK)
{ {
fprintf(stderr, "Cannot clean node details in the witness, %s\n", fprintf(stderr, "Cannot clean node details in the witness, %s\n",
PQerrorMessage(witnessconn)); PQerrorMessage(witnessconn));
@@ -2383,33 +2452,35 @@ copy_configuration(PGconn *masterconn, PGconn *witnessconn)
sqlquery_snprintf(sqlquery, "SELECT id, name, conninfo, priority, witness FROM %s.repl_nodes", sqlquery_snprintf(sqlquery, "SELECT id, name, conninfo, priority, witness FROM %s.repl_nodes",
repmgr_schema); repmgr_schema);
res = PQexec(masterconn, sqlquery); res1 = PQexec(masterconn, sqlquery);
if (PQresultStatus(res) != PGRES_TUPLES_OK) if (PQresultStatus(res1) != PGRES_TUPLES_OK)
{ {
fprintf(stderr, "Can't get configuration from master: %s\n", fprintf(stderr, "Can't get configuration from master: %s\n",
PQerrorMessage(masterconn)); PQerrorMessage(masterconn));
PQclear(res); PQclear(res1);
return false; return false;
} }
for (i = 0; i < PQntuples(res); i++) for (i = 0; i < PQntuples(res1); i++)
{ {
sqlquery_snprintf(sqlquery, "INSERT INTO %s.repl_nodes(id, cluster, name, conninfo, priority, witness) " sqlquery_snprintf(sqlquery, "INSERT INTO %s.repl_nodes(id, cluster, name, conninfo, priority, witness) "
"VALUES (%d, '%s', '%s', '%s', %d, '%s')", "VALUES (%d, '%s', '%s', '%s', %d, '%s')",
repmgr_schema, atoi(PQgetvalue(res, i, 0)), repmgr_schema, atoi(PQgetvalue(res1, i, 0)),
options.cluster_name, PQgetvalue(res, i, 1), options.cluster_name, PQgetvalue(res1, i, 1),
PQgetvalue(res, i, 2), PQgetvalue(res1, i, 2),
atoi(PQgetvalue(res, i, 3)), atoi(PQgetvalue(res1, i, 3)),
PQgetvalue(res, i, 4)); PQgetvalue(res1, i, 4));
res = PQexec(witnessconn, sqlquery); res2 = PQexec(witnessconn, sqlquery);
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) if (!res2 || PQresultStatus(res2) != PGRES_COMMAND_OK)
{ {
fprintf(stderr, "Cannot copy configuration to witness, %s\n", fprintf(stderr, "Cannot copy configuration to witness, %s\n",
PQerrorMessage(witnessconn)); PQerrorMessage(witnessconn));
PQclear(res); PQclear(res2);
return false; return false;
} }
PQclear(res2);
} }
PQclear(res1);
return true; return true;
} }

View File

@@ -20,9 +20,9 @@
#ifndef _REPMGR_H_ #ifndef _REPMGR_H_
#define _REPMGR_H_ #define _REPMGR_H_
#include "postgres_fe.h" #include <libpq-fe.h>
#include "getopt_long.h" #include <postgres_fe.h>
#include "libpq-fe.h" #include <getopt_long.h>
#include "strutil.h" #include "strutil.h"
#include "dbutils.h" #include "dbutils.h"
@@ -56,21 +56,22 @@ typedef struct
char dest_dir[MAXFILENAME]; char dest_dir[MAXFILENAME];
char config_file[MAXFILENAME]; char config_file[MAXFILENAME];
char remote_user[MAXLEN]; char remote_user[MAXLEN];
char superuser[MAXLEN];
char wal_keep_segments[MAXLEN]; char wal_keep_segments[MAXLEN];
bool verbose; bool verbose;
bool force; bool force;
bool wait_for_master; bool wait_for_master;
bool ignore_rsync_warn; bool ignore_rsync_warn;
bool initdb_no_pwprompt;
bool fast_checkpoint;
char masterport[MAXLEN]; char masterport[MAXLEN];
char localport[MAXLEN]; char localport[MAXLEN];
/* parameter used by CLUSTER CLEANUP */ /* parameter used by CLUSTER CLEANUP */
int keep_history; int keep_history;
char min_recovery_apply_delay[MAXLEN];
} t_runtime_options; } t_runtime_options;
#define T_RUNTIME_OPTIONS_INITIALIZER { "", "", "", "", "", "", DEFAULT_WAL_KEEP_SEGMENTS, false, false, false, false, "", "", 0, "" } #define T_RUNTIME_OPTIONS_INITIALIZER { "", "", "", "", "", "", "", DEFAULT_WAL_KEEP_SEGMENTS, false, false, false, false, false, false, "", "", 0}
#endif #endif

View File

@@ -218,6 +218,17 @@ main(int argc, char **argv)
} }
} }
/*
* Read the configuration file: repmgr.conf
*/
parse_config(config_file, &local_options);
if (local_options.node == -1)
{
log_err(_("Node information is missing. "
"Check the configuration file, or provide one if you have not done so.\n"));
terminate(ERR_BAD_CONFIG);
}
if (daemonize) if (daemonize)
{ {
do_daemonize(); do_daemonize();
@@ -232,17 +243,6 @@ main(int argc, char **argv)
setup_event_handlers(); setup_event_handlers();
#endif #endif
/*
* Read the configuration file: repmgr.conf
*/
parse_config(config_file, &local_options);
if (local_options.node == -1)
{
log_err(_("Node information is missing. "
"Check the configuration file, or provide one if you have not done so.\n"));
terminate(ERR_BAD_CONFIG);
}
fd = freopen("/dev/null", "r", stdin); fd = freopen("/dev/null", "r", stdin);
if (fd == NULL) if (fd == NULL)
{ {
@@ -551,7 +551,7 @@ witness_monitor(void)
sqlquery_snprintf(sqlquery, sqlquery_snprintf(sqlquery,
"INSERT INTO %s.repl_monitor " "INSERT INTO %s.repl_monitor "
"VALUES(%d, %d, '%s'::timestamp with time zone, " "VALUES(%d, %d, '%s'::timestamp with time zone, "
" pg_current_xlog_location(), null, " " null, pg_current_xlog_location(), null, "
" 0, 0)", " 0, 0)",
repmgr_schema, primary_options.node, local_options.node, repmgr_schema, primary_options.node, local_options.node,
monitor_witness_timestamp); monitor_witness_timestamp);

View File

@@ -25,9 +25,15 @@
#include "log.h" #include "log.h"
#include "strutil.h" #include "strutil.h"
#if (PG_VERSION_NUM >= 90100)
static int static int
xvsnprintf(char *str, size_t size, const char *format, va_list ap) xvsnprintf(char *str, size_t size, const char *format, va_list ap)
__attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 0))); __attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 0)));
#else
static int
xvsnprintf(char *str, size_t size, const char *format, va_list ap)
__attribute__((format(printf, 3, 0)));
#endif
static int static int
xvsnprintf(char *str, size_t size, const char *format, va_list ap) xvsnprintf(char *str, size_t size, const char *format, va_list ap)

View File

@@ -22,7 +22,7 @@
#define _STRUTIL_H_ #define _STRUTIL_H_
#include <stdlib.h> #include <stdlib.h>
#include <errcode.h> #include "errcode.h"
#define QUERY_STR_LEN 8192 #define QUERY_STR_LEN 8192
#define MAXLEN 1024 #define MAXLEN 1024
@@ -31,6 +31,7 @@
#define MAXCONNINFO 1024 #define MAXCONNINFO 1024
#if (PG_VERSION_NUM >= 90100)
extern int extern int
xsnprintf(char *str, size_t size, const char *format,...) xsnprintf(char *str, size_t size, const char *format,...)
__attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 4))); __attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 4)));
@@ -42,5 +43,18 @@ __attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3)));
extern int extern int
maxlen_snprintf(char *str, const char *format,...) maxlen_snprintf(char *str, const char *format,...)
__attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3))); __attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3)));
#else
extern int
xsnprintf(char *str, size_t size, const char *format,...)
__attribute__((format(printf, 3, 4)));
extern int
sqlquery_snprintf(char *str, const char *format,...)
__attribute__((format(printf, 2, 3)));
extern int
maxlen_snprintf(char *str, const char *format,...)
__attribute__((format(printf, 2, 3)));
#endif
#endif /* _STRUTIL_H_ */ #endif /* _STRUTIL_H_ */

View File

@@ -1,6 +1,6 @@
#ifndef _VERSION_H_ #ifndef _VERSION_H_
#define _VERSION_H_ #define _VERSION_H_
#define REPMGR_VERSION "2.1dev" #define REPMGR_VERSION "2.0.3"
#endif #endif