Compare commits

..

35 Commits

Author SHA1 Message Date
Ian Barwick
47b7c4ce06 Update HISTORY for minor release 2.0.1 2014-07-16 11:00:58 +09:00
Ian Barwick
99ed9a065e Formatting fixes 2014-07-16 10:58:05 +09:00
Ian Barwick
a87d859e56 Correct year in specfile changelog 2014-07-16 09:58:51 +09:00
Ian Barwick
7350a8bf57 Fix code block formatting 2014-07-16 08:07:07 +09:00
Ian Barwick
75baed233b Convert QUICKSTART file to markdown format
Less effort for more consistent formatting (at least the way
github renders it).
2014-07-16 07:57:00 +09:00
Ian Barwick
5b9ac4585b Formatting fixes 2014-07-07 14:10:00 +09:00
Ian Barwick
2cbee90f35 Fix formatting 2014-07-07 11:51:10 +09:00
Ian Barwick
fa7d8df534 Add a "quickstart" guide
Provides a succinct overview of the steps needed to get repmgr
up and running as.
2014-07-07 11:39:26 +09:00
Ian Barwick
0cbd5d3933 Fix log messages in do_standby_promote()
Initial connection is to current standby, before attempting to
connect to old master.
2014-07-07 11:30:29 +09:00
Ian Barwick
a0e4c99ab4 Typo fixes 2014-07-07 11:10:32 +09:00
Ian Barwick
98c5215871 Change successful standby promotion message to log level 'NOTICE'
Was previously 'ERROR'.
2014-07-07 11:09:07 +09:00
Ian Barwick
e40b9db0a6 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-07-07 10:42:45 +09:00
Ian Barwick
54e62c3d65 Typo fixes and minor wording tweaks for clarity 2014-07-03 15:41:51 +09:00
Abhijit Menon-Sen
bfd482bebc Merge pull request #28 from Nexperteam/rhel-scripts
adapt makefile for RHEL + RHEL specific files
2014-06-26 22:55:56 +05:30
Abhijit Menon-Sen
6a0fc43086 Merge pull request #26 from Nexperteam/master
Makefile: create bindir before instal + force dir
2014-06-26 22:54:09 +05:30
Abhijit Menon-Sen
8f47111072 Merge pull request #31 from riegie/patch-1
Update README.rst
2014-06-26 22:51:52 +05:30
Riegie Godwin Jeyaranchen
0b5b3aaa4b Update README.rst
Fixing a grammar mistake.
2014-06-19 20:53:42 -04:00
Nathan Van Overloop
d8bba0de03 init script: make status call return proper return code 2014-06-06 15:47:33 +02:00
Nathan Van Overloop
73d352b2a2 adapt makefile for RHEL + RHEL specific files 2014-06-06 14:30:37 +02:00
brynhood
143aa57bb8 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-04-28 14:27:52 +02:00
Abhijit Menon-Sen
5b15fcff5c Merge pull request #24 from PriceChild/patch-1
Typo in example command.
2014-04-08 11:04:09 +05:30
PriceChild
4469de533e Typo in example command. 2014-04-01 16:31:33 +01:00
Christian Kruse
7c89a4d762 Merge pull request #20 from kjoe/master
debian init script and config file documentation fixes
2014-03-24 07:46:56 +01:00
József Kószó
b3c68dead8 debian init script and config file documentation fixes 2014-03-22 22:23:15 +01:00
József Kószó
b9ab9010c0 debian init script and config file documentation fixes 2014-03-22 22:13:33 +01:00
József Kószó
2a6c835a5a debian init script and config file documentation fixes 2014-03-21 14:18:07 +01:00
Christian Kruse
2d48d5aee4 fixing some documentation errors 2014-03-10 15:48:44 +01:00
Christian Kruse
653e11c2a7 basic min_recovery_apply_delay support 2014-03-10 15:41:38 +01:00
Christian Kruse
91c29fe2a2 removed old comment 2014-03-06 18:34:41 +01:00
Christian Kruse
573f1d3b2e no longer use global variable for SQL query buffer 2014-03-06 18:34:41 +01:00
Christian Kruse
0a6ff7faec removed no-longer used variable 2014-03-06 18:34:41 +01:00
Christian Kruse
98b1f8d28a 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.
2014-03-06 18:34:40 +01:00
Christian Kruse
9eba986833 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-03-06 18:34:40 +01:00
Christian Kruse
164cf9d08f completely avoid usage of strnlen() 2014-03-06 18:34:40 +01:00
Christian Kruse
d8b8bf0e2a pg_indent'ing all files… 2014-03-06 18:34:40 +01:00
7 changed files with 164 additions and 206 deletions

19
HISTORY
View File

@@ -1,17 +1,10 @@
2.0.2 2015-02-17 2.0.1 2014-07-16
Add "--checksum" in rsync when using "--force" (Jaime) Documentation fixes and new QUICKSTART file (Ian)
Use createdb/createuser instead of psql (Jaime) Explicitly specify directories to ignore when cloning (Ian)
Fixes to witness creation and monitoring (wamonite) Fix log level for some log messages (Ian)
Use default master port if none supplied (Martín) RHEL/CentOS specfile, init script and Makefile fixes (Nathan Van Overloop)
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)

View File

@@ -34,7 +34,7 @@ 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
@@ -55,7 +55,7 @@ repmgr must be installed on each PostgreSQL server node.
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
Configuration Configuration
@@ -71,23 +71,20 @@ between all server nodes to enable repmgr to copy required files.
The master PostgreSQL node needs to be configured for replication with the The master PostgreSQL node needs to be configured for replication with the
following settings: following settings:
wal_level = 'hot_standby' # minimal, archive, hot_standby, or logical wal_level = 'hot_standby' # minimal, archive, hot_standby, or logical
archive_mode = on # allows archiving to be done archive_mode = on # allows archiving to be done
archive_command = 'cd .' # command to use to archive a logfile segment archive_command = 'cd .' # command to use to archive a logfile segment
max_wal_senders = 10 # max number of walsender processes max_wal_senders = 10 # max number of walsender processes
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 repmgr and a database in which to store monitoring and replication data. The
user account will also be used for replication connections from the standby, database can in principle be any database, including the default postgres
so a seperate replication user with the `REPLICATION` privilege is not required. one, however it's probably advisable to create a dedicated repmgr database.
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
@@ -95,11 +92,11 @@ usage.
Each PostgreSQL node requires a repmgr configuration file containing Each PostgreSQL node requires a repmgr configuration file containing
identification and database connection information: identification and database connection information:
cluster=test cluster=test
node=1 node=1
node_name=node1 node_name=node1
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
* `cluster`: common name for the replication cluster; this must be the same on all nodes * `cluster`: common name for the replication cluster; this must be the same on all nodes
* `node`: a unique, abitrary integer identifier * `node`: a unique, abitrary integer identifier
@@ -110,11 +107,11 @@ identification and database connection information:
resolvable by all nodes on the cluster. resolvable by all nodes on the cluster.
* `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.
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).
@@ -143,31 +140,30 @@ Master setup
- configure postgresql.conf for replication (see above) - configure postgresql.conf for replication (see above)
- update pg_hba.conf, e.g.: - update pg_hba.conf:
``` ```
host repmgr_db repmgr_usr 192.168.1.0/24 trust host repmgr_usr repmgr_db 192.168.1.0/24 trust
host replication repmgr_usr 192.168.1.0/24 trust host replication all 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
node=1 node=1
node_name=node1 node_name=node1
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: 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
[2014-07-04 10:43:42] [INFO] repmgr connected to master, checking its state [2014-07-04 10:43:42] [INFO] repmgr connected to master, checking its state
[2014-07-04 10:43:42] [INFO] master register: creating database objects inside the repmgr_test schema [2014-07-04 10:43:42] [INFO] master register: creating database objects inside the repmgr_test schema
[2014-07-04 10:43:43] [NOTICE] Master node correctly registered for cluster test with id 1 (conninfo: host=localhost user=repmgr_usr dbname=repmgr_db) [2014-07-04 10:43:43] [NOTICE] Master node correctly registered for cluster test with id 1 (conninfo: host=localhost user=repmgr_usr dbname=repmgr_db)
Slave/standby setup Slave/standby setup
@@ -175,54 +171,52 @@ 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 -f $HOME/repmgr/repmgr.conf -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
[2014-07-04 10:49:00] [INFO] repmgr connected to master, checking its state [2014-07-04 10:49:00] [INFO] repmgr connected to master, checking its state
[2014-07-04 10:49:00] [INFO] Successfully connected to primary. Current installation size is 1807 MB [2014-07-04 10:49:00] [INFO] Successfully connected to primary. Current installation size is 1807 MB
[2014-07-04 10:49:00] [NOTICE] Starting backup... [2014-07-04 10:49:00] [NOTICE] Starting backup...
[2014-07-04 10:49:00] [INFO] creating directory "/path/to/data/"... [2014-07-04 10:49:00] [INFO] creating directory "/path/to/data/"...
(...) (...)
[2014-07-04 10:53:19] [NOTICE] Finishing backup... [2014-07-04 10:53:19] [NOTICE] Finishing backup...
NOTICE: pg_stop_backup complete, all required WAL segments have been archived NOTICE: pg_stop_backup complete, all required WAL segments have been archived
[2014-07-04 10:53:21] [INFO] repmgr requires primary to keep WAL files 0000000100000000000000AD until at least 0000000100000000000000AD [2014-07-04 10:53:21] [INFO] repmgr requires primary to keep WAL files 0000000100000000000000AD until at least 0000000100000000000000AD
[2014-07-04 10:53:21] [NOTICE] repmgr standby clone complete [2014-07-04 10:53:21] [NOTICE] repmgr standby clone complete
[2014-07-04 10:53:21] [NOTICE] HINT: You can now start your postgresql server [2014-07-04 10:53:21] [NOTICE] HINT: You can now start your postgresql server
[2014-07-04 10:53:21] [NOTICE] for example : /etc/init.d/postgresql start [2014-07-04 10:53:21] [NOTICE] for example : /etc/init.d/postgresql start
-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, including its This will clone the PostgreSQL database files from the master, and additionally
`postgresql.conf` and `pg_hba.conf` files, and additionally automatically create create an appropriate `recovery.conf` file.
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
node=2 node=2
node_name=node2 node_name=node2
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
[2014-07-04 11:48:13] [INFO] repmgr connecting to standby database [2014-07-04 11:48:13] [INFO] repmgr connecting to standby database
[2014-07-04 11:48:13] [INFO] repmgr connected to standby, checking its state [2014-07-04 11:48:13] [INFO] repmgr connected to standby, checking its state
[2014-07-04 11:48:13] [INFO] repmgr connecting to master database [2014-07-04 11:48:13] [INFO] repmgr connecting to master database
[2014-07-04 11:48:13] [INFO] finding node list for cluster 'test' [2014-07-04 11:48:13] [INFO] finding node list for cluster 'test'
[2014-07-04 11:48:13] [INFO] checking role of cluster node 'host=repmgr_node1 user=repmgr_usr dbname=repmgr_db' [2014-07-04 11:48:13] [INFO] checking role of cluster node 'host=repmgr_node1 user=repmgr_usr dbname=repmgr_db'
[2014-07-04 11:48:13] [INFO] repmgr connected to master, checking its state [2014-07-04 11:48:13] [INFO] repmgr connected to master, checking its state
[2014-07-04 11:48:13] [INFO] repmgr registering the standby [2014-07-04 11:48:13] [INFO] repmgr registering the standby
[2014-07-04 11:48:13] [INFO] repmgr registering the standby complete [2014-07-04 11:48:13] [INFO] repmgr registering the standby complete
[2014-07-04 11:48:13] [NOTICE] Standby node correctly registered for cluster test with id 2 (conninfo: host=localhost user=repmgr_usr dbname=repmgr_db) [2014-07-04 11:48:13] [NOTICE] Standby node correctly registered for cluster test with id 2 (conninfo: host=localhost user=repmgr_usr dbname=repmgr_db)
Monitoring Monitoring
---------- ----------

193
repmgr.c
View File

@@ -109,13 +109,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'},
{NULL, 0, NULL, 0} {NULL, 0, NULL, 0}
}; };
int optindex; int optindex;
int c; int c, targ;
int action = NO_ACTION; int action = NO_ACTION;
char *ptr = NULL;
progname = get_progname(argv[0]); progname = get_progname(argv[0]);
@@ -134,7 +136,7 @@ main(int argc, char **argv)
} }
while ((c = getopt_long(argc, argv, "d:h:p:U:D:l:f:R:w:k:FWIv", long_options, while ((c = getopt_long(argc, argv, "d:h:p:U:D:l:f:R:w:k:FWIvr:", long_options,
&optindex)) != -1) &optindex)) != -1)
{ {
switch (c) switch (c)
@@ -184,6 +186,25 @@ 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;
@@ -288,12 +309,6 @@ 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);
@@ -1730,53 +1745,6 @@ 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 postgres %s", options.pg_bindir,
runtime_options.localport,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 postgres --owner=%s %s",
options.pg_bindir, runtime_options.localport,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 "
@@ -1810,19 +1778,18 @@ do_witness_create(void)
exit(ERR_BAD_CONFIG); exit(ERR_BAD_CONFIG);
} }
/* reload to adapt for changed pg_hba.conf */ /* start new instance */
sprintf(script, "%s/pg_ctl %s -w -D %s reload", options.pg_bindir, sprintf(script, "%s/pg_ctl %s -w -D %s start", options.pg_bindir,
options.pgctl_options, runtime_options.dest_dir); options.pgctl_options, runtime_options.dest_dir);
log_info(_("Reload cluster config for witness: %s"), script); log_info(_("Start cluster for witness: %s"), script);
r = system(script); r = system(script);
if (r != 0) if (r != 0)
{ {
log_err(_("Can't reload cluster for witness server\n")); log_err(_("Can't start 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)",
@@ -1858,24 +1825,6 @@ 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);
@@ -1925,6 +1874,7 @@ 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(_("\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"));
@@ -1977,6 +1927,19 @@ 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);
@@ -1987,25 +1950,34 @@ 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; int r = 1, i;
/* 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
#ifdef __FreeBSD__ * we have to try them all until all alternatives are gone or we
#define TRUEBIN_PATH "/usr/bin/true" * found `true' because the target OS may differ from the source
#else * OS
#define TRUEBIN_PATH "/bin/true" */
#endif const char *truebin_pathes[] = {
"/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 */
if (!remote_user[0]) for(i = 0; truebin_pathes[i] && r != 0; ++i)
maxlen_snprintf(script, "ssh -o Batchmode=yes %s %s %s", {
options.ssh_options, host, TRUEBIN_PATH); if (!remote_user[0])
else maxlen_snprintf(script, "ssh -o Batchmode=yes %s %s %s",
maxlen_snprintf(script, "ssh -o Batchmode=yes %s %s -l %s %s", options.ssh_options, host, truebin_pathes[i]);
options.ssh_options, host, remote_user, TRUEBIN_PATH); else
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;
@@ -2028,7 +2000,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 --checksum"); strcat(rsync_flags, " --delete");
if (!remote_user[0]) if (!remote_user[0])
{ {
@@ -2396,14 +2368,13 @@ static bool
copy_configuration(PGconn *masterconn, PGconn *witnessconn) copy_configuration(PGconn *masterconn, PGconn *witnessconn)
{ {
char sqlquery[MAXLEN]; char sqlquery[MAXLEN];
PGresult *res1; PGresult *res;
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);
res1 = PQexec(witnessconn, sqlquery); res = PQexec(witnessconn, sqlquery);
if (!res1 || PQresultStatus(res1) != PGRES_COMMAND_OK) if (!res || PQresultStatus(res) != 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));
@@ -2412,35 +2383,33 @@ 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);
res1 = PQexec(masterconn, sqlquery); res = PQexec(masterconn, sqlquery);
if (PQresultStatus(res1) != PGRES_TUPLES_OK) if (PQresultStatus(res) != 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(res1); PQclear(res);
return false; return false;
} }
for (i = 0; i < PQntuples(res1); i++) for (i = 0; i < PQntuples(res); 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(res1, i, 0)), repmgr_schema, atoi(PQgetvalue(res, i, 0)),
options.cluster_name, PQgetvalue(res1, i, 1), options.cluster_name, PQgetvalue(res, i, 1),
PQgetvalue(res1, i, 2), PQgetvalue(res, i, 2),
atoi(PQgetvalue(res1, i, 3)), atoi(PQgetvalue(res, i, 3)),
PQgetvalue(res1, i, 4)); PQgetvalue(res, i, 4));
res2 = PQexec(witnessconn, sqlquery); res = PQexec(witnessconn, sqlquery);
if (!res2 || PQresultStatus(res2) != PGRES_COMMAND_OK) if (!res || PQresultStatus(res) != 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(res2); PQclear(res);
return false; return false;
} }
PQclear(res2);
} }
PQclear(res1);
return true; return true;
} }

View File

@@ -67,8 +67,10 @@ typedef struct
/* 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, "", "", 0, "" }
#endif #endif

View File

@@ -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, "
" null, pg_current_xlog_location(), 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

@@ -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

View File

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