📄 ctdb.c
字号:
/* ctdb control tool Copyright (C) Andrew Tridgell 2007 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>.*/#include "includes.h"#include "lib/events/events.h"#include "system/filesys.h"#include "system/network.h"#include "popt.h"#include "cmdline.h"#include "../include/ctdb.h"#include "../include/ctdb_private.h"static void usage(void);static struct { int timelimit; uint32_t vnn; int machinereadable;} options;#define TIMELIMIT() timeval_current_ofs(options.timelimit, 0)/* see if a process exists */static int control_process_exists(struct ctdb_context *ctdb, int argc, const char **argv){ uint32_t vnn, pid; int ret; if (argc < 1) { usage(); } if (sscanf(argv[0], "%u:%u", &vnn, &pid) != 2) { printf("Badly formed vnn:pid\n"); return -1; } ret = ctdb_ctrl_process_exists(ctdb, vnn, pid); if (ret == 0) { printf("%u:%u exists\n", vnn, pid); } else { printf("%u:%u does not exist\n", vnn, pid); } return ret;}/* display statistics structure */static void show_statistics(struct ctdb_statistics *s){ TALLOC_CTX *tmp_ctx = talloc_new(NULL); int i; const char *prefix=NULL; int preflen=0; const struct { const char *name; uint32_t offset; } fields[] = {#define STATISTICS_FIELD(n) { #n, offsetof(struct ctdb_statistics, n) } STATISTICS_FIELD(num_clients), STATISTICS_FIELD(frozen), STATISTICS_FIELD(recovering), STATISTICS_FIELD(client_packets_sent), STATISTICS_FIELD(client_packets_recv), STATISTICS_FIELD(node_packets_sent), STATISTICS_FIELD(node_packets_recv), STATISTICS_FIELD(keepalive_packets_sent), STATISTICS_FIELD(keepalive_packets_recv), STATISTICS_FIELD(node.req_call), STATISTICS_FIELD(node.reply_call), STATISTICS_FIELD(node.req_dmaster), STATISTICS_FIELD(node.reply_dmaster), STATISTICS_FIELD(node.reply_error), STATISTICS_FIELD(node.req_message), STATISTICS_FIELD(node.req_control), STATISTICS_FIELD(node.reply_control), STATISTICS_FIELD(client.req_call), STATISTICS_FIELD(client.req_message), STATISTICS_FIELD(client.req_control), STATISTICS_FIELD(timeouts.call), STATISTICS_FIELD(timeouts.control), STATISTICS_FIELD(timeouts.traverse), STATISTICS_FIELD(total_calls), STATISTICS_FIELD(pending_calls), STATISTICS_FIELD(lockwait_calls), STATISTICS_FIELD(pending_lockwait_calls), STATISTICS_FIELD(memory_used), STATISTICS_FIELD(max_hop_count), }; printf("CTDB version %u\n", CTDB_VERSION); for (i=0;i<ARRAY_SIZE(fields);i++) { if (strchr(fields[i].name, '.')) { preflen = strcspn(fields[i].name, ".")+1; if (!prefix || strncmp(prefix, fields[i].name, preflen) != 0) { prefix = fields[i].name; printf(" %*.*s\n", preflen-1, preflen-1, fields[i].name); } } else { preflen = 0; } printf(" %*s%-22s%*s%10u\n", preflen?4:0, "", fields[i].name+preflen, preflen?0:4, "", *(uint32_t *)(fields[i].offset+(uint8_t *)s)); } printf(" %-30s %.6f sec\n", "max_call_latency", s->max_call_latency); printf(" %-30s %.6f sec\n", "max_lockwait_latency", s->max_lockwait_latency); talloc_free(tmp_ctx);}/* display remote ctdb statistics combined from all nodes */static int control_statistics_all(struct ctdb_context *ctdb){ int ret, i; struct ctdb_statistics statistics; uint32_t *nodes; uint32_t num_nodes; nodes = ctdb_get_connected_nodes(ctdb, TIMELIMIT(), ctdb, &num_nodes); CTDB_NO_MEMORY(ctdb, nodes); ZERO_STRUCT(statistics); for (i=0;i<num_nodes;i++) { struct ctdb_statistics s1; int j; uint32_t *v1 = (uint32_t *)&s1; uint32_t *v2 = (uint32_t *)&statistics; uint32_t num_ints = offsetof(struct ctdb_statistics, __last_counter) / sizeof(uint32_t); ret = ctdb_ctrl_statistics(ctdb, nodes[i], &s1); if (ret != 0) { printf("Unable to get statistics from node %u\n", nodes[i]); return ret; } for (j=0;j<num_ints;j++) { v2[j] += v1[j]; } statistics.max_hop_count = MAX(statistics.max_hop_count, s1.max_hop_count); statistics.max_call_latency = MAX(statistics.max_call_latency, s1.max_call_latency); statistics.max_lockwait_latency = MAX(statistics.max_lockwait_latency, s1.max_lockwait_latency); } talloc_free(nodes); printf("Gathered statistics for %u nodes\n", num_nodes); show_statistics(&statistics); return 0;}/* display remote ctdb statistics */static int control_statistics(struct ctdb_context *ctdb, int argc, const char **argv){ int ret; struct ctdb_statistics statistics; if (options.vnn == CTDB_BROADCAST_ALL) { return control_statistics_all(ctdb); } ret = ctdb_ctrl_statistics(ctdb, options.vnn, &statistics); if (ret != 0) { printf("Unable to get statistics from node %u\n", options.vnn); return ret; } show_statistics(&statistics); return 0;}/* reset remote ctdb statistics */static int control_statistics_reset(struct ctdb_context *ctdb, int argc, const char **argv){ int ret; ret = ctdb_statistics_reset(ctdb, options.vnn); if (ret != 0) { printf("Unable to reset statistics on node %u\n", options.vnn); return ret; } return 0;}/* display remote ctdb status */static int control_status(struct ctdb_context *ctdb, int argc, const char **argv){ int i, ret; struct ctdb_vnn_map *vnnmap=NULL; struct ctdb_node_map *nodemap=NULL; uint32_t recmode, recmaster; uint32_t myvnn; myvnn = ctdb_ctrl_getvnn(ctdb, TIMELIMIT(), options.vnn); ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.vnn, ctdb, &nodemap); if (ret != 0) { printf("Unable to get nodemap from node %u\n", options.vnn); return ret; } if(options.machinereadable){ printf(":Node:IP:Disonnected:Disabled:Permanently Disabled:\n"); for(i=0;i<nodemap->num;i++){ printf(":%d:%s:%d:%d:%d:\n", nodemap->nodes[i].vnn, inet_ntoa(nodemap->nodes[i].sin.sin_addr), !!(nodemap->nodes[i].flags&NODE_FLAGS_DISCONNECTED), !!(nodemap->nodes[i].flags&NODE_FLAGS_UNHEALTHY), !!(nodemap->nodes[i].flags&NODE_FLAGS_PERMANENTLY_DISABLED)); } return 0; } printf("Number of nodes:%d\n", nodemap->num); for(i=0;i<nodemap->num;i++){ static const struct { uint32_t flag; const char *name; } flag_names[] = { { NODE_FLAGS_DISCONNECTED, "DISCONNECTED" }, { NODE_FLAGS_PERMANENTLY_DISABLED, "DISABLED" }, { NODE_FLAGS_BANNED, "BANNED" }, { NODE_FLAGS_UNHEALTHY, "UNHEALTHY" }, }; char *flags_str = NULL; int j; for (j=0;j<ARRAY_SIZE(flag_names);j++) { if (nodemap->nodes[i].flags & flag_names[j].flag) { if (flags_str == NULL) { flags_str = talloc_strdup(ctdb, flag_names[j].name); } else { flags_str = talloc_asprintf_append(flags_str, "|%s", flag_names[j].name); } CTDB_NO_MEMORY_FATAL(ctdb, flags_str); } } if (flags_str == NULL) { flags_str = talloc_strdup(ctdb, "OK"); CTDB_NO_MEMORY_FATAL(ctdb, flags_str); } printf("vnn:%d %-16s %s%s\n", nodemap->nodes[i].vnn, inet_ntoa(nodemap->nodes[i].sin.sin_addr), flags_str, nodemap->nodes[i].vnn == myvnn?" (THIS NODE)":""); talloc_free(flags_str); } ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.vnn, ctdb, &vnnmap); if (ret != 0) { printf("Unable to get vnnmap from node %u\n", options.vnn); return ret; } printf("Generation:%d\n",vnnmap->generation); printf("Size:%d\n",vnnmap->size); for(i=0;i<vnnmap->size;i++){ printf("hash:%d lmaster:%d\n", i, vnnmap->map[i]); } ret = ctdb_ctrl_getrecmode(ctdb, TIMELIMIT(), options.vnn, &recmode); if (ret != 0) { printf("Unable to get recmode from node %u\n", options.vnn); return ret; } printf("Recovery mode:%s (%d)\n",recmode==CTDB_RECOVERY_NORMAL?"NORMAL":"RECOVERY",recmode); ret = ctdb_ctrl_getrecmaster(ctdb, TIMELIMIT(), options.vnn, &recmaster); if (ret != 0) { printf("Unable to get recmaster from node %u\n", options.vnn); return ret; } printf("Recovery master:%d\n",recmaster); return 0;}/* kill a tcp connection */static int kill_tcp(struct ctdb_context *ctdb, int argc, const char **argv){ int i, ret, numrst; struct sockaddr_in src, dst; if (argc < 3) { usage(); } if (!parse_ip_port(argv[0], &src)) { printf("Bad IP:port '%s'\n", argv[0]); return -1; } if (!parse_ip_port(argv[1], &dst)) { printf("Bad IP:port '%s'\n", argv[1]); return -1; } numrst = strtoul(argv[2], NULL, 0); for (i=0;i<numrst;i++) { ret = ctdb_sys_kill_tcp(ctdb->ev, &src, &dst); printf("ret:%d\n", ret); if (ret==0) { return 0; } } return -1;}/* send a tcp tickle ack */static int tickle_tcp(struct ctdb_context *ctdb, int argc, const char **argv){ int ret; struct sockaddr_in src, dst; if (argc < 2) { usage(); } if (!parse_ip_port(argv[0], &src)) { printf("Bad IP:port '%s'\n", argv[0]); return -1; } if (!parse_ip_port(argv[1], &dst)) { printf("Bad IP:port '%s'\n", argv[1]); return -1; } ret = ctdb_sys_send_tcp(&src, &dst, 0, 0, 0); if (ret==0) { return 0; } printf("Error while sending tickle ack\n"); return -1;}/* display public ip status */static int control_ip(struct ctdb_context *ctdb, int argc, const char **argv){ int i, ret; struct ctdb_all_public_ips *ips; uint32_t myvnn; myvnn = ctdb_ctrl_getvnn(ctdb, TIMELIMIT(), options.vnn); ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), options.vnn, ctdb, &ips); if (ret != 0) { printf("Unable to get public ips from node %u\n", options.vnn); return ret; } if(options.machinereadable){ printf(":Public IP:Node:\n"); for(i=0;i<ips->num;i++){ printf(":%s:%d:\n", inet_ntoa(ips->ips[i].sin.sin_addr), ips->ips[i].takeover_vnn); } return 0; } printf("Number of nodes:%d\n", ips->num); for(i=0;i<ips->num;i++){ printf("%-16s %d\n", inet_ntoa(ips->ips[i].sin.sin_addr), ips->ips[i].takeover_vnn); } return 0;}/* display pid of a ctdb daemon */static int control_getpid(struct ctdb_context *ctdb, int argc, const char **argv){ uint32_t pid; int ret; ret = ctdb_ctrl_getpid(ctdb, TIMELIMIT(), options.vnn, &pid); if (ret != 0) { printf("Unable to get daemon pid from node %u\n", options.vnn); return ret; } printf("Pid:%d\n", pid); return 0;}/* disable a remote node */static int control_disable(struct ctdb_context *ctdb, int argc, const char **argv){ int ret; ret = ctdb_ctrl_modflags(ctdb, TIMELIMIT(), options.vnn, NODE_FLAGS_PERMANENTLY_DISABLED, 0); if (ret != 0) { printf("Unable to disable node %u\n", options.vnn); return ret; } return 0;}/* enable a disabled remote node */static int control_enable(struct ctdb_context *ctdb, int argc, const char **argv){ int ret; ret = ctdb_ctrl_modflags(ctdb, TIMELIMIT(), options.vnn, 0, NODE_FLAGS_PERMANENTLY_DISABLED); if (ret != 0) { printf("Unable to enable node %u\n", options.vnn); return ret; } return 0;}/* ban a node from the cluster */static int control_ban(struct ctdb_context *ctdb, int argc, const char **argv){ int ret; uint32_t recmaster; struct ctdb_ban_info b; TDB_DATA data; uint32_t ban_time; if (argc < 1) { usage(); } ban_time = strtoul(argv[0], NULL, 0); ret = ctdb_ctrl_getrecmaster(ctdb, TIMELIMIT(), options.vnn, &recmaster); if (ret != 0) { DEBUG(0,("Failed to find the recmaster\n")); return -1; } b.vnn = options.vnn; b.ban_time = ban_time; data.dptr = (uint8_t *)&b; data.dsize = sizeof(b); ret = ctdb_send_message(ctdb, recmaster, CTDB_SRVID_BAN_NODE, data); if (ret != 0) { DEBUG(0,("Failed to tell the recmaster to ban node %u\n", options.vnn)); return -1; } return 0;}/* unban a node from the cluster */static int control_unban(struct ctdb_context *ctdb, int argc, const char **argv){ int ret; uint32_t recmaster; TDB_DATA data; ret = ctdb_ctrl_getrecmaster(ctdb, TIMELIMIT(), options.vnn, &recmaster); if (ret != 0) { DEBUG(0,("Failed to find the recmaster\n")); return -1; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -