diff --git a/HISTORY b/HISTORY
index 82caa430..16de911f 100644
--- a/HISTORY
+++ b/HISTORY
@@ -11,11 +11,12 @@
repmgr: add -q/--quiet option to suppress non-error output; GitHub #468 (Ian)
repmgr: "node status" returns non-zero value if an issue encountered (Ian)
repmgr: enable "recovery_min_apply_delay" to be 0; GitHub #448 (Ian)
- repmgr: "cluster cleanup" - add missing help options; GitHub #461/#462 (gclough)
- repmgr: ensure witness node follows new primary after switchover;
- GitHub #453 (Ian)
- repmgr: fix witness node handling in "node check"/"node status";
- GitHub #451 (Ian)
+ repmgr: "cluster cleanup" - add missing help options; GitHub #461/#462 (gclough)
+ repmgr: ensure witness node follows new primary after switchover;
+ GitHub #453 (Ian)
+ repmgr: fix witness node handling in "node check"/"node status";
+ GitHub #451 (Ian)
+ repmgr: enable "witness unregister" to be run on any node; GitHub #472 (Ian)
repmgrd: create a PID file by default; GitHub #457 (Ian)
repmgrd: daemonize process by default; GitHub #458 (Ian)
diff --git a/doc/appendix-release-notes.sgml b/doc/appendix-release-notes.sgml
index 29474f78..8345a517 100644
--- a/doc/appendix-release-notes.sgml
+++ b/doc/appendix-release-notes.sgml
@@ -98,6 +98,14 @@
+
+
+ repmgr witness unregister
+ can be run on any node, by providing the ID of the witness node with .
+ (GitHub #472).
+
+
+
diff --git a/doc/repmgr-primary-register.sgml b/doc/repmgr-primary-register.sgml
index 1a926180..553c61c3 100644
--- a/doc/repmgr-primary-register.sgml
+++ b/doc/repmgr-primary-register.sgml
@@ -17,7 +17,7 @@
Descriptionrepmgr primary register registers a primary node in a
- streaming replication cluster, and configures it for use with repmgr, including
+ streaming replication cluster, and configures it for use with &repmgr;, including
installing the &repmgr; extension. This command needs to be executed before any
standby nodes are registered.
diff --git a/doc/repmgr-witness-unregister.sgml b/doc/repmgr-witness-unregister.sgml
index 00fb3c59..cbe6ebdc 100644
--- a/doc/repmgr-witness-unregister.sgml
+++ b/doc/repmgr-witness-unregister.sgml
@@ -20,7 +20,10 @@
The node does not have to be running to be unregistered, however if this is the
- case then connection information for the primary server must be provided.
+ case then either provide connection information for the primary server, or
+ execute repmgr witness unregister on a running node and
+ provide the parameter with the node ID of the
+ witness server.
Execute with the --dry-run option to check what would happen
@@ -36,17 +39,17 @@
INFO: connecting to witness node "node3" (ID: 3)
INFO: unregistering witness node 3
INFO: witness unregistration complete
- DETAIL: witness node with id 3 (conninfo: host=node3 dbname=repmgr user=repmgr port=5499) successfully unregistered
+ DETAIL: witness node with UD 3 successfully unregistered
Unregistering a non-running witness node:
$ repmgr -f /etc/repmgr.conf witness unregister -h node1 -p 5501 -F
- INFO: connecting to witness node "node3" (ID: 3)
- NOTICE: unable to connect to witness node "node3" (ID: 3), removing node record on cluster primary only
+ INFO: connecting to node "node3" (ID: 3)
+ NOTICE: unable to connect to node "node3" (ID: 3), removing node record on cluster primary only
INFO: unregistering witness node 3
INFO: witness unregistration complete
- DETAIL: witness node with id 3 (conninfo: host=node3 dbname=repmgr user=repmgr port=5499) successfully unregistered
+ DETAIL: witness node with id ID 3 successfully unregistered
@@ -62,6 +65,32 @@
+
+
+ Options
+
+
+
+
+
+
+ Check prerequisites but don't actually unregister the witness.
+
+
+
+
+
+
+
+
+ Unregister witness server with the specified node ID.
+
+
+
+
+
+
+
Event notifications
diff --git a/repmgr-action-witness.c b/repmgr-action-witness.c
index de7a5da9..9def498f 100644
--- a/repmgr-action-witness.c
+++ b/repmgr-action-witness.c
@@ -310,55 +310,59 @@ do_witness_register(void)
void
do_witness_unregister(void)
{
- PGconn *witness_conn = NULL;
+ PGconn *local_conn = NULL;
PGconn *primary_conn = NULL;
t_node_info node_record = T_NODE_INFO_INITIALIZER;
RecordStatus record_status = RECORD_NOT_FOUND;
bool node_record_deleted = false;
- bool witness_available = true;
+ bool local_node_available = true;
+ int witness_node_id = UNKNOWN_NODE_ID;
- log_info(_("connecting to witness node \"%s\" (ID: %i)"),
+ if (runtime_options.node_id != UNKNOWN_NODE_ID)
+ {
+ /* user has specified the witness node id */
+ witness_node_id = runtime_options.node_id;
+ }
+ else
+ {
+ /* assume witness node is local node */
+ witness_node_id = config_file_options.node_id;
+ }
+
+ log_info(_("connecting to node \"%s\" (ID: %i)"),
config_file_options.node_name,
config_file_options.node_id);
- witness_conn = establish_db_connection_quiet(config_file_options.conninfo);
+ local_conn = establish_db_connection_quiet(config_file_options.conninfo);
- if (PQstatus(witness_conn) != CONNECTION_OK)
+ if (PQstatus(local_conn) != CONNECTION_OK)
{
if (!runtime_options.force)
{
- log_error(_("unable to connect to witness node \"%s\" (ID: %i)"),
+ log_error(_("unable to connect to node \"%s\" (ID: %i)"),
config_file_options.node_name,
config_file_options.node_id);
- log_detail("%s", PQerrorMessage(witness_conn));
- log_hint(_("provide -F/--force to remove the witness record if the server is not running"));
+ log_detail("%s", PQerrorMessage(local_conn));
exit(ERR_BAD_CONFIG);
}
log_notice(_("unable to connect to witness node \"%s\" (ID: %i), removing node record on cluster primary only"),
config_file_options.node_name,
config_file_options.node_id);
- witness_available = false;
+ local_node_available = false;
}
- if (witness_available == true)
+ if (local_node_available == true)
{
- primary_conn = get_primary_connection_quiet(witness_conn, NULL, NULL);
+ primary_conn = get_primary_connection_quiet(local_conn, NULL, NULL);
}
else
{
/*
- * Extract the repmgr user and database names from the conninfo string
- * provided in repmgr.conf
+ * Assume user has provided connection details for the primary server
*/
- get_conninfo_value(config_file_options.conninfo, "user", repmgr_user);
- get_conninfo_value(config_file_options.conninfo, "dbname", repmgr_db);
-
- param_set_ine(&source_conninfo, "user", repmgr_user);
- param_set_ine(&source_conninfo, "dbname", repmgr_db);
primary_conn = establish_db_connection_by_params(&source_conninfo, false);
-
}
if (PQstatus(primary_conn) != CONNECTION_OK)
@@ -366,26 +370,26 @@ do_witness_unregister(void)
log_error(_("unable to connect to primary"));
log_detail("%s", PQerrorMessage(primary_conn));
- if (witness_available == true)
+ if (local_node_available == true)
{
- PQfinish(witness_conn);
+ PQfinish(local_conn);
}
- else
+ else if (runtime_options.connection_param_provided == false)
{
- log_hint(_("provide connection details to primary server"));
+ log_hint(_("provide connection details for the primary server"));
}
exit(ERR_BAD_CONFIG);
}
/* Check node exists and is really a witness */
- record_status = get_node_record(primary_conn, config_file_options.node_id, &node_record);
+ record_status = get_node_record(primary_conn, witness_node_id, &node_record);
if (record_status != RECORD_FOUND)
{
- log_error(_("no record found for node %i"), config_file_options.node_id);
+ log_error(_("no record found for node %i"), witness_node_id);
- if (witness_available == true)
- PQfinish(witness_conn);
+ if (local_node_available == true)
+ PQfinish(local_conn);
PQfinish(primary_conn);
exit(ERR_BAD_CONFIG);
@@ -393,11 +397,17 @@ do_witness_unregister(void)
if (node_record.type != WITNESS)
{
+ /*
+ * The node (either explicitly provided with --node-id, or the local node)
+ * is not a witness.
+ *
+ * TODO: scan node list and print hint about identity of known witness servers.
+ */
log_error(_("node %i is not a witness node"), config_file_options.node_id);
log_detail(_("node %i is a %s node"), config_file_options.node_id, get_node_type_string(node_record.type));
- if (witness_available == true)
- PQfinish(witness_conn);
+ if (local_node_available == true)
+ PQfinish(local_conn);
PQfinish(primary_conn);
exit(ERR_BAD_CONFIG);
@@ -406,49 +416,43 @@ do_witness_unregister(void)
if (runtime_options.dry_run == true)
{
log_info(_("prerequisites for unregistering the witness node are met"));
- if (witness_available == true)
- PQfinish(witness_conn);
+ if (local_node_available == true)
+ PQfinish(local_conn);
PQfinish(primary_conn);
exit(SUCCESS);
}
- log_info(_("unregistering witness node %i"), config_file_options.node_id);
+ log_info(_("unregistering witness node %i"), witness_node_id);
node_record_deleted = delete_node_record(primary_conn,
- config_file_options.node_id);
+ witness_node_id);
if (node_record_deleted == false)
{
PQfinish(primary_conn);
- PQfinish(witness_conn);
- exit(ERR_BAD_CONFIG);
- }
- /* sync records from primary */
- if (witness_available == true && witness_copy_node_records(primary_conn, witness_conn) == false)
- {
- log_error(_("unable to copy repmgr node records from primary"));
- PQfinish(primary_conn);
- PQfinish(witness_conn);
+ if (local_node_available == true)
+ PQfinish(local_conn);
+ PQfinish(local_conn);
exit(ERR_BAD_CONFIG);
}
/* Log the event */
create_event_record(primary_conn,
&config_file_options,
- config_file_options.node_id,
+ witness_node_id,
"witness_unregister",
true,
NULL);
PQfinish(primary_conn);
- if (witness_available == true)
- PQfinish(witness_conn);
+ if (local_node_available == true)
+ PQfinish(local_conn);
log_info(_("witness unregistration complete"));
- log_detail(_("witness node with id %i (conninfo: %s) successfully unregistered"),
- config_file_options.node_id, config_file_options.conninfo);
+ log_detail(_("witness node with ID %i successfully unregistered"),
+ witness_node_id);
return;
}
@@ -468,16 +472,19 @@ void do_witness_help(void)
puts("");
printf(_(" Requires provision of connection information for the primary\n"));
puts("");
- printf(_(" --dry-run check prerequisites but don't make any changes\n"));
- printf(_(" -F, --force overwrite an existing node record\n"));
+ printf(_(" --dry-run check prerequisites but don't make any changes\n"));
+ printf(_(" -F, --force overwrite an existing node record\n"));
puts("");
printf(_("WITNESS UNREGISTER\n"));
puts("");
printf(_(" \"witness register\" unregisters a witness node.\n"));
puts("");
- printf(_(" --dry-run check prerequisites but don't make any changes\n"));
- printf(_(" -F, --force unregister when witness node not running\n"));
+ printf(_(" --dry-run check prerequisites but don't make any changes\n"));
+ printf(_(" -F, --force unregister when witness node not running\n"));
+ printf(_(" --node-id node ID of the witness node (provide if executing on\n"));
+ printf(_(" another node)\n"));
+
puts("");
return;
diff --git a/repmgr-client.c b/repmgr-client.c
index 8b620dac..8c900a2c 100644
--- a/repmgr-client.c
+++ b/repmgr-client.c
@@ -1519,6 +1519,7 @@ check_cli_parameters(const int action)
{
case PRIMARY_UNREGISTER:
case STANDBY_UNREGISTER:
+ case WITNESS_UNREGISTER:
case CLUSTER_EVENT:
case CLUSTER_MATRIX:
case CLUSTER_CROSSCHECK: