mirror of
https://github.com/EnterpriseDB/repmgr.git
synced 2026-03-26 08:36:30 +00:00
Barman support, draft #1
TODO: we need to check what happens with configuration files placed in non-standard locations.
This commit is contained in:
70
README.md
70
README.md
@@ -504,6 +504,76 @@ standby's upstream server is the replication cluster master. While of limited
|
|||||||
use in a simple master/standby replication cluster, this information is required
|
use in a simple master/standby replication cluster, this information is required
|
||||||
to effectively manage cascading replication (see below).
|
to effectively manage cascading replication (see below).
|
||||||
|
|
||||||
|
### Using Barman to clone a standby
|
||||||
|
|
||||||
|
`repmgr standby clone` also supports Barman, the Backup and
|
||||||
|
Replication manager (http://www.pgbarman.org/), as a provider of both
|
||||||
|
base backups and WAL files.
|
||||||
|
|
||||||
|
Barman support provides the following advantages:
|
||||||
|
|
||||||
|
- the primary node does not need to perform a new backup every time a
|
||||||
|
new standby is cloned;
|
||||||
|
- a standby node can be disconnected for longer periods without losing
|
||||||
|
the ability to catch up, and without causing accumulation of WAL
|
||||||
|
files on the primary node;
|
||||||
|
- therefore, `repmgr` does not need to use replication slots, and the
|
||||||
|
primary node does not need to set `wal_keep_segments`.
|
||||||
|
|
||||||
|
> *NOTE*: In view of the above, Barman support is incompatible with
|
||||||
|
> the `use_replication_slots` setting in `repmgr.conf`.
|
||||||
|
|
||||||
|
In order to enable Barman support for `repmgr standby clone`, you must
|
||||||
|
ensure that:
|
||||||
|
|
||||||
|
- the name of the server configured in Barman is equal to the
|
||||||
|
`cluster_name` setting in `repmgr.conf`;
|
||||||
|
- the `barman_server` setting in `repmgr.conf` is set to the SSH
|
||||||
|
hostname of the Barman server;
|
||||||
|
- the `pg_restore_command` setting in `repmgr.conf` is configured to
|
||||||
|
use a copy of the `barman-wal-restore` script shipped with Barman
|
||||||
|
(see below);
|
||||||
|
- the Barman catalogue includes at least one valid backup for this
|
||||||
|
server.
|
||||||
|
|
||||||
|
> *NOTE*: Barman support is automatically enabled if `barman_server`
|
||||||
|
> is set. Normally this is a good practice; however, the command line
|
||||||
|
> option `--without-barman` can be used to disable it.
|
||||||
|
|
||||||
|
> *NOTE*: if you have a non-default SSH configuration on the Barman
|
||||||
|
> server, e.g. using a port other than 22, then you can set those
|
||||||
|
> parameters in a dedicated Host section in `~/.ssh/config`
|
||||||
|
> corresponding to the value of `barman_server` in `repmgr.conf`. See
|
||||||
|
> the "Host" section in `man 5 ssh_config` for more details.
|
||||||
|
|
||||||
|
`barman-wal-restore` is a short shell script provided by the Barman
|
||||||
|
development team, which must be copied in a location accessible to
|
||||||
|
`repmgr`, and marked as executable; `pg_restore_command` must then be
|
||||||
|
set as follows:
|
||||||
|
|
||||||
|
<script> <Barman hostname> <cluster_name> %f %p
|
||||||
|
|
||||||
|
For instance, suppose that we have installed Barman on the `barmansrv`
|
||||||
|
host, and that we have placed a copy of `barman-wal-restore` into the
|
||||||
|
`/usr/local/bin` directory. First, we ensure that the script is
|
||||||
|
executable:
|
||||||
|
|
||||||
|
sudo chmod +x /usr/local/bin/barman-wal-restore
|
||||||
|
|
||||||
|
Then we check that `repmgr.conf` includes the following lines:
|
||||||
|
|
||||||
|
barman_server=barmansrv
|
||||||
|
pg_restore_command=/usr/local/bin/barman-wal-restore barmansrv test %f %p
|
||||||
|
|
||||||
|
Now we can clone a standby using the Barman server:
|
||||||
|
|
||||||
|
$ repmgr -h node1 -D 9.5/main -f /etc/repmgr.conf standby clone
|
||||||
|
[2016-06-12 20:08:35] [NOTICE] destination directory '9.5/main' provided
|
||||||
|
[2016-06-12 20:08:35] [NOTICE] getting backup from Barman...
|
||||||
|
[2016-06-12 20:08:36] [NOTICE] standby clone (from Barman) complete
|
||||||
|
[2016-06-12 20:08:36] [NOTICE] you can now start your PostgreSQL server
|
||||||
|
[2016-06-12 20:08:36] [HINT] for example : pg_ctl -D 9.5/data start
|
||||||
|
[2016-06-12 20:08:36] [HINT] After starting the server, you need to register this standby with "repmgr standby register"
|
||||||
|
|
||||||
Advanced options for cloning a standby
|
Advanced options for cloning a standby
|
||||||
--------------------------------------
|
--------------------------------------
|
||||||
|
|||||||
10
config.c
10
config.c
@@ -215,6 +215,7 @@ parse_config(t_configuration_options *options)
|
|||||||
options->upstream_node = NO_UPSTREAM_NODE;
|
options->upstream_node = NO_UPSTREAM_NODE;
|
||||||
options->use_replication_slots = 0;
|
options->use_replication_slots = 0;
|
||||||
memset(options->conninfo, 0, sizeof(options->conninfo));
|
memset(options->conninfo, 0, sizeof(options->conninfo));
|
||||||
|
memset(options->barman_server, 0, sizeof(options->barman_server));
|
||||||
options->failover = MANUAL_FAILOVER;
|
options->failover = MANUAL_FAILOVER;
|
||||||
options->priority = DEFAULT_PRIORITY;
|
options->priority = DEFAULT_PRIORITY;
|
||||||
memset(options->node_name, 0, sizeof(options->node_name));
|
memset(options->node_name, 0, sizeof(options->node_name));
|
||||||
@@ -310,6 +311,8 @@ parse_config(t_configuration_options *options)
|
|||||||
options->upstream_node = repmgr_atoi(value, "upstream_node", &config_errors, false);
|
options->upstream_node = repmgr_atoi(value, "upstream_node", &config_errors, false);
|
||||||
else if (strcmp(name, "conninfo") == 0)
|
else if (strcmp(name, "conninfo") == 0)
|
||||||
strncpy(options->conninfo, value, MAXLEN);
|
strncpy(options->conninfo, value, MAXLEN);
|
||||||
|
else if (strcmp(name, "barman_server") == 0)
|
||||||
|
strncpy(options->barman_server, value, MAXLEN);
|
||||||
else if (strcmp(name, "rsync_options") == 0)
|
else if (strcmp(name, "rsync_options") == 0)
|
||||||
strncpy(options->rsync_options, value, QUERY_STR_LEN);
|
strncpy(options->rsync_options, value, QUERY_STR_LEN);
|
||||||
else if (strcmp(name, "ssh_options") == 0)
|
else if (strcmp(name, "ssh_options") == 0)
|
||||||
@@ -635,6 +638,13 @@ reload_config(t_configuration_options *orig_options)
|
|||||||
config_changed = true;
|
config_changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* barman_server */
|
||||||
|
if (strcmp(orig_options->barman_server, new_options.barman_server) != 0)
|
||||||
|
{
|
||||||
|
strcpy(orig_options->barman_server, new_options.barman_server);
|
||||||
|
config_changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
/* node */
|
/* node */
|
||||||
if (orig_options->node != new_options.node)
|
if (orig_options->node != new_options.node)
|
||||||
{
|
{
|
||||||
|
|||||||
3
config.h
3
config.h
@@ -58,6 +58,7 @@ typedef struct
|
|||||||
int node;
|
int node;
|
||||||
int upstream_node;
|
int upstream_node;
|
||||||
char conninfo[MAXLEN];
|
char conninfo[MAXLEN];
|
||||||
|
char barman_server[MAXLEN];
|
||||||
int failover;
|
int failover;
|
||||||
int priority;
|
int priority;
|
||||||
char node_name[MAXLEN];
|
char node_name[MAXLEN];
|
||||||
@@ -91,7 +92,7 @@ typedef struct
|
|||||||
* The following will initialize the structure with a minimal set of options;
|
* The following will initialize the structure with a minimal set of options;
|
||||||
* actual defaults are set in parse_config() before parsing the configuration file
|
* actual defaults are set in parse_config() before parsing the configuration file
|
||||||
*/
|
*/
|
||||||
#define T_CONFIGURATION_OPTIONS_INITIALIZER { "", -1, NO_UPSTREAM_NODE, "", MANUAL_FAILOVER, -1, "", "", "", "", "", "", "", "", "", "", -1, -1, -1, "", "", "", "", "", 0, 0, 0, 0, "", { NULL, NULL }, {NULL, NULL} }
|
#define T_CONFIGURATION_OPTIONS_INITIALIZER { "", -1, NO_UPSTREAM_NODE, "", "", MANUAL_FAILOVER, -1, "", "", "", "", "", "", "", "", "", "", -1, -1, -1, "", "", "", "", "", 0, 0, 0, 0, "", { NULL, NULL }, {NULL, NULL} }
|
||||||
|
|
||||||
typedef struct ItemListCell
|
typedef struct ItemListCell
|
||||||
{
|
{
|
||||||
|
|||||||
561
repmgr.c
561
repmgr.c
@@ -105,6 +105,10 @@ static bool check_upstream_config(PGconn *conn, int server_version_num, bool exi
|
|||||||
static bool update_node_record_set_master(PGconn *conn, int this_node_id);
|
static bool update_node_record_set_master(PGconn *conn, int this_node_id);
|
||||||
static void tablespace_data_append(TablespaceDataList *list, const char *name, const char *oid, const char *location);
|
static void tablespace_data_append(TablespaceDataList *list, const char *name, const char *oid, const char *location);
|
||||||
static int get_tablespace_data(PGconn *upstream_conn, TablespaceDataList *list);
|
static int get_tablespace_data(PGconn *upstream_conn, TablespaceDataList *list);
|
||||||
|
static int get_tablespace_data_barman(char *, TablespaceDataList *);
|
||||||
|
|
||||||
|
static char *string_skip_prefix(const char *prefix, char *string);
|
||||||
|
static char *string_remove_trailing_newlines(char *string);
|
||||||
|
|
||||||
static char *make_pg_path(char *file);
|
static char *make_pg_path(char *file);
|
||||||
|
|
||||||
@@ -211,6 +215,7 @@ main(int argc, char **argv)
|
|||||||
{"pwprompt", optional_argument, NULL, OPT_PWPROMPT},
|
{"pwprompt", optional_argument, NULL, OPT_PWPROMPT},
|
||||||
{"csv", no_argument, NULL, OPT_CSV},
|
{"csv", no_argument, NULL, OPT_CSV},
|
||||||
{"node", required_argument, NULL, OPT_NODE},
|
{"node", required_argument, NULL, OPT_NODE},
|
||||||
|
{"without-barman", no_argument, NULL, OPT_WITHOUT_BARMAN},
|
||||||
{"version", no_argument, NULL, 'V'},
|
{"version", no_argument, NULL, 'V'},
|
||||||
{NULL, 0, NULL, 0}
|
{NULL, 0, NULL, 0}
|
||||||
};
|
};
|
||||||
@@ -508,6 +513,9 @@ main(int argc, char **argv)
|
|||||||
case OPT_NODE:
|
case OPT_NODE:
|
||||||
runtime_options.node = repmgr_atoi(optarg, "--node", &cli_errors, false);
|
runtime_options.node = repmgr_atoi(optarg, "--node", &cli_errors, false);
|
||||||
break;
|
break;
|
||||||
|
case OPT_WITHOUT_BARMAN:
|
||||||
|
runtime_options.without_barman = true;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
unknown_option:
|
unknown_option:
|
||||||
@@ -832,6 +840,18 @@ main(int argc, char **argv)
|
|||||||
log_warning(_("-w/--wal-keep-segments has no effect when replication slots in use\n"));
|
log_warning(_("-w/--wal-keep-segments has no effect when replication slots in use\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* STANDBY CLONE in Barman mode is incompatible with
|
||||||
|
* `use_replication_slots`.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (action == STANDBY_CLONE &&
|
||||||
|
! runtime_options.without_barman
|
||||||
|
&& strcmp(options.barman_server, "") == 0)
|
||||||
|
{
|
||||||
|
log_err(_("STANDBY CLONE in Barman mode is incompatible with configuration option \"use_replication_slots\""));
|
||||||
|
}
|
||||||
|
|
||||||
/* Initialise the repmgr schema name */
|
/* Initialise the repmgr schema name */
|
||||||
maxlen_snprintf(repmgr_schema, "%s%s", DEFAULT_REPMGR_SCHEMA_PREFIX,
|
maxlen_snprintf(repmgr_schema, "%s%s", DEFAULT_REPMGR_SCHEMA_PREFIX,
|
||||||
options.cluster_name);
|
options.cluster_name);
|
||||||
@@ -1562,16 +1582,107 @@ get_tablespace_data(PGconn *upstream_conn, TablespaceDataList *list)
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
string_skip_prefix(const char *prefix, char *string)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
n = strlen(prefix);
|
||||||
|
|
||||||
|
if (strncmp(prefix, string, n))
|
||||||
|
return NULL;
|
||||||
|
else
|
||||||
|
return string + n;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
string_remove_trailing_newlines(char *string)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
n = strlen(string) - 1;
|
||||||
|
|
||||||
|
while (n >= 0 && string[n] == '\n')
|
||||||
|
string[n] = 0;
|
||||||
|
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
get_tablespace_data_barman
|
||||||
|
( char *tablespace_data_barman,
|
||||||
|
TablespaceDataList *tablespace_list)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Example:
|
||||||
|
* [('main', 24674, '/var/lib/postgresql/tablespaces/9.5/main'), ('alt', 24678, '/var/lib/postgresql/tablespaces/9.5/alt')]
|
||||||
|
*/
|
||||||
|
|
||||||
|
char name[MAXLEN];
|
||||||
|
char oid[MAXLEN];
|
||||||
|
char location[MAXPGPATH];
|
||||||
|
char *p = tablespace_data_barman;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
tablespace_list->head = NULL;
|
||||||
|
tablespace_list->tail = NULL;
|
||||||
|
|
||||||
|
p = string_skip_prefix("[", p);
|
||||||
|
|
||||||
|
while (*p == '(')
|
||||||
|
{
|
||||||
|
p = string_skip_prefix("('", p);
|
||||||
|
if (p == NULL) return -1;
|
||||||
|
|
||||||
|
i = strcspn(p, "'");
|
||||||
|
strncpy(name, p, i);
|
||||||
|
name[i] = 0;
|
||||||
|
|
||||||
|
p = string_skip_prefix("', ", p + i);
|
||||||
|
if (p == NULL) return -1;
|
||||||
|
|
||||||
|
i = strcspn(p, ",");
|
||||||
|
strncpy(oid, p, i);
|
||||||
|
oid[i] = 0;
|
||||||
|
|
||||||
|
p = string_skip_prefix(", '", p + i);
|
||||||
|
if (p == NULL) return -1;
|
||||||
|
|
||||||
|
i = strcspn(p, "'");
|
||||||
|
strncpy(location, p, i);
|
||||||
|
location[i] = 0;
|
||||||
|
|
||||||
|
p = string_skip_prefix("')", p + i);
|
||||||
|
if (p == NULL) return -1;
|
||||||
|
|
||||||
|
tablespace_data_append (tablespace_list, name, oid, location);
|
||||||
|
|
||||||
|
if (*p == ']')
|
||||||
|
break;
|
||||||
|
|
||||||
|
p = string_skip_prefix(", ", p);
|
||||||
|
if (p == NULL) return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
do_standby_clone(void)
|
do_standby_clone(void)
|
||||||
{
|
{
|
||||||
PGconn *primary_conn = NULL;
|
PGconn *primary_conn = NULL;
|
||||||
PGconn *upstream_conn;
|
PGconn *upstream_conn = NULL;
|
||||||
PGresult *res;
|
PGresult *res;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
barman,
|
||||||
|
rsync,
|
||||||
|
pg_basebackup
|
||||||
|
} mode;
|
||||||
|
|
||||||
char sqlquery[QUERY_STR_LEN];
|
char sqlquery[QUERY_STR_LEN];
|
||||||
|
|
||||||
int server_version_num;
|
int server_version_num = -1;
|
||||||
|
|
||||||
char cluster_size[MAXLEN];
|
char cluster_size[MAXLEN];
|
||||||
|
|
||||||
@@ -1586,6 +1697,8 @@ do_standby_clone(void)
|
|||||||
char master_data_directory[MAXPGPATH];
|
char master_data_directory[MAXPGPATH];
|
||||||
char local_data_directory[MAXPGPATH];
|
char local_data_directory[MAXPGPATH];
|
||||||
|
|
||||||
|
char local_repmgr_directory[MAXPGPATH];
|
||||||
|
|
||||||
char master_config_file[MAXPGPATH] = "";
|
char master_config_file[MAXPGPATH] = "";
|
||||||
char local_config_file[MAXPGPATH] = "";
|
char local_config_file[MAXPGPATH] = "";
|
||||||
bool config_file_outside_pgdata = false;
|
bool config_file_outside_pgdata = false;
|
||||||
@@ -1606,6 +1719,15 @@ do_standby_clone(void)
|
|||||||
|
|
||||||
PQExpBufferData event_details;
|
PQExpBufferData event_details;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Detecting the appropriate mode
|
||||||
|
*/
|
||||||
|
if (runtime_options.rsync_only)
|
||||||
|
mode = rsync;
|
||||||
|
else if (strcmp(options.barman_server, "") != 0 && ! runtime_options.without_barman)
|
||||||
|
mode = barman;
|
||||||
|
else
|
||||||
|
mode = pg_basebackup;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If dest_dir (-D/--pgdata) was provided, this will become the new data
|
* If dest_dir (-D/--pgdata) was provided, this will become the new data
|
||||||
@@ -1619,6 +1741,9 @@ do_standby_clone(void)
|
|||||||
runtime_options.dest_dir);
|
runtime_options.dest_dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mode != barman)
|
||||||
|
{
|
||||||
|
|
||||||
param_set("application_name", options.node_name);
|
param_set("application_name", options.node_name);
|
||||||
|
|
||||||
/* Connect to check configuration */
|
/* Connect to check configuration */
|
||||||
@@ -1799,6 +1924,8 @@ do_standby_clone(void)
|
|||||||
|
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* target directory (-D/--pgdata) provided - use that as new data directory
|
* target directory (-D/--pgdata) provided - use that as new data directory
|
||||||
* (useful when executing backup on local machine only or creating the backup
|
* (useful when executing backup on local machine only or creating the backup
|
||||||
@@ -1811,6 +1938,12 @@ do_standby_clone(void)
|
|||||||
strncpy(local_hba_file, runtime_options.dest_dir, MAXPGPATH);
|
strncpy(local_hba_file, runtime_options.dest_dir, MAXPGPATH);
|
||||||
strncpy(local_ident_file, runtime_options.dest_dir, MAXPGPATH);
|
strncpy(local_ident_file, runtime_options.dest_dir, MAXPGPATH);
|
||||||
}
|
}
|
||||||
|
else if (mode == barman)
|
||||||
|
{
|
||||||
|
log_err(_("Barman mode requires a destination directory\n"));
|
||||||
|
log_hint(_("use -D/--data-dir to explicitly specify a data directory\n"));
|
||||||
|
exit(ERR_BAD_CONFIG);
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* Otherwise use the same data directory as on the remote host
|
* Otherwise use the same data directory as on the remote host
|
||||||
*/
|
*/
|
||||||
@@ -1826,9 +1959,9 @@ do_standby_clone(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When using rsync only, we need to check the SSH connection early
|
* In rsync mode, we need to check the SSH connection early
|
||||||
*/
|
*/
|
||||||
if (runtime_options.rsync_only)
|
if (mode == rsync)
|
||||||
{
|
{
|
||||||
r = test_ssh_connection(runtime_options.host, runtime_options.remote_user);
|
r = test_ssh_connection(runtime_options.host, runtime_options.remote_user);
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
@@ -1856,8 +1989,11 @@ do_standby_clone(void)
|
|||||||
* If replication slots requested, create appropriate slot on
|
* If replication slots requested, create appropriate slot on
|
||||||
* the primary; this must be done before pg_start_backup() is
|
* the primary; this must be done before pg_start_backup() is
|
||||||
* issued, either by us or by pg_basebackup.
|
* issued, either by us or by pg_basebackup.
|
||||||
|
*
|
||||||
|
* Replication slots are not supported (and not very useful
|
||||||
|
* anyway) in Barman mode.
|
||||||
*/
|
*/
|
||||||
if (options.use_replication_slots)
|
if (mode != barman && options.use_replication_slots)
|
||||||
{
|
{
|
||||||
if (create_replication_slot(upstream_conn, repmgr_slot_name, server_version_num) == false)
|
if (create_replication_slot(upstream_conn, repmgr_slot_name, server_version_num) == false)
|
||||||
{
|
{
|
||||||
@@ -1866,24 +2002,324 @@ do_standby_clone(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (runtime_options.rsync_only)
|
if (mode == rsync)
|
||||||
{
|
{
|
||||||
log_notice(_("starting backup (using rsync)...\n"));
|
log_notice(_("starting backup (using rsync)...\n"));
|
||||||
}
|
}
|
||||||
else
|
else if (mode == barman)
|
||||||
|
{
|
||||||
|
log_notice(_("getting backup from Barman...\n"));
|
||||||
|
}
|
||||||
|
else if (mode == pg_basebackup)
|
||||||
{
|
{
|
||||||
log_notice(_("starting backup (using pg_basebackup)...\n"));
|
log_notice(_("starting backup (using pg_basebackup)...\n"));
|
||||||
if (runtime_options.fast_checkpoint == false)
|
if (runtime_options.fast_checkpoint == false)
|
||||||
log_hint(_("this may take some time; consider using the -c/--fast-checkpoint option\n"));
|
log_hint(_("this may take some time; consider using the -c/--fast-checkpoint option\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (runtime_options.rsync_only)
|
if (mode == barman || mode == rsync)
|
||||||
{
|
{
|
||||||
PQExpBufferData tablespace_map;
|
char command[MAXLEN];
|
||||||
bool tablespace_map_rewrite = false;
|
char filename[MAXLEN];
|
||||||
|
char buf[MAXLEN];
|
||||||
|
char backup_directory[MAXLEN];
|
||||||
|
char backup_id[MAXLEN] = "";
|
||||||
|
char datadir_list_filename[MAXLEN];
|
||||||
|
char *p, *q;
|
||||||
|
PQExpBufferData command_output;
|
||||||
TablespaceDataList tablespace_list = { NULL, NULL };
|
TablespaceDataList tablespace_list = { NULL, NULL };
|
||||||
TablespaceDataListCell *cell_t;
|
TablespaceDataListCell *cell_t;
|
||||||
|
|
||||||
|
PQExpBufferData tablespace_map;
|
||||||
|
bool tablespace_map_rewrite = false;
|
||||||
|
|
||||||
|
if (mode == barman)
|
||||||
|
{
|
||||||
|
bool command_ok;
|
||||||
|
/*
|
||||||
|
* Check that there is at least one valid backup
|
||||||
|
*/
|
||||||
|
|
||||||
|
maxlen_snprintf(command, "ssh %s barman show-backup %s latest > /dev/null",
|
||||||
|
options.barman_server,
|
||||||
|
options.cluster_name);
|
||||||
|
command_ok = local_command(command, NULL);
|
||||||
|
if (command_ok == false)
|
||||||
|
{
|
||||||
|
log_err(_("No valid backup for server %s was found in the Barman catalogue\n"),
|
||||||
|
options.barman_server);
|
||||||
|
log_hint(_("Refer to the Barman documentation for more information\n"));
|
||||||
|
exit(ERR_INTERNAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Locate Barman's backup directory
|
||||||
|
*/
|
||||||
|
|
||||||
|
maxlen_snprintf(command, "ssh %s barman show-server %s | grep 'backup_directory'",
|
||||||
|
options.barman_server,
|
||||||
|
options.cluster_name);
|
||||||
|
|
||||||
|
initPQExpBuffer(&command_output);
|
||||||
|
(void)local_command(
|
||||||
|
command,
|
||||||
|
&command_output);
|
||||||
|
|
||||||
|
p = string_skip_prefix("\tbackup_directory: ", command_output.data);
|
||||||
|
if (p == NULL)
|
||||||
|
{
|
||||||
|
log_err("Unexpected output from Barman: %s\n",
|
||||||
|
command_output.data);
|
||||||
|
exit(ERR_INTERNAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy(backup_directory, p, MAXLEN);
|
||||||
|
string_remove_trailing_newlines(backup_directory);
|
||||||
|
|
||||||
|
termPQExpBuffer(&command_output);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create the local repmgr subdirectory
|
||||||
|
*/
|
||||||
|
|
||||||
|
maxlen_snprintf(local_repmgr_directory, "%s/repmgr", local_data_directory );
|
||||||
|
maxlen_snprintf(datadir_list_filename, "%s/data.txt", local_repmgr_directory);
|
||||||
|
|
||||||
|
if (!create_pg_dir(local_repmgr_directory, runtime_options.force))
|
||||||
|
{
|
||||||
|
log_err(_("unable to use directory %s ...\n"),
|
||||||
|
local_repmgr_directory);
|
||||||
|
log_hint(_("use -F/--force option to force this directory to be overwritten\n"));
|
||||||
|
r = ERR_BAD_CONFIG;
|
||||||
|
retval = ERR_BAD_CONFIG;
|
||||||
|
goto stop_backup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read the list of backup files into a local file. In the
|
||||||
|
* process:
|
||||||
|
*
|
||||||
|
* - determine the backup ID;
|
||||||
|
* - check, and remove, the prefix;
|
||||||
|
* - detect tablespaces;
|
||||||
|
* - filter files in one list per tablespace;
|
||||||
|
*/
|
||||||
|
|
||||||
|
{
|
||||||
|
FILE *fi; /* input stream */
|
||||||
|
FILE *fd; /* output for data.txt */
|
||||||
|
char prefix[MAXLEN];
|
||||||
|
char output[MAXLEN];
|
||||||
|
int n;
|
||||||
|
|
||||||
|
maxlen_snprintf(command, "ssh %s barman list-files --target=data %s latest",
|
||||||
|
options.barman_server,
|
||||||
|
options.cluster_name);
|
||||||
|
|
||||||
|
fi = popen(command, "r");
|
||||||
|
if (fi == NULL)
|
||||||
|
{
|
||||||
|
log_err("Cannot launch command: %s\n", command);
|
||||||
|
exit(ERR_INTERNAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
fd = fopen(datadir_list_filename, "w");
|
||||||
|
if (fd == NULL)
|
||||||
|
{
|
||||||
|
log_err("Cannot open file: %s\n", datadir_list_filename);
|
||||||
|
exit(ERR_INTERNAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
maxlen_snprintf(prefix, "%s/base/", backup_directory);
|
||||||
|
while (fgets(output, MAXLEN, fi) != NULL)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Remove prefix
|
||||||
|
*/
|
||||||
|
p = string_skip_prefix(prefix, output);
|
||||||
|
if (p == NULL)
|
||||||
|
{
|
||||||
|
log_err("Unexpected output from \"barman list-files\": %s\n",
|
||||||
|
output);
|
||||||
|
exit(ERR_INTERNAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove and note backup ID; copy backup.info
|
||||||
|
*/
|
||||||
|
if (! strcmp(backup_id, ""))
|
||||||
|
{
|
||||||
|
FILE *fi2;
|
||||||
|
|
||||||
|
n = strcspn(p, "/");
|
||||||
|
|
||||||
|
strncpy(backup_id, p, n);
|
||||||
|
|
||||||
|
strncat(prefix,backup_id,MAXLEN-1);
|
||||||
|
strncat(prefix,"/",MAXLEN-1);
|
||||||
|
p = string_skip_prefix(backup_id, p);
|
||||||
|
p = string_skip_prefix("/", p);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy backup.info
|
||||||
|
*/
|
||||||
|
maxlen_snprintf(command,
|
||||||
|
"rsync -a %s:%s/base/%s/backup.info %s",
|
||||||
|
options.barman_server,
|
||||||
|
backup_directory,
|
||||||
|
backup_id,
|
||||||
|
local_repmgr_directory);
|
||||||
|
(void)local_command(
|
||||||
|
command,
|
||||||
|
&command_output);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get tablespace data
|
||||||
|
*/
|
||||||
|
maxlen_snprintf(filename, "%s/backup.info",
|
||||||
|
local_repmgr_directory);
|
||||||
|
fi2 = fopen(filename, "r");
|
||||||
|
if (fi2 == NULL)
|
||||||
|
{
|
||||||
|
log_err("Cannot open file: %s\n", filename);
|
||||||
|
exit(ERR_INTERNAL);
|
||||||
|
}
|
||||||
|
while (fgets(buf, MAXLEN, fi2) != NULL)
|
||||||
|
{
|
||||||
|
q = string_skip_prefix("tablespaces=", buf);
|
||||||
|
if (q != NULL)
|
||||||
|
{
|
||||||
|
get_tablespace_data_barman
|
||||||
|
(q, &tablespace_list);
|
||||||
|
}
|
||||||
|
q = string_skip_prefix("version=", buf);
|
||||||
|
if (q != NULL)
|
||||||
|
{
|
||||||
|
server_version_num = strtol(q, NULL, 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(fi2);
|
||||||
|
unlink(filename);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Skip backup.info
|
||||||
|
*/
|
||||||
|
if (string_skip_prefix("backup.info", p))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Filter data directory files
|
||||||
|
*/
|
||||||
|
if ((q = string_skip_prefix("data/", p)) != NULL)
|
||||||
|
{
|
||||||
|
fputs(q, fd);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Filter other files (i.e. tablespaces)
|
||||||
|
*/
|
||||||
|
for (cell_t = tablespace_list.head; cell_t; cell_t = cell_t->next)
|
||||||
|
{
|
||||||
|
if ((q = string_skip_prefix(cell_t->oid, p)) != NULL && *q == '/')
|
||||||
|
{
|
||||||
|
if (cell_t->f == NULL)
|
||||||
|
{
|
||||||
|
maxlen_snprintf(filename, "%s/%s.txt", local_repmgr_directory, cell_t->oid);
|
||||||
|
cell_t->f = fopen(filename, "w");
|
||||||
|
if (cell_t->f == NULL)
|
||||||
|
{
|
||||||
|
log_err("Cannot open file: %s\n", filename);
|
||||||
|
exit(ERR_INTERNAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fputs(q + 1, cell_t->f);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fd);
|
||||||
|
|
||||||
|
pclose(fi);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For 9.5 and greater, create our own tablespace_map file */
|
||||||
|
if (server_version_num >= 90500)
|
||||||
|
{
|
||||||
|
initPQExpBuffer(&tablespace_map);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* As of Barman version 1.6.1, the file structure of a backup
|
||||||
|
* is as follows:
|
||||||
|
*
|
||||||
|
* base/ - base backup
|
||||||
|
* wals/ - WAL files associated to the backup
|
||||||
|
*
|
||||||
|
* base/<ID> - backup files
|
||||||
|
*
|
||||||
|
* here ID has the standard timestamp form yyyymmddThhmmss
|
||||||
|
*
|
||||||
|
* base/<ID>/backup.info - backup metadata, in text format
|
||||||
|
* base/<ID>/data - data directory
|
||||||
|
* base/<ID>/<OID> - tablespace with the given oid
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy all backup files from the Barman server
|
||||||
|
*/
|
||||||
|
|
||||||
|
maxlen_snprintf(command,
|
||||||
|
"rsync --progress -a --files-from=%s %s:%s/base/%s/data %s",
|
||||||
|
datadir_list_filename,
|
||||||
|
options.barman_server,
|
||||||
|
backup_directory,
|
||||||
|
backup_id,
|
||||||
|
local_data_directory);
|
||||||
|
(void)local_command(
|
||||||
|
command,
|
||||||
|
&command_output);
|
||||||
|
unlink(datadir_list_filename);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We must create some PGDATA subdirectories because they are
|
||||||
|
* not included in the Barman backup.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
const char* const dirs[] = {
|
||||||
|
/* Only from 9.5 */
|
||||||
|
"pg_commit_ts",
|
||||||
|
/* Only from 9.4 */
|
||||||
|
"pg_dynshmem", "pg_logical",
|
||||||
|
/* Already in 9.3 */
|
||||||
|
"pg_serial", "pg_snapshots", "pg_stat", "pg_stat_tmp", "pg_tblspc",
|
||||||
|
"pg_twophase", "pg_xlog", 0
|
||||||
|
};
|
||||||
|
const int vers[] = {
|
||||||
|
90500,
|
||||||
|
90400, 90400,
|
||||||
|
0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0
|
||||||
|
};
|
||||||
|
for (i = 0; dirs[i]; i++)
|
||||||
|
{
|
||||||
|
if (vers[i] > 0 && server_version_num < vers[i])
|
||||||
|
continue;
|
||||||
|
maxlen_snprintf(filename, "%s/%s", local_data_directory, dirs[i]);
|
||||||
|
if(mkdir(filename, S_IRWXU) != 0 && errno != EEXIST)
|
||||||
|
{
|
||||||
|
log_err(_("unable to create the %s directory\n"), dirs[i]);
|
||||||
|
exit(ERR_INTERNAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (mode == rsync)
|
||||||
|
{
|
||||||
/* For 9.5 and greater, create our own tablespace_map file */
|
/* For 9.5 and greater, create our own tablespace_map file */
|
||||||
if (server_version_num >= 90500)
|
if (server_version_num >= 90500)
|
||||||
{
|
{
|
||||||
@@ -1952,6 +2388,7 @@ do_standby_clone(void)
|
|||||||
/* Copy tablespaces and, if required, remap to a new location */
|
/* Copy tablespaces and, if required, remap to a new location */
|
||||||
retval = get_tablespace_data(upstream_conn, &tablespace_list);
|
retval = get_tablespace_data(upstream_conn, &tablespace_list);
|
||||||
if(retval != SUCCESS) goto stop_backup;
|
if(retval != SUCCESS) goto stop_backup;
|
||||||
|
}
|
||||||
|
|
||||||
for (cell_t = tablespace_list.head; cell_t; cell_t = cell_t->next)
|
for (cell_t = tablespace_list.head; cell_t; cell_t = cell_t->next)
|
||||||
{
|
{
|
||||||
@@ -1983,7 +2420,38 @@ do_standby_clone(void)
|
|||||||
tblspc_dir_dest = cell_t->location;
|
tblspc_dir_dest = cell_t->location;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tablespace file copy
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (mode == barman)
|
||||||
|
{
|
||||||
|
create_pg_dir(cell_t->location, false);
|
||||||
|
|
||||||
|
if (cell_t->f != NULL) /* cell_t->f == NULL iff the tablespace is empty */
|
||||||
|
{
|
||||||
|
maxlen_snprintf(command,
|
||||||
|
"rsync --progress -a --files-from=%s/%s.txt %s:%s/base/%s/%s %s",
|
||||||
|
local_repmgr_directory,
|
||||||
|
cell_t->oid,
|
||||||
|
options.barman_server,
|
||||||
|
backup_directory,
|
||||||
|
backup_id,
|
||||||
|
cell_t->oid,
|
||||||
|
tblspc_dir_dest);
|
||||||
|
(void)local_command(
|
||||||
|
command,
|
||||||
|
&command_output);
|
||||||
|
fclose(cell_t->f);
|
||||||
|
maxlen_snprintf(filename,
|
||||||
|
"%s/%s.txt",
|
||||||
|
local_repmgr_directory,
|
||||||
|
cell_t->oid);
|
||||||
|
unlink(filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (mode == rsync)
|
||||||
|
{
|
||||||
/* Copy tablespace directory */
|
/* Copy tablespace directory */
|
||||||
r = copy_remote_files(runtime_options.host, runtime_options.remote_user,
|
r = copy_remote_files(runtime_options.host, runtime_options.remote_user,
|
||||||
cell_t->location, tblspc_dir_dest,
|
cell_t->location, tblspc_dir_dest,
|
||||||
@@ -2001,6 +2469,7 @@ do_standby_clone(void)
|
|||||||
cell_t->location);
|
cell_t->location);
|
||||||
goto stop_backup;
|
goto stop_backup;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If a valid mapping was provide for this tablespace, arrange for it to
|
* If a valid mapping was provide for this tablespace, arrange for it to
|
||||||
@@ -2008,7 +2477,7 @@ do_standby_clone(void)
|
|||||||
* (if no tablespace mappings was provided, the link will be copied as-is
|
* (if no tablespace mappings was provided, the link will be copied as-is
|
||||||
* by pg_basebackup or rsync and no action is required)
|
* by pg_basebackup or rsync and no action is required)
|
||||||
*/
|
*/
|
||||||
if (mapping_found == true)
|
if (mapping_found == true || mode == barman)
|
||||||
{
|
{
|
||||||
/* 9.5 and later - append to the tablespace_map file */
|
/* 9.5 and later - append to the tablespace_map file */
|
||||||
if (server_version_num >= 90500)
|
if (server_version_num >= 90500)
|
||||||
@@ -2116,7 +2585,9 @@ do_standby_clone(void)
|
|||||||
* standby server as on the primary?
|
* standby server as on the primary?
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (external_config_file_copy_required && !runtime_options.ignore_external_config_files)
|
if (mode != barman &&
|
||||||
|
external_config_file_copy_required &&
|
||||||
|
!runtime_options.ignore_external_config_files)
|
||||||
{
|
{
|
||||||
log_notice(_("copying configuration files from master\n"));
|
log_notice(_("copying configuration files from master\n"));
|
||||||
r = test_ssh_connection(runtime_options.host, runtime_options.remote_user);
|
r = test_ssh_connection(runtime_options.host, runtime_options.remote_user);
|
||||||
@@ -2175,7 +2646,7 @@ do_standby_clone(void)
|
|||||||
* When using rsync, copy pg_control file last, emulating the base backup
|
* When using rsync, copy pg_control file last, emulating the base backup
|
||||||
* protocol.
|
* protocol.
|
||||||
*/
|
*/
|
||||||
if (runtime_options.rsync_only)
|
if (mode == rsync)
|
||||||
{
|
{
|
||||||
maxlen_snprintf(local_control_file, "%s/global", local_data_directory);
|
maxlen_snprintf(local_control_file, "%s/global", local_data_directory);
|
||||||
|
|
||||||
@@ -2207,7 +2678,7 @@ do_standby_clone(void)
|
|||||||
|
|
||||||
stop_backup:
|
stop_backup:
|
||||||
|
|
||||||
if (runtime_options.rsync_only && pg_start_backup_executed)
|
if (mode == rsync && pg_start_backup_executed)
|
||||||
{
|
{
|
||||||
log_notice(_("notifying master about backup completion...\n"));
|
log_notice(_("notifying master about backup completion...\n"));
|
||||||
if (stop_backup(upstream_conn, last_wal_segment) == false)
|
if (stop_backup(upstream_conn, last_wal_segment) == false)
|
||||||
@@ -2239,7 +2710,7 @@ stop_backup:
|
|||||||
* files which won't be removed by rsync and which could
|
* files which won't be removed by rsync and which could
|
||||||
* be stale or are otherwise not required
|
* be stale or are otherwise not required
|
||||||
*/
|
*/
|
||||||
if (runtime_options.rsync_only)
|
if (mode == rsync)
|
||||||
{
|
{
|
||||||
char label_path[MAXPGPATH];
|
char label_path[MAXPGPATH];
|
||||||
char dirpath[MAXLEN] = "";
|
char dirpath[MAXLEN] = "";
|
||||||
@@ -2303,13 +2774,18 @@ stop_backup:
|
|||||||
/* Finally, write the recovery.conf file */
|
/* Finally, write the recovery.conf file */
|
||||||
create_recovery_file(local_data_directory, upstream_conn);
|
create_recovery_file(local_data_directory, upstream_conn);
|
||||||
|
|
||||||
if (runtime_options.rsync_only)
|
/* In Barman mode, remove local_repmgr_directory */
|
||||||
|
if (mode == barman)
|
||||||
|
rmdir(local_repmgr_directory);
|
||||||
|
|
||||||
|
switch(mode)
|
||||||
{
|
{
|
||||||
|
case rsync:
|
||||||
log_notice(_("standby clone (using rsync) complete\n"));
|
log_notice(_("standby clone (using rsync) complete\n"));
|
||||||
}
|
case pg_basebackup:
|
||||||
else
|
|
||||||
{
|
|
||||||
log_notice(_("standby clone (using pg_basebackup) complete\n"));
|
log_notice(_("standby clone (using pg_basebackup) complete\n"));
|
||||||
|
case barman:
|
||||||
|
log_notice(_("standby clone (from Barman) complete\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -4544,6 +5020,7 @@ do_help(void)
|
|||||||
printf(_("Command-specific configuration options:\n"));
|
printf(_("Command-specific configuration options:\n"));
|
||||||
printf(_(" -c, --fast-checkpoint (standby clone) force fast checkpoint\n"));
|
printf(_(" -c, --fast-checkpoint (standby clone) force fast checkpoint\n"));
|
||||||
printf(_(" -r, --rsync-only (standby clone) use only rsync, not pg_basebackup\n"));
|
printf(_(" -r, --rsync-only (standby clone) use only rsync, not pg_basebackup\n"));
|
||||||
|
printf(_(" --without-barman (standby clone) do not use Barman even if configured\n"));
|
||||||
printf(_(" --recovery-min-apply-delay=VALUE (standby clone, follow) set recovery_min_apply_delay\n" \
|
printf(_(" --recovery-min-apply-delay=VALUE (standby clone, follow) set recovery_min_apply_delay\n" \
|
||||||
" in recovery.conf (PostgreSQL 9.4 and later)\n"));
|
" in recovery.conf (PostgreSQL 9.4 and later)\n"));
|
||||||
printf(_(" --ignore-external-config-files (standby clone) don't copy configuration files located\n" \
|
printf(_(" --ignore-external-config-files (standby clone) don't copy configuration files located\n" \
|
||||||
@@ -5707,10 +6184,10 @@ check_upstream_config(PGconn *conn, int server_version_num, bool exit_on_error)
|
|||||||
|
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* physical replication slots not available or not requested -
|
* physical replication slots not available or not requested, and Barman mode not used -
|
||||||
* ensure some reasonably high value set for `wal_keep_segments`
|
* ensure some reasonably high value set for `wal_keep_segments`
|
||||||
*/
|
*/
|
||||||
else
|
else if (! runtime_options.without_barman && strcmp(options.barman_server, "") == 0)
|
||||||
{
|
{
|
||||||
i = guc_set_typed(conn, "wal_keep_segments", ">=",
|
i = guc_set_typed(conn, "wal_keep_segments", ">=",
|
||||||
runtime_options.wal_keep_segments, "integer");
|
runtime_options.wal_keep_segments, "integer");
|
||||||
@@ -6005,33 +6482,43 @@ remote_command(const char *host, const char *user, const char *command, PQExpBuf
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Execute a command locally.
|
* Execute a command locally. If outputbuf == NULL, discard the
|
||||||
|
* output.
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool
|
||||||
local_command(const char *command, PQExpBufferData *outputbuf)
|
local_command(const char *command, PQExpBufferData *outputbuf)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char output[MAXLEN];
|
char output[MAXLEN];
|
||||||
|
int retval;
|
||||||
|
|
||||||
fp = popen(command, "r");
|
if (outputbuf == NULL)
|
||||||
|
|
||||||
if (fp == NULL)
|
|
||||||
{
|
{
|
||||||
log_err(_("unable to execute local command:\n%s\n"), command);
|
retval = system(command);
|
||||||
return false;
|
return (retval == 0) ? true : false;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
/* TODO: better error handling */
|
|
||||||
while (fgets(output, MAXLEN, fp) != NULL)
|
|
||||||
{
|
{
|
||||||
appendPQExpBuffer(outputbuf, "%s", output);
|
fp = popen(command, "r");
|
||||||
|
|
||||||
|
if (fp == NULL)
|
||||||
|
{
|
||||||
|
log_err(_("unable to execute local command:\n%s\n"), command);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: better error handling */
|
||||||
|
while (fgets(output, MAXLEN, fp) != NULL)
|
||||||
|
{
|
||||||
|
appendPQExpBuffer(outputbuf, "%s", output);
|
||||||
|
}
|
||||||
|
|
||||||
|
pclose(fp);
|
||||||
|
|
||||||
|
log_verbose(LOG_DEBUG, "local_command(): output returned was:\n%s", outputbuf->data);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pclose(fp);
|
|
||||||
|
|
||||||
log_verbose(LOG_DEBUG, "local_command(): output returned was:\n%s", outputbuf->data);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
4
repmgr.h
4
repmgr.h
@@ -56,6 +56,7 @@
|
|||||||
#define OPT_PWPROMPT 7
|
#define OPT_PWPROMPT 7
|
||||||
#define OPT_CSV 8
|
#define OPT_CSV 8
|
||||||
#define OPT_NODE 9
|
#define OPT_NODE 9
|
||||||
|
#define OPT_WITHOUT_BARMAN 10
|
||||||
|
|
||||||
|
|
||||||
/* Run time options type */
|
/* Run time options type */
|
||||||
@@ -79,6 +80,7 @@ typedef struct
|
|||||||
bool fast_checkpoint;
|
bool fast_checkpoint;
|
||||||
bool ignore_external_config_files;
|
bool ignore_external_config_files;
|
||||||
bool csv_mode;
|
bool csv_mode;
|
||||||
|
bool without_barman;
|
||||||
char masterport[MAXLEN];
|
char masterport[MAXLEN];
|
||||||
/*
|
/*
|
||||||
* configuration file parameters which can be overridden on the
|
* configuration file parameters which can be overridden on the
|
||||||
@@ -102,7 +104,7 @@ typedef struct
|
|||||||
char recovery_min_apply_delay[MAXLEN];
|
char recovery_min_apply_delay[MAXLEN];
|
||||||
} t_runtime_options;
|
} t_runtime_options;
|
||||||
|
|
||||||
#define T_RUNTIME_OPTIONS_INITIALIZER { "", "", "", "", "", "", "", DEFAULT_WAL_KEEP_SEGMENTS, false, false, false, false, false, false, false, false, false, false, "", "", "", "", "fast", "", 0, 0, "", ""}
|
#define T_RUNTIME_OPTIONS_INITIALIZER { "", "", "", "", "", "", "", DEFAULT_WAL_KEEP_SEGMENTS, false, false, false, false, false, false, false, false, false, false, false, "", "", "", "", "fast", "", 0, 0, "", ""}
|
||||||
|
|
||||||
struct BackupLabel
|
struct BackupLabel
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user