mirror of
https://github.com/EnterpriseDB/repmgr.git
synced 2026-03-23 07:06:30 +00:00
standby/witness unregister - enable even if node isn't running
If the `--node` option is provided with the id of the node to unregister, the action can be executed on any node. This addresses GitHub #211.
This commit is contained in:
3
HISTORY
3
HISTORY
@@ -3,6 +3,9 @@
|
||||
unless `--verbose` supplied (Ian)
|
||||
repmgr: remove deprecated command line options --initdb-no-pwprompt and
|
||||
-l/--local-port (Ian)
|
||||
repmgr: add command `witness unregister`
|
||||
repmgr: enable `standby unregister` / `witness unregister` to be
|
||||
executed for a node which is not running
|
||||
|
||||
3.1.4 2016-07-12
|
||||
repmgr: new configuration option for setting "restore_command"
|
||||
|
||||
12
README.md
12
README.md
@@ -940,13 +940,13 @@ recorded in the `repl_events` table.
|
||||
Note that this command will not stop the server itself or remove
|
||||
it from the replication cluster.
|
||||
|
||||
If the standby is not running, the standby record must be manually
|
||||
removed from the `repl_nodes` table with e.g.:
|
||||
If the standby is not running, the command can be executed on another
|
||||
node by providing the id of the node to be unregistered using
|
||||
the command line parameter `--node`, e.g. executing the following
|
||||
command on the master server will unregister the standby with
|
||||
id 3:
|
||||
|
||||
DELETE FROM repmgr_test.repl_nodes WHERE id = 3;
|
||||
|
||||
Adjust schema and node ID accordingly. A future `repmgr` release
|
||||
will make it possible to unregister failed standbys.
|
||||
repmgr standby unregister -f /etc/repmgr.conf --node=3
|
||||
|
||||
|
||||
Automatic failover with `repmgrd`
|
||||
|
||||
79
repmgr.c
79
repmgr.c
@@ -200,6 +200,7 @@ main(int argc, char **argv)
|
||||
{"pg_rewind", optional_argument, NULL, OPT_PG_REWIND},
|
||||
{"pwprompt", optional_argument, NULL, OPT_PWPROMPT},
|
||||
{"csv", no_argument, NULL, OPT_CSV},
|
||||
{"node", required_argument, NULL, OPT_NODE},
|
||||
{"version", no_argument, NULL, 'V'},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
@@ -494,6 +495,10 @@ main(int argc, char **argv)
|
||||
case OPT_CSV:
|
||||
runtime_options.csv_mode = true;
|
||||
break;
|
||||
case OPT_NODE:
|
||||
runtime_options.node = repmgr_atoi(optarg, "--node", &cli_errors, false);
|
||||
break;
|
||||
|
||||
default:
|
||||
unknown_option:
|
||||
{
|
||||
@@ -1394,15 +1399,17 @@ do_standby_unregister(void)
|
||||
{
|
||||
PGconn *conn;
|
||||
PGconn *master_conn;
|
||||
int ret;
|
||||
|
||||
int target_node_id;
|
||||
t_node_info node_info = T_NODE_INFO_INITIALIZER;
|
||||
|
||||
bool node_record_deleted;
|
||||
|
||||
log_info(_("connecting to standby database\n"));
|
||||
log_info(_("connecting to database\n"));
|
||||
conn = establish_db_connection(options.conninfo, true);
|
||||
|
||||
/* Check we are a standby */
|
||||
ret = is_standby(conn);
|
||||
/* ret = is_standby(conn);
|
||||
if (ret == 0 || ret == -1)
|
||||
{
|
||||
log_err(_(ret == 0 ? "this node should be a standby (%s)\n" :
|
||||
@@ -1410,7 +1417,7 @@ do_standby_unregister(void)
|
||||
|
||||
PQfinish(conn);
|
||||
exit(ERR_BAD_CONFIG);
|
||||
}
|
||||
}*/
|
||||
|
||||
/* Check if there is a schema for this cluster */
|
||||
if (check_cluster_schema(conn) == false)
|
||||
@@ -1431,16 +1438,29 @@ do_standby_unregister(void)
|
||||
exit(ERR_BAD_CONFIG);
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that standby and master are supported and compatible server
|
||||
* versions
|
||||
*/
|
||||
check_master_standby_version_match(conn, master_conn);
|
||||
if (runtime_options.node)
|
||||
target_node_id = runtime_options.node;
|
||||
else
|
||||
target_node_id = options.node;
|
||||
|
||||
/* Check node exists and is really a standby */
|
||||
|
||||
if (!get_node_record(master_conn, options.cluster_name, target_node_id, &node_info))
|
||||
{
|
||||
log_err(_("No record found for node %i\n"), target_node_id);
|
||||
exit(ERR_BAD_CONFIG);
|
||||
}
|
||||
|
||||
if (node_info.type != STANDBY)
|
||||
{
|
||||
log_err(_("Node %i is not a standby server\n"), target_node_id);
|
||||
exit(ERR_BAD_CONFIG);
|
||||
}
|
||||
|
||||
/* Now unregister the standby */
|
||||
log_info(_("unregistering the standby\n"));
|
||||
node_record_deleted = delete_node_record(master_conn,
|
||||
options.node,
|
||||
target_node_id,
|
||||
"standby unregister");
|
||||
|
||||
if (node_record_deleted == false)
|
||||
@@ -1453,7 +1473,7 @@ do_standby_unregister(void)
|
||||
/* Log the event */
|
||||
create_event_record(master_conn,
|
||||
&options,
|
||||
options.node,
|
||||
target_node_id,
|
||||
"standby_unregister",
|
||||
true,
|
||||
NULL);
|
||||
@@ -1463,7 +1483,7 @@ do_standby_unregister(void)
|
||||
|
||||
log_info(_("standby unregistration complete\n"));
|
||||
log_notice(_("standby node correctly unregistered for cluster %s with id %d (conninfo: %s)\n"),
|
||||
options.cluster_name, options.node, options.conninfo);
|
||||
options.cluster_name, target_node_id, options.conninfo);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4304,10 +4324,12 @@ do_witness_unregister(void)
|
||||
{
|
||||
PGconn *conn;
|
||||
PGconn *master_conn;
|
||||
int ret;
|
||||
|
||||
int target_node_id;
|
||||
t_node_info node_info = T_NODE_INFO_INITIALIZER;
|
||||
|
||||
bool node_record_deleted;
|
||||
t_node_info node_info = T_NODE_INFO_INITIALIZER;
|
||||
|
||||
|
||||
log_info(_("connecting to witness database\n"));
|
||||
conn = establish_db_connection(options.conninfo, true);
|
||||
@@ -4331,23 +4353,28 @@ do_witness_unregister(void)
|
||||
exit(ERR_BAD_CONFIG);
|
||||
}
|
||||
|
||||
if (runtime_options.node)
|
||||
target_node_id = runtime_options.node;
|
||||
else
|
||||
target_node_id = options.node;
|
||||
|
||||
/* Check node exists and is really a witness */
|
||||
|
||||
if (!get_node_record(master_conn, options.cluster_name, options.node, &node_info))
|
||||
if (!get_node_record(master_conn, options.cluster_name, target_node_id, &node_info))
|
||||
{
|
||||
log_err(_("No record found for node %i\n"), options.node);
|
||||
log_err(_("No record found for node %i\n"), target_node_id);
|
||||
exit(ERR_BAD_CONFIG);
|
||||
}
|
||||
|
||||
if (node_info.type != WITNESS)
|
||||
{
|
||||
log_err(_("Node %i is not a witness server\n"), options.node);
|
||||
log_err(_("Node %i is not a witness server\n"), target_node_id);
|
||||
exit(ERR_BAD_CONFIG);
|
||||
}
|
||||
|
||||
log_info(_("unregistering the witness server\n"));
|
||||
node_record_deleted = delete_node_record(master_conn,
|
||||
options.node,
|
||||
target_node_id,
|
||||
"witness unregister");
|
||||
|
||||
if (node_record_deleted == false)
|
||||
@@ -4360,7 +4387,7 @@ do_witness_unregister(void)
|
||||
/* Log the event */
|
||||
create_event_record(master_conn,
|
||||
&options,
|
||||
options.node,
|
||||
target_node_id,
|
||||
"witness_unregister",
|
||||
true,
|
||||
NULL);
|
||||
@@ -4370,7 +4397,7 @@ do_witness_unregister(void)
|
||||
|
||||
log_info(_("witness unregistration complete\n"));
|
||||
log_notice(_("witness node correctly unregistered for cluster %s with id %d (conninfo: %s)\n"),
|
||||
options.cluster_name, options.node, options.conninfo);
|
||||
options.cluster_name, target_node_id, options.conninfo);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -4842,6 +4869,7 @@ check_parameters_for_action(const int action)
|
||||
item_list_append(&cli_warnings, _("destination directory not required when executing MASTER REGISTER"));
|
||||
}
|
||||
break;
|
||||
|
||||
case STANDBY_REGISTER:
|
||||
|
||||
/*
|
||||
@@ -4858,6 +4886,7 @@ check_parameters_for_action(const int action)
|
||||
item_list_append(&cli_warnings, _("destination directory not required when executing STANDBY REGISTER"));
|
||||
}
|
||||
break;
|
||||
|
||||
case STANDBY_UNREGISTER:
|
||||
|
||||
/*
|
||||
@@ -4874,6 +4903,7 @@ check_parameters_for_action(const int action)
|
||||
item_list_append(&cli_warnings, _("destination directory not required when executing STANDBY UNREGISTER"));
|
||||
}
|
||||
break;
|
||||
|
||||
case STANDBY_PROMOTE:
|
||||
|
||||
/*
|
||||
@@ -5015,6 +5045,14 @@ check_parameters_for_action(const int action)
|
||||
}
|
||||
}
|
||||
|
||||
if (action != WITNESS_UNREGISTER)
|
||||
{
|
||||
if (runtime_options.node)
|
||||
{
|
||||
item_list_append(&cli_warnings, _("--node can only be supplied when executing WITNESS UNREGISTER"));
|
||||
}
|
||||
}
|
||||
|
||||
/* Warn about parameters which apply to CLUSTER SHOW only */
|
||||
if (action != CLUSTER_SHOW)
|
||||
{
|
||||
@@ -5024,6 +5062,7 @@ check_parameters_for_action(const int action)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
6
repmgr.h
6
repmgr.h
@@ -55,7 +55,7 @@
|
||||
#define OPT_PG_REWIND 6
|
||||
#define OPT_PWPROMPT 7
|
||||
#define OPT_CSV 8
|
||||
|
||||
#define OPT_NODE 9
|
||||
|
||||
|
||||
/* Run time options type */
|
||||
@@ -94,13 +94,15 @@ typedef struct
|
||||
char config_archive_dir[MAXLEN];
|
||||
/* parameter used by CLUSTER CLEANUP */
|
||||
int keep_history;
|
||||
/* paramater used by {STANDBY|WITNESS} UNREGISTER */
|
||||
int node;
|
||||
|
||||
char pg_bindir[MAXLEN];
|
||||
|
||||
char recovery_min_apply_delay[MAXLEN];
|
||||
} t_runtime_options;
|
||||
|
||||
#define T_RUNTIME_OPTIONS_INITIALIZER { "", "", "", "", "", "", "", DEFAULT_WAL_KEEP_SEGMENTS, false, false, false, false, false, false, false, false, false, false, "", "", "", "", "fast", "", 0, "", ""}
|
||||
#define T_RUNTIME_OPTIONS_INITIALIZER { "", "", "", "", "", "", "", DEFAULT_WAL_KEEP_SEGMENTS, false, false, false, false, false, false, false, false, false, false, "", "", "", "", "fast", "", 0, 0, "", ""}
|
||||
|
||||
struct BackupLabel
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user