[Issue #102] now it is possible to set restore_command via set-config

This commit is contained in:
Grigory Smolkin
2019-10-03 23:56:47 +03:00
parent 56726b25fa
commit 544de123a4
7 changed files with 156 additions and 46 deletions
+1 -4
View File
@@ -702,11 +702,8 @@ do_backup(time_t start_time, bool no_validate)
current.compress_level = instance_config.compress_level;
/* Save list of external directories */
if (instance_config.external_dir_str &&
pg_strcasecmp(instance_config.external_dir_str, "none") != 0)
{
if (instance_config.external_dir_str)
current.external_dir_str = instance_config.external_dir_str;
}
elog(INFO, "Backup start, pg_probackup version: %s, instance: %s, backup ID: %s, backup mode: %s, "
"wal mode: %s, remote: %s, compress-algorithm: %s, compress-level: %i",
+69 -36
View File
@@ -137,97 +137,102 @@ ConfigOption instance_options[] =
&instance_config.archive.user, SOURCE_CMD, 0,
OPTION_ARCHIVE_GROUP, 0, option_get_value
},
{
's', 211, "restore-command",
&instance_config.restore_command, SOURCE_CMD, SOURCE_DEFAULT,
OPTION_ARCHIVE_GROUP, 0, option_get_value
},
/* Logging options */
{
'f', 211, "log-level-console",
'f', 212, "log-level-console",
assign_log_level_console, SOURCE_CMD, 0,
OPTION_LOG_GROUP, 0, get_log_level_console
},
{
'f', 212, "log-level-file",
'f', 213, "log-level-file",
assign_log_level_file, SOURCE_CMD, 0,
OPTION_LOG_GROUP, 0, get_log_level_file
},
{
's', 213, "log-filename",
's', 214, "log-filename",
&instance_config.logger.log_filename, SOURCE_CMD, 0,
OPTION_LOG_GROUP, 0, option_get_value
},
{
's', 214, "error-log-filename",
's', 215, "error-log-filename",
&instance_config.logger.error_log_filename, SOURCE_CMD, 0,
OPTION_LOG_GROUP, 0, option_get_value
},
{
's', 215, "log-directory",
's', 216, "log-directory",
&instance_config.logger.log_directory, SOURCE_CMD, 0,
OPTION_LOG_GROUP, 0, option_get_value
},
{
'U', 216, "log-rotation-size",
'U', 217, "log-rotation-size",
&instance_config.logger.log_rotation_size, SOURCE_CMD, SOURCE_DEFAULT,
OPTION_LOG_GROUP, OPTION_UNIT_KB, option_get_value
},
{
'U', 217, "log-rotation-age",
'U', 218, "log-rotation-age",
&instance_config.logger.log_rotation_age, SOURCE_CMD, SOURCE_DEFAULT,
OPTION_LOG_GROUP, OPTION_UNIT_MS, option_get_value
},
/* Retention options */
{
'u', 218, "retention-redundancy",
'u', 219, "retention-redundancy",
&instance_config.retention_redundancy, SOURCE_CMD, 0,
OPTION_RETENTION_GROUP, 0, option_get_value
},
{
'u', 219, "retention-window",
'u', 220, "retention-window",
&instance_config.retention_window, SOURCE_CMD, 0,
OPTION_RETENTION_GROUP, 0, option_get_value
},
/* Compression options */
{
'f', 220, "compress-algorithm",
'f', 221, "compress-algorithm",
assign_compress_alg, SOURCE_CMD, 0,
OPTION_COMPRESS_GROUP, 0, get_compress_alg
},
{
'u', 221, "compress-level",
'u', 222, "compress-level",
&instance_config.compress_level, SOURCE_CMD, 0,
OPTION_COMPRESS_GROUP, 0, option_get_value
},
/* Remote backup options */
{
's', 222, "remote-proto",
's', 223, "remote-proto",
&instance_config.remote.proto, SOURCE_CMD, 0,
OPTION_REMOTE_GROUP, 0, option_get_value
},
{
's', 223, "remote-host",
's', 224, "remote-host",
&instance_config.remote.host, SOURCE_CMD, 0,
OPTION_REMOTE_GROUP, 0, option_get_value
},
{
's', 224, "remote-port",
's', 225, "remote-port",
&instance_config.remote.port, SOURCE_CMD, 0,
OPTION_REMOTE_GROUP, 0, option_get_value
},
{
's', 225, "remote-path",
's', 226, "remote-path",
&instance_config.remote.path, SOURCE_CMD, 0,
OPTION_REMOTE_GROUP, 0, option_get_value
},
{
's', 226, "remote-user",
's', 227, "remote-user",
&instance_config.remote.user, SOURCE_CMD, 0,
OPTION_REMOTE_GROUP, 0, option_get_value
},
{
's', 227, "ssh-options",
's', 228, "ssh-options",
&instance_config.remote.ssh_options, SOURCE_CMD, 0,
OPTION_REMOTE_GROUP, 0, option_get_value
},
{
's', 228, "ssh-config",
's', 229, "ssh-config",
&instance_config.remote.ssh_config, SOURCE_CMD, 0,
OPTION_REMOTE_GROUP, 0, option_get_value
},
@@ -450,97 +455,125 @@ readInstanceConfigFile(const char *instance_name)
&instance->archive_timeout, SOURCE_CMD, SOURCE_DEFAULT,
OPTION_ARCHIVE_GROUP, OPTION_UNIT_S, option_get_value
},
{
's', 208, "archive-host",
&instance_config.archive.host, SOURCE_CMD, 0,
OPTION_ARCHIVE_GROUP, 0, option_get_value
},
{
's', 209, "archive-port",
&instance_config.archive.port, SOURCE_CMD, 0,
OPTION_ARCHIVE_GROUP, 0, option_get_value
},
{
's', 210, "archive-user",
&instance_config.archive.user, SOURCE_CMD, 0,
OPTION_ARCHIVE_GROUP, 0, option_get_value
},
{
's', 211, "restore-command",
&instance->restore_command, SOURCE_CMD, 0,
OPTION_ARCHIVE_GROUP, 0, option_get_value
},
/* Instance options */
{
's', 'D', "pgdata",
&instance->pgdata, SOURCE_CMD, 0,
OPTION_INSTANCE_GROUP, 0, option_get_value
},
/* Logging options */
{
's', 208, "log-level-console",
's', 212, "log-level-console",
&log_level_console, SOURCE_CMD, 0,
OPTION_LOG_GROUP, 0, option_get_value
},
{
's', 209, "log-level-file",
's', 213, "log-level-file",
&log_level_file, SOURCE_CMD, 0,
OPTION_LOG_GROUP, 0, option_get_value
},
{
's', 210, "log-filename",
's', 214, "log-filename",
&instance->logger.log_filename, SOURCE_CMD, 0,
OPTION_LOG_GROUP, 0, option_get_value
},
{
's', 211, "error-log-filename",
's', 215, "error-log-filename",
&instance->logger.error_log_filename, SOURCE_CMD, 0,
OPTION_LOG_GROUP, 0, option_get_value
},
{
's', 212, "log-directory",
's', 216, "log-directory",
&instance->logger.log_directory, SOURCE_CMD, 0,
OPTION_LOG_GROUP, 0, option_get_value
},
{
'U', 213, "log-rotation-size",
'U', 217, "log-rotation-size",
&instance->logger.log_rotation_size, SOURCE_CMD, SOURCE_DEFAULT,
OPTION_LOG_GROUP, OPTION_UNIT_KB, option_get_value
},
{
'U', 214, "log-rotation-age",
'U', 218, "log-rotation-age",
&instance->logger.log_rotation_age, SOURCE_CMD, SOURCE_DEFAULT,
OPTION_LOG_GROUP, OPTION_UNIT_MS, option_get_value
},
/* Retention options */
{
'u', 215, "retention-redundancy",
'u', 219, "retention-redundancy",
&instance->retention_redundancy, SOURCE_CMD, 0,
OPTION_RETENTION_GROUP, 0, option_get_value
},
{
'u', 216, "retention-window",
'u', 220, "retention-window",
&instance->retention_window, SOURCE_CMD, 0,
OPTION_RETENTION_GROUP, 0, option_get_value
},
/* Compression options */
{
's', 217, "compress-algorithm",
's', 221, "compress-algorithm",
&compress_alg, SOURCE_CMD, 0,
OPTION_LOG_GROUP, 0, option_get_value
},
{
'u', 218, "compress-level",
'u', 222, "compress-level",
&instance->compress_level, SOURCE_CMD, 0,
OPTION_COMPRESS_GROUP, 0, option_get_value
},
/* Remote backup options */
{
's', 219, "remote-proto",
's', 223, "remote-proto",
&instance->remote.proto, SOURCE_CMD, 0,
OPTION_REMOTE_GROUP, 0, option_get_value
},
{
's', 220, "remote-host",
's', 224, "remote-host",
&instance->remote.host, SOURCE_CMD, 0,
OPTION_REMOTE_GROUP, 0, option_get_value
},
{
's', 221, "remote-port",
's', 225, "remote-port",
&instance->remote.port, SOURCE_CMD, 0,
OPTION_REMOTE_GROUP, 0, option_get_value
},
{
's', 222, "remote-path",
's', 226, "remote-path",
&instance->remote.path, SOURCE_CMD, 0,
OPTION_REMOTE_GROUP, 0, option_get_value
},
{
's', 223, "remote-user",
's', 227, "remote-user",
&instance->remote.user, SOURCE_CMD, 0,
OPTION_REMOTE_GROUP, 0, option_get_value
},
{
's', 224, "ssh-options",
's', 228, "ssh-options",
&instance->remote.ssh_options, SOURCE_CMD, 0,
OPTION_REMOTE_GROUP, 0, option_get_value
},
{
's', 225, "ssh-config",
's', 229, "ssh-config",
&instance->remote.ssh_config, SOURCE_CMD, 0,
OPTION_REMOTE_GROUP, 0, option_get_value
},
-3
View File
@@ -87,7 +87,6 @@ static char *target_stop;
static bool target_immediate;
static char *target_name = NULL;
static char *target_action = NULL;
static char *restore_command = NULL;
static pgRecoveryTarget *recovery_target_options = NULL;
static pgRestoreParams *restore_params = NULL;
@@ -183,7 +182,6 @@ static ConfigOption cmd_options[] =
{ 'b', 156, "skip-external-dirs", &skip_external_dirs, SOURCE_CMD_STRICT },
{ 'f', 158, "db-include", opt_datname_include_list, SOURCE_CMD_STRICT },
{ 'f', 159, "db-exclude", opt_datname_exclude_list, SOURCE_CMD_STRICT },
{ 's', 160, "restore-command", &restore_command, SOURCE_CMD_STRICT },
/* checkdb options */
{ 'b', 195, "amcheck", &need_amcheck, SOURCE_CMD_STRICT },
{ 'b', 196, "heapallindexed", &heapallindexed, SOURCE_CMD_STRICT },
@@ -643,7 +641,6 @@ main(int argc, char *argv[])
restore_params->skip_external_dirs = skip_external_dirs;
restore_params->partial_db_list = NULL;
restore_params->partial_restore_type = NONE;
restore_params->restore_command = restore_command;
/* handle partial restore parameters */
if (datname_exclude_list && datname_include_list)
+3
View File
@@ -252,6 +252,9 @@ typedef struct InstanceConfig
/* Wait timeout for WAL segment archiving */
uint32 archive_timeout;
/* cmdline to be used as restore_command */
char *restore_command;
/* Logger parameters */
LoggerConfig logger;
+3 -3
View File
@@ -857,15 +857,15 @@ create_recovery_conf(time_t backup_id,
fio_fprintf(fp, "# recovery.conf generated by pg_probackup %s\n",
PROGRAM_VERSION);
/* construct restore_command */
if (need_restore_conf)
{
char restore_command_guc[16384];
/* If restore_command is provided, use it */
if (params->restore_command)
sprintf(restore_command_guc, "%s", params->restore_command);
/* construct restore_command */
if (instance_config.restore_command)
sprintf(restore_command_guc, "%s", instance_config.restore_command);
else
{
/* default cmdline, ok for local restore */
+13
View File
@@ -250,6 +250,15 @@ assign_option(ConfigOption *opt, const char *optarg, OptionSource src)
case 's':
if (orig_source != SOURCE_DEFAULT)
free(*(char **) opt->var);
/* 'none' and 'off' are always disable the string parameter */
if ((pg_strcasecmp(optarg, "none") == 0) ||
(pg_strcasecmp(optarg, "off") == 0))
{
opt->var = NULL;
return;
}
*(char **) opt->var = pgut_strdup(optarg);
if (strcmp(optarg,"") != 0)
return;
@@ -656,6 +665,10 @@ option_get_value(ConfigOption *opt)
case 's':
if (*((char **) opt->var) == NULL)
return NULL;
/* 'none' and 'off' are always disable the string parameter */
if ((pg_strcasecmp(*((char **) opt->var), "none") == 0) ||
(pg_strcasecmp(*((char **) opt->var), "off") == 0))
return NULL;
return pstrdup(*((char **) opt->var));
case 't':
{
+67
View File
@@ -1614,6 +1614,73 @@ class ArchiveTest(ProbackupTest, unittest.TestCase):
self.del_test_dir(module_name, fname)
# @unittest.expectedFailure
# @unittest.skip("skip")
def test_archive_options_1(self):
"""
check that '--archive-host', '--archive-user', '--archiver-port'
and '--restore-command' are working as expected with set-config
"""
fname = self.id().split('.')[3]
backup_dir = os.path.join(self.tmp_path, module_name, fname, 'backup')
node = self.make_simple_node(
base_dir=os.path.join(module_name, fname, 'node'),
set_replication=True,
initdb_params=['--data-checksums'])
self.init_pb(backup_dir)
self.add_instance(backup_dir, 'node', node)
self.set_archiving(backup_dir, 'node', node, compress=True)
node.slow_start()
# FULL
self.backup_node(backup_dir, 'node', node)
node.pgbench_init(scale=1)
node.cleanup()
wal_dir = os.path.join(backup_dir, 'wal', 'node')
self.set_config(
backup_dir, 'node',
options=[
'--restore-command="cp {0}/%f %p"'.format(wal_dir),
'--archive-host=localhost',
'--archive-port=22',
'--archive-user={0}'.format(self.user)])
self.restore_node(backup_dir, 'node', node)
recovery_conf = os.path.join(node.data_dir, 'recovery.conf')
with open(recovery_conf, 'r') as f:
recovery_content = f.read()
self.assertIn(
'restore_command = \'"cp {0}/%f %p"\''.format(wal_dir),
recovery_content)
node.cleanup()
self.restore_node(
backup_dir, 'node', node,
options=[
'--restore-command=none'.format(wal_dir),
'--archive-host=localhost1',
'--archive-port=23',
'--archive-user={0}'.format(self.user)
])
with open(recovery_conf, 'r') as f:
recovery_content = f.read()
self.assertIn(
"restore_command = '{0} archive-get -B {1} --instance {2} "
"--wal-file-path=%p --wal-file-name=%f --remote-host=localhost1 "
"--remote-port=23 --remote-user={3}'".format(
self.probackup_path, backup_dir, 'node', self.user),
recovery_content)
self.del_test_dir(module_name, fname)
# important - switchpoint may be NullOffset LSN and not actually existing in archive to boot.
# so write validation code accordingly