Add "repmgr cluster show"

This commit is contained in:
Ian Barwick
2017-07-19 17:36:21 +09:00
parent d3776ad13e
commit 49ac9cf9ca
8 changed files with 225 additions and 25 deletions

View File

@@ -1298,6 +1298,9 @@ _populate_node_record(PGresult *res, t_node_info *node_info, int row)
node_info->priority = atoi(PQgetvalue(res, row, 8));
node_info->active = atobool(PQgetvalue(res, row, 9));
/* This won't normally be set */
strncpy(node_info->upstream_node_name, PQgetvalue(res, row, 10), MAXLEN);
/* Set remaining struct fields with default values */
node_info->node_status = NODE_STATUS_UNKNOWN;
node_info->last_wal_receive_lsn = InvalidXLogRecPtr;
@@ -1354,7 +1357,7 @@ get_node_record(PGconn *conn, int node_id, t_node_info *node_info)
initPQExpBuffer(&query);
appendPQExpBuffer(&query,
"SELECT node_id, type, upstream_node_id, node_name, conninfo, repluser, slot_name, location, priority, active"
"SELECT " REPMGR_NODES_COLUMNS
" FROM repmgr.nodes "
" WHERE node_id = %i",
node_id);
@@ -1382,7 +1385,7 @@ get_node_record_by_name(PGconn *conn, const char *node_name, t_node_info *node_i
initPQExpBuffer(&query);
appendPQExpBuffer(&query,
"SELECT node_id, type, upstream_node_id, node_name, conninfo, repluser, slot_name, location, priority, active"
"SELECT " REPMGR_NODES_COLUMNS
" FROM repmgr.nodes "
" WHERE node_name = '%s' ",
node_name);
@@ -1507,10 +1510,11 @@ get_all_node_records(PGconn *conn, NodeInfoList *node_list)
initPQExpBuffer(&query);
appendPQExpBuffer(&query,
" SELECT node_id, type, upstream_node_id, node_name, conninfo, repluser, slot_name, location, priority, active"
" FROM repmgr.nodes "
"ORDER BY node_id ");
appendPQExpBuffer(
&query,
" SELECT " REPMGR_NODES_COLUMNS
" FROM repmgr.nodes "
"ORDER BY node_id ");
log_verbose(LOG_DEBUG, "get_all_node_records():\n%s", query.data);
@@ -1533,12 +1537,13 @@ get_downstream_node_records(PGconn *conn, int node_id, NodeInfoList *node_list)
initPQExpBuffer(&query);
appendPQExpBuffer(&query,
" SELECT node_id, type, upstream_node_id, node_name, conninfo, repluser, slot_name, location, priority, active"
" FROM repmgr.nodes "
" WHERE upstream_node_id = %i "
"ORDER BY node_id ",
node_id);
appendPQExpBuffer(
&query,
" SELECT " REPMGR_NODES_COLUMNS
" FROM repmgr.nodes "
" WHERE upstream_node_id = %i "
"ORDER BY node_id ",
node_id);
log_verbose(LOG_DEBUG, "get_downstream_node_records():\n%s", query.data);
@@ -1562,15 +1567,16 @@ get_active_sibling_node_records(PGconn *conn, int node_id, int upstream_node_id,
initPQExpBuffer(&query);
appendPQExpBuffer(&query,
" SELECT node_id, type, upstream_node_id, node_name, conninfo, repluser, slot_name, location, priority, active"
" FROM repmgr.nodes "
" WHERE upstream_node_id = %i "
" AND node_id != %i "
" AND active IS TRUE "
"ORDER BY node_id ",
upstream_node_id,
node_id);
appendPQExpBuffer(
&query,
" SELECT " REPMGR_NODES_COLUMNS
" FROM repmgr.nodes "
" WHERE upstream_node_id = %i "
" AND node_id != %i "
" AND active IS TRUE "
"ORDER BY node_id ",
upstream_node_id,
node_id);
log_verbose(LOG_DEBUG, "get_active_sibling_node_records():\n%s", query.data);
@@ -1596,7 +1602,7 @@ get_node_records_by_priority(PGconn *conn, NodeInfoList *node_list)
appendPQExpBuffer(
&query,
" SELECT node_id, type, upstream_node_id, node_name, conninfo, repluser, slot_name, location, priority, active"
" SELECT " REPMGR_NODES_COLUMNS
" FROM repmgr.nodes "
"ORDER BY priority DESC, node_name ");
@@ -1613,6 +1619,35 @@ get_node_records_by_priority(PGconn *conn, NodeInfoList *node_list)
return;
}
void
get_all_node_records_with_upstream(PGconn *conn, NodeInfoList *node_list)
{
PQExpBufferData query;
PGresult *res;
initPQExpBuffer(&query);
appendPQExpBuffer(
&query,
" SELECT n.node_id, n.type, n.upstream_node_id, n.node_name, n.conninfo, n.repluser, "
" n.slot_name, n.location, n.priority, n.active, un.node_name AS upstream_node_name "
" FROM repmgr.nodes n "
" LEFT JOIN nodes un "
" ON un.node_id = n.upstream_node_id"
" ORDER BY n.node_id ");
log_verbose(LOG_DEBUG, "get_all_node_records_with_upstream():\n%s", query.data);
res = PQexec(conn, query.data);
termPQExpBuffer(&query);
_populate_node_records(res, node_list);
return;
}
bool
create_node_record(PGconn *conn, char *repmgr_action, t_node_info *node_info)

View File

@@ -15,6 +15,8 @@
#include "strutil.h"
#include "voting.h"
#define REPMGR_NODES_COLUMNS "node_id, type, upstream_node_id, node_name, conninfo, repluser, slot_name, location, priority, active, '' AS upstream_node_name "
typedef enum {
UNKNOWN = 0,
PRIMARY,
@@ -67,6 +69,7 @@ typedef struct s_node_info
int upstream_node_id;
t_server_type type;
char node_name[MAXLEN];
char upstream_node_name[MAXLEN];
char conninfo[MAXLEN];
char repluser[NAMEDATALEN];
char location[MAXLEN];
@@ -78,6 +81,8 @@ typedef struct s_node_info
NodeStatus node_status;
MonitoringState monitoring_state;
PGconn *conn;
/* for ad-hoc use e.g. when working with a list of nodes */
char details[MAXLEN];
} t_node_info;
@@ -88,6 +93,7 @@ typedef struct s_node_info
"", \
"", \
"", \
"", \
DEFAULT_LOCATION, \
DEFAULT_PRIORITY, \
true, \
@@ -95,7 +101,8 @@ typedef struct s_node_info
InvalidXLogRecPtr, \
NODE_STATUS_UNKNOWN, \
MS_NORMAL, \
NULL \
NULL, \
"" \
}
@@ -283,6 +290,7 @@ void get_all_node_records(PGconn *conn, NodeInfoList *node_list);
void get_downstream_node_records(PGconn *conn, int node_id, NodeInfoList *nodes);
void get_active_sibling_node_records(PGconn *conn, int node_id, int upstream_node_id, NodeInfoList *node_list);
void get_node_records_by_priority(PGconn *conn, NodeInfoList *node_list);
void get_all_node_records_with_upstream(PGconn *conn, NodeInfoList *node_list);
bool create_node_record(PGconn *conn, char *repmgr_action, t_node_info *node_info);
bool update_node_record(PGconn *conn, char *repmgr_action, t_node_info *node_info);

View File

@@ -26,6 +26,8 @@ CREATE TABLE events (
CREATE VIEW show_nodes AS
SELECT n.node_id,
n.node_name,
n.active,
n.upstream_node_id,
un.node_name AS upstream_node_name,
n.type,
n.priority,

View File

@@ -11,6 +11,137 @@
#include "repmgr-client-global.h"
#include "repmgr-action-cluster.h"
void
do_cluster_show(void)
{
PGconn *conn;
NodeInfoList nodes = T_NODE_INFO_LIST_INITIALIZER;
NodeInfoListCell *cell;
char name_header[MAXLEN];
char upstream_header[MAXLEN];
int name_length,
upstream_length,
conninfo_length = 0;
/* Connect to local database to obtain cluster connection data */
log_verbose(LOG_INFO, _("connecting to database\n"));
if (strlen(config_file_options.conninfo))
conn = establish_db_connection(config_file_options.conninfo, true);
else
conn = establish_db_connection_by_params(&source_conninfo, true);
get_all_node_records_with_upstream(conn, &nodes);
if (nodes.node_count == 0)
{
log_error(_("unable to retrieve any node records"));
PQfinish(conn);
exit(ERR_BAD_CONFIG);
}
strncpy(name_header, _("Name"), MAXLEN);
strncpy(upstream_header, _("Upstream"), MAXLEN);
/*
* XXX if repmgr is ever localized into non-ASCII locales,
* use pg_wcssize() or similar to establish printed column length
*/
name_length = strlen(name_header);
upstream_length = strlen(upstream_header);
for (cell = nodes.head; cell; cell = cell->next)
{
int conninfo_length_cur,
name_length_cur,
upstream_length_cur;
conninfo_length_cur = strlen(cell->node_info->conninfo);
if (conninfo_length_cur > conninfo_length)
conninfo_length = conninfo_length_cur;
name_length_cur = strlen(cell->node_info->node_name);
if (name_length_cur > name_length)
name_length = name_length_cur;
upstream_length_cur = strlen(cell->node_info->upstream_node_name);
if (upstream_length_cur > upstream_length)
upstream_length = upstream_length_cur;
cell->node_info->conn = establish_db_connection_quiet(cell->node_info->conninfo);
if (PQstatus(conn) != CONNECTION_OK)
{
strcpy(cell->node_info->details, " FAILED");
}
else if (cell->node_info->type == BDR)
{
strcpy(cell->node_info->details, " BDR");
}
else
{
RecoveryType rec_type = get_recovery_type(cell->node_info->conn);
switch (rec_type)
{
case RECTYPE_PRIMARY:
strcpy(cell->node_info->details, "* primary");
break;
case RECTYPE_STANDBY:
strcpy(cell->node_info->details, " standby");
break;
case RECTYPE_UNKNOWN:
strcpy(cell->node_info->details, " unknown");
break;
}
}
PQfinish(cell->node_info->conn);
}
if (! runtime_options.csv)
{
int i;
printf(" Role | %-*s | %-*s | Connection string\n", name_length, name_header, upstream_length, upstream_header);
printf("----------+-");
for (i = 0; i < name_length; i++)
printf("-");
printf("-+-");
for (i = 0; i < upstream_length; i++)
printf("-");
printf("-+-");
for (i = 0; i < conninfo_length; i++)
printf("-");
printf("\n");
}
for (cell = nodes.head; cell; cell = cell->next)
{
if (runtime_options.csv)
{
int connection_status =
(PQstatus(conn) == CONNECTION_OK) ? 0 : -1;
printf("%i,%d\n", cell->node_info->node_id, connection_status);
}
else
{
printf("%-10s", cell->node_info->details);
printf("| %-*s ", name_length, cell->node_info->node_name);
printf("| %-*s ", upstream_length, cell->node_info->upstream_node_name);
printf("| %s\n", cell->node_info->conninfo);
}
}
PQfinish(conn);
}
/*
* CLUSTER EVENT
*

View File

@@ -6,6 +6,7 @@
#ifndef _REPMGR_ACTION_CLUSTER_H_
#define _REPMGR_ACTION_CLUSTER_H_
extern void do_cluster_show(void);
extern void do_cluster_event(void);

View File

@@ -37,6 +37,9 @@ typedef struct
bool terse;
bool verbose;
/* output options */
bool csv;
/* standard connection options */
char dbname[MAXLEN];
char host[MAXLEN];
@@ -84,6 +87,8 @@ typedef struct
"", false, false, "", false, \
/* logging options */ \
"", false, false, false, \
/* output options */ \
false, \
/* database connection options */ \
"", "", "", "", \
/* other connection options */ \

View File

@@ -16,6 +16,7 @@
* STANDBY UNREGISTER
* STANDBY PROMOTE
*
* CLUSTER SHOW
* CLUSTER EVENT
*/
@@ -438,6 +439,14 @@ main(int argc, char **argv)
runtime_options.verbose = true;
break;
/* output options */
/* -------------- */
case OPT_CSV:
runtime_options.csv = true;
break;
/* options deprecated since 3.3 *
* ---------------------------- */
case OPT_DATA_DIR:
@@ -615,7 +624,10 @@ main(int argc, char **argv)
else if (strcasecmp(repmgr_node_type, "CLUSTER") == 0)
{
if (strcasecmp(repmgr_action, "EVENT") == 0)
if (strcasecmp(repmgr_action, "SHOW") == 0)
action = CLUSTER_SHOW;
else if (strcasecmp(repmgr_action, "EVENT") == 0)
action = CLUSTER_EVENT;
}
else
@@ -916,6 +928,9 @@ main(int argc, char **argv)
break;
/* CLUSTER */
case CLUSTER_SHOW:
do_cluster_show();
break;
case CLUSTER_EVENT:
do_cluster_event();
break;

View File

@@ -93,6 +93,9 @@ static struct option long_options[] =
{"terse", required_argument, NULL, 't'},
{"verbose", no_argument, NULL, 'v'},
/* output options */
{"csv", no_argument, NULL, OPT_CSV},
/* standby clone options */
{"copy-external-config-files", optional_argument, NULL, OPT_COPY_EXTERNAL_CONFIG_FILES},
{"fast-checkpoint", no_argument, NULL, 'c'},
@@ -125,7 +128,7 @@ static struct option long_options[] =
{"check-upstream-config", no_argument, NULL, OPT_CHECK_UPSTREAM_CONFIG},
{"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},
{"without-barman", no_argument, NULL, OPT_WITHOUT_BARMAN},
{"copy-external-config-files", optional_argument, NULL, OPT_COPY_EXTERNAL_CONFIG_FILES},