Add "repmgr node restore-config"

This commit is contained in:
Ian Barwick
2017-08-01 22:13:32 +09:00
parent f023b9c90c
commit a1ad62d04e
2 changed files with 134 additions and 13 deletions

View File

@@ -15,6 +15,7 @@
#include "repmgr-action-node.h" #include "repmgr-action-node.h"
static bool copy_file(const char *src_file, const char *dest_file); static bool copy_file(const char *src_file, const char *dest_file);
static void format_archive_dir(char *archive_dir);
void void
do_node_status(void) do_node_status(void)
@@ -282,12 +283,12 @@ do_node_check(void)
/* /*
* Intended mainly for "internal" use by `standby switchover`, which * Intended mainly for "internal" use by `node switchover`, which
* calls this on the target server to archive any configuration files * calls this on the target server to archive any configuration files
* in the data directory, which may be overwritten by an operation * in the data directory, which may be overwritten by an operation
* like pg_rewind * like pg_rewind
* *
* Requires configuration file. * Requires configuration file, optionally --config_archive_dir
*/ */
void void
do_node_archive_config(void) do_node_archive_config(void)
@@ -302,13 +303,7 @@ do_node_archive_config(void)
KeyValueListCell *cell; KeyValueListCell *cell;
int copied_count = 0; int copied_count = 0;
snprintf(archive_dir, format_archive_dir(archive_dir);
MAXPGPATH,
"%s/repmgr-config-archive-%s",
runtime_options.config_archive_dir,
config_file_options.node_name);
log_verbose(LOG_DEBUG, "using archive directory \"%s\"", archive_dir);
/* sanity-check directory path */ /* sanity-check directory path */
if (stat(archive_dir, &statbuf) == -1) if (stat(archive_dir, &statbuf) == -1)
@@ -317,7 +312,7 @@ do_node_archive_config(void)
{ {
log_error(_("error encountered when checking archive directory \"%s\""), log_error(_("error encountered when checking archive directory \"%s\""),
archive_dir); archive_dir);
log_detail("%s",strerror(errno)); log_detail("%s", strerror(errno));
exit(ERR_BAD_CONFIG); exit(ERR_BAD_CONFIG);
} }
@@ -406,12 +401,120 @@ do_node_archive_config(void)
} }
/*
* Intended mainly for "internal" use by `standby switchover`, which
* calls this on the target server to restore any configuration files
* to the data directory, which may have been overwritten by an operation
* like pg_rewind
*
* Not designed to be called if the instance is running, but does
* not currently check.
*
* Requires -D/--pgdata, optionally --config_archive_dir
*
* Removes --config_archive_dir after successful copy
*/
void void
do_node_restore_config(void) do_node_restore_config(void)
{ {
char archive_dir[MAXPGPATH];
DIR *arcdir;
struct dirent *arcdir_ent;
int copied_count = 0;
bool copy_ok = true;
format_archive_dir(archive_dir);
arcdir = opendir(archive_dir);
if (arcdir == NULL)
{
log_error(_("unable to open archive directory \"%s\""),
archive_dir);
log_detail("%s", strerror(errno));
exit(ERR_BAD_CONFIG);
}
while ((arcdir_ent = readdir(arcdir)) != NULL) {
struct stat statbuf;
char src_file_path[MAXPGPATH];
char dest_file_path[MAXPGPATH];
snprintf(src_file_path, MAXPGPATH,
"%s/%s",
archive_dir,
arcdir_ent->d_name);
/* skip non-files */
if (stat(src_file_path, &statbuf) == 0 && !S_ISREG(statbuf.st_mode))
{
continue;
}
snprintf(dest_file_path, MAXPGPATH,
"%s/%s",
runtime_options.data_dir,
arcdir_ent->d_name);
log_verbose(LOG_DEBUG, "copying \"%s\" to \"%s\"", src_file_path, dest_file_path);
if (copy_file(src_file_path, dest_file_path) == false)
{
copy_ok = false;
log_warning(_("unable to copy \"%s\" to \"%s\""),
arcdir_ent->d_name, runtime_options.data_dir);
}
else
{
unlink(src_file_path);
copied_count++;
}
}
closedir(arcdir);
if (copy_ok == false)
{
log_error(_("unable to copy all files from %s"), archive_dir);
exit(ERR_BAD_CONFIG);
}
log_notice(_("%i files copied to %s"), copied_count, runtime_options.data_dir);
/*
* Finally, delete directory - it should be empty unless it's been interfered
* with for some reason, in which case manual intervention is required
*/
if (rmdir(archive_dir) != 0 && errno != EEXIST)
{
log_warning(_("unable to delete %s"), archive_dir);
log_detail(_("directory may need to be manually removed"));
}
else
{
log_verbose(LOG_NOTICE, "directory %s deleted", archive_dir);
}
return; return;
} }
static void
format_archive_dir(char *archive_dir)
{
snprintf(archive_dir,
MAXPGPATH,
"%s/repmgr-config-archive-%s",
runtime_options.config_archive_dir,
config_file_options.node_name);
log_verbose(LOG_DEBUG, "using archive directory \"%s\"", archive_dir);
}
static bool static bool
copy_file(const char *src_file, const char *dest_file) copy_file(const char *src_file, const char *dest_file)
{ {

View File

@@ -1086,7 +1086,8 @@ check_cli_parameters(const int action)
} }
} }
} }
break; break;
case STANDBY_FOLLOW: case STANDBY_FOLLOW:
{ {
/* /*
@@ -1101,8 +1102,20 @@ check_cli_parameters(const int action)
_("-D/--pgdata required when providing connection parameters for \"standby follow\"")); _("-D/--pgdata required when providing connection parameters for \"standby follow\""));
} }
} }
} }
break;
case NODE_RESTORE_CONFIG:
{
if (strcmp(runtime_options.data_dir, "") == 0)
{
item_list_append(&cli_errors, _("-D/--pgdata required when executing NODE RESTORE-CONFIG"));
}
config_file_required = false;
}
break;
case CLUSTER_SHOW: case CLUSTER_SHOW:
case CLUSTER_MATRIX: case CLUSTER_MATRIX:
case CLUSTER_CROSSCHECK: case CLUSTER_CROSSCHECK:
@@ -1311,6 +1324,12 @@ action_name(const int action)
case NODE_STATUS: case NODE_STATUS:
return "NODE STATUS"; return "NODE STATUS";
case NODE_CHECK:
return "NODE CHECK";
case NODE_ARCHIVE_CONFIG:
return "NODE ARCHIVE-CONFIG";
case NODE_RESTORE_CONFIG:
return "NODE RESTORE-CONFIG";
case CLUSTER_SHOW: case CLUSTER_SHOW:
return "CLUSTER SHOW"; return "CLUSTER SHOW";
@@ -1320,7 +1339,6 @@ action_name(const int action)
return "CLUSTER MATRIX"; return "CLUSTER MATRIX";
case CLUSTER_CROSSCHECK: case CLUSTER_CROSSCHECK:
return "CLUSTER CROSSCHECK"; return "CLUSTER CROSSCHECK";
} }
return "UNKNOWN ACTION"; return "UNKNOWN ACTION";