Compare commits

..

46 Commits

Author SHA1 Message Date
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
7 changed files with 206 additions and 164 deletions

View File

@@ -1,3 +1,10 @@
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)

View File

@@ -34,7 +34,7 @@ same PostgreSQL major version, and preferably should be running the same minor
version.
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
@@ -82,9 +82,12 @@ Note that repmgr expects a default of 5000 wal_keep_segments, although this
value can be overridden when executing the `repmgr` client.
Additionally, repmgr requires a dedicated PostgreSQL superuser account
and a database in which to store monitoring and replication data. The
database can in principle be any database, including the default postgres
one, however it's probably advisable to create a dedicated repmgr database.
and a database in which to store monitoring and replication data. The repmgr
user account will also be used for replication connections from the standby,
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
@@ -107,11 +110,11 @@ identification and database connection information:
resolvable by all nodes on the cluster.
* `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.
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).
@@ -140,14 +143,15 @@ Master setup
- 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 replication all 192.168.1.0/24 trust
host repmgr_db repmgr_usr 192.168.1.0/24 trust
host replication repmgr_usr 192.168.1.0/24 trust
```
Restart the PostgreSQL server after making these changes.
2. Create the repmgr configuration file:
$ cat $HOME/repmgr/repmgr.conf
@@ -190,8 +194,10 @@ Slave/standby setup
-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.
This will clone the PostgreSQL database files from the master, and additionally
create an appropriate `recovery.conf` file.
This will clone the PostgreSQL database files from the master, including its
`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

181
repmgr.c
View File

@@ -109,15 +109,13 @@ main(int argc, char **argv)
{"force", no_argument, NULL, 'F'},
{"wait", no_argument, NULL, 'W'},
{"ignore-rsync-warning", no_argument, NULL, 'I'},
{"min-recovery-apply-delay", required_argument, NULL, 'r'},
{"verbose", no_argument, NULL, 'v'},
{NULL, 0, NULL, 0}
};
int optindex;
int c, targ;
int c;
int action = NO_ACTION;
char *ptr = NULL;
progname = get_progname(argv[0]);
@@ -136,7 +134,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:D:l:f:R:w:k:FWIv", long_options,
&optindex)) != -1)
{
switch (c)
@@ -186,25 +184,6 @@ main(int argc, char **argv)
case 'I':
runtime_options.ignore_rsync_warn = true;
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':
runtime_options.verbose = true;
break;
@@ -309,6 +288,12 @@ main(int argc, char **argv)
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 */
if (!runtime_options.config_file[0])
strncpy(runtime_options.config_file, DEFAULT_CONFIG_FILE, MAXLEN);
@@ -1745,6 +1730,53 @@ do_witness_create(void)
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 */
sqlquery_snprintf(sqlquery, "SELECT name, setting "
" FROM pg_settings "
@@ -1778,18 +1810,19 @@ do_witness_create(void)
exit(ERR_BAD_CONFIG);
}
/* start new instance */
sprintf(script, "%s/pg_ctl %s -w -D %s start", options.pg_bindir,
/* reload to adapt for changed pg_hba.conf */
sprintf(script, "%s/pg_ctl %s -w -D %s reload", options.pg_bindir,
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);
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);
exit(ERR_BAD_CONFIG);
}
/* register ourselves in the master */
sqlquery_snprintf(sqlquery, "INSERT INTO %s.repl_nodes(id, cluster, name, conninfo, priority, witness) "
"VALUES (%d, '%s', '%s', '%s', %d, true)",
@@ -1825,6 +1858,24 @@ do_witness_create(void)
PQfinish(witnessconn);
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(witnessconn);
@@ -1874,7 +1925,6 @@ help(const char *progname)
printf(_(" -F, --force force potentially dangerous operations\n" \
" to happen\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(_("another node and then exits.\n\n"));
@@ -1927,19 +1977,6 @@ create_recovery_file(const char *data_dir)
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); */
fclose(recovery_file);
@@ -1950,34 +1987,25 @@ static int
test_ssh_connection(char *host, char *remote_user)
{
char script[MAXLEN];
int r = 1, i;
int r;
/* 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
* found `true' because the target OS may differ from the source
* OS
*/
const char *truebin_pathes[] = {
"/bin/true",
"/usr/bin/true",
NULL
};
/* On some OS, true is located in a different place than in Linux */
#ifdef __FreeBSD__
#define TRUEBIN_PATH "/usr/bin/true"
#else
#define TRUEBIN_PATH "/bin/true"
#endif
/* 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",
options.ssh_options, host, truebin_pathes[i]);
options.ssh_options, host, TRUEBIN_PATH);
else
maxlen_snprintf(script, "ssh -o Batchmode=yes %s %s -l %s %s",
options.ssh_options, host, remote_user,
truebin_pathes[i]);
options.ssh_options, host, remote_user, TRUEBIN_PATH);
log_debug(_("command is: %s\n"), script);
r = system(script);
}
if (r != 0)
log_info(_("Can not connect to the remote host (%s)\n"), host);
return r;
@@ -2000,7 +2028,7 @@ copy_remote_files(char *host, char *remote_user, char *remote_path,
maxlen_snprintf(rsync_flags, "%s", options.rsync_options);
if (runtime_options.force)
strcat(rsync_flags, " --delete");
strcat(rsync_flags, " --delete --checksum");
if (!remote_user[0])
{
@@ -2368,13 +2396,14 @@ static bool
copy_configuration(PGconn *masterconn, PGconn *witnessconn)
{
char sqlquery[MAXLEN];
PGresult *res;
PGresult *res1;
PGresult *res2;
int i;
sqlquery_snprintf(sqlquery, "TRUNCATE TABLE %s.repl_nodes", repmgr_schema);
log_debug("copy_configuration: %s\n", sqlquery);
res = PQexec(witnessconn, sqlquery);
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
res1 = PQexec(witnessconn, sqlquery);
if (!res1 || PQresultStatus(res1) != PGRES_COMMAND_OK)
{
fprintf(stderr, "Cannot clean node details in the witness, %s\n",
PQerrorMessage(witnessconn));
@@ -2383,33 +2412,35 @@ copy_configuration(PGconn *masterconn, PGconn *witnessconn)
sqlquery_snprintf(sqlquery, "SELECT id, name, conninfo, priority, witness FROM %s.repl_nodes",
repmgr_schema);
res = PQexec(masterconn, sqlquery);
if (PQresultStatus(res) != PGRES_TUPLES_OK)
res1 = PQexec(masterconn, sqlquery);
if (PQresultStatus(res1) != PGRES_TUPLES_OK)
{
fprintf(stderr, "Can't get configuration from master: %s\n",
PQerrorMessage(masterconn));
PQclear(res);
PQclear(res1);
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) "
"VALUES (%d, '%s', '%s', '%s', %d, '%s')",
repmgr_schema, atoi(PQgetvalue(res, i, 0)),
options.cluster_name, PQgetvalue(res, i, 1),
PQgetvalue(res, i, 2),
atoi(PQgetvalue(res, i, 3)),
PQgetvalue(res, i, 4));
repmgr_schema, atoi(PQgetvalue(res1, i, 0)),
options.cluster_name, PQgetvalue(res1, i, 1),
PQgetvalue(res1, i, 2),
atoi(PQgetvalue(res1, i, 3)),
PQgetvalue(res1, i, 4));
res = PQexec(witnessconn, sqlquery);
if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
res2 = PQexec(witnessconn, sqlquery);
if (!res2 || PQresultStatus(res2) != PGRES_COMMAND_OK)
{
fprintf(stderr, "Cannot copy configuration to witness, %s\n",
PQerrorMessage(witnessconn));
PQclear(res);
PQclear(res2);
return false;
}
PQclear(res2);
}
PQclear(res1);
return true;
}

View File

@@ -67,10 +67,8 @@ typedef struct
/* parameter used by CLUSTER CLEANUP */
int keep_history;
char min_recovery_apply_delay[MAXLEN];
} 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

View File

@@ -551,7 +551,7 @@ witness_monitor(void)
sqlquery_snprintf(sqlquery,
"INSERT INTO %s.repl_monitor "
"VALUES(%d, %d, '%s'::timestamp with time zone, "
" pg_current_xlog_location(), null, "
" null, pg_current_xlog_location(), null, "
" 0, 0)",
repmgr_schema, primary_options.node, local_options.node,
monitor_witness_timestamp);

View File

@@ -22,7 +22,7 @@
#define _STRUTIL_H_
#include <stdlib.h>
#include <errcode.h>
#include "errcode.h"
#define QUERY_STR_LEN 8192
#define MAXLEN 1024

View File

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