|
@@ -71,6 +71,7 @@
|
|
|
enum user_action {
|
|
enum user_action {
|
|
|
ACTION_NOOP=0,
|
|
ACTION_NOOP=0,
|
|
|
ACTION_LINKSTATUS_GET,
|
|
ACTION_LINKSTATUS_GET,
|
|
|
|
|
+ ACTION_NODESTATUS_GET,
|
|
|
ACTION_RELOAD_CONFIG,
|
|
ACTION_RELOAD_CONFIG,
|
|
|
ACTION_REOPEN_LOG_FILES,
|
|
ACTION_REOPEN_LOG_FILES,
|
|
|
ACTION_SHUTDOW,
|
|
ACTION_SHUTDOW,
|
|
@@ -89,35 +90,35 @@ static int node_compare(const void *aptr, const void *bptr)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
static int
|
|
|
-linkstatusget_do (char *interface_name, int brief)
|
|
|
|
|
|
|
+nodestatusget_do (enum user_action action, int brief)
|
|
|
{
|
|
{
|
|
|
cs_error_t result;
|
|
cs_error_t result;
|
|
|
corosync_cfg_handle_t handle;
|
|
corosync_cfg_handle_t handle;
|
|
|
cmap_handle_t cmap_handle;
|
|
cmap_handle_t cmap_handle;
|
|
|
- unsigned int interface_count;
|
|
|
|
|
- char **interface_names;
|
|
|
|
|
- char **interface_status;
|
|
|
|
|
- uint32_t nodeid_list[KNET_MAX_HOST];
|
|
|
|
|
char iter_key[CMAP_KEYNAME_MAXLEN];
|
|
char iter_key[CMAP_KEYNAME_MAXLEN];
|
|
|
- unsigned int i;
|
|
|
|
|
cmap_iter_handle_t iter;
|
|
cmap_iter_handle_t iter;
|
|
|
|
|
+ unsigned int local_nodeid;
|
|
|
|
|
+ unsigned int local_nodeid_index=0;
|
|
|
|
|
+ unsigned int other_nodeid_index=0;
|
|
|
unsigned int nodeid;
|
|
unsigned int nodeid;
|
|
|
int nodeid_match_guard;
|
|
int nodeid_match_guard;
|
|
|
cmap_value_types_t type;
|
|
cmap_value_types_t type;
|
|
|
size_t value_len;
|
|
size_t value_len;
|
|
|
- int rc = EXIT_SUCCESS;
|
|
|
|
|
- int len, s = 0, t;
|
|
|
|
|
- char stat_ch;
|
|
|
|
|
char *str;
|
|
char *str;
|
|
|
- totem_transport_t transport_number = TOTEM_TRANSPORT_KNET;
|
|
|
|
|
- int no_match = 1;
|
|
|
|
|
|
|
+ char *transport_str = NULL;
|
|
|
|
|
+ uint32_t nodeid_list[KNET_MAX_HOST];
|
|
|
|
|
+ int s = 0;
|
|
|
|
|
+ int rc = EXIT_SUCCESS;
|
|
|
|
|
+ int transport_number = TOTEM_TRANSPORT_KNET;
|
|
|
|
|
+ int i,j;
|
|
|
|
|
+ struct corosync_knet_node_status node_status;
|
|
|
|
|
|
|
|
- printf ("Printing link status.\n");
|
|
|
|
|
result = corosync_cfg_initialize (&handle, NULL);
|
|
result = corosync_cfg_initialize (&handle, NULL);
|
|
|
if (result != CS_OK) {
|
|
if (result != CS_OK) {
|
|
|
fprintf (stderr, "Could not initialize corosync configuration API error %d\n", result);
|
|
fprintf (stderr, "Could not initialize corosync configuration API error %d\n", result);
|
|
|
exit (EXIT_FAILURE);
|
|
exit (EXIT_FAILURE);
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
result = cmap_initialize (&cmap_handle);
|
|
result = cmap_initialize (&cmap_handle);
|
|
|
if (result != CS_OK) {
|
|
if (result != CS_OK) {
|
|
|
fprintf (stderr, "Could not initialize corosync cmap API error %d\n", result);
|
|
fprintf (stderr, "Could not initialize corosync cmap API error %d\n", result);
|
|
@@ -132,7 +133,19 @@ linkstatusget_do (char *interface_name, int brief)
|
|
|
if (strcmp (str, "udp") == 0) {
|
|
if (strcmp (str, "udp") == 0) {
|
|
|
transport_number = TOTEM_TRANSPORT_UDP;
|
|
transport_number = TOTEM_TRANSPORT_UDP;
|
|
|
}
|
|
}
|
|
|
- free(str);
|
|
|
|
|
|
|
+ transport_str = str;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!transport_str) {
|
|
|
|
|
+ transport_str = strdup("knet"); /* It's the default */
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ result = corosync_cfg_local_get(handle, &local_nodeid);
|
|
|
|
|
+ if (result != CS_OK) {
|
|
|
|
|
+ fprintf (stderr, "Could not get the local node id, the error is: %d\n", result);
|
|
|
|
|
+ free(transport_str);
|
|
|
|
|
+ cmap_finalize(cmap_handle);
|
|
|
|
|
+ corosync_cfg_finalize(handle);
|
|
|
|
|
+ return EXIT_FAILURE;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* Get a list of nodes. We do it this way rather than using votequorum as cfgtool
|
|
/* Get a list of nodes. We do it this way rather than using votequorum as cfgtool
|
|
@@ -141,6 +154,9 @@ linkstatusget_do (char *interface_name, int brief)
|
|
|
result = cmap_iter_init(cmap_handle, "nodelist.node.", &iter);
|
|
result = cmap_iter_init(cmap_handle, "nodelist.node.", &iter);
|
|
|
if (result != CS_OK) {
|
|
if (result != CS_OK) {
|
|
|
fprintf (stderr, "Could not get nodelist from cmap. error %d\n", result);
|
|
fprintf (stderr, "Could not get nodelist from cmap. error %d\n", result);
|
|
|
|
|
+ free(transport_str);
|
|
|
|
|
+ cmap_finalize(cmap_handle);
|
|
|
|
|
+ corosync_cfg_finalize(handle);
|
|
|
exit (EXIT_FAILURE);
|
|
exit (EXIT_FAILURE);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -154,140 +170,120 @@ linkstatusget_do (char *interface_name, int brief)
|
|
|
continue;
|
|
continue;
|
|
|
}
|
|
}
|
|
|
if (cmap_get_uint32(cmap_handle, iter_key, &nodeid) == CS_OK) {
|
|
if (cmap_get_uint32(cmap_handle, iter_key, &nodeid) == CS_OK) {
|
|
|
|
|
+ if (nodeid == local_nodeid) {
|
|
|
|
|
+ local_nodeid_index = s;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ /* Bit of an odd one this. but local node only uses one link (of course, to itself)
|
|
|
|
|
+ so if we want to know which links are active across the cluster we need to look
|
|
|
|
|
+ at another node (any other) node's link list */
|
|
|
|
|
+ other_nodeid_index = s;
|
|
|
|
|
+ }
|
|
|
nodeid_list[s++] = nodeid;
|
|
nodeid_list[s++] = nodeid;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- /* totemknet returns nodes in nodeid order - even though it doesn't tell us
|
|
|
|
|
- what the nodeid is. So sort our node list and we can then look up
|
|
|
|
|
- knet node pos to get an actual nodeid.
|
|
|
|
|
- Yep, I really should have totally rewritten the cfg interface for this.
|
|
|
|
|
- */
|
|
|
|
|
|
|
+ /* It's nice to have these in nodeid order */
|
|
|
qsort(nodeid_list, s, sizeof(uint32_t), node_compare);
|
|
qsort(nodeid_list, s, sizeof(uint32_t), node_compare);
|
|
|
|
|
|
|
|
- result = corosync_cfg_local_get(handle, &nodeid);
|
|
|
|
|
- if (result != CS_OK) {
|
|
|
|
|
- fprintf (stderr, "Could not get the local node id, the error is: %d\n", result);
|
|
|
|
|
|
|
+ cmap_finalize(cmap_handle);
|
|
|
|
|
+
|
|
|
|
|
+ printf ("Local node ID " CS_PRI_NODE_ID ", transport %s\n", local_nodeid, transport_str);
|
|
|
|
|
+
|
|
|
|
|
+ /* If node status requested then do print node-based info */
|
|
|
|
|
+ if (action == ACTION_NODESTATUS_GET) {
|
|
|
|
|
+ for (i=0; i<s; i++) {
|
|
|
|
|
+ result = corosync_cfg_node_status_get(handle, nodeid_list[i], &node_status);
|
|
|
|
|
+ if (result == CS_OK) {
|
|
|
|
|
+ /* Only display node info if it is reachable (and not us) */
|
|
|
|
|
+ if (node_status.reachable && node_status.nodeid != local_nodeid) {
|
|
|
|
|
+ printf("nodeid: %d", node_status.nodeid);
|
|
|
|
|
+ printf(" reachable");
|
|
|
|
|
+ if (node_status.remote) {
|
|
|
|
|
+ printf(" remote");
|
|
|
|
|
+ }
|
|
|
|
|
+ if (node_status.external) {
|
|
|
|
|
+ printf(" external");
|
|
|
|
|
+ }
|
|
|
|
|
+#ifdef HAVE_KNET_ONWIRE_VER
|
|
|
|
|
+ if (transport_number == TOTEM_TRANSPORT_KNET) {
|
|
|
|
|
+ printf(" onwire (min/max/cur): %d, %d, %d",
|
|
|
|
|
+ node_status.onwire_min,
|
|
|
|
|
+ node_status.onwire_max,
|
|
|
|
|
+ node_status.onwire_ver);
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
+ printf("\n");
|
|
|
|
|
+ for (j=0; j<CFG_MAX_LINKS; j++) {
|
|
|
|
|
+ if (node_status.link_status[j].enabled) {
|
|
|
|
|
+ printf(" LINK: %d", j);
|
|
|
|
|
+ printf(" (%s%s%s)",
|
|
|
|
|
+ node_status.link_status[j].src_ipaddr,
|
|
|
|
|
+ transport_number==TOTEM_TRANSPORT_KNET?"->":"",
|
|
|
|
|
+ node_status.link_status[j].dst_ipaddr);
|
|
|
|
|
+ if (node_status.link_status[j].enabled) {
|
|
|
|
|
+ printf(" enabled");
|
|
|
|
|
+ }
|
|
|
|
|
+ if (node_status.link_status[j].connected) {
|
|
|
|
|
+ printf(" connected");
|
|
|
|
|
+ }
|
|
|
|
|
+ if (node_status.link_status[j].dynconnected) {
|
|
|
|
|
+ printf(" dynconnected");
|
|
|
|
|
+ }
|
|
|
|
|
+ printf(" mtu: %d\n", node_status.link_status[j].mtu);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ printf("\n");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
+ /* Print in link order */
|
|
|
else {
|
|
else {
|
|
|
- printf ("Local node ID " CS_PRI_NODE_ID "\n", nodeid);
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ struct corosync_knet_node_status node_info[s];
|
|
|
|
|
+ memset(node_info, 0, sizeof(node_info));
|
|
|
|
|
|
|
|
- result = corosync_cfg_ring_status_get (handle,
|
|
|
|
|
- &interface_names,
|
|
|
|
|
- &interface_status,
|
|
|
|
|
- &interface_count);
|
|
|
|
|
- if (result != CS_OK) {
|
|
|
|
|
- fprintf (stderr, "Could not get the link status, the error is: %d\n", result);
|
|
|
|
|
- } else {
|
|
|
|
|
- for (i = 0; i < interface_count; i++) {
|
|
|
|
|
- char *cur_iface_name_space = strchr(interface_names[i], ' ');
|
|
|
|
|
- int show_current_iface;
|
|
|
|
|
-
|
|
|
|
|
- s = 0;
|
|
|
|
|
- /*
|
|
|
|
|
- * Interface_name is "<linkid> <IP address>"
|
|
|
|
|
- * separate them out
|
|
|
|
|
- */
|
|
|
|
|
- if (!cur_iface_name_space) {
|
|
|
|
|
- continue;
|
|
|
|
|
- }
|
|
|
|
|
- *cur_iface_name_space = '\0';
|
|
|
|
|
-
|
|
|
|
|
- show_current_iface = 1;
|
|
|
|
|
- if (interface_name != NULL && interface_name[0] != '\0' &&
|
|
|
|
|
- strcmp(interface_name, interface_names[i]) != 0 &&
|
|
|
|
|
- strcmp(interface_name, cur_iface_name_space + 1) != 0) {
|
|
|
|
|
- show_current_iface = 0;
|
|
|
|
|
|
|
+ for (i=0; i<s; i++) {
|
|
|
|
|
+ result = corosync_cfg_node_status_get(handle, nodeid_list[i], &node_info[i]);
|
|
|
|
|
+ if (result != CS_OK) {
|
|
|
|
|
+ fprintf (stderr, "Could not get the node status for nodeid %d, the error is: %d\n", nodeid_list[i], result);
|
|
|
}
|
|
}
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- if (show_current_iface) {
|
|
|
|
|
- no_match = 0;
|
|
|
|
|
- printf ("LINK ID %s\n", interface_names[i]);
|
|
|
|
|
- printf ("\taddr\t= %s\n", cur_iface_name_space + 1);
|
|
|
|
|
- /*
|
|
|
|
|
- * UDP(U) interface_status is always OK and doesn't contain
|
|
|
|
|
- * detailed information (only knet does).
|
|
|
|
|
- */
|
|
|
|
|
- if ((!brief) && (transport_number == TOTEM_TRANSPORT_KNET)) {
|
|
|
|
|
- len = strlen(interface_status[i]);
|
|
|
|
|
- printf ("\tstatus:\n");
|
|
|
|
|
- while (s < len) {
|
|
|
|
|
- nodeid = nodeid_list[s];
|
|
|
|
|
- printf("\t\tnodeid %2d:\t", nodeid);
|
|
|
|
|
- stat_ch = interface_status[i][s];
|
|
|
|
|
-
|
|
|
|
|
- /* Set return code to 1 if status is not localhost or connected. */
|
|
|
|
|
- if (rc == EXIT_SUCCESS) {
|
|
|
|
|
- if ((stat_ch != 'n') && (stat_ch != '3')) {
|
|
|
|
|
- rc = EXIT_FAILURE;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ for (i=0; i<CFG_MAX_LINKS; i++) {
|
|
|
|
|
+ if (node_info[other_nodeid_index].link_status[i].enabled) {
|
|
|
|
|
+ printf("LINK ID %d\n", i);
|
|
|
|
|
+ printf("\taddr\t= %s\n", node_info[other_nodeid_index].link_status[i].src_ipaddr);
|
|
|
|
|
+ if (brief) {
|
|
|
|
|
+ printf("\tstatus\t= ");
|
|
|
|
|
+ for (j=0; j<s; j++) {
|
|
|
|
|
+ char status = (node_info[j].link_status[i].enabled |
|
|
|
|
|
+ (node_info[j].link_status[i].connected << 1)) + '0';
|
|
|
|
|
+ if (status == '0') {
|
|
|
|
|
+ status = 'n';
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- if (stat_ch >= '0' && stat_ch <= '9') {
|
|
|
|
|
- t = stat_ch - '0';
|
|
|
|
|
-
|
|
|
|
|
- /*
|
|
|
|
|
- * bit 0 - enabled
|
|
|
|
|
- * bit 1 - connected
|
|
|
|
|
- * bit 2 - dynconnected
|
|
|
|
|
- */
|
|
|
|
|
- if (t & 0x2) {
|
|
|
|
|
|
|
+ printf("%c", status);
|
|
|
|
|
+ }
|
|
|
|
|
+ printf("\n");
|
|
|
|
|
+ } else {
|
|
|
|
|
+ printf("\tstatus:\n");
|
|
|
|
|
+ for (j=0; j<s; j++) {
|
|
|
|
|
+ printf("\t\tnodeid: %3d:\t", node_info[j].nodeid);
|
|
|
|
|
+ if (j == local_nodeid_index) {
|
|
|
|
|
+ printf("localhost");
|
|
|
|
|
+ } else {
|
|
|
|
|
+ if (node_info[j].link_status[i].connected) {
|
|
|
printf("connected");
|
|
printf("connected");
|
|
|
} else {
|
|
} else {
|
|
|
printf("disconnected");
|
|
printf("disconnected");
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- if (!(t & 0x1)) {
|
|
|
|
|
- printf(" (not enabled)");
|
|
|
|
|
- }
|
|
|
|
|
- printf("\n");
|
|
|
|
|
- } else if (stat_ch == 'n') {
|
|
|
|
|
- printf("localhost\n");
|
|
|
|
|
- } else if (stat_ch == '?') {
|
|
|
|
|
- printf("knet error\n");
|
|
|
|
|
- } else if (stat_ch == 'd') {
|
|
|
|
|
- printf("config error\n");
|
|
|
|
|
- } else {
|
|
|
|
|
- printf("can't decode status character '%c'\n", stat_ch);
|
|
|
|
|
- }
|
|
|
|
|
- s++;
|
|
|
|
|
- }
|
|
|
|
|
- } else {
|
|
|
|
|
- printf ("\tstatus\t= %s\n", interface_status[i]);
|
|
|
|
|
-
|
|
|
|
|
- /* Set return code to 1 if status is not localhost or connected. */
|
|
|
|
|
- if ((rc == EXIT_SUCCESS) && (transport_number == TOTEM_TRANSPORT_KNET)) {
|
|
|
|
|
- len = strlen(interface_status[i]);
|
|
|
|
|
- while (s < len) {
|
|
|
|
|
- stat_ch = interface_status[i][s];
|
|
|
|
|
- if ((stat_ch != 'n') && (stat_ch != '3')) {
|
|
|
|
|
- rc = EXIT_FAILURE;
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
- s++;
|
|
|
|
|
}
|
|
}
|
|
|
|
|
+ printf("\n");
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- /* No match for value of -i option */
|
|
|
|
|
- if (no_match) {
|
|
|
|
|
- rc = EXIT_FAILURE;
|
|
|
|
|
- fprintf(stderr, "Can't match any IP address or link id\n");
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- for (i = 0; i < interface_count; i++) {
|
|
|
|
|
- free(interface_status[i]);
|
|
|
|
|
- free(interface_names[i]);
|
|
|
|
|
- }
|
|
|
|
|
- free(interface_status);
|
|
|
|
|
- free(interface_names);
|
|
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- (void)cmap_finalize (cmap_handle);
|
|
|
|
|
- (void)corosync_cfg_finalize (handle);
|
|
|
|
|
|
|
+ free(transport_str);
|
|
|
|
|
+ corosync_cfg_finalize(handle);
|
|
|
return rc;
|
|
return rc;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -445,8 +441,9 @@ static void usage_do (void)
|
|
|
printf ("A tool for displaying and configuring active parameters within corosync.\n");
|
|
printf ("A tool for displaying and configuring active parameters within corosync.\n");
|
|
|
printf ("options:\n");
|
|
printf ("options:\n");
|
|
|
printf ("\t-i\tFinds only information about the specified interface IP address or link id when used with -s..\n");
|
|
printf ("\t-i\tFinds only information about the specified interface IP address or link id when used with -s..\n");
|
|
|
- printf ("\t-s\tDisplays the status of the current links on this node(UDP/UDPU), with extended status for KNET.\n");
|
|
|
|
|
- printf ("\t-b\tDisplays the brief status of the current links on this node when used with -s.(KNET only)\n");
|
|
|
|
|
|
|
+ printf ("\t-s\tDisplays the status of the current links on this node.\n");
|
|
|
|
|
+ printf ("\t-n\tDisplays the status of the connected nodes and their links.\n");
|
|
|
|
|
+ printf ("\t-b\tDisplays the brief status of the current links on this node when used with -s.\n");
|
|
|
printf ("\t-R\tTell all instances of corosync in this cluster to reload corosync.conf.\n");
|
|
printf ("\t-R\tTell all instances of corosync in this cluster to reload corosync.conf.\n");
|
|
|
printf ("\t-L\tTell corosync to reopen all logging files.\n");
|
|
printf ("\t-L\tTell corosync to reopen all logging files.\n");
|
|
|
printf ("\t-k\tKill a node identified by node id.\n");
|
|
printf ("\t-k\tKill a node identified by node id.\n");
|
|
@@ -456,7 +453,7 @@ static void usage_do (void)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
int main (int argc, char *argv[]) {
|
|
int main (int argc, char *argv[]) {
|
|
|
- const char *options = "i:sbrRLk:a:hH";
|
|
|
|
|
|
|
+ const char *options = "i:snbrRLk:a:hH";
|
|
|
int opt;
|
|
int opt;
|
|
|
unsigned int nodeid = 0;
|
|
unsigned int nodeid = 0;
|
|
|
char interface_name[128] = "";
|
|
char interface_name[128] = "";
|
|
@@ -474,6 +471,9 @@ int main (int argc, char *argv[]) {
|
|
|
case 's':
|
|
case 's':
|
|
|
action = ACTION_LINKSTATUS_GET;
|
|
action = ACTION_LINKSTATUS_GET;
|
|
|
break;
|
|
break;
|
|
|
|
|
+ case 'n':
|
|
|
|
|
+ action = ACTION_NODESTATUS_GET;
|
|
|
|
|
+ break;
|
|
|
case 'b':
|
|
case 'b':
|
|
|
brief = 1;
|
|
brief = 1;
|
|
|
break;
|
|
break;
|
|
@@ -512,7 +512,10 @@ int main (int argc, char *argv[]) {
|
|
|
}
|
|
}
|
|
|
switch(action) {
|
|
switch(action) {
|
|
|
case ACTION_LINKSTATUS_GET:
|
|
case ACTION_LINKSTATUS_GET:
|
|
|
- rc = linkstatusget_do(interface_name, brief);
|
|
|
|
|
|
|
+ rc = nodestatusget_do(action, brief);
|
|
|
|
|
+ break;
|
|
|
|
|
+ case ACTION_NODESTATUS_GET:
|
|
|
|
|
+ rc = nodestatusget_do(action, brief);
|
|
|
break;
|
|
break;
|
|
|
case ACTION_RELOAD_CONFIG:
|
|
case ACTION_RELOAD_CONFIG:
|
|
|
rc = reload_config_do();
|
|
rc = reload_config_do();
|