mirror of
https://github.com/EnterpriseDB/repmgr.git
synced 2026-03-25 16:16:29 +00:00
Initial code for standby clone
This commit is contained in:
@@ -26,7 +26,7 @@ include Makefile.global
|
|||||||
|
|
||||||
$(info Building against PostgreSQL $(MAJORVERSION))
|
$(info Building against PostgreSQL $(MAJORVERSION))
|
||||||
|
|
||||||
REPMGR_CLIENT_OBJS = repmgr-client.o repmgr-action-master.o repmgr-action-cluster.o \
|
REPMGR_CLIENT_OBJS = repmgr-client.o repmgr-action-master.o repmgr-action-standby.o repmgr-action-cluster.o \
|
||||||
config.o log.o strutil.o dbutils.o
|
config.o log.o strutil.o dbutils.o
|
||||||
REPMGRD_OBJS = repmgrd.o
|
REPMGRD_OBJS = repmgrd.o
|
||||||
|
|
||||||
|
|||||||
75
repmgr-action-standby.c
Normal file
75
repmgr-action-standby.c
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* repmgr-action-standby.c
|
||||||
|
*
|
||||||
|
* Implements standby actions for the repmgr command line utility
|
||||||
|
*
|
||||||
|
* Copyright (c) 2ndQuadrant, 2010-2017
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "repmgr.h"
|
||||||
|
|
||||||
|
#include "repmgr-client-global.h"
|
||||||
|
#include "repmgr-action-standby.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
do_standby_clone(void)
|
||||||
|
{
|
||||||
|
PGconn *primary_conn = NULL;
|
||||||
|
PGconn *source_conn = NULL;
|
||||||
|
PGresult *res;
|
||||||
|
|
||||||
|
int server_version_num = -1;
|
||||||
|
char cluster_size[MAXLEN];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* conninfo params for the actual upstream node (which might be different
|
||||||
|
* to the node we're cloning from) to write to recovery.conf
|
||||||
|
*/
|
||||||
|
t_conninfo_param_list recovery_conninfo;
|
||||||
|
char recovery_conninfo_str[MAXLEN];
|
||||||
|
bool upstream_record_found = false;
|
||||||
|
int upstream_node_id = UNKNOWN_NODE_ID;
|
||||||
|
|
||||||
|
|
||||||
|
enum {
|
||||||
|
barman,
|
||||||
|
rsync,
|
||||||
|
pg_basebackup
|
||||||
|
} mode;
|
||||||
|
|
||||||
|
/* used by barman mode */
|
||||||
|
char datadir_list_filename[MAXLEN];
|
||||||
|
char local_repmgr_tmp_directory[MAXPGPATH];
|
||||||
|
|
||||||
|
puts("standby clone");
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* detecting the cloning mode
|
||||||
|
*/
|
||||||
|
if (runtime_options.rsync_only)
|
||||||
|
mode = rsync;
|
||||||
|
else if (strcmp(config_file_options.barman_server, "") != 0 && ! runtime_options.without_barman)
|
||||||
|
mode = barman;
|
||||||
|
else
|
||||||
|
mode = pg_basebackup;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In rsync mode, we need to check the SSH connection early
|
||||||
|
*/
|
||||||
|
if (mode == rsync)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = test_ssh_connection(runtime_options.host, runtime_options.remote_user);
|
||||||
|
if (r != 0)
|
||||||
|
{
|
||||||
|
log_error(_("remote host %s is not reachable via SSH"),
|
||||||
|
runtime_options.host);
|
||||||
|
exit(ERR_BAD_SSH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
12
repmgr-action-standby.h
Normal file
12
repmgr-action-standby.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
* repmgr-action-standby.h
|
||||||
|
* Copyright (c) 2ndQuadrant, 2010-2017
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _REPMGR_ACTION_STANDBY_H_
|
||||||
|
#define _REPMGR_ACTION_STANDBY_H_
|
||||||
|
|
||||||
|
extern void do_standby_clone(void);
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -28,6 +28,8 @@ typedef struct
|
|||||||
bool verbose;
|
bool verbose;
|
||||||
|
|
||||||
/* connection options */
|
/* connection options */
|
||||||
|
char host[MAXLEN];
|
||||||
|
char remote_user[MAXLEN];
|
||||||
char superuser[MAXLEN];
|
char superuser[MAXLEN];
|
||||||
|
|
||||||
/* node options */
|
/* node options */
|
||||||
@@ -35,6 +37,10 @@ typedef struct
|
|||||||
char node_name[MAXLEN];
|
char node_name[MAXLEN];
|
||||||
char data_dir[MAXPGPATH];
|
char data_dir[MAXPGPATH];
|
||||||
|
|
||||||
|
/* standby clone options */
|
||||||
|
bool rsync_only;
|
||||||
|
bool without_barman;
|
||||||
|
|
||||||
/* event options */
|
/* event options */
|
||||||
char event[MAXLEN];
|
char event[MAXLEN];
|
||||||
int limit;
|
int limit;
|
||||||
@@ -42,12 +48,32 @@ typedef struct
|
|||||||
|
|
||||||
} t_runtime_options;
|
} t_runtime_options;
|
||||||
|
|
||||||
|
#define T_RUNTIME_OPTIONS_INITIALIZER { \
|
||||||
|
/* configuration metadata */ \
|
||||||
|
false, false, false, false, \
|
||||||
|
/* general configuration options */ \
|
||||||
|
"", false, "", \
|
||||||
|
/* logging options */ \
|
||||||
|
"", false, false, false, \
|
||||||
|
/* connection options */ \
|
||||||
|
"", "", "", \
|
||||||
|
/* node options */ \
|
||||||
|
UNKNOWN_NODE_ID, "", "", \
|
||||||
|
/* standby clone options */ \
|
||||||
|
false, false, \
|
||||||
|
/* event options */ \
|
||||||
|
"", 20, false}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* global configuration structures */
|
/* global configuration structures */
|
||||||
extern t_runtime_options runtime_options;
|
extern t_runtime_options runtime_options;
|
||||||
extern t_configuration_options config_file_options;
|
extern t_configuration_options config_file_options;
|
||||||
|
|
||||||
|
t_conninfo_param_list source_conninfo;
|
||||||
|
|
||||||
extern bool config_file_required;
|
|
||||||
|
extern bool config_file_required;
|
||||||
extern char pg_bindir[MAXLEN];
|
extern char pg_bindir[MAXLEN];
|
||||||
|
|
||||||
extern char repmgr_slot_name[MAXLEN];
|
extern char repmgr_slot_name[MAXLEN];
|
||||||
@@ -58,5 +84,7 @@ extern t_node_info target_node_info;
|
|||||||
|
|
||||||
extern int check_server_version(PGconn *conn, char *server_type, bool exit_on_error, char *server_version_string);
|
extern int check_server_version(PGconn *conn, char *server_type, bool exit_on_error, char *server_version_string);
|
||||||
extern bool create_repmgr_extension(PGconn *conn);
|
extern bool create_repmgr_extension(PGconn *conn);
|
||||||
|
extern int test_ssh_connection(char *host, char *remote_user);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -20,20 +20,30 @@
|
|||||||
#include "repmgr.h"
|
#include "repmgr.h"
|
||||||
#include "repmgr-client.h"
|
#include "repmgr-client.h"
|
||||||
#include "repmgr-client-global.h"
|
#include "repmgr-client-global.h"
|
||||||
#include "repmgr-action-cluster.h"
|
|
||||||
#include "repmgr-action-master.h"
|
#include "repmgr-action-master.h"
|
||||||
|
#include "repmgr-action-standby.h"
|
||||||
|
#include "repmgr-action-cluster.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* globally available variables *
|
||||||
|
* ============================ */
|
||||||
|
|
||||||
t_runtime_options runtime_options = T_RUNTIME_OPTIONS_INITIALIZER;
|
t_runtime_options runtime_options = T_RUNTIME_OPTIONS_INITIALIZER;
|
||||||
t_configuration_options config_file_options = T_CONFIGURATION_OPTIONS_INITIALIZER;
|
t_configuration_options config_file_options = T_CONFIGURATION_OPTIONS_INITIALIZER;
|
||||||
|
|
||||||
|
/* conninfo params for the node we're cloning from */
|
||||||
|
t_conninfo_param_list source_conninfo;
|
||||||
|
|
||||||
|
bool config_file_required = true;
|
||||||
bool config_file_required = true;
|
|
||||||
char pg_bindir[MAXLEN] = "";
|
char pg_bindir[MAXLEN] = "";
|
||||||
|
|
||||||
char repmgr_slot_name[MAXLEN] = "";
|
char repmgr_slot_name[MAXLEN] = "";
|
||||||
char *repmgr_slot_name_ptr = NULL;
|
char *repmgr_slot_name_ptr = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if --node-id/--node-name provided, place that node's record here
|
||||||
|
* for later use
|
||||||
|
*/
|
||||||
t_node_info target_node_info = T_NODE_INFO_INITIALIZER;
|
t_node_info target_node_info = T_NODE_INFO_INITIALIZER;
|
||||||
|
|
||||||
|
|
||||||
@@ -115,6 +125,19 @@ main(int argc, char **argv)
|
|||||||
/* connection options */
|
/* connection options */
|
||||||
/* ------------------ */
|
/* ------------------ */
|
||||||
|
|
||||||
|
/* -h/--host */
|
||||||
|
case 'h':
|
||||||
|
strncpy(runtime_options.host, optarg, MAXLEN);
|
||||||
|
param_set(&source_conninfo, "host", optarg);
|
||||||
|
runtime_options.connection_param_provided = true;
|
||||||
|
runtime_options.host_param_provided = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* -R/--remote_user */
|
||||||
|
case 'R':
|
||||||
|
strncpy(runtime_options.remote_user, optarg, MAXLEN);
|
||||||
|
break;
|
||||||
|
|
||||||
/* -S/--superuser */
|
/* -S/--superuser */
|
||||||
case 'S':
|
case 'S':
|
||||||
strncpy(runtime_options.superuser, optarg, MAXLEN);
|
strncpy(runtime_options.superuser, optarg, MAXLEN);
|
||||||
@@ -748,12 +771,6 @@ do_help(void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
do_standby_clone(void)
|
|
||||||
{
|
|
||||||
puts("standby clone");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -992,3 +1009,41 @@ check_server_version(PGconn *conn, char *server_type, bool exit_on_error, char *
|
|||||||
|
|
||||||
return server_version_num;
|
return server_version_num;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
test_ssh_connection(char *host, char *remote_user)
|
||||||
|
{
|
||||||
|
char script[MAXLEN];
|
||||||
|
int r = 1, i;
|
||||||
|
|
||||||
|
/* 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 *bin_true_paths[] = {
|
||||||
|
"/bin/true",
|
||||||
|
"/usr/bin/true",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
for (i = 0; bin_true_paths[i] && r != 0; ++i)
|
||||||
|
{
|
||||||
|
if (!remote_user[0])
|
||||||
|
maxlen_snprintf(script, "ssh -o Batchmode=yes %s %s %s 2>/dev/null",
|
||||||
|
config_file_options.ssh_options, host, bin_true_paths[i]);
|
||||||
|
else
|
||||||
|
maxlen_snprintf(script, "ssh -o Batchmode=yes %s %s -l %s %s 2>/dev/null",
|
||||||
|
config_file_options.ssh_options, host, remote_user,
|
||||||
|
bin_true_paths[i]);
|
||||||
|
|
||||||
|
log_verbose(LOG_DEBUG, _("test_ssh_connection(): executing %s"), script);
|
||||||
|
r = system(script);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r != 0)
|
||||||
|
log_warning(_("unable to connect to remote host '%s' via SSH"), host);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|||||||
@@ -70,9 +70,10 @@ static struct option long_options[] =
|
|||||||
{"pg_bindir", required_argument, NULL, 'b'},
|
{"pg_bindir", required_argument, NULL, 'b'},
|
||||||
|
|
||||||
/* connection options */
|
/* connection options */
|
||||||
|
{"host", required_argument, NULL, 'h'},
|
||||||
|
{"remote-user", required_argument, NULL, 'R'},
|
||||||
{"superuser", required_argument, NULL, 'S'},
|
{"superuser", required_argument, NULL, 'S'},
|
||||||
|
|
||||||
|
|
||||||
/* node options */
|
/* node options */
|
||||||
{"pgdata", required_argument, NULL, 'D'},
|
{"pgdata", required_argument, NULL, 'D'},
|
||||||
/* legacy alias for -D/--pgdata*/
|
/* legacy alias for -D/--pgdata*/
|
||||||
@@ -86,6 +87,10 @@ static struct option long_options[] =
|
|||||||
{"terse", required_argument, NULL, 't'},
|
{"terse", required_argument, NULL, 't'},
|
||||||
{"verbose", no_argument, NULL, 'v'},
|
{"verbose", no_argument, NULL, 'v'},
|
||||||
|
|
||||||
|
/* standby clone options */
|
||||||
|
{"rsync-only", no_argument, NULL, 'r'},
|
||||||
|
{"without-barman", no_argument, NULL, OPT_WITHOUT_BARMAN},
|
||||||
|
|
||||||
/* event options */
|
/* event options */
|
||||||
{"event", required_argument, NULL, OPT_EVENT },
|
{"event", required_argument, NULL, OPT_EVENT },
|
||||||
{"limit", required_argument, NULL, OPT_LIMIT },
|
{"limit", required_argument, NULL, OPT_LIMIT },
|
||||||
@@ -93,10 +98,8 @@ static struct option long_options[] =
|
|||||||
|
|
||||||
/* not yet handled */
|
/* not yet handled */
|
||||||
{"dbname", required_argument, NULL, 'd'},
|
{"dbname", required_argument, NULL, 'd'},
|
||||||
{"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'},
|
||||||
{"remote-user", required_argument, NULL, 'R'},
|
|
||||||
{"wal-keep-segments", required_argument, NULL, 'w'},
|
{"wal-keep-segments", required_argument, NULL, 'w'},
|
||||||
{"keep-history", required_argument, NULL, 'k'},
|
{"keep-history", required_argument, NULL, 'k'},
|
||||||
{"wait", no_argument, NULL, 'W'},
|
{"wait", no_argument, NULL, 'W'},
|
||||||
@@ -125,21 +128,6 @@ static struct option long_options[] =
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define T_RUNTIME_OPTIONS_INITIALIZER { \
|
|
||||||
/* configuration metadata */ \
|
|
||||||
false, false, false, false, \
|
|
||||||
/* general configuration options */ \
|
|
||||||
"", false, "", \
|
|
||||||
/* logging options */ \
|
|
||||||
"", false, false, false, \
|
|
||||||
/* connection options */ \
|
|
||||||
"", \
|
|
||||||
/* node options */ \
|
|
||||||
UNKNOWN_NODE_ID, "", "", \
|
|
||||||
/* event options */ \
|
|
||||||
"", 20, false}
|
|
||||||
|
|
||||||
|
|
||||||
static void do_help(void);
|
static void do_help(void);
|
||||||
|
|
||||||
static void do_standby_clone(void);
|
static void do_standby_clone(void);
|
||||||
|
|||||||
Reference in New Issue
Block a user