| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454 |
- /*
- * Copyright (c) 2006-2019 Red Hat, Inc.
- *
- * All rights reserved.
- *
- * Author: Steven Dake <sdake@redhat.com>
- *
- * This software licensed under BSD license, the text of which follows:
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- * - Neither the name of the MontaVista Software, Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
- #include <config.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <errno.h>
- #include <unistd.h>
- #include <string.h>
- #include <pthread.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <sys/select.h>
- #include <sys/un.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <corosync/corotypes.h>
- #include <corosync/totem/totem.h>
- #include <corosync/cfg.h>
- #include <corosync/cmap.h>
- #define cs_repeat(result, max, code) \
- do { \
- int counter = 0; \
- do { \
- result = code; \
- if (result == CS_ERR_TRY_AGAIN) { \
- sleep(1); \
- counter++; \
- } else { \
- break; \
- } \
- } while (counter < max); \
- } while (0)
- enum user_action {
- ACTION_NOOP=0,
- ACTION_LINKSTATUS_GET,
- ACTION_RELOAD_CONFIG,
- ACTION_REOPEN_LOG_FILES,
- ACTION_SHUTDOW,
- ACTION_SHOWADDR,
- ACTION_KILL_NODE,
- };
- static int node_compare(const void *aptr, const void *bptr)
- {
- uint32_t a,b;
- a = *(uint32_t *)aptr;
- b = *(uint32_t *)bptr;
- return a > b;
- }
- static int
- linkstatusget_do (char *interface_name, int brief)
- {
- cs_error_t result;
- corosync_cfg_handle_t 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];
- unsigned int i;
- cmap_iter_handle_t iter;
- unsigned int nodeid;
- int nodeid_match_guard;
- cmap_value_types_t type;
- size_t value_len;
- int rc = 0;
- int len, s = 0, t;
- printf ("Printing link status.\n");
- result = corosync_cfg_initialize (&handle, NULL);
- if (result != CS_OK) {
- printf ("Could not initialize corosync configuration API error %d\n", result);
- exit (1);
- }
- result = cmap_initialize (&cmap_handle);
- if (result != CS_OK) {
- printf ("Could not initialize corosync cmap API error %d\n", result);
- exit (1);
- }
- /* Get a list of nodes. We do it this way rather than using votequorum as cfgtool
- * needs to be independent of quorum type
- */
- result = cmap_iter_init(cmap_handle, "nodelist.node.", &iter);
- if (result != CS_OK) {
- printf ("Could not get nodelist from cmap. error %d\n", result);
- exit (1);
- }
- while ((cmap_iter_next(cmap_handle, iter, iter_key, &value_len, &type)) == CS_OK) {
- nodeid_match_guard = 0;
- if (sscanf(iter_key, "nodelist.node.%*u.nodeid%n", &nodeid_match_guard) != 0) {
- continue;
- }
- /* check for exact match */
- if (nodeid_match_guard != strlen(iter_key)) {
- continue;
- }
- if (cmap_get_uint32(cmap_handle, iter_key, &nodeid) == CS_OK) {
- 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.
- */
- qsort(nodeid_list, s, sizeof(uint32_t), node_compare);
- result = corosync_cfg_local_get(handle, &nodeid);
- if (result != CS_OK) {
- printf ("Could not get the local node id, the error is: %d\n", result);
- }
- else {
- printf ("Local node ID " CS_PRI_NODE_ID "\n", nodeid);
- }
- result = corosync_cfg_ring_status_get (handle,
- &interface_names,
- &interface_status,
- &interface_count);
- if (result != CS_OK) {
- printf ("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;
- }
- if (show_current_iface) {
- 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) && (strcmp(interface_status[i], "OK") != 0)) {
- len = strlen(interface_status[i]);
- printf ("\tstatus:\n");
- while (s < len) {
- nodeid = nodeid_list[s];
- t = interface_status[i][s] - '0';
- s++;
- printf("\t\tnodeid %2d:\t", nodeid);
- printf("link enabled:%d\t", t&1? 1 : 0);
- printf("link connected:%d\n", t&2? 1: 0);
- }
- } else {
- printf ("\tstatus\t= %s\n", interface_status[i]);
- }
- }
- }
- 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);
- return rc;
- }
- static int reload_config_do (void)
- {
- cs_error_t result;
- corosync_cfg_handle_t handle;
- int rc;
- rc = 0;
- printf ("Reloading corosync.conf...\n");
- result = corosync_cfg_initialize (&handle, NULL);
- if (result != CS_OK) {
- printf ("Could not initialize corosync configuration API error %s\n", cs_strerror(result));
- exit (1);
- }
- result = corosync_cfg_reload_config (handle);
- if (result != CS_OK) {
- printf ("Could not reload configuration. Error %s\n", cs_strerror(result));
- rc = (int)result;
- }
- else {
- printf ("Done\n");
- }
- (void)corosync_cfg_finalize (handle);
- return (rc);
- }
- static int reopen_log_files_do (void)
- {
- cs_error_t result;
- corosync_cfg_handle_t handle;
- int rc;
- rc = 0;
- result = corosync_cfg_initialize (&handle, NULL);
- if (result != CS_OK) {
- fprintf (stderr, "Could not initialize corosync configuration API error %s\n", cs_strerror(result));
- exit (1);
- }
- result = corosync_cfg_reopen_log_files (handle);
- if (result != CS_OK) {
- fprintf (stderr, "Could not reopen corosync logging files. Error %s\n", cs_strerror(result));
- rc = (int)result;
- }
- (void)corosync_cfg_finalize (handle);
- return (rc);
- }
- static void shutdown_do(void)
- {
- cs_error_t result;
- corosync_cfg_handle_t handle;
- corosync_cfg_callbacks_t callbacks;
- callbacks.corosync_cfg_shutdown_callback = NULL;
- result = corosync_cfg_initialize (&handle, &callbacks);
- if (result != CS_OK) {
- printf ("Could not initialize corosync configuration API error %d\n", result);
- exit (1);
- }
- printf ("Shutting down corosync\n");
- cs_repeat(result, 30, corosync_cfg_try_shutdown (handle, COROSYNC_CFG_SHUTDOWN_FLAG_REQUEST));
- if (result != CS_OK) {
- printf ("Could not shutdown (error = %d)\n", result);
- }
- (void)corosync_cfg_finalize (handle);
- }
- static void showaddrs_do(unsigned int nodeid)
- {
- cs_error_t result;
- corosync_cfg_handle_t handle;
- int numaddrs;
- int i;
- corosync_cfg_node_address_t addrs[INTERFACE_MAX];
- result = corosync_cfg_initialize (&handle, NULL);
- if (result != CS_OK) {
- printf ("Could not initialize corosync configuration API error %d\n", result);
- exit (1);
- }
- if (corosync_cfg_get_node_addrs(handle, nodeid, INTERFACE_MAX, &numaddrs, addrs) == CS_OK) {
- for (i=0; i<numaddrs; i++) {
- char buf[INET6_ADDRSTRLEN];
- struct sockaddr_storage *ss = (struct sockaddr_storage *)addrs[i].address;
- struct sockaddr_in *sin = (struct sockaddr_in *)addrs[i].address;
- struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addrs[i].address;
- void *saddr;
- if (!ss->ss_family) {
- continue;
- }
- if (ss->ss_family == AF_INET6) {
- saddr = &sin6->sin6_addr;
- } else {
- saddr = &sin->sin_addr;
- }
- inet_ntop(ss->ss_family, saddr, buf, sizeof(buf));
- if (i != 0) {
- printf(" ");
- }
- printf("%s", buf);
- }
- printf("\n");
- }
- (void)corosync_cfg_finalize (handle);
- }
- static void killnode_do(unsigned int nodeid)
- {
- cs_error_t result;
- corosync_cfg_handle_t handle;
- printf ("Killing node " CS_PRI_NODE_ID "\n", nodeid);
- result = corosync_cfg_initialize (&handle, NULL);
- if (result != CS_OK) {
- printf ("Could not initialize corosync configuration API error %d\n", result);
- exit (1);
- }
- result = corosync_cfg_kill_node (handle, nodeid, "Killed by corosync-cfgtool");
- if (result != CS_OK) {
- printf ("Could not kill node (error = %d)\n", result);
- }
- (void)corosync_cfg_finalize (handle);
- }
- static void usage_do (void)
- {
- printf ("corosync-cfgtool [[-i <interface ip>] [-b] -s] [-R] [-L] [-k nodeid] [-a nodeid] [-h] [-H]\n\n");
- printf ("A tool for displaying and configuring active parameters within corosync.\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-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-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-k\tKill a node identified by node id.\n");
- printf ("\t-a\tDisplay the IP address(es) of a node\n");
- printf ("\t-h\tPrint basic usage.\n");
- printf ("\t-H\tShutdown corosync cleanly on this node.\n");
- }
- int main (int argc, char *argv[]) {
- const char *options = "i:sbrRLk:a:hH";
- int opt;
- unsigned int nodeid = 0;
- char interface_name[128] = "";
- int rc = 0;
- enum user_action action = ACTION_NOOP;
- int brief = 0;
- while ( (opt = getopt(argc, argv, options)) != -1 ) {
- switch (opt) {
- case 'i':
- strncpy(interface_name, optarg, sizeof(interface_name));
- interface_name[sizeof(interface_name) - 1] = '\0';
- break;
- case 's':
- action = ACTION_LINKSTATUS_GET;
- break;
- case 'b':
- brief = 1;
- break;
- case 'R':
- action = ACTION_RELOAD_CONFIG;
- break;
- case 'L':
- action = ACTION_REOPEN_LOG_FILES;
- break;
- case 'k':
- nodeid = atoi (optarg);
- action = ACTION_KILL_NODE;
- break;
- case 'H':
- action = ACTION_SHUTDOW;
- break;
- case 'a':
- nodeid = atoi (optarg);
- action = ACTION_SHOWADDR;
- break;
- case '?':
- return (EXIT_FAILURE);
- break;
- case 'h':
- default:
- break;
- }
- }
- switch(action) {
- case ACTION_LINKSTATUS_GET:
- rc = linkstatusget_do(interface_name, brief);
- break;
- case ACTION_RELOAD_CONFIG:
- rc = reload_config_do();
- break;
- case ACTION_REOPEN_LOG_FILES:
- rc = reopen_log_files_do();
- break;
- case ACTION_KILL_NODE:
- killnode_do(nodeid);
- break;
- case ACTION_SHUTDOW:
- shutdown_do();
- break;
- case ACTION_SHOWADDR:
- showaddrs_do(nodeid);
- break;
- case ACTION_NOOP:
- default:
- usage_do();
- break;
- }
- return (rc);
- }
|