From ea45158f5069fb24219ca7f204f6d3db2014301e Mon Sep 17 00:00:00 2001 From: Ian Barwick Date: Thu, 29 Sep 2016 11:41:14 +0900 Subject: [PATCH] Refactor `cluster diagnose` - use the remote user setting, like other SSH-based remote operations (avoid hardcoding the user name) - enable `repmgr cluster matrix' to accept the cluster name, node id and the database connection information instead of requiring repmgr.conf; this means we don't have to assume that repmgr.conf is in one of the default locations --- repmgr.c | 162 ++++++++++++++++++++++++++++++++++++++++--------------- repmgr.h | 2 +- 2 files changed, 121 insertions(+), 43 deletions(-) diff --git a/repmgr.c b/repmgr.c index d9dc2cb5..d83e308a 100644 --- a/repmgr.c +++ b/repmgr.c @@ -662,7 +662,7 @@ main(int argc, char **argv) * { MASTER | PRIMARY } REGISTER | * STANDBY {REGISTER | UNREGISTER | CLONE [node] | PROMOTE | FOLLOW [node] | SWITCHOVER | REWIND} | * WITNESS { CREATE | REGISTER | UNREGISTER } | - * CLUSTER {SHOW | CLEANUP} + * CLUSTER { DIAGNOSE | MATRIX | SHOW | CLEANUP} * * the node part is optional, if we receive it then we shouldn't have * received a -h option @@ -902,6 +902,7 @@ main(int argc, char **argv) /* Initialise the repmgr schema name */ if (strlen(repmgr_cluster)) + /* --cluster parameter provided */ maxlen_snprintf(repmgr_schema, "%s%s", DEFAULT_REPMGR_SCHEMA_PREFIX, repmgr_cluster); else @@ -1117,22 +1118,34 @@ build_cluster_matrix(int **matrix, char **node_names, int *name_length) int i, j; int n; - int x, y; - char *p; + int x, y; - char command[MAXLEN]; + int local_node_id; + + PQExpBufferData command; PQExpBufferData command_output; /* We need to connect to get the list of nodes */ log_info(_("connecting to database\n")); - conn = establish_db_connection(options.conninfo, true); + + if (strlen(options.conninfo)) + { + conn = establish_db_connection(options.conninfo, true); + local_node_id = options.node; + } + else + { + conn = establish_db_connection_by_params((const char**)source_conninfo.keywords, + (const char**)source_conninfo.values, true); + local_node_id = runtime_options.node; + } sqlquery_snprintf(sqlquery, - "SELECT conninfo, type, name, upstream_node_name, id" + "SELECT conninfo, type, name, upstream_node_name, id, cluster" " FROM %s.repl_show_nodes ORDER BY id", get_repmgr_schema_quoted(conn)); - log_verbose(LOG_DEBUG, "do_cluster_show(): \n%s\n",sqlquery ); + log_verbose(LOG_DEBUG, "build_cluster_matrix(): \n%s\n", sqlquery); res = PQexec(conn, sqlquery); @@ -1181,8 +1194,8 @@ build_cluster_matrix(int **matrix, char **node_names, int *name_length) for (i = 0; i < n; i++) { strncpy(*node_names + i * (*name_length + 1), - PQgetvalue(res, i, 3), - strlen(PQgetvalue(res, i, 3)) + 1); + PQgetvalue(res, i, 2), + strlen(PQgetvalue(res, i, 2)) + 1); } /* @@ -1193,7 +1206,7 @@ build_cluster_matrix(int **matrix, char **node_names, int *name_length) { int connection_status; t_conninfo_param_list remote_conninfo; - char *host; + char *host, *p; initialize_conninfo_params(&remote_conninfo, false); parse_conninfo_string(PQgetvalue(res, i, 0), @@ -1208,31 +1221,46 @@ build_cluster_matrix(int **matrix, char **node_names, int *name_length) connection_status = (PQstatus(conn) == CONNECTION_OK) ? 0 : -1; - (*matrix)[(options.node - 1) * n + i] = + (*matrix)[(local_node_id - 1) * n + i] = connection_status; if (connection_status) continue; - if (i + 1 == options.node) + if (i + 1 == local_node_id) continue; - maxlen_snprintf(command, - "\"%s -d '%s' --cluster '%s' cluster show --csv\"", - make_pg_path("repmgr"), - PQgetvalue(res, i, 0), - options.cluster_name); + initPQExpBuffer(&command); + appendPQExpBuffer(&command, + "\"%s -d '%s' --cluster '%s' ", + make_pg_path("repmgr"), + PQgetvalue(res, i, 0), + PQgetvalue(res, i, 5)); + + + if (strlen(pg_bindir)) + // XXX escape path! + appendPQExpBuffer(&command, + "--pg_bindir=%s ", + pg_bindir); + + appendPQExpBuffer(&command, + " cluster show --csv\""); + + log_verbose(LOG_DEBUG, "build_cluster_matrix(): executing\n%s\n", command.data); initPQExpBuffer(&command_output); (void)remote_command( host, runtime_options.remote_user, - command, + command.data, &command_output); p = command_output.data; + termPQExpBuffer(&command); + for (j = 0; j < n; j++) { if (sscanf(p, "%d,%d", &x, &y) != 2) @@ -1331,9 +1359,8 @@ build_cluster_diagnose(int **cube, char **node_names, int *name_length) int x, y, z; int n = 0; /* number of nodes */ - char *p; - char command[MAXLEN]; + PQExpBufferData command; PQExpBufferData command_output; /* We need to connect to get the list of nodes */ @@ -1341,11 +1368,11 @@ build_cluster_diagnose(int **cube, char **node_names, int *name_length) conn = establish_db_connection(options.conninfo, true); sqlquery_snprintf(sqlquery, - "SELECT conninfo, ssh_hostname, type, name, upstream_node_name, id" + "SELECT conninfo, type, name, upstream_node_name, id" " FROM %s.repl_show_nodes ORDER BY id", get_repmgr_schema_quoted(conn)); - log_verbose(LOG_DEBUG, "do_cluster_show(): \n%s\n",sqlquery ); + log_verbose(LOG_DEBUG, "build_cluster_diagnose(): \n%s\n",sqlquery ); res = PQexec(conn, sqlquery); @@ -1380,7 +1407,7 @@ build_cluster_diagnose(int **cube, char **node_names, int *name_length) { int name_length_cur; - name_length_cur = strlen(PQgetvalue(res, i, 3)); + name_length_cur = strlen(PQgetvalue(res, i, 2)); if (name_length_cur > *name_length) *name_length = name_length_cur; } @@ -1394,8 +1421,8 @@ build_cluster_diagnose(int **cube, char **node_names, int *name_length) for (i = 0; i < n; i++) { strncpy(*node_names + i * (*name_length + 1), - PQgetvalue(res, i, 3), - strlen(PQgetvalue(res, i, 3)) + 1); + PQgetvalue(res, i, 2), + strlen(PQgetvalue(res, i, 2)) + 1); } /* @@ -1404,26 +1431,68 @@ build_cluster_diagnose(int **cube, char **node_names, int *name_length) for (i = 0; i < n; i++) { - maxlen_snprintf(command, - "repmgr cluster matrix --csv"); + char *p; + int remote_node_id; + + remote_node_id = atoi(PQgetvalue(res, i, 4)); + + initPQExpBuffer(&command); + + appendPQExpBuffer(&command, + "%s -d '%s' --cluster '%s' --node=%i ", + make_pg_path("repmgr"), + PQgetvalue(res, i, 0), + options.cluster_name, + remote_node_id); + + + if (strlen(pg_bindir)) + // XXX escape path! + appendPQExpBuffer(&command, + "--pg_bindir=%s ", + pg_bindir); + + appendPQExpBuffer(&command, + "cluster matrix --csv"); initPQExpBuffer(&command_output); if (i + 1 == options.node) { (void)local_command( - command, + command.data, &command_output); } else { - (void)remote_command( - PQgetvalue(res, i, 1), - "postgres", - command, - &command_output); - } + t_conninfo_param_list remote_conninfo; + char *host; + PQExpBufferData quoted_command; + initPQExpBuffer("ed_command); + appendPQExpBuffer("ed_command, + "\"%s\"", + command.data); + + initialize_conninfo_params(&remote_conninfo, false); + parse_conninfo_string(PQgetvalue(res, i, 0), + &remote_conninfo, + NULL, + false); + + host = param_get(&remote_conninfo, "host"); + + log_verbose(LOG_DEBUG, "build_cluster_diagnose(): executing\n%s\n", quoted_command.data); + + (void)remote_command( + host, + runtime_options.remote_user, + quoted_command.data, + &command_output); + + termPQExpBuffer("ed_command); + } + termPQExpBuffer(&command); p = command_output.data; for (j = 0; j < n * n; j++) @@ -2025,7 +2094,7 @@ do_standby_unregister(void) exit(ERR_BAD_CONFIG); } - if (runtime_options.node) + if (runtime_options.node != UNKNOWN_NODE_ID) target_node_id = runtime_options.node; else target_node_id = options.node; @@ -5918,7 +5987,7 @@ do_witness_unregister(void) exit(ERR_BAD_CONFIG); } - if (runtime_options.node) + if (runtime_options.node != UNKNOWN_NODE_ID) target_node_id = runtime_options.node; else target_node_id = options.node; @@ -6596,6 +6665,7 @@ check_parameters_for_action(const int action) config_file_required = false; break; + case STANDBY_SWITCHOVER: /* allow all parameters to be supplied */ break; @@ -6630,10 +6700,18 @@ check_parameters_for_action(const int action) /* allow all parameters to be supplied */ break; - case CLUSTER_SHOW: - /* host parameters can be supplied */ + case CLUSTER_MATRIX: + /* config file not required if database connection parameters and cluster name supplied */ + config_file_required = false; + + if (strlen(repmgr_cluster) && runtime_options.node == UNKNOWN_NODE_ID) + item_list_append(&cli_errors, _("--node required when executing CLUSTER MATRIX with --cluster")); + + break; + + case CLUSTER_SHOW: + /* config file not required if database connection parameters and cluster name supplied */ config_file_required = false; - /* allow all parameters to be supplied */ break; case CLUSTER_CLEANUP: @@ -6694,11 +6772,11 @@ check_parameters_for_action(const int action) } /* Warn about parameters which apply to WITNESS UNREGISTER only */ - if (action != WITNESS_UNREGISTER) + if (action != WITNESS_UNREGISTER && action != STANDBY_UNREGISTER && action != CLUSTER_MATRIX) { - if (runtime_options.node) + if (runtime_options.node != UNKNOWN_NODE_ID) { - item_list_append(&cli_warnings, _("--node can only be supplied when executing WITNESS UNREGISTER")); + item_list_append(&cli_warnings, _("--node not required with this action")); } } diff --git a/repmgr.h b/repmgr.h index a6370034..3a6d17f4 100644 --- a/repmgr.h +++ b/repmgr.h @@ -120,7 +120,7 @@ typedef struct 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, false, false, CONFIG_FILE_SAMEPATH, false, 0, "", "", "", "", "fast", "", 0, 0, "", ""} +#define T_RUNTIME_OPTIONS_INITIALIZER { "", "", "", "", "", "", "", DEFAULT_WAL_KEEP_SEGMENTS, false, false, false, false, false, false, false, false, false, false, false, false, CONFIG_FILE_SAMEPATH, false, 0, "", "", "", "", "fast", "", 0, UNKNOWN_NODE_ID, "", ""} struct BackupLabel {