mirror of
https://github.com/EnterpriseDB/repmgr.git
synced 2026-03-26 16:46:28 +00:00
Add "repmgr node restore-config"
This commit is contained in:
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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";
|
||||||
|
|||||||
Reference in New Issue
Block a user