Add rsync remote user name option. Expand docs to

include command line help examples.
This commit is contained in:
Greg Smith
2010-11-08 15:29:53 -05:00
parent 2082a6acd4
commit 3172ad97cf
2 changed files with 164 additions and 76 deletions

View File

@@ -32,7 +32,7 @@ To install and use repmgr and repmgrd follow these steps:
3. Check your primary server is correctly configured 3. Check your primary server is correctly configured
4. Write a suitable repmgr.conf for the node 4. Write a suitable ``repmgr.conf`` for the node
5. Setup repmgrd to aid in failover transitions 5. Setup repmgrd to aid in failover transitions
@@ -132,9 +132,9 @@ You may need to include
the full path of the binary instead, such as this RHEL example:: the full path of the binary instead, such as this RHEL example::
/usr/pgsql-9.0/bin/repmgr --version /usr/pgsql-9.0/bin/repmgr --version
/usr/pgsql-9.0/bin/repmgr --version /usr/pgsql-9.0/bin/repmgrd --version
Below this base binary installation directory is referred to as PGDIR. Below this binary installation base directory is referred to as PGDIR.
Set up trusted copy between postgres accounts Set up trusted copy between postgres accounts
--------------------------------------------- ---------------------------------------------
@@ -172,7 +172,39 @@ user's account::
Now test that ssh in both directions works. You may have to accept some new Now test that ssh in both directions works. You may have to accept some new
known hosts in the process. known hosts in the process.
CONFIGURATION FILE Primary server configuration
============================
PostgreSQL should have been previously built and installed on the system. Here
is a sample of changes to the ``postgresql.conf`` file::
listen_addresses='*'
wal_level = 'hot_standby'
archive_mode = on
archive_command = 'cd .' # we can also use exit 0, anything that
# just does nothing
max_wal_senders = 10
wal_keep_segments = 5000 # 80 GB required on pg_xlog
hot_standby = on
Also you need to add the machines that will participate in the cluster in
``pg_hba.conf`` file. One possibility is to trust all connections from the
replication users from all internal addresses, such as::
host all all 192.168.1.0/24 trust
host replication all 192.168.1.0/24 trust
A more secure setup adds a repmgr user and database, just giving
access to that user::
host repmgr repmgr 192.168.1.0/24 trust
host replication all 192.168.1.0/24 trust
If you give a password to the user, you need to create a ``.pgpass`` file for
them as well to allow automatic login. In this case you might use the
``md5`` authentication method instead of ``trust`` for the repmgr user.
Configuration File
================== ==================
``repmgr.conf`` is looked for in the directory repmgrd or repmgr exists. ``repmgr.conf`` is looked for in the directory repmgrd or repmgr exists.
@@ -186,11 +218,52 @@ It should have these three parameters:
3. conninfo: A string (single quoted) specifying how we can connect to this node's PostgreSQL service 3. conninfo: A string (single quoted) specifying how we can connect to this node's PostgreSQL service
Command line syntax
===================
The current supported syntax for the program can be seen using::
repmgr --help
The output from this program looks like this::
repmgr: Replicator manager
Usage:
repmgr [OPTIONS] master {register}
repmgr [OPTIONS] standby {register|clone|promote|follow}
General options:
--help show this help, then exit
--version output version information, then exit
--verbose output verbose activity information
Connection options:
-d, --dbname=DBNAME database to connect to
-h, --host=HOSTNAME database server host or socket directory
-p, --port=PORT database server port
-U, --username=USERNAME database user name to connect as
Configuration options:
-D, --data-dir=DIR local directory where the files will be copied to
-f, --config_file=PATH path to the configuration file
-R, --remote-user=USERNAME database server username for rsync
repmgr performs some tasks like clone a node, promote it or making follow another node and then exits.
COMMANDS:
master register - registers the master in a cluster
standby register - registers a standby in a cluster
standby clone [node] - allows creation of a new standby
standby promote - allows manual promotion of a specific standby into a new master in the event of a failover
standby follow - allows the standby to re-point itself to a new master
The ``--verbose`` option can be useful in troubleshooting issues with
the program.
Commands Commands
======== ========
None of this commands need the ``repmgr.conf`` file but they need to be able to Not all of these commands need the ``repmgr.conf`` file, but they need to be able to
connect to the remote and local database. connect to the remote and local databases.
You can teach it which is the remote database by using the -h parameter or You can teach it which is the remote database by using the -h parameter or
as a last parameter in standby clone and standby follow. If you need to specify as a last parameter in standby clone and standby follow. If you need to specify
@@ -212,7 +285,7 @@ its port if is different from the default one.
* Backup via rsync the data directory of the primary. And creates the recovery file * Backup via rsync the data directory of the primary. And creates the recovery file
we need to start a new hot standby server. we need to start a new hot standby server.
It doesn't need the repmgr.conf so it can be executed anywhere in the new node. It doesn't need the ``repmgr.conf`` so it can be executed anywhere in the new node.
So, you can step where you want your new data directory and execute:: So, you can step where you want your new data directory and execute::
./repmgr standby clone 10.68.1.161 ./repmgr standby clone 10.68.1.161
@@ -245,38 +318,6 @@ its port if is different from the default one.
./repmgr standby follow ./repmgr standby follow
Primary server configuration
============================
PostgreSQL should have been previously built and installed on the system. Here
is a sample of changes to the postgresql.conf file::
listen_addresses='*'
wal_level = 'hot_standby'
archive_mode = on
archive_command = 'cd .' # we can also use exit 0, anything that
# just does nothing
max_wal_senders = 10
wal_keep_segments = 5000 # 80 GB required on pg_xlog
hot_standby = on
Also you need to add the machines that will participate in the cluster in
``pg_hba.conf`` file. One possibility is to trust all connections from the
replication users from all internal addresses, such as::
host all all 192.168.1.0/24 trust
host replication all 192.168.1.0/24 trust
A more secure setup adds a repmgr user and database, just giving
access to that user::
host repmgr repmgr 192.168.1.0/24 trust
host replication all 192.168.1.0/24 trust
If you give a password to the user, you need to create a ``.pgpass`` file for
them as well to allow automatic login. In this case you might use the
``md5`` authentication method instead of ``trust`` for the repmgr user.
Examples Examples
======== ========
@@ -302,14 +343,38 @@ and run::
repmgr -D /var/lib/postgresql/9.0 standby clone node2 repmgr -D /var/lib/postgresql/9.0 standby clone node2
NOTE: you need to have PGDIR/bin in your path, if you don't want that as a NOTE: you need to have PGDIR/bin in your path. If you don't want that as a
permanent setting you can do it this way:: permanent setting, you can do it this way::
PATH=$PGDIR/bin:$PATH repmgr standby promote PATH=$PGDIR/bin:$PATH repmgr standby promote
repmgr Daemon repmgr Daemon
============= =============
Command line syntax
-------------------
The current supported syntax for the program can be seen using::
repmgrd --help
The output from this program looks like this::
repmgrd: Replicator manager daemon
Usage:
repmgrd [OPTIONS]
Options:
--help show this help, then exit
--version output version information, then exit
--verbose output verbose activity information
-f, --config_file=PATH database to connect to
repmgrd monitors a cluster of servers.
The ``--verbose`` option can be useful in troubleshooting issues with
the program.
Setup Setup
----- -----

View File

@@ -30,9 +30,11 @@
#define STANDBY_PROMOTE 4 #define STANDBY_PROMOTE 4
#define STANDBY_FOLLOW 5 #define STANDBY_FOLLOW 5
#define QUERY_STR_LEN 8192
static void help(const char *progname); static void help(const char *progname);
static bool create_recovery_file(const char *data_dir); static bool create_recovery_file(const char *data_dir);
static int copy_remote_files(char *host, char *remote_path, char *local_path, bool is_directory); static int copy_remote_files(char *host, char *remote_user, char *remote_path, char *local_path, bool is_directory);
static bool check_parameters_for_action(const int action); static bool check_parameters_for_action(const int action);
static void do_master_register(void); static void do_master_register(void);
@@ -51,6 +53,7 @@ char *host = NULL;
char *username = NULL; char *username = NULL;
char *dest_dir = NULL; char *dest_dir = NULL;
char *config_file = NULL; char *config_file = NULL;
char *remote_user = NULL;
bool verbose = false; bool verbose = false;
bool force = false; bool force = false;
@@ -71,6 +74,7 @@ main(int argc, char **argv)
{"username", required_argument, NULL, 'U'}, {"username", required_argument, NULL, 'U'},
{"dest-dir", required_argument, NULL, 'D'}, {"dest-dir", required_argument, NULL, 'D'},
{"config-file", required_argument, NULL, 'f'}, {"config-file", required_argument, NULL, 'f'},
{"remote-user", required_argument, NULL, 'R'},
{"force", no_argument, NULL, 'F'}, {"force", no_argument, NULL, 'F'},
{"verbose", no_argument, NULL, 'v'}, {"verbose", no_argument, NULL, 'v'},
{NULL, 0, NULL, 0} {NULL, 0, NULL, 0}
@@ -97,7 +101,7 @@ main(int argc, char **argv)
} }
while ((c = getopt_long(argc, argv, "d:h:p:U:D:f:F:v", long_options, &optindex)) != -1) while ((c = getopt_long(argc, argv, "d:h:p:U:D:f:R:F:v", long_options, &optindex)) != -1)
{ {
switch (c) switch (c)
{ {
@@ -119,6 +123,9 @@ main(int argc, char **argv)
case 'f': case 'f':
config_file = optarg; config_file = optarg;
break; break;
case 'R':
remote_user = optarg;
break;
case 'F': case 'F':
force = true; force = true;
break; break;
@@ -262,7 +269,7 @@ do_master_register(void)
{ {
PGconn *conn; PGconn *conn;
PGresult *res; PGresult *res;
char sqlquery[8192]; char sqlquery[QUERY_STR_LEN];
char myClusterName[MAXLEN]; char myClusterName[MAXLEN];
int myLocalId = -1; int myLocalId = -1;
@@ -440,7 +447,7 @@ do_standby_register(void)
int master_id; int master_id;
PGresult *res; PGresult *res;
char sqlquery[8192]; char sqlquery[QUERY_STR_LEN];
char myClusterName[MAXLEN]; char myClusterName[MAXLEN];
int myLocalId = -1; int myLocalId = -1;
@@ -566,7 +573,7 @@ do_standby_clone(void)
{ {
PGconn *conn; PGconn *conn;
PGresult *res; PGresult *res;
char sqlquery[8192]; char sqlquery[QUERY_STR_LEN];
int r = 0; int r = 0;
int i; int i;
@@ -842,11 +849,11 @@ do_standby_clone(void)
goto stop_backup; goto stop_backup;
} }
r = copy_remote_files(host, master_control_file, local_control_file, false); r = copy_remote_files(host, remote_user, master_control_file, local_control_file, false);
if (r != 0) if (r != 0)
goto stop_backup; goto stop_backup;
r = copy_remote_files(host, master_data_directory, dest_dir, true); r = copy_remote_files(host, remote_user, master_data_directory, dest_dir, true);
if (r != 0) if (r != 0)
goto stop_backup; goto stop_backup;
@@ -864,20 +871,20 @@ do_standby_clone(void)
} }
for (i = 0; i < PQntuples(res); i++) for (i = 0; i < PQntuples(res); i++)
{ {
r = copy_remote_files(host, PQgetvalue(res, i, 0), PQgetvalue(res, i, 0), true); r = copy_remote_files(host, remote_user, PQgetvalue(res, i, 0), PQgetvalue(res, i, 0), true);
if (r != 0) if (r != 0)
goto stop_backup; goto stop_backup;
} }
r = copy_remote_files(host, master_config_file, dest_dir, false); r = copy_remote_files(host, remote_user, master_config_file, dest_dir, false);
if (r != 0) if (r != 0)
goto stop_backup; goto stop_backup;
r = copy_remote_files(host, master_hba_file, dest_dir, false); r = copy_remote_files(host, remote_user, master_hba_file, dest_dir, false);
if (r != 0) if (r != 0)
goto stop_backup; goto stop_backup;
r = copy_remote_files(host, master_ident_file, dest_dir, false); r = copy_remote_files(host, remote_user, master_ident_file, dest_dir, false);
if (r != 0) if (r != 0)
goto stop_backup; goto stop_backup;
@@ -911,14 +918,14 @@ stop_backup:
return; return;
if (verbose) if (verbose)
printf(_("%s requires primary to keep WAL files %s until at least %s"), printf(_("%s requires primary to keep WAL files %s until at least %s\n"),
progname, first_wal_segment, last_wal_segment); progname, first_wal_segment, last_wal_segment);
/* we need to create the pg_xlog sub directory too, i'm reusing a variable here */ /* we need to create the pg_xlog sub directory too, i'm reusing a variable here */
sprintf(local_control_file, "%s/pg_xlog", dest_dir); sprintf(local_control_file, "%s/pg_xlog", dest_dir);
if (!create_directory(local_control_file)) if (!create_directory(local_control_file))
{ {
fprintf(stderr, _("%s: couldn't create directory %s, you will need to do it manually... "), fprintf(stderr, _("%s: couldn't create directory %s, you will need to do it manually...\n"),
progname, dest_dir); progname, dest_dir);
} }
@@ -935,8 +942,8 @@ do_standby_promote(void)
{ {
PGconn *conn; PGconn *conn;
PGresult *res; PGresult *res;
char sqlquery[8192]; char sqlquery[QUERY_STR_LEN];
char script[8192]; char script[QUERY_STR_LEN];
char myClusterName[MAXLEN]; char myClusterName[MAXLEN];
int myLocalId = -1; int myLocalId = -1;
@@ -1043,8 +1050,8 @@ do_standby_follow(void)
{ {
PGconn *conn; PGconn *conn;
PGresult *res; PGresult *res;
char sqlquery[8192]; char sqlquery[QUERY_STR_LEN];
char script[8192]; char script[QUERY_STR_LEN];
char myClusterName[MAXLEN]; char myClusterName[MAXLEN];
int myLocalId = -1; int myLocalId = -1;
@@ -1180,18 +1187,21 @@ help(const char *progname)
printf(_("Usage:\n")); printf(_("Usage:\n"));
printf(_(" %s [OPTIONS] master {register}\n"), progname); printf(_(" %s [OPTIONS] master {register}\n"), progname);
printf(_(" %s [OPTIONS] standby {register|clone|promote|follow}\n"), progname); printf(_(" %s [OPTIONS] standby {register|clone|promote|follow}\n"), progname);
printf(_("\nOptions:\n")); printf(_("\nGeneral options:\n"));
printf(_(" --help show this help, then exit\n")); printf(_(" --help show this help, then exit\n"));
printf(_(" --version output version information, then exit\n")); printf(_(" --version output version information, then exit\n"));
printf(_(" --verbose output verbose activity information\n")); printf(_(" --verbose output verbose activity information\n"));
printf(_("\nConnection options:\n")); printf(_("\nConnection options:\n"));
printf(_(" -d, --dbname=DBNAME database to connect to\n")); printf(_(" -d, --dbname=DBNAME database to connect to\n"));
printf(_(" -h, --host=HOSTNAME database server host or socket directory\n")); printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
printf(_(" -p, --port=PORT database server port\n")); printf(_(" -p, --port=PORT database server port\n"));
printf(_(" -U, --username=USERNAME user name to connect as\n")); printf(_(" -U, --username=USERNAME database user name to connect as\n"));
printf(_(" -D, --data-dir=DIR directory where the files will be copied to\n")); printf(_("\nConfiguration options:\n"));
printf(_(" -f, --config_file=PATH path to the configuration file\n")); printf(_(" -D, --data-dir=DIR local directory where the files will be copied to\n"));
printf(_("\n%s performs some tasks like clone a node, promote it "), progname); printf(_(" -f, --config_file=PATH path to the configuration file\n"));
printf(_(" -R, --remote-user=USERNAME database server username for rsync\n"));
printf(_("\n%s performs some tasks like clone a node, promote it "), progname);
printf(_("or making follow another node and then exits.\n")); printf(_("or making follow another node and then exits.\n"));
printf(_("COMMANDS:\n")); printf(_("COMMANDS:\n"));
printf(_(" master register - registers the master in a cluster\n")); printf(_(" master register - registers the master in a cluster\n"));
@@ -1243,33 +1253,46 @@ create_recovery_file(const char *data_dir)
static int static int
copy_remote_files(char *host, char *remote_path, char *local_path, bool is_directory) copy_remote_files(char *host, char *remote_user, char *remote_path, char *local_path, bool is_directory)
{ {
char script[8192]; char script[QUERY_STR_LEN];
char options[8192]; char options[QUERY_STR_LEN];
char host_string[QUERY_STR_LEN];
int r; int r;
sprintf(options, "--archive --checksum --compress --progress --rsh=ssh"); sprintf(options, "--archive --checksum --compress --progress --rsh=ssh");
if (force) if (force)
strcat(options, " --delete"); strcat(options, " --delete");
if (remote_user == NULL)
{
sprintf(host_string,"%s",host);
}
else
{
sprintf(host_string,"%s@%s",remote_user,host);
}
if (is_directory) if (is_directory)
{ {
strcat(options, " --exclude=pg_xlog* --exclude=pg_control --exclude=*.pid"); strcat(options, " --exclude=pg_xlog* --exclude=pg_control --exclude=*.pid");
sprintf(script, "rsync %s %s:%s/* %s", sprintf(script, "rsync %s %s:%s/* %s",
options, host, remote_path, local_path); options, host_string, remote_path, local_path);
} }
else else
{ {
sprintf(script, "rsync %s %s:%s %s/.", sprintf(script, "rsync %s %s:%s %s/.",
options, host, remote_path, local_path); options, host_string, remote_path, local_path);
} }
if (verbose)
printf("rsync command line: '%s'\n",script);
r = system(script); r = system(script);
if (r != 0) if (r != 0)
fprintf(stderr, _("Can't rsync from remote file or directory (%s:%s)\n"), fprintf(stderr, _("Can't rsync from remote file or directory (%s:%s)\n"),
host, remote_path); host_string, remote_path);
return r; return r;
} }