mirror of
https://github.com/EnterpriseDB/repmgr.git
synced 2026-03-22 22:56:29 +00:00
Add "repmgr bdr register"
This commit is contained in:
@@ -26,7 +26,8 @@ include Makefile.global
|
|||||||
|
|
||||||
$(info Building against PostgreSQL $(MAJORVERSION))
|
$(info Building against PostgreSQL $(MAJORVERSION))
|
||||||
|
|
||||||
REPMGR_CLIENT_OBJS = repmgr-client.o repmgr-action-primary.o repmgr-action-standby.o repmgr-action-cluster.o \
|
REPMGR_CLIENT_OBJS = repmgr-client.o \
|
||||||
|
repmgr-action-primary.o repmgr-action-standby.o repmgr-action-bdr.o repmgr-action-cluster.o \
|
||||||
config.o log.o strutil.o dbutils.o dirutil.o compat.o controldata.o
|
config.o log.o strutil.o dbutils.o dirutil.o compat.o controldata.o
|
||||||
REPMGRD_OBJS = repmgrd.o config.o log.o dbutils.o strutil.o
|
REPMGRD_OBJS = repmgrd.o config.o log.o dbutils.o strutil.o
|
||||||
|
|
||||||
@@ -52,9 +53,10 @@ maintainer-clean: additional-maintainer-clean
|
|||||||
|
|
||||||
additional-clean:
|
additional-clean:
|
||||||
rm -f repmgr-client.o
|
rm -f repmgr-client.o
|
||||||
rm -f repmgr-action-cluster.o
|
|
||||||
rm -f repmgr-action-primary.o
|
rm -f repmgr-action-primary.o
|
||||||
rm -f repmgr-action-standby.o
|
rm -f repmgr-action-standby.o
|
||||||
|
rm -f repmgr-action-bdr.o
|
||||||
|
rm -f repmgr-action-cluster.o
|
||||||
rm -f repmgrd.o
|
rm -f repmgrd.o
|
||||||
rm -f compat.o
|
rm -f compat.o
|
||||||
rm -f config.o
|
rm -f config.o
|
||||||
|
|||||||
66
README.md
66
README.md
@@ -37,6 +37,8 @@ Currently available:
|
|||||||
repmgr standby promote
|
repmgr standby promote
|
||||||
repmgr standby follow
|
repmgr standby follow
|
||||||
|
|
||||||
|
repmgr bdr register
|
||||||
|
|
||||||
repmgr cluster event [--all] [--node-id] [--node-name] [--event] [--event-matching]
|
repmgr cluster event [--all] [--node-id] [--node-name] [--event] [--event-matching]
|
||||||
|
|
||||||
|
|
||||||
@@ -63,3 +65,67 @@ and vice-versa, e.g. to avoid hard-coding things like a node's
|
|||||||
upstream ID which might change.
|
upstream ID which might change.
|
||||||
|
|
||||||
TODO: possibly add a config file conversion script/function.
|
TODO: possibly add a config file conversion script/function.
|
||||||
|
|
||||||
|
Generating event notifications with repmgr/repmgrd
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
Each time `repmgr` or `repmgrd` perform a significant event, a record
|
||||||
|
of that event is written into the `repl_events` table together with
|
||||||
|
a timestamp, an indication of failure or success, and further details
|
||||||
|
if appropriate. This is useful for gaining an overview of events
|
||||||
|
affecting the replication cluster. However note that this table has
|
||||||
|
advisory character and should be used in combination with the `repmgr`
|
||||||
|
and PostgreSQL logs to obtain details of any events.
|
||||||
|
|
||||||
|
Example output after a master was registered and a standby cloned
|
||||||
|
and registered:
|
||||||
|
|
||||||
|
repmgr=# SELECT * from repmgr_test.repl_events ;
|
||||||
|
node_id | event | successful | event_timestamp | details
|
||||||
|
---------+------------------+------------+-------------------------------+-------------------------------------------------------------------------------------
|
||||||
|
1 | master_register | t | 2016-01-08 15:04:39.781733+09 |
|
||||||
|
2 | standby_clone | t | 2016-01-08 15:04:49.530001+09 | Cloned from host 'repmgr_node1', port 5432; backup method: pg_basebackup; --force: N
|
||||||
|
2 | standby_register | t | 2016-01-08 15:04:50.621292+09 |
|
||||||
|
(3 rows)
|
||||||
|
|
||||||
|
Additionally, event notifications can be passed to a user-defined program
|
||||||
|
or script which can take further action, e.g. send email notifications.
|
||||||
|
This is done by setting the `event_notification_command` parameter in
|
||||||
|
`repmgr.conf`.
|
||||||
|
|
||||||
|
This parameter accepts the following format placeholders:
|
||||||
|
|
||||||
|
%n - node ID
|
||||||
|
%e - event type
|
||||||
|
%s - success (1 or 0)
|
||||||
|
%t - timestamp
|
||||||
|
%d - details
|
||||||
|
|
||||||
|
The values provided for "%t" and "%d" will probably contain spaces,
|
||||||
|
so should be quoted in the provided command configuration, e.g.:
|
||||||
|
|
||||||
|
event_notification_command='/path/to/some/script %n %e %s "%t" "%d"'
|
||||||
|
|
||||||
|
Additionally the following format placeholders are available for the even
|
||||||
|
type `bdr_failover`:
|
||||||
|
|
||||||
|
%c - conninfo string of the next available node
|
||||||
|
%a - name of the next available node
|
||||||
|
|
||||||
|
These should always be quoted.
|
||||||
|
|
||||||
|
By default, all notification type will be passed to the designated script;
|
||||||
|
the notification types can be filtered to explicitly named ones:
|
||||||
|
|
||||||
|
event_notifications=master_register,standby_register
|
||||||
|
|
||||||
|
The following event types are available:
|
||||||
|
|
||||||
|
...
|
||||||
|
* `bdr_failover`
|
||||||
|
* `bdr_register`
|
||||||
|
* `bdr_unregister`
|
||||||
|
|
||||||
|
Note that under some circumstances (e.g. no replication cluster master could
|
||||||
|
be located), it will not be possible to write an entry into the `repl_events`
|
||||||
|
table, in which case `event_notification_command` can serve as a fallback.
|
||||||
|
|||||||
111
dbutils.c
111
dbutils.c
@@ -47,6 +47,33 @@ parse_lsn(const char *str)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wrap query with appropriate DDL function, if required.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
wrap_ddl_query(PQExpBufferData *query_buf, int replication_type, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list arglist;
|
||||||
|
char buf[MAXLEN];
|
||||||
|
|
||||||
|
if (replication_type == REPLICATION_TYPE_BDR)
|
||||||
|
{
|
||||||
|
appendPQExpBuffer(query_buf, "SELECT bdr.bdr_replicate_ddl_command($repmgr$");
|
||||||
|
}
|
||||||
|
|
||||||
|
va_start(arglist, fmt);
|
||||||
|
vsnprintf(buf, MAXLEN, fmt, arglist);
|
||||||
|
va_end(arglist);
|
||||||
|
|
||||||
|
appendPQExpBuffer(query_buf, "%s", buf);
|
||||||
|
|
||||||
|
if (replication_type == REPLICATION_TYPE_BDR)
|
||||||
|
{
|
||||||
|
appendPQExpBuffer(query_buf, "$repmgr$)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ==================== */
|
/* ==================== */
|
||||||
/* Connection functions */
|
/* Connection functions */
|
||||||
/* ==================== */
|
/* ==================== */
|
||||||
@@ -1517,6 +1544,7 @@ update_node_record(PGconn *conn, char *repmgr_action, t_node_info *node_info)
|
|||||||
return _create_update_node_record(conn, "update", node_info);
|
return _create_update_node_record(conn, "update", node_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
_create_update_node_record(PGconn *conn, char *action, t_node_info *node_info)
|
_create_update_node_record(PGconn *conn, char *action, t_node_info *node_info)
|
||||||
{
|
{
|
||||||
@@ -2793,7 +2821,7 @@ is_bdr_repmgr(PGconn *conn)
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
is_table_in_bdr_replication_set(PGconn *conn, char *tablename, char *set)
|
is_table_in_bdr_replication_set(PGconn *conn, const char *tablename, const char *set)
|
||||||
{
|
{
|
||||||
PQExpBufferData query;
|
PQExpBufferData query;
|
||||||
PGresult *res;
|
PGresult *res;
|
||||||
@@ -2829,10 +2857,10 @@ is_table_in_bdr_replication_set(PGconn *conn, char *tablename, char *set)
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
add_table_to_bdr_replication_set(PGconn *conn, char *tablename, char *set)
|
add_table_to_bdr_replication_set(PGconn *conn, const char *tablename, const char *set)
|
||||||
{
|
{
|
||||||
PQExpBufferData query;
|
PQExpBufferData query;
|
||||||
PGresult *res;
|
PGresult *res;
|
||||||
|
|
||||||
initPQExpBuffer(&query);
|
initPQExpBuffer(&query);
|
||||||
|
|
||||||
@@ -2861,3 +2889,80 @@ add_table_to_bdr_replication_set(PGconn *conn, char *tablename, char *set)
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
bdr_node_exists(PGconn *conn, const char *node_name)
|
||||||
|
{
|
||||||
|
PQExpBufferData query;
|
||||||
|
PGresult *res;
|
||||||
|
bool node_exists;
|
||||||
|
|
||||||
|
initPQExpBuffer(&query);
|
||||||
|
|
||||||
|
appendPQExpBuffer(
|
||||||
|
&query,
|
||||||
|
"SELECT COUNT(*)"
|
||||||
|
" FROM bdr.bdr_nodes"
|
||||||
|
" WHERE node_name = '%s'",
|
||||||
|
node_name);
|
||||||
|
|
||||||
|
res = PQexec(conn, query.data);
|
||||||
|
termPQExpBuffer(&query);
|
||||||
|
|
||||||
|
if (!res || PQresultStatus(res) != PGRES_TUPLES_OK)
|
||||||
|
{
|
||||||
|
node_exists = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
node_exists = atoi(PQgetvalue(res, 0, 0)) == 1 ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
PQclear(res);
|
||||||
|
|
||||||
|
return node_exists;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
add_extension_tables_to_bdr_replication_set(PGconn *conn)
|
||||||
|
{
|
||||||
|
PQExpBufferData query;
|
||||||
|
PGresult *res;
|
||||||
|
|
||||||
|
initPQExpBuffer(&query);
|
||||||
|
|
||||||
|
appendPQExpBuffer(
|
||||||
|
&query,
|
||||||
|
" SELECT c.relname "
|
||||||
|
" FROM pg_class c "
|
||||||
|
"INNER JOIN pg_namespace n "
|
||||||
|
" ON c.relnamespace = n.oid "
|
||||||
|
" WHERE n.nspname = 'repmgr' "
|
||||||
|
" AND c.relkind = 'r' ");
|
||||||
|
|
||||||
|
res = PQexec(conn, query.data);
|
||||||
|
termPQExpBuffer(&query);
|
||||||
|
|
||||||
|
if (!res || PQresultStatus(res) != PGRES_TUPLES_OK)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < PQntuples(res); i++)
|
||||||
|
{
|
||||||
|
add_table_to_bdr_replication_set(
|
||||||
|
conn,
|
||||||
|
PQgetvalue(res, i, 0),
|
||||||
|
"repmgr");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PQclear(res);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|||||||
@@ -148,6 +148,8 @@ typedef struct s_connection_user
|
|||||||
|
|
||||||
XLogRecPtr parse_lsn(const char *str);
|
XLogRecPtr parse_lsn(const char *str);
|
||||||
|
|
||||||
|
extern void wrap_ddl_query(PQExpBufferData *query_buf, int replication_type, const char *fmt, ...)
|
||||||
|
__attribute__((format(PG_PRINTF_ATTRIBUTE, 3, 4)));
|
||||||
|
|
||||||
/* connection functions */
|
/* connection functions */
|
||||||
PGconn *establish_db_connection(const char *conninfo,
|
PGconn *establish_db_connection(const char *conninfo,
|
||||||
@@ -268,8 +270,10 @@ XLogRecPtr get_last_wal_receive_location(PGconn *conn);
|
|||||||
|
|
||||||
bool is_bdr_db(PGconn *conn);
|
bool is_bdr_db(PGconn *conn);
|
||||||
bool is_bdr_repmgr(PGconn *conn);
|
bool is_bdr_repmgr(PGconn *conn);
|
||||||
bool is_table_in_bdr_replication_set(PGconn *conn, char *tablename, char *set);
|
bool is_table_in_bdr_replication_set(PGconn *conn, const char *tablename, const char *set);
|
||||||
bool add_table_to_bdr_replication_set(PGconn *conn, char *tablename, char *set);
|
bool add_table_to_bdr_replication_set(PGconn *conn, const char *tablename, const char *set);
|
||||||
|
bool bdr_node_exists(PGconn *conn, const char *node_name);
|
||||||
|
void add_extension_tables_to_bdr_replication_set(PGconn *conn);
|
||||||
|
|
||||||
#endif /* dbutils.h */
|
#endif /* dbutils.h */
|
||||||
|
|
||||||
|
|||||||
221
repmgr-action-bdr.c
Normal file
221
repmgr-action-bdr.c
Normal file
@@ -0,0 +1,221 @@
|
|||||||
|
/*
|
||||||
|
* repmgr-action-standby.c
|
||||||
|
*
|
||||||
|
* Implements BDR-related actions for the repmgr command line utility
|
||||||
|
*
|
||||||
|
* Copyright (c) 2ndQuadrant, 2010-2017
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "repmgr.h"
|
||||||
|
|
||||||
|
#include "repmgr-client-global.h"
|
||||||
|
#include "repmgr-action-bdr.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* do_bdr_register()
|
||||||
|
*
|
||||||
|
* As each BDR node is its own master, registering a BDR node
|
||||||
|
* will create the repmgr metadata schema if necessary.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
do_bdr_register(void)
|
||||||
|
{
|
||||||
|
PGconn *conn = NULL;
|
||||||
|
ExtensionStatus extension_status;
|
||||||
|
t_node_info node_info = T_NODE_INFO_INITIALIZER;
|
||||||
|
RecordStatus record_status;
|
||||||
|
PQExpBufferData event_details;
|
||||||
|
bool success = true;
|
||||||
|
|
||||||
|
/* sanity-check configuration for BDR-compatability */
|
||||||
|
if (config_file_options.replication_type != REPLICATION_TYPE_BDR)
|
||||||
|
{
|
||||||
|
log_error(_("cannot run BDR REGISTER on a non-BDR node"));
|
||||||
|
exit(ERR_BAD_CONFIG);
|
||||||
|
}
|
||||||
|
|
||||||
|
conn = establish_db_connection(config_file_options.conninfo, true);
|
||||||
|
|
||||||
|
if (!is_bdr_db(conn))
|
||||||
|
{
|
||||||
|
/* TODO: name database */
|
||||||
|
log_error(_("database is not BDR-enabled"));
|
||||||
|
log_hint(_("when using repmgr with BDR, the repmgr schema must be stored in the BDR database"));
|
||||||
|
exit(ERR_BAD_CONFIG);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check whether repmgr extension exists, and that any other nodes are BDR */
|
||||||
|
extension_status = get_repmgr_extension_status(conn);
|
||||||
|
|
||||||
|
if (extension_status == REPMGR_UNKNOWN)
|
||||||
|
{
|
||||||
|
log_error(_("unable to determine status of \"repmgr\" extension"));
|
||||||
|
PQfinish(conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (extension_status == REPMGR_UNAVAILABLE)
|
||||||
|
{
|
||||||
|
log_error(_("\"repmgr\" extension is not available"));
|
||||||
|
PQfinish(conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extension_status == REPMGR_INSTALLED)
|
||||||
|
{
|
||||||
|
if (!is_bdr_repmgr(conn))
|
||||||
|
{
|
||||||
|
log_error(_("repmgr metadatabase contains records for non-BDR nodes"));
|
||||||
|
exit(ERR_BAD_CONFIG);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//log_info(_("bdr register: creating database objects inside the %s schema"),
|
||||||
|
// get_repmgr_schema());
|
||||||
|
|
||||||
|
begin_transaction(conn);
|
||||||
|
|
||||||
|
if (!create_repmgr_extension(conn))
|
||||||
|
{
|
||||||
|
log_error(_("unable to create repmgr extension - see preceding error message(s); aborting"));
|
||||||
|
rollback_transaction(conn);
|
||||||
|
PQfinish(conn);
|
||||||
|
exit(ERR_BAD_CONFIG);
|
||||||
|
}
|
||||||
|
|
||||||
|
commit_transaction(conn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check for a matching BDR node */
|
||||||
|
{
|
||||||
|
bool node_exists = bdr_node_exists(conn, config_file_options.node_name);
|
||||||
|
|
||||||
|
if (node_exists == false)
|
||||||
|
{
|
||||||
|
log_error(_("no BDR node with node_name '%s' found"), config_file_options.node_name);
|
||||||
|
log_hint(_("'node_name' in repmgr.conf must match 'node_name' in bdr.bdr_nodes\n"));
|
||||||
|
PQfinish(conn);
|
||||||
|
exit(ERR_BAD_CONFIG);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
initPQExpBuffer(&event_details);
|
||||||
|
|
||||||
|
begin_transaction(conn);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* we'll check if a record exists (even if the schema was just created),
|
||||||
|
* as there's a faint chance of a race condition
|
||||||
|
*/
|
||||||
|
|
||||||
|
record_status = get_node_record(conn, config_file_options.node_id, &node_info);
|
||||||
|
|
||||||
|
/* Update internal node record */
|
||||||
|
|
||||||
|
node_info.type = BDR;
|
||||||
|
node_info.node_id = config_file_options.node_id;
|
||||||
|
node_info.upstream_node_id = NO_UPSTREAM_NODE;
|
||||||
|
node_info.active = true;
|
||||||
|
node_info.priority = config_file_options.priority;
|
||||||
|
|
||||||
|
strncpy(node_info.node_name, config_file_options.node_name, MAXLEN);
|
||||||
|
strncpy(node_info.location, config_file_options.location, MAXLEN);
|
||||||
|
strncpy(node_info.conninfo, config_file_options.conninfo, MAXLEN);
|
||||||
|
|
||||||
|
if (record_status == RECORD_FOUND)
|
||||||
|
{
|
||||||
|
bool node_updated;
|
||||||
|
/*
|
||||||
|
* At this point we will have established there are no non-BDR records,
|
||||||
|
* so no need to verify the node type
|
||||||
|
*/
|
||||||
|
if (!runtime_options.force)
|
||||||
|
{
|
||||||
|
log_error(_("this node is already registered"));
|
||||||
|
log_hint(_("use -F/--force to overwrite the existing node record"));
|
||||||
|
rollback_transaction(conn);
|
||||||
|
PQfinish(conn);
|
||||||
|
exit(ERR_BAD_CONFIG);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* don't permit changing the node name - this must match the
|
||||||
|
* BDR node name set when the node was registered.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (strncmp(node_info.node_name, config_file_options.node_name, MAXLEN) != 0)
|
||||||
|
{
|
||||||
|
log_error(_("a record for node %i is already registered with node_name '%s'"),
|
||||||
|
config_file_options.node_id, node_info.node_name);
|
||||||
|
log_hint(_("node_name configured in repmgr.conf is '%s'"), config_file_options.node_name);
|
||||||
|
|
||||||
|
rollback_transaction(conn);
|
||||||
|
PQfinish(conn);
|
||||||
|
exit(ERR_BAD_CONFIG);
|
||||||
|
}
|
||||||
|
|
||||||
|
node_updated = update_node_record(conn, "bdr register", &node_info);
|
||||||
|
|
||||||
|
if (node_updated == true)
|
||||||
|
{
|
||||||
|
appendPQExpBuffer(&event_details, _("node record updated for node '%s' (%i)"),
|
||||||
|
config_file_options.node_name, config_file_options.node_id);
|
||||||
|
log_verbose(LOG_NOTICE, "%s\n", event_details.data);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* create new node record */
|
||||||
|
bool node_created = create_node_record(conn, "bdr register", &node_info);
|
||||||
|
|
||||||
|
if (node_created == true)
|
||||||
|
{
|
||||||
|
appendPQExpBuffer(&event_details,
|
||||||
|
_("node record created for node '%s' (ID: %i)"),
|
||||||
|
config_file_options.node_name, config_file_options.node_id);
|
||||||
|
log_notice("%s", event_details.data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success == false)
|
||||||
|
{
|
||||||
|
rollback_transaction(conn);
|
||||||
|
PQfinish(conn);
|
||||||
|
exit(ERR_DB_QUERY);
|
||||||
|
}
|
||||||
|
|
||||||
|
commit_transaction(conn);
|
||||||
|
/* Log the event */
|
||||||
|
create_event_notification(
|
||||||
|
conn,
|
||||||
|
&config_file_options,
|
||||||
|
config_file_options.node_id,
|
||||||
|
"bdr_register",
|
||||||
|
true,
|
||||||
|
event_details.data);
|
||||||
|
|
||||||
|
termPQExpBuffer(&event_details);
|
||||||
|
|
||||||
|
PQfinish(conn);
|
||||||
|
|
||||||
|
log_notice(_("BDR node %i registered (conninfo: %s)"),
|
||||||
|
config_file_options.node_id, config_file_options.conninfo);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
do_bdr_unregister(void)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
13
repmgr-action-bdr.h
Normal file
13
repmgr-action-bdr.h
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
/*
|
||||||
|
* repmgr-action-bdr.h
|
||||||
|
* Copyright (c) 2ndQuadrant, 2010-2017
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _REPMGR_ACTION_BDR_H_
|
||||||
|
#define _REPMGR_ACTION_BDR_H_
|
||||||
|
|
||||||
|
extern void do_bdr_register(void);
|
||||||
|
extern void do_bdr_unregister(void);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _REPMGR_ACTION_BDR_H_ */
|
||||||
@@ -33,4 +33,4 @@ typedef struct
|
|||||||
#define T_CONFIGFILE_LIST_INITIALIZER { 0, 0, NULL }
|
#define T_CONFIGFILE_LIST_INITIALIZER { 0, 0, NULL }
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif /* _REPMGR_ACTION_STANDBY_H_ */
|
||||||
|
|||||||
@@ -28,6 +28,8 @@
|
|||||||
#include "repmgr-client-global.h"
|
#include "repmgr-client-global.h"
|
||||||
#include "repmgr-action-primary.h"
|
#include "repmgr-action-primary.h"
|
||||||
#include "repmgr-action-standby.h"
|
#include "repmgr-action-standby.h"
|
||||||
|
#include "repmgr-action-bdr.h"
|
||||||
|
|
||||||
#include "repmgr-action-cluster.h"
|
#include "repmgr-action-cluster.h"
|
||||||
|
|
||||||
#include <storage/fd.h> /* for PG_TEMP_FILE_PREFIX */
|
#include <storage/fd.h> /* for PG_TEMP_FILE_PREFIX */
|
||||||
@@ -579,6 +581,7 @@ main(int argc, char **argv)
|
|||||||
else if (strcasecmp(repmgr_action, "UNREGISTER") == 0)
|
else if (strcasecmp(repmgr_action, "UNREGISTER") == 0)
|
||||||
action = PRIMARY_UNREGISTER;
|
action = PRIMARY_UNREGISTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (strcasecmp(repmgr_node_type, "STANDBY") == 0)
|
else if (strcasecmp(repmgr_node_type, "STANDBY") == 0)
|
||||||
{
|
{
|
||||||
if (strcasecmp(repmgr_action, "CLONE") == 0)
|
if (strcasecmp(repmgr_action, "CLONE") == 0)
|
||||||
@@ -599,6 +602,14 @@ main(int argc, char **argv)
|
|||||||
action = STANDBY_RESTORE_CONFIG;
|
action = STANDBY_RESTORE_CONFIG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (strcasecmp(repmgr_node_type, "BDR") == 0)
|
||||||
|
{
|
||||||
|
if (strcasecmp(repmgr_action, "REGISTER") == 0)
|
||||||
|
action = BDR_REGISTER;
|
||||||
|
else if (strcasecmp(repmgr_action, "UNREGISTER") == 0)
|
||||||
|
action = BDR_UNREGISTER;
|
||||||
|
}
|
||||||
|
|
||||||
else if (strcasecmp(repmgr_node_type, "CLUSTER") == 0)
|
else if (strcasecmp(repmgr_node_type, "CLUSTER") == 0)
|
||||||
{
|
{
|
||||||
if (strcasecmp(repmgr_action, "EVENT") == 0)
|
if (strcasecmp(repmgr_action, "EVENT") == 0)
|
||||||
@@ -845,6 +856,7 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
|
/* PRIMARY */
|
||||||
case PRIMARY_REGISTER:
|
case PRIMARY_REGISTER:
|
||||||
do_primary_register();
|
do_primary_register();
|
||||||
break;
|
break;
|
||||||
@@ -852,6 +864,7 @@ main(int argc, char **argv)
|
|||||||
do_primary_unregister();
|
do_primary_unregister();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/* STANDBY */
|
||||||
case STANDBY_CLONE:
|
case STANDBY_CLONE:
|
||||||
do_standby_clone();
|
do_standby_clone();
|
||||||
break;
|
break;
|
||||||
@@ -877,6 +890,15 @@ main(int argc, char **argv)
|
|||||||
do_standby_restore_config();
|
do_standby_restore_config();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/* BDR */
|
||||||
|
case BDR_REGISTER:
|
||||||
|
do_bdr_register();
|
||||||
|
break;
|
||||||
|
case BDR_UNREGISTER:
|
||||||
|
do_bdr_unregister();
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* CLUSTER */
|
||||||
case CLUSTER_EVENT:
|
case CLUSTER_EVENT:
|
||||||
do_cluster_event();
|
do_cluster_event();
|
||||||
break;
|
break;
|
||||||
@@ -1336,14 +1358,14 @@ create_repmgr_extension(PGconn *conn)
|
|||||||
/* 4. Create extension */
|
/* 4. Create extension */
|
||||||
initPQExpBuffer(&query);
|
initPQExpBuffer(&query);
|
||||||
|
|
||||||
appendPQExpBuffer(&query,
|
wrap_ddl_query(&query, config_file_options.replication_type,
|
||||||
"CREATE EXTENSION repmgr");
|
"CREATE EXTENSION repmgr");
|
||||||
|
|
||||||
res = PQexec(schema_create_conn, query.data);
|
res = PQexec(schema_create_conn, query.data);
|
||||||
|
|
||||||
termPQExpBuffer(&query);
|
termPQExpBuffer(&query);
|
||||||
|
|
||||||
if (PQresultStatus(res) != PGRES_COMMAND_OK)
|
if ((PQresultStatus(res) != PGRES_COMMAND_OK && PQresultStatus(res) != PGRES_TUPLES_OK))
|
||||||
{
|
{
|
||||||
log_error(_("unable to create \"repmgr\" extension:\n %s"),
|
log_error(_("unable to create \"repmgr\" extension:\n %s"),
|
||||||
PQerrorMessage(schema_create_conn));
|
PQerrorMessage(schema_create_conn));
|
||||||
@@ -1357,14 +1379,21 @@ create_repmgr_extension(PGconn *conn)
|
|||||||
|
|
||||||
PQclear(res);
|
PQclear(res);
|
||||||
|
|
||||||
|
/* For BDR, we'll need to add the repmgr extension tables to a replication set */
|
||||||
|
if (config_file_options.replication_type == REPLICATION_TYPE_BDR)
|
||||||
|
{
|
||||||
|
add_extension_tables_to_bdr_replication_set(conn);
|
||||||
|
}
|
||||||
|
|
||||||
/* 5. If not superuser, grant usage */
|
/* 5. If not superuser, grant usage */
|
||||||
if (is_superuser == false)
|
if (is_superuser == false)
|
||||||
{
|
{
|
||||||
initPQExpBuffer(&query);
|
initPQExpBuffer(&query);
|
||||||
|
|
||||||
appendPQExpBuffer(&query,
|
wrap_ddl_query(&query, config_file_options.replication_type,
|
||||||
"GRANT USAGE ON SCHEMA repmgr TO %s",
|
"GRANT USAGE ON SCHEMA repmgr TO %s",
|
||||||
userinfo.username);
|
userinfo.username);
|
||||||
|
|
||||||
res = PQexec(schema_create_conn, query.data);
|
res = PQexec(schema_create_conn, query.data);
|
||||||
|
|
||||||
termPQExpBuffer(&query);
|
termPQExpBuffer(&query);
|
||||||
@@ -1382,9 +1411,10 @@ create_repmgr_extension(PGconn *conn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
initPQExpBuffer(&query);
|
initPQExpBuffer(&query);
|
||||||
appendPQExpBuffer(&query,
|
wrap_ddl_query(&query, config_file_options.replication_type,
|
||||||
"GRANT ALL ON ALL TABLES IN SCHEMA repmgr TO %s",
|
"GRANT ALL ON ALL TABLES IN SCHEMA repmgr TO %s",
|
||||||
userinfo.username);
|
userinfo.username);
|
||||||
|
|
||||||
res = PQexec(schema_create_conn, query.data);
|
res = PQexec(schema_create_conn, query.data);
|
||||||
|
|
||||||
termPQExpBuffer(&query);
|
termPQExpBuffer(&query);
|
||||||
|
|||||||
Reference in New Issue
Block a user