4 Copyright (C) Andrew Tridgell 2007
5 Copyright (C) Ronnie Sahlberg 2007
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, see <http://www.gnu.org/licenses/>.
22 #include "lib/events/events.h"
23 #include "system/time.h"
24 #include "system/filesys.h"
25 #include "system/network.h"
26 #include "system/locale.h"
29 #include "../include/ctdb.h"
30 #include "../include/ctdb_private.h"
31 #include "../common/rb_tree.h"
35 #define ERR_TIMEOUT 20 /* timed out trying to reach node */
36 #define ERR_NONODE 21 /* node does not exist */
37 #define ERR_DISNODE 22 /* node is disconnected */
39 static void usage(void);
48 #define TIMELIMIT() timeval_current_ofs(options.timelimit, 0)
51 static int control_version(struct ctdb_context *ctdb, int argc, const char **argv)
54 #define XSTR(x) STR(x)
55 printf("CTDB version: %s\n", XSTR(CTDB_VERS));
62 verify that a node exists and is reachable
64 static void verify_node(struct ctdb_context *ctdb)
67 struct ctdb_node_map *nodemap=NULL;
69 if (options.pnn == CTDB_CURRENT_NODE) {
72 if (options.pnn == CTDB_BROADCAST_ALL) {
76 /* verify the node exists */
77 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
78 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
81 if (options.pnn >= nodemap->num) {
82 DEBUG(DEBUG_ERR, ("Node %u does not exist\n", options.pnn));
85 if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_DELETED) {
86 DEBUG(DEBUG_ERR, ("Node %u is DELETED\n", options.pnn));
89 if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_DISCONNECTED) {
90 DEBUG(DEBUG_ERR, ("Node %u is DISCONNECTED\n", options.pnn));
94 /* verify we can access the node */
95 ret = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
97 DEBUG(DEBUG_ERR,("Can not ban node. Node is not operational.\n"));
103 check if a database exists
105 static int db_exists(struct ctdb_context *ctdb, const char *db_name)
108 struct ctdb_dbid_map *dbmap=NULL;
110 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
112 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
116 for(i=0;i<dbmap->num;i++){
119 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
120 if (!strcmp(name, db_name)) {
129 see if a process exists
131 static int control_process_exists(struct ctdb_context *ctdb, int argc, const char **argv)
139 if (sscanf(argv[0], "%u:%u", &pnn, &pid) != 2) {
140 DEBUG(DEBUG_ERR, ("Badly formed pnn:pid\n"));
144 ret = ctdb_ctrl_process_exists(ctdb, pnn, pid);
146 printf("%u:%u exists\n", pnn, pid);
148 printf("%u:%u does not exist\n", pnn, pid);
154 display statistics structure
156 static void show_statistics(struct ctdb_statistics *s)
158 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
160 const char *prefix=NULL;
166 #define STATISTICS_FIELD(n) { #n, offsetof(struct ctdb_statistics, n) }
167 STATISTICS_FIELD(num_clients),
168 STATISTICS_FIELD(frozen),
169 STATISTICS_FIELD(recovering),
170 STATISTICS_FIELD(client_packets_sent),
171 STATISTICS_FIELD(client_packets_recv),
172 STATISTICS_FIELD(node_packets_sent),
173 STATISTICS_FIELD(node_packets_recv),
174 STATISTICS_FIELD(keepalive_packets_sent),
175 STATISTICS_FIELD(keepalive_packets_recv),
176 STATISTICS_FIELD(node.req_call),
177 STATISTICS_FIELD(node.reply_call),
178 STATISTICS_FIELD(node.req_dmaster),
179 STATISTICS_FIELD(node.reply_dmaster),
180 STATISTICS_FIELD(node.reply_error),
181 STATISTICS_FIELD(node.req_message),
182 STATISTICS_FIELD(node.req_control),
183 STATISTICS_FIELD(node.reply_control),
184 STATISTICS_FIELD(client.req_call),
185 STATISTICS_FIELD(client.req_message),
186 STATISTICS_FIELD(client.req_control),
187 STATISTICS_FIELD(timeouts.call),
188 STATISTICS_FIELD(timeouts.control),
189 STATISTICS_FIELD(timeouts.traverse),
190 STATISTICS_FIELD(total_calls),
191 STATISTICS_FIELD(pending_calls),
192 STATISTICS_FIELD(lockwait_calls),
193 STATISTICS_FIELD(pending_lockwait_calls),
194 STATISTICS_FIELD(childwrite_calls),
195 STATISTICS_FIELD(pending_childwrite_calls),
196 STATISTICS_FIELD(memory_used),
197 STATISTICS_FIELD(max_hop_count),
199 printf("CTDB version %u\n", CTDB_VERSION);
200 for (i=0;i<ARRAY_SIZE(fields);i++) {
201 if (strchr(fields[i].name, '.')) {
202 preflen = strcspn(fields[i].name, ".")+1;
203 if (!prefix || strncmp(prefix, fields[i].name, preflen) != 0) {
204 prefix = fields[i].name;
205 printf(" %*.*s\n", preflen-1, preflen-1, fields[i].name);
210 printf(" %*s%-22s%*s%10u\n",
212 fields[i].name+preflen,
214 *(uint32_t *)(fields[i].offset+(uint8_t *)s));
216 printf(" %-30s %.6f sec\n", "max_reclock_ctdbd", s->reclock.ctdbd);
217 printf(" %-30s %.6f sec\n", "max_reclock_recd", s->reclock.recd);
219 printf(" %-30s %.6f sec\n", "max_call_latency", s->max_call_latency);
220 printf(" %-30s %.6f sec\n", "max_lockwait_latency", s->max_lockwait_latency);
221 printf(" %-30s %.6f sec\n", "max_childwrite_latency", s->max_childwrite_latency);
222 talloc_free(tmp_ctx);
226 display remote ctdb statistics combined from all nodes
228 static int control_statistics_all(struct ctdb_context *ctdb)
231 struct ctdb_statistics statistics;
235 nodes = ctdb_get_connected_nodes(ctdb, TIMELIMIT(), ctdb, &num_nodes);
236 CTDB_NO_MEMORY(ctdb, nodes);
238 ZERO_STRUCT(statistics);
240 for (i=0;i<num_nodes;i++) {
241 struct ctdb_statistics s1;
243 uint32_t *v1 = (uint32_t *)&s1;
244 uint32_t *v2 = (uint32_t *)&statistics;
246 offsetof(struct ctdb_statistics, __last_counter) / sizeof(uint32_t);
247 ret = ctdb_ctrl_statistics(ctdb, nodes[i], &s1);
249 DEBUG(DEBUG_ERR, ("Unable to get statistics from node %u\n", nodes[i]));
252 for (j=0;j<num_ints;j++) {
255 statistics.max_hop_count =
256 MAX(statistics.max_hop_count, s1.max_hop_count);
257 statistics.max_call_latency =
258 MAX(statistics.max_call_latency, s1.max_call_latency);
259 statistics.max_lockwait_latency =
260 MAX(statistics.max_lockwait_latency, s1.max_lockwait_latency);
263 printf("Gathered statistics for %u nodes\n", num_nodes);
264 show_statistics(&statistics);
269 display remote ctdb statistics
271 static int control_statistics(struct ctdb_context *ctdb, int argc, const char **argv)
274 struct ctdb_statistics statistics;
276 if (options.pnn == CTDB_BROADCAST_ALL) {
277 return control_statistics_all(ctdb);
280 ret = ctdb_ctrl_statistics(ctdb, options.pnn, &statistics);
282 DEBUG(DEBUG_ERR, ("Unable to get statistics from node %u\n", options.pnn));
285 show_statistics(&statistics);
291 reset remote ctdb statistics
293 static int control_statistics_reset(struct ctdb_context *ctdb, int argc, const char **argv)
297 ret = ctdb_statistics_reset(ctdb, options.pnn);
299 DEBUG(DEBUG_ERR, ("Unable to reset statistics on node %u\n", options.pnn));
307 display uptime of remote node
309 static int control_uptime(struct ctdb_context *ctdb, int argc, const char **argv)
312 struct ctdb_uptime *uptime = NULL;
313 int tmp, days, hours, minutes, seconds;
315 ret = ctdb_ctrl_uptime(ctdb, ctdb, TIMELIMIT(), options.pnn, &uptime);
317 DEBUG(DEBUG_ERR, ("Unable to get uptime from node %u\n", options.pnn));
321 if (options.machinereadable){
322 printf(":Current Node Time:Ctdb Start Time:Last Recovery Time:Last Recovery Duration:\n");
323 printf(":%u:%u:%u:%lf\n",
324 (unsigned int)uptime->current_time.tv_sec,
325 (unsigned int)uptime->ctdbd_start_time.tv_sec,
326 (unsigned int)uptime->last_recovery_finished.tv_sec,
327 timeval_delta(&uptime->last_recovery_finished,
328 &uptime->last_recovery_started)
333 printf("Current time of node : %s", ctime(&uptime->current_time.tv_sec));
335 tmp = uptime->current_time.tv_sec - uptime->ctdbd_start_time.tv_sec;
343 printf("Ctdbd start time : (%03d %02d:%02d:%02d) %s", days, hours, minutes, seconds, ctime(&uptime->ctdbd_start_time.tv_sec));
345 tmp = uptime->current_time.tv_sec - uptime->last_recovery_finished.tv_sec;
353 printf("Time of last recovery : (%03d %02d:%02d:%02d) %s", days, hours, minutes, seconds, ctime(&uptime->last_recovery_finished.tv_sec));
355 printf("Duration of last recovery : %lf seconds\n",
356 timeval_delta(&uptime->last_recovery_finished,
357 &uptime->last_recovery_started));
363 show the PNN of the current node
365 static int control_pnn(struct ctdb_context *ctdb, int argc, const char **argv)
369 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
371 DEBUG(DEBUG_ERR, ("Unable to get pnn from local node."));
375 printf("PNN:%d\n", mypnn);
381 struct pnn_node *next;
386 static struct pnn_node *read_nodes_file(TALLOC_CTX *mem_ctx)
388 const char *nodes_list;
392 struct pnn_node *pnn_nodes = NULL;
393 struct pnn_node *pnn_node;
394 struct pnn_node *tmp_node;
396 /* read the nodes file */
397 nodes_list = getenv("CTDB_NODES");
398 if (nodes_list == NULL) {
399 nodes_list = "/etc/ctdb/nodes";
401 lines = file_lines_load(nodes_list, &nlines, mem_ctx);
405 while (nlines > 0 && strcmp(lines[nlines-1], "") == 0) {
408 for (i=0, pnn=0; i<nlines; i++) {
412 /* strip leading spaces */
413 while((*node == ' ') || (*node == '\t')) {
420 if (strcmp(node, "") == 0) {
423 pnn_node = talloc(mem_ctx, struct pnn_node);
424 pnn_node->pnn = pnn++;
425 pnn_node->addr = talloc_strdup(pnn_node, node);
426 pnn_node->next = pnn_nodes;
427 pnn_nodes = pnn_node;
430 /* swap them around so we return them in incrementing order */
431 pnn_node = pnn_nodes;
435 pnn_node = pnn_node->next;
437 tmp_node->next = pnn_nodes;
438 pnn_nodes = tmp_node;
445 show the PNN of the current node
446 discover the pnn by loading the nodes file and try to bind to all
447 addresses one at a time until the ip address is found.
449 static int control_xpnn(struct ctdb_context *ctdb, int argc, const char **argv)
451 TALLOC_CTX *mem_ctx = talloc_new(NULL);
452 struct pnn_node *pnn_nodes;
453 struct pnn_node *pnn_node;
455 pnn_nodes = read_nodes_file(mem_ctx);
456 if (pnn_nodes == NULL) {
457 DEBUG(DEBUG_ERR,("Failed to read nodes file\n"));
458 talloc_free(mem_ctx);
462 for(pnn_node=pnn_nodes;pnn_node;pnn_node=pnn_node->next) {
465 if (parse_ip(pnn_node->addr, NULL, 63999, &addr) == 0) {
466 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s' in nodes file\n", pnn_node->addr));
467 talloc_free(mem_ctx);
471 if (ctdb_sys_have_ip(&addr)) {
472 printf("PNN:%d\n", pnn_node->pnn);
473 talloc_free(mem_ctx);
478 printf("Failed to detect which PNN this node is\n");
479 talloc_free(mem_ctx);
484 display remote ctdb status
486 static int control_status(struct ctdb_context *ctdb, int argc, const char **argv)
489 struct ctdb_vnn_map *vnnmap=NULL;
490 struct ctdb_node_map *nodemap=NULL;
491 uint32_t recmode, recmaster;
494 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
499 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
501 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
505 if(options.machinereadable){
506 printf(":Node:IP:Disconnected:Banned:Disabled:Unhealthy:Stopped:\n");
507 for(i=0;i<nodemap->num;i++){
508 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
511 printf(":%d:%s:%d:%d:%d:%d:%d:\n", nodemap->nodes[i].pnn,
512 ctdb_addr_to_str(&nodemap->nodes[i].addr),
513 !!(nodemap->nodes[i].flags&NODE_FLAGS_DISCONNECTED),
514 !!(nodemap->nodes[i].flags&NODE_FLAGS_BANNED),
515 !!(nodemap->nodes[i].flags&NODE_FLAGS_PERMANENTLY_DISABLED),
516 !!(nodemap->nodes[i].flags&NODE_FLAGS_UNHEALTHY),
517 !!(nodemap->nodes[i].flags&NODE_FLAGS_STOPPED));
522 printf("Number of nodes:%d\n", nodemap->num);
523 for(i=0;i<nodemap->num;i++){
524 static const struct {
528 { NODE_FLAGS_DISCONNECTED, "DISCONNECTED" },
529 { NODE_FLAGS_PERMANENTLY_DISABLED, "DISABLED" },
530 { NODE_FLAGS_BANNED, "BANNED" },
531 { NODE_FLAGS_UNHEALTHY, "UNHEALTHY" },
532 { NODE_FLAGS_DELETED, "DELETED" },
533 { NODE_FLAGS_STOPPED, "STOPPED" },
535 char *flags_str = NULL;
538 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
541 for (j=0;j<ARRAY_SIZE(flag_names);j++) {
542 if (nodemap->nodes[i].flags & flag_names[j].flag) {
543 if (flags_str == NULL) {
544 flags_str = talloc_strdup(ctdb, flag_names[j].name);
546 flags_str = talloc_asprintf_append(flags_str, "|%s",
549 CTDB_NO_MEMORY_FATAL(ctdb, flags_str);
552 if (flags_str == NULL) {
553 flags_str = talloc_strdup(ctdb, "OK");
554 CTDB_NO_MEMORY_FATAL(ctdb, flags_str);
556 printf("pnn:%d %-16s %s%s\n", nodemap->nodes[i].pnn,
557 ctdb_addr_to_str(&nodemap->nodes[i].addr),
559 nodemap->nodes[i].pnn == mypnn?" (THIS NODE)":"");
560 talloc_free(flags_str);
563 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &vnnmap);
565 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n", options.pnn));
568 if (vnnmap->generation == INVALID_GENERATION) {
569 printf("Generation:INVALID\n");
571 printf("Generation:%d\n",vnnmap->generation);
573 printf("Size:%d\n",vnnmap->size);
574 for(i=0;i<vnnmap->size;i++){
575 printf("hash:%d lmaster:%d\n", i, vnnmap->map[i]);
578 ret = ctdb_ctrl_getrecmode(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmode);
580 DEBUG(DEBUG_ERR, ("Unable to get recmode from node %u\n", options.pnn));
583 printf("Recovery mode:%s (%d)\n",recmode==CTDB_RECOVERY_NORMAL?"NORMAL":"RECOVERY",recmode);
585 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
587 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
590 printf("Recovery master:%d\n",recmaster);
597 struct natgw_node *next;
602 display the list of nodes belonging to this natgw configuration
604 static int control_natgwlist(struct ctdb_context *ctdb, int argc, const char **argv)
607 const char *natgw_list;
610 struct natgw_node *natgw_nodes = NULL;
611 struct natgw_node *natgw_node;
612 struct ctdb_node_map *nodemap=NULL;
615 /* read the natgw nodes file into a linked list */
616 natgw_list = getenv("NATGW_NODES");
617 if (natgw_list == NULL) {
618 natgw_list = "/etc/ctdb/natgw_nodes";
620 lines = file_lines_load(natgw_list, &nlines, ctdb);
622 ctdb_set_error(ctdb, "Failed to load natgw node list '%s'\n", natgw_list);
625 while (nlines > 0 && strcmp(lines[nlines-1], "") == 0) {
628 for (i=0;i<nlines;i++) {
632 /* strip leading spaces */
633 while((*node == ' ') || (*node == '\t')) {
639 if (strcmp(node, "") == 0) {
642 natgw_node = talloc(ctdb, struct natgw_node);
643 natgw_node->addr = talloc_strdup(natgw_node, node);
644 CTDB_NO_MEMORY(ctdb, natgw_node->addr);
645 natgw_node->next = natgw_nodes;
646 natgw_nodes = natgw_node;
649 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
651 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node.\n"));
656 while(i<nodemap->num) {
657 for(natgw_node=natgw_nodes;natgw_node;natgw_node=natgw_node->next) {
658 if (!strcmp(natgw_node->addr, ctdb_addr_to_str(&nodemap->nodes[i].addr))) {
663 /* this node was not in the natgw so we just remove it from
666 if ((natgw_node == NULL)
667 || (nodemap->nodes[i].flags & NODE_FLAGS_DISCONNECTED) ) {
670 for (j=i+1; j<nodemap->num; j++) {
671 nodemap->nodes[j-1] = nodemap->nodes[j];
680 /* print the natgw master
681 * we dont allow STOPPED or DELETED nodes to become the natgwmaster
683 for(i=0;i<nodemap->num;i++){
684 if (!(nodemap->nodes[i].flags & (NODE_FLAGS_DISCONNECTED|NODE_FLAGS_STOPPED|NODE_FLAGS_DELETED))) {
685 printf("%d %s\n", nodemap->nodes[i].pnn,ctdb_addr_to_str(&nodemap->nodes[i].addr));
689 /* unless all nodes are STOPPED, when we pick one anyway */
690 if (i == nodemap->num) {
691 for(i=0;i<nodemap->num;i++){
692 if (!(nodemap->nodes[i].flags & (NODE_FLAGS_DISCONNECTED|NODE_FLAGS_DELETED))) {
693 printf("%d %s\n", nodemap->nodes[i].pnn, ctdb_addr_to_str(&nodemap->nodes[i].addr));
697 /* or if we still can not find any */
698 if (i == nodemap->num) {
699 printf("-1 0.0.0.0\n");
703 /* print the pruned list of nodes belonging to this natgw list */
704 for(i=0;i<nodemap->num;i++){
705 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
708 printf(":%d:%s:%d:%d:%d:%d:%d\n", nodemap->nodes[i].pnn,
709 ctdb_addr_to_str(&nodemap->nodes[i].addr),
710 !!(nodemap->nodes[i].flags&NODE_FLAGS_DISCONNECTED),
711 !!(nodemap->nodes[i].flags&NODE_FLAGS_BANNED),
712 !!(nodemap->nodes[i].flags&NODE_FLAGS_PERMANENTLY_DISABLED),
713 !!(nodemap->nodes[i].flags&NODE_FLAGS_UNHEALTHY),
714 !!(nodemap->nodes[i].flags&NODE_FLAGS_STOPPED));
722 display the status of the monitoring scripts
724 static int control_scriptstatus(struct ctdb_context *ctdb, int argc, const char **argv)
727 struct ctdb_monitoring_wire *script_status;
729 ret = ctdb_ctrl_getscriptstatus(ctdb, TIMELIMIT(), options.pnn, ctdb, &script_status);
731 DEBUG(DEBUG_ERR, ("Unable to get script status from node %u\n", options.pnn));
735 printf("%d scripts were executed last monitoring cycle\n", script_status->num_scripts);
736 for (i=0; i<script_status->num_scripts; i++) {
737 if (script_status->scripts[i].disabled) {
738 printf("%-20s Status:DISABLED\n",
739 script_status->scripts[i].name);
742 printf("%-20s Status:%s ",
743 script_status->scripts[i].name,
744 script_status->scripts[i].timedout?"TIMEDOUT":script_status->scripts[i].status==0?"OK":"ERROR");
745 if (script_status->scripts[i].timedout == 0) {
746 printf("Duration:%.3lf ",
747 timeval_delta(&script_status->scripts[i].finished,
748 &script_status->scripts[i].start));
751 ctime(&script_status->scripts[i].start.tv_sec));
752 if ((script_status->scripts[i].timedout != 0)
753 || (script_status->scripts[i].status != 0) ) {
754 printf(" OUTPUT:%s\n",
755 script_status->scripts[i].output);
764 enable an eventscript
766 static int control_enablescript(struct ctdb_context *ctdb, int argc, const char **argv)
774 ret = ctdb_ctrl_enablescript(ctdb, TIMELIMIT(), options.pnn, argv[0]);
776 DEBUG(DEBUG_ERR, ("Unable to enable script %s on node %u\n", argv[0], options.pnn));
784 disable an eventscript
786 static int control_disablescript(struct ctdb_context *ctdb, int argc, const char **argv)
794 ret = ctdb_ctrl_disablescript(ctdb, TIMELIMIT(), options.pnn, argv[0]);
796 DEBUG(DEBUG_ERR, ("Unable to disable script %s on node %u\n", argv[0], options.pnn));
804 display the pnn of the recovery master
806 static int control_recmaster(struct ctdb_context *ctdb, int argc, const char **argv)
811 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
813 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
816 printf("%d\n",recmaster);
822 get a list of all tickles for this pnn
824 static int control_get_tickles(struct ctdb_context *ctdb, int argc, const char **argv)
826 struct ctdb_control_tcp_tickle_list *list;
834 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
835 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
839 ret = ctdb_ctrl_get_tcp_tickles(ctdb, TIMELIMIT(), options.pnn, ctdb, &addr, &list);
841 DEBUG(DEBUG_ERR, ("Unable to list tickles\n"));
845 printf("Tickles for ip:%s\n", ctdb_addr_to_str(&list->addr));
846 printf("Num tickles:%u\n", list->tickles.num);
847 for (i=0;i<list->tickles.num;i++) {
848 printf("SRC: %s:%u ", ctdb_addr_to_str(&list->tickles.connections[i].src_addr), ntohs(list->tickles.connections[i].src_addr.ip.sin_port));
849 printf("DST: %s:%u\n", ctdb_addr_to_str(&list->tickles.connections[i].dst_addr), ntohs(list->tickles.connections[i].dst_addr.ip.sin_port));
859 static int move_ip(struct ctdb_context *ctdb, ctdb_sock_addr *addr, uint32_t pnn)
861 struct ctdb_all_public_ips *ips;
862 struct ctdb_public_ip ip;
866 struct ctdb_node_map *nodemap=NULL;
867 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
869 /* read the public ip list from the node */
870 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), pnn, ctdb, &ips);
872 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", pnn));
873 talloc_free(tmp_ctx);
877 for (i=0;i<ips->num;i++) {
878 if (ctdb_same_ip(addr, &ips->ips[i].addr)) {
883 DEBUG(DEBUG_ERR, ("Node %u can not host ip address '%s'\n",
884 pnn, ctdb_addr_to_str(addr)));
885 talloc_free(tmp_ctx);
888 if (ips->ips[i].pnn == pnn) {
889 DEBUG(DEBUG_ERR, ("Host %u is already hosting '%s'\n",
890 pnn, ctdb_addr_to_str(&ips->ips[i].addr)));
891 talloc_free(tmp_ctx);
898 data.dptr = (uint8_t *)&ip;
899 data.dsize = sizeof(ip);
901 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &nodemap);
903 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
904 talloc_free(tmp_ctx);
908 nodes = list_of_active_nodes_except_pnn(ctdb, nodemap, tmp_ctx, pnn);
909 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_RELEASE_IP,
915 DEBUG(DEBUG_ERR,("Failed to release IP on nodes\n"));
916 talloc_free(tmp_ctx);
920 ret = ctdb_ctrl_takeover_ip(ctdb, TIMELIMIT(), pnn, &ip);
922 DEBUG(DEBUG_ERR,("Failed to take over IP on node %d\n", pnn));
923 talloc_free(tmp_ctx);
927 talloc_free(tmp_ctx);
932 move/failover an ip address to a specific node
934 static int control_moveip(struct ctdb_context *ctdb, int argc, const char **argv)
944 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
945 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
950 if (sscanf(argv[1], "%u", &pnn) != 1) {
951 DEBUG(DEBUG_ERR, ("Badly formed pnn\n"));
955 if (move_ip(ctdb, &addr, pnn) != 0) {
956 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", pnn));
963 void getips_store_callback(void *param, void *data)
965 struct ctdb_public_ip *node_ip = (struct ctdb_public_ip *)data;
966 struct ctdb_all_public_ips *ips = param;
970 ips->ips[i].pnn = node_ip->pnn;
971 ips->ips[i].addr = node_ip->addr;
974 void getips_count_callback(void *param, void *data)
976 uint32_t *count = param;
982 static uint32_t *ip_key(ctdb_sock_addr *ip)
984 static uint32_t key[IP_KEYLEN];
986 bzero(key, sizeof(key));
988 switch (ip->sa.sa_family) {
990 key[0] = ip->ip.sin_addr.s_addr;
993 key[0] = ip->ip6.sin6_addr.s6_addr32[3];
994 key[1] = ip->ip6.sin6_addr.s6_addr32[2];
995 key[2] = ip->ip6.sin6_addr.s6_addr32[1];
996 key[3] = ip->ip6.sin6_addr.s6_addr32[0];
999 DEBUG(DEBUG_ERR, (__location__ " ERROR, unknown family passed :%u\n", ip->sa.sa_family));
1006 static void *add_ip_callback(void *parm, void *data)
1012 control_get_all_public_ips(struct ctdb_context *ctdb, TALLOC_CTX *tmp_ctx, struct ctdb_all_public_ips **ips)
1014 struct ctdb_all_public_ips *tmp_ips;
1015 struct ctdb_node_map *nodemap=NULL;
1016 trbt_tree_t *ip_tree;
1020 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1022 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1026 ip_tree = trbt_create(tmp_ctx, 0);
1028 for(i=0;i<nodemap->num;i++){
1029 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
1032 if (nodemap->nodes[i].flags & NODE_FLAGS_DISCONNECTED) {
1036 /* read the public ip list from this node */
1037 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &tmp_ips);
1039 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", nodemap->nodes[i].pnn));
1043 for (j=0; j<tmp_ips->num;j++) {
1044 struct ctdb_public_ip *node_ip;
1046 node_ip = talloc(tmp_ctx, struct ctdb_public_ip);
1047 node_ip->pnn = tmp_ips->ips[j].pnn;
1048 node_ip->addr = tmp_ips->ips[j].addr;
1050 trbt_insertarray32_callback(ip_tree,
1051 IP_KEYLEN, ip_key(&tmp_ips->ips[j].addr),
1055 talloc_free(tmp_ips);
1060 trbt_traversearray32(ip_tree, IP_KEYLEN, getips_count_callback, &count);
1062 len = offsetof(struct ctdb_all_public_ips, ips) +
1063 count*sizeof(struct ctdb_public_ip);
1064 tmp_ips = talloc_zero_size(tmp_ctx, len);
1065 trbt_traversearray32(ip_tree, IP_KEYLEN, getips_store_callback, tmp_ips);
1074 * scans all other nodes and returns a pnn for another node that can host this
1078 find_other_host_for_public_ip(struct ctdb_context *ctdb, ctdb_sock_addr *addr)
1080 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1081 struct ctdb_all_public_ips *ips;
1082 struct ctdb_node_map *nodemap=NULL;
1085 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1087 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1088 talloc_free(tmp_ctx);
1092 for(i=0;i<nodemap->num;i++){
1093 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1096 if (nodemap->nodes[i].pnn == options.pnn) {
1100 /* read the public ip list from this node */
1101 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips);
1103 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", nodemap->nodes[i].pnn));
1107 for (j=0;j<ips->num;j++) {
1108 if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1109 talloc_free(tmp_ctx);
1110 return nodemap->nodes[i].pnn;
1116 talloc_free(tmp_ctx);
1121 add a public ip address to a node
1123 static int control_addip(struct ctdb_context *ctdb, int argc, const char **argv)
1129 ctdb_sock_addr addr;
1130 struct ctdb_control_ip_iface *pub;
1131 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1132 struct ctdb_all_public_ips *ips;
1136 talloc_free(tmp_ctx);
1140 if (!parse_ip_mask(argv[0], argv[1], &addr, &mask)) {
1141 DEBUG(DEBUG_ERR, ("Badly formed ip/mask : %s\n", argv[0]));
1142 talloc_free(tmp_ctx);
1146 ret = control_get_all_public_ips(ctdb, tmp_ctx, &ips);
1148 DEBUG(DEBUG_ERR, ("Unable to get public ip list from cluster\n"));
1149 talloc_free(tmp_ctx);
1154 /* check if some other node is already serving this ip, if not,
1157 for (i=0;i<ips->num;i++) {
1158 if (ctdb_same_ip(&addr, &ips->ips[i].addr)) {
1163 len = offsetof(struct ctdb_control_ip_iface, iface) + strlen(argv[1]) + 1;
1164 pub = talloc_size(tmp_ctx, len);
1165 CTDB_NO_MEMORY(ctdb, pub);
1169 pub->len = strlen(argv[1])+1;
1170 memcpy(&pub->iface[0], argv[1], strlen(argv[1])+1);
1172 ret = ctdb_ctrl_add_public_ip(ctdb, TIMELIMIT(), options.pnn, pub);
1174 DEBUG(DEBUG_ERR, ("Unable to add public ip to node %u\n", options.pnn));
1175 talloc_free(tmp_ctx);
1179 if (i == ips->num) {
1180 /* no one has this ip so we claim it */
1183 pnn = ips->ips[i].pnn;
1186 if (move_ip(ctdb, &addr, pnn) != 0) {
1187 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", pnn));
1191 talloc_free(tmp_ctx);
1195 static int control_delip(struct ctdb_context *ctdb, int argc, const char **argv);
1197 static int control_delip_all(struct ctdb_context *ctdb, int argc, const char **argv, ctdb_sock_addr *addr)
1199 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1200 struct ctdb_node_map *nodemap=NULL;
1201 struct ctdb_all_public_ips *ips;
1204 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1206 DEBUG(DEBUG_ERR, ("Unable to get nodemap from current node\n"));
1210 /* remove it from the nodes that are not hosting the ip currently */
1211 for(i=0;i<nodemap->num;i++){
1212 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1215 if (ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips) != 0) {
1216 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %d\n", nodemap->nodes[i].pnn));
1220 for (j=0;j<ips->num;j++) {
1221 if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1229 if (ips->ips[j].pnn == nodemap->nodes[i].pnn) {
1233 options.pnn = nodemap->nodes[i].pnn;
1234 control_delip(ctdb, argc, argv);
1238 /* remove it from every node (also the one hosting it) */
1239 for(i=0;i<nodemap->num;i++){
1240 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1243 if (ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips) != 0) {
1244 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %d\n", nodemap->nodes[i].pnn));
1248 for (j=0;j<ips->num;j++) {
1249 if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1257 options.pnn = nodemap->nodes[i].pnn;
1258 control_delip(ctdb, argc, argv);
1261 talloc_free(tmp_ctx);
1266 delete a public ip address from a node
1268 static int control_delip(struct ctdb_context *ctdb, int argc, const char **argv)
1271 ctdb_sock_addr addr;
1272 struct ctdb_control_ip_iface pub;
1273 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1274 struct ctdb_all_public_ips *ips;
1277 talloc_free(tmp_ctx);
1281 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1282 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1286 if (options.pnn == CTDB_BROADCAST_ALL) {
1287 return control_delip_all(ctdb, argc, argv, &addr);
1294 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &ips);
1296 DEBUG(DEBUG_ERR, ("Unable to get public ip list from cluster\n"));
1297 talloc_free(tmp_ctx);
1301 for (i=0;i<ips->num;i++) {
1302 if (ctdb_same_ip(&addr, &ips->ips[i].addr)) {
1308 DEBUG(DEBUG_ERR, ("This node does not support this public address '%s'\n",
1309 ctdb_addr_to_str(&addr)));
1310 talloc_free(tmp_ctx);
1314 if (ips->ips[i].pnn == options.pnn) {
1315 ret = find_other_host_for_public_ip(ctdb, &addr);
1317 if (move_ip(ctdb, &addr, ret) != 0) {
1318 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", ret));
1324 ret = ctdb_ctrl_del_public_ip(ctdb, TIMELIMIT(), options.pnn, &pub);
1326 DEBUG(DEBUG_ERR, ("Unable to del public ip from node %u\n", options.pnn));
1327 talloc_free(tmp_ctx);
1331 talloc_free(tmp_ctx);
1336 kill a tcp connection
1338 static int kill_tcp(struct ctdb_context *ctdb, int argc, const char **argv)
1341 struct ctdb_control_killtcp killtcp;
1347 if (!parse_ip_port(argv[0], &killtcp.src_addr)) {
1348 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[0]));
1352 if (!parse_ip_port(argv[1], &killtcp.dst_addr)) {
1353 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[1]));
1357 ret = ctdb_ctrl_killtcp(ctdb, TIMELIMIT(), options.pnn, &killtcp);
1359 DEBUG(DEBUG_ERR, ("Unable to killtcp from node %u\n", options.pnn));
1370 static int control_gratious_arp(struct ctdb_context *ctdb, int argc, const char **argv)
1373 ctdb_sock_addr addr;
1379 if (!parse_ip(argv[0], NULL, 0, &addr)) {
1380 DEBUG(DEBUG_ERR, ("Bad IP '%s'\n", argv[0]));
1384 ret = ctdb_ctrl_gratious_arp(ctdb, TIMELIMIT(), options.pnn, &addr, argv[1]);
1386 DEBUG(DEBUG_ERR, ("Unable to send gratious_arp from node %u\n", options.pnn));
1394 register a server id
1396 static int regsrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1399 struct ctdb_server_id server_id;
1405 server_id.pnn = strtoul(argv[0], NULL, 0);
1406 server_id.type = strtoul(argv[1], NULL, 0);
1407 server_id.server_id = strtoul(argv[2], NULL, 0);
1409 ret = ctdb_ctrl_register_server_id(ctdb, TIMELIMIT(), &server_id);
1411 DEBUG(DEBUG_ERR, ("Unable to register server_id from node %u\n", options.pnn));
1418 unregister a server id
1420 static int unregsrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1423 struct ctdb_server_id server_id;
1429 server_id.pnn = strtoul(argv[0], NULL, 0);
1430 server_id.type = strtoul(argv[1], NULL, 0);
1431 server_id.server_id = strtoul(argv[2], NULL, 0);
1433 ret = ctdb_ctrl_unregister_server_id(ctdb, TIMELIMIT(), &server_id);
1435 DEBUG(DEBUG_ERR, ("Unable to unregister server_id from node %u\n", options.pnn));
1442 check if a server id exists
1444 static int chksrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1448 struct ctdb_server_id server_id;
1454 server_id.pnn = strtoul(argv[0], NULL, 0);
1455 server_id.type = strtoul(argv[1], NULL, 0);
1456 server_id.server_id = strtoul(argv[2], NULL, 0);
1458 ret = ctdb_ctrl_check_server_id(ctdb, TIMELIMIT(), options.pnn, &server_id, &status);
1460 DEBUG(DEBUG_ERR, ("Unable to check server_id from node %u\n", options.pnn));
1465 printf("Server id %d:%d:%d EXISTS\n", server_id.pnn, server_id.type, server_id.server_id);
1467 printf("Server id %d:%d:%d does NOT exist\n", server_id.pnn, server_id.type, server_id.server_id);
1473 get a list of all server ids that are registered on a node
1475 static int getsrvids(struct ctdb_context *ctdb, int argc, const char **argv)
1478 struct ctdb_server_id_list *server_ids;
1480 ret = ctdb_ctrl_get_server_id_list(ctdb, ctdb, TIMELIMIT(), options.pnn, &server_ids);
1482 DEBUG(DEBUG_ERR, ("Unable to get server_id list from node %u\n", options.pnn));
1486 for (i=0; i<server_ids->num; i++) {
1487 printf("Server id %d:%d:%d\n",
1488 server_ids->server_ids[i].pnn,
1489 server_ids->server_ids[i].type,
1490 server_ids->server_ids[i].server_id);
1497 send a tcp tickle ack
1499 static int tickle_tcp(struct ctdb_context *ctdb, int argc, const char **argv)
1502 ctdb_sock_addr src, dst;
1508 if (!parse_ip_port(argv[0], &src)) {
1509 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[0]));
1513 if (!parse_ip_port(argv[1], &dst)) {
1514 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[1]));
1518 ret = ctdb_sys_send_tcp(&src, &dst, 0, 0, 0);
1522 DEBUG(DEBUG_ERR, ("Error while sending tickle ack\n"));
1529 display public ip status
1531 static int control_ip(struct ctdb_context *ctdb, int argc, const char **argv)
1534 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1535 struct ctdb_all_public_ips *ips;
1537 if (options.pnn == CTDB_BROADCAST_ALL) {
1538 /* read the list of public ips from all nodes */
1539 ret = control_get_all_public_ips(ctdb, tmp_ctx, &ips);
1541 /* read the public ip list from this node */
1542 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &ips);
1545 DEBUG(DEBUG_ERR, ("Unable to get public ips from node %u\n", options.pnn));
1546 talloc_free(tmp_ctx);
1550 if (options.machinereadable){
1551 printf(":Public IP:Node:\n");
1553 if (options.pnn == CTDB_BROADCAST_ALL) {
1554 printf("Public IPs on ALL nodes\n");
1556 printf("Public IPs on node %u\n", options.pnn);
1560 for (i=1;i<=ips->num;i++) {
1561 if (options.machinereadable){
1562 printf(":%s:%d:\n", ctdb_addr_to_str(&ips->ips[ips->num-i].addr), ips->ips[ips->num-i].pnn);
1564 printf("%s %d\n", ctdb_addr_to_str(&ips->ips[ips->num-i].addr), ips->ips[ips->num-i].pnn);
1568 talloc_free(tmp_ctx);
1573 display pid of a ctdb daemon
1575 static int control_getpid(struct ctdb_context *ctdb, int argc, const char **argv)
1580 ret = ctdb_ctrl_getpid(ctdb, TIMELIMIT(), options.pnn, &pid);
1582 DEBUG(DEBUG_ERR, ("Unable to get daemon pid from node %u\n", options.pnn));
1585 printf("Pid:%d\n", pid);
1591 handler for receiving the response to ipreallocate
1593 static void ip_reallocate_handler(struct ctdb_context *ctdb, uint64_t srvid,
1594 TDB_DATA data, void *private_data)
1599 static void ctdb_every_second(struct event_context *ev, struct timed_event *te, struct timeval t, void *p)
1601 struct ctdb_context *ctdb = talloc_get_type(p, struct ctdb_context);
1603 event_add_timed(ctdb->ev, ctdb,
1604 timeval_current_ofs(1, 0),
1605 ctdb_every_second, ctdb);
1609 ask the recovery daemon on the recovery master to perform a ip reallocation
1611 static int control_ipreallocate(struct ctdb_context *ctdb, int argc, const char **argv)
1615 struct rd_memdump_reply rd;
1617 struct ctdb_node_map *nodemap=NULL;
1619 struct timeval tv = timeval_current();
1621 /* we need some events to trigger so we can timeout and restart
1624 event_add_timed(ctdb->ev, ctdb,
1625 timeval_current_ofs(1, 0),
1626 ctdb_every_second, ctdb);
1628 rd.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
1630 DEBUG(DEBUG_ERR, ("Failed to get pnn of local node\n"));
1633 rd.srvid = getpid();
1635 /* register a message port for receiveing the reply so that we
1636 can receive the reply
1638 ctdb_set_message_handler(ctdb, rd.srvid, ip_reallocate_handler, NULL);
1640 data.dptr = (uint8_t *)&rd;
1641 data.dsize = sizeof(rd);
1645 DEBUG(DEBUG_ERR,("Failed waiting for cluster convergense\n"));
1649 /* check that there are valid nodes available */
1650 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap) != 0) {
1651 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
1654 for (i=0; i<nodemap->num;i++) {
1655 if ((nodemap->nodes[i].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) == 0) {
1659 if (i==nodemap->num) {
1660 DEBUG(DEBUG_ERR,("No recmaster available, no need to wait for cluster convergence\n"));
1665 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
1667 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
1671 /* verify the node exists */
1672 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), recmaster, ctdb, &nodemap) != 0) {
1673 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
1678 /* check tha there are nodes available that can act as a recmaster */
1679 for (i=0; i<nodemap->num; i++) {
1680 if (nodemap->nodes[i].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
1684 if (i == nodemap->num) {
1688 /* verify the recovery master is not STOPPED, nor BANNED */
1689 if (nodemap->nodes[recmaster].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
1690 DEBUG(DEBUG_ERR,("No suitable recmaster found. Try again\n"));
1697 /* verify the recovery master is not STOPPED, nor BANNED */
1698 if (nodemap->nodes[recmaster].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
1699 DEBUG(DEBUG_ERR,("No suitable recmaster found. Try again\n"));
1705 ret = ctdb_send_message(ctdb, recmaster, CTDB_SRVID_TAKEOVER_RUN, data);
1707 DEBUG(DEBUG_ERR,("Failed to send ip takeover run request message to %u\n", options.pnn));
1711 tv = timeval_current();
1712 /* this loop will terminate when we have received the reply */
1713 while (timeval_elapsed(&tv) < 3.0) {
1714 event_loop_once(ctdb->ev);
1717 DEBUG(DEBUG_INFO,("Timed out waiting for recmaster ipreallocate. Trying again\n"));
1727 disable a remote node
1729 static int control_disable(struct ctdb_context *ctdb, int argc, const char **argv)
1732 struct ctdb_node_map *nodemap=NULL;
1735 ret = ctdb_ctrl_modflags(ctdb, TIMELIMIT(), options.pnn, NODE_FLAGS_PERMANENTLY_DISABLED, 0);
1737 DEBUG(DEBUG_ERR, ("Unable to disable node %u\n", options.pnn));
1743 /* read the nodemap and verify the change took effect */
1744 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
1745 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
1749 } while (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED));
1750 ret = control_ipreallocate(ctdb, argc, argv);
1752 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
1760 enable a disabled remote node
1762 static int control_enable(struct ctdb_context *ctdb, int argc, const char **argv)
1766 struct ctdb_node_map *nodemap=NULL;
1769 ret = ctdb_ctrl_modflags(ctdb, TIMELIMIT(), options.pnn, 0, NODE_FLAGS_PERMANENTLY_DISABLED);
1771 DEBUG(DEBUG_ERR, ("Unable to enable node %u\n", options.pnn));
1777 /* read the nodemap and verify the change took effect */
1778 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
1779 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
1783 } while (nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED);
1784 ret = control_ipreallocate(ctdb, argc, argv);
1786 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
1796 static int control_stop(struct ctdb_context *ctdb, int argc, const char **argv)
1799 struct ctdb_node_map *nodemap=NULL;
1802 ret = ctdb_ctrl_stop_node(ctdb, TIMELIMIT(), options.pnn);
1804 DEBUG(DEBUG_ERR, ("Unable to stop node %u try again\n", options.pnn));
1809 /* read the nodemap and verify the change took effect */
1810 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
1811 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
1815 } while (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_STOPPED));
1816 ret = control_ipreallocate(ctdb, argc, argv);
1818 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
1826 restart a stopped remote node
1828 static int control_continue(struct ctdb_context *ctdb, int argc, const char **argv)
1832 struct ctdb_node_map *nodemap=NULL;
1835 ret = ctdb_ctrl_continue_node(ctdb, TIMELIMIT(), options.pnn);
1837 DEBUG(DEBUG_ERR, ("Unable to continue node %u\n", options.pnn));
1843 /* read the nodemap and verify the change took effect */
1844 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
1845 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
1849 } while (nodemap->nodes[options.pnn].flags & NODE_FLAGS_STOPPED);
1850 ret = control_ipreallocate(ctdb, argc, argv);
1852 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
1859 static uint32_t get_generation(struct ctdb_context *ctdb)
1861 struct ctdb_vnn_map *vnnmap=NULL;
1864 /* wait until the recmaster is not in recovery mode */
1866 uint32_t recmode, recmaster;
1868 if (vnnmap != NULL) {
1869 talloc_free(vnnmap);
1873 /* get the recmaster */
1874 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, &recmaster);
1876 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
1880 /* get recovery mode */
1881 ret = ctdb_ctrl_getrecmode(ctdb, ctdb, TIMELIMIT(), recmaster, &recmode);
1883 DEBUG(DEBUG_ERR, ("Unable to get recmode from node %u\n", options.pnn));
1887 /* get the current generation number */
1888 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), recmaster, ctdb, &vnnmap);
1890 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from recmaster (%u)\n", recmaster));
1894 if ((recmode == CTDB_RECOVERY_NORMAL)
1895 && (vnnmap->generation != 1)){
1896 return vnnmap->generation;
1903 ban a node from the cluster
1905 static int control_ban(struct ctdb_context *ctdb, int argc, const char **argv)
1908 struct ctdb_node_map *nodemap=NULL;
1909 struct ctdb_ban_time bantime;
1915 /* verify the node exists */
1916 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
1918 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
1922 if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_BANNED) {
1923 DEBUG(DEBUG_ERR,("Node %u is already banned.\n", options.pnn));
1927 bantime.pnn = options.pnn;
1928 bantime.time = strtoul(argv[0], NULL, 0);
1930 ret = ctdb_ctrl_set_ban(ctdb, TIMELIMIT(), options.pnn, &bantime);
1932 DEBUG(DEBUG_ERR,("Banning node %d for %d seconds failed.\n", bantime.pnn, bantime.time));
1936 ret = control_ipreallocate(ctdb, argc, argv);
1938 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
1947 unban a node from the cluster
1949 static int control_unban(struct ctdb_context *ctdb, int argc, const char **argv)
1952 struct ctdb_node_map *nodemap=NULL;
1953 struct ctdb_ban_time bantime;
1955 /* verify the node exists */
1956 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
1958 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
1962 if (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_BANNED)) {
1963 DEBUG(DEBUG_ERR,("Node %u is not banned.\n", options.pnn));
1967 bantime.pnn = options.pnn;
1970 ret = ctdb_ctrl_set_ban(ctdb, TIMELIMIT(), options.pnn, &bantime);
1972 DEBUG(DEBUG_ERR,("Unbanning node %d failed.\n", bantime.pnn));
1976 ret = control_ipreallocate(ctdb, argc, argv);
1978 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
1987 show ban information for a node
1989 static int control_showban(struct ctdb_context *ctdb, int argc, const char **argv)
1992 struct ctdb_node_map *nodemap=NULL;
1993 struct ctdb_ban_time *bantime;
1995 /* verify the node exists */
1996 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
1998 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2002 ret = ctdb_ctrl_get_ban(ctdb, TIMELIMIT(), options.pnn, ctdb, &bantime);
2004 DEBUG(DEBUG_ERR,("Showing ban info for node %d failed.\n", options.pnn));
2008 if (bantime->time == 0) {
2009 printf("Node %u is not banned\n", bantime->pnn);
2011 printf("Node %u is banned banned for %d seconds\n", bantime->pnn, bantime->time);
2020 static int control_shutdown(struct ctdb_context *ctdb, int argc, const char **argv)
2024 ret = ctdb_ctrl_shutdown(ctdb, TIMELIMIT(), options.pnn);
2026 DEBUG(DEBUG_ERR, ("Unable to shutdown node %u\n", options.pnn));
2036 static int control_recover(struct ctdb_context *ctdb, int argc, const char **argv)
2039 uint32_t generation, next_generation;
2041 /* record the current generation number */
2042 generation = get_generation(ctdb);
2044 ret = ctdb_ctrl_freeze(ctdb, TIMELIMIT(), options.pnn);
2046 DEBUG(DEBUG_ERR, ("Unable to freeze node\n"));
2050 ret = ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
2052 DEBUG(DEBUG_ERR, ("Unable to set recovery mode\n"));
2056 /* wait until we are in a new generation */
2058 next_generation = get_generation(ctdb);
2059 if (next_generation != generation) {
2070 display monitoring mode of a remote node
2072 static int control_getmonmode(struct ctdb_context *ctdb, int argc, const char **argv)
2077 ret = ctdb_ctrl_getmonmode(ctdb, TIMELIMIT(), options.pnn, &monmode);
2079 DEBUG(DEBUG_ERR, ("Unable to get monmode from node %u\n", options.pnn));
2082 if (!options.machinereadable){
2083 printf("Monitoring mode:%s (%d)\n",monmode==CTDB_MONITORING_ACTIVE?"ACTIVE":"DISABLED",monmode);
2086 printf(":%d:\n",monmode);
2093 display capabilities of a remote node
2095 static int control_getcapabilities(struct ctdb_context *ctdb, int argc, const char **argv)
2097 uint32_t capabilities;
2100 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), options.pnn, &capabilities);
2102 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", options.pnn));
2106 if (!options.machinereadable){
2107 printf("RECMASTER: %s\n", (capabilities&CTDB_CAP_RECMASTER)?"YES":"NO");
2108 printf("LMASTER: %s\n", (capabilities&CTDB_CAP_LMASTER)?"YES":"NO");
2109 printf("LVS: %s\n", (capabilities&CTDB_CAP_LVS)?"YES":"NO");
2110 printf("NATGW: %s\n", (capabilities&CTDB_CAP_NATGW)?"YES":"NO");
2112 printf(":RECMASTER:LMASTER:LVS:NATGW:\n");
2113 printf(":%d:%d:%d:%d:\n",
2114 !!(capabilities&CTDB_CAP_RECMASTER),
2115 !!(capabilities&CTDB_CAP_LMASTER),
2116 !!(capabilities&CTDB_CAP_LVS),
2117 !!(capabilities&CTDB_CAP_NATGW));
2123 display lvs configuration
2125 static int control_lvs(struct ctdb_context *ctdb, int argc, const char **argv)
2127 uint32_t *capabilities;
2128 struct ctdb_node_map *nodemap=NULL;
2130 int healthy_count = 0;
2132 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
2134 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
2138 capabilities = talloc_array(ctdb, uint32_t, nodemap->num);
2139 CTDB_NO_MEMORY(ctdb, capabilities);
2141 /* collect capabilities for all connected nodes */
2142 for (i=0; i<nodemap->num; i++) {
2143 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2146 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2150 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), i, &capabilities[i]);
2152 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", i));
2156 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2160 if (!(nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY)) {
2165 /* Print all LVS nodes */
2166 for (i=0; i<nodemap->num; i++) {
2167 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2170 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2173 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2177 if (healthy_count != 0) {
2178 if (nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY) {
2183 printf("%d:%s\n", i,
2184 ctdb_addr_to_str(&nodemap->nodes[i].addr));
2191 display who is the lvs master
2193 static int control_lvsmaster(struct ctdb_context *ctdb, int argc, const char **argv)
2195 uint32_t *capabilities;
2196 struct ctdb_node_map *nodemap=NULL;
2198 int healthy_count = 0;
2200 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
2202 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
2206 capabilities = talloc_array(ctdb, uint32_t, nodemap->num);
2207 CTDB_NO_MEMORY(ctdb, capabilities);
2209 /* collect capabilities for all connected nodes */
2210 for (i=0; i<nodemap->num; i++) {
2211 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2214 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2218 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), i, &capabilities[i]);
2220 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", i));
2224 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2228 if (!(nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY)) {
2233 /* find and show the lvsmaster */
2234 for (i=0; i<nodemap->num; i++) {
2235 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2238 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2241 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2245 if (healthy_count != 0) {
2246 if (nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY) {
2251 if (options.machinereadable){
2254 printf("Node %d is LVS master\n", i);
2259 printf("There is no LVS master\n");
2264 disable monitoring on a node
2266 static int control_disable_monmode(struct ctdb_context *ctdb, int argc, const char **argv)
2271 ret = ctdb_ctrl_disable_monmode(ctdb, TIMELIMIT(), options.pnn);
2273 DEBUG(DEBUG_ERR, ("Unable to disable monmode on node %u\n", options.pnn));
2276 printf("Monitoring mode:%s\n","DISABLED");
2282 enable monitoring on a node
2284 static int control_enable_monmode(struct ctdb_context *ctdb, int argc, const char **argv)
2289 ret = ctdb_ctrl_enable_monmode(ctdb, TIMELIMIT(), options.pnn);
2291 DEBUG(DEBUG_ERR, ("Unable to enable monmode on node %u\n", options.pnn));
2294 printf("Monitoring mode:%s\n","ACTIVE");
2300 display remote list of keys/data for a db
2302 static int control_catdb(struct ctdb_context *ctdb, int argc, const char **argv)
2304 const char *db_name;
2305 struct ctdb_db_context *ctdb_db;
2315 if (db_exists(ctdb, db_name)) {
2316 DEBUG(DEBUG_ERR,("Database '%s' does not exist\n", db_name));
2320 ctdb_db = ctdb_attach(ctdb, db_name, false, 0);
2322 if (ctdb_db == NULL) {
2323 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
2327 /* traverse and dump the cluster tdb */
2328 ret = ctdb_dump_db(ctdb_db, stdout);
2330 DEBUG(DEBUG_ERR, ("Unable to dump database\n"));
2333 talloc_free(ctdb_db);
2335 printf("Dumped %d records\n", ret);
2341 display a list of the databases on a remote ctdb
2343 static int control_getdbmap(struct ctdb_context *ctdb, int argc, const char **argv)
2346 struct ctdb_dbid_map *dbmap=NULL;
2348 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
2350 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
2354 printf("Number of databases:%d\n", dbmap->num);
2355 for(i=0;i<dbmap->num;i++){
2360 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &path);
2361 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
2362 persistent = dbmap->dbs[i].persistent;
2363 printf("dbid:0x%08x name:%s path:%s %s\n", dbmap->dbs[i].dbid, name,
2364 path, persistent?"PERSISTENT":"");
2371 check if the local node is recmaster or not
2372 it will return 1 if this node is the recmaster and 0 if it is not
2373 or if the local ctdb daemon could not be contacted
2375 static int control_isnotrecmaster(struct ctdb_context *ctdb, int argc, const char **argv)
2377 uint32_t mypnn, recmaster;
2380 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
2382 printf("Failed to get pnn of node\n");
2386 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
2388 printf("Failed to get the recmaster\n");
2392 if (recmaster != mypnn) {
2393 printf("this node is not the recmaster\n");
2397 printf("this node is the recmaster\n");
2404 static int control_ping(struct ctdb_context *ctdb, int argc, const char **argv)
2407 struct timeval tv = timeval_current();
2408 ret = ctdb_ctrl_ping(ctdb, options.pnn);
2410 printf("Unable to get ping response from node %u\n", options.pnn);
2413 printf("response from %u time=%.6f sec (%d clients)\n",
2414 options.pnn, timeval_elapsed(&tv), ret);
2423 static int control_getvar(struct ctdb_context *ctdb, int argc, const char **argv)
2434 ret = ctdb_ctrl_get_tunable(ctdb, TIMELIMIT(), options.pnn, name, &value);
2436 DEBUG(DEBUG_ERR, ("Unable to get tunable variable '%s'\n", name));
2440 printf("%-19s = %u\n", name, value);
2447 static int control_setvar(struct ctdb_context *ctdb, int argc, const char **argv)
2458 value = strtoul(argv[1], NULL, 0);
2460 ret = ctdb_ctrl_set_tunable(ctdb, TIMELIMIT(), options.pnn, name, value);
2462 DEBUG(DEBUG_ERR, ("Unable to set tunable variable '%s'\n", name));
2471 static int control_listvars(struct ctdb_context *ctdb, int argc, const char **argv)
2477 ret = ctdb_ctrl_list_tunables(ctdb, TIMELIMIT(), options.pnn, ctdb, &list, &count);
2479 DEBUG(DEBUG_ERR, ("Unable to list tunable variables\n"));
2483 for (i=0;i<count;i++) {
2484 control_getvar(ctdb, 1, &list[i]);
2493 display debug level on a node
2495 static int control_getdebug(struct ctdb_context *ctdb, int argc, const char **argv)
2500 ret = ctdb_ctrl_get_debuglevel(ctdb, options.pnn, &level);
2502 DEBUG(DEBUG_ERR, ("Unable to get debuglevel response from node %u\n", options.pnn));
2505 if (options.machinereadable){
2506 printf(":Name:Level:\n");
2507 printf(":%s:%d:\n",get_debug_by_level(level),level);
2509 printf("Node %u is at debug level %s (%d)\n", options.pnn, get_debug_by_level(level), level);
2516 display reclock file of a node
2518 static int control_getreclock(struct ctdb_context *ctdb, int argc, const char **argv)
2521 const char *reclock;
2523 ret = ctdb_ctrl_getreclock(ctdb, TIMELIMIT(), options.pnn, ctdb, &reclock);
2525 DEBUG(DEBUG_ERR, ("Unable to get reclock file from node %u\n", options.pnn));
2528 if (options.machinereadable){
2529 if (reclock != NULL) {
2530 printf("%s", reclock);
2533 if (reclock == NULL) {
2534 printf("No reclock file used.\n");
2536 printf("Reclock file:%s\n", reclock);
2544 set the reclock file of a node
2546 static int control_setreclock(struct ctdb_context *ctdb, int argc, const char **argv)
2549 const char *reclock;
2553 } else if (argc == 1) {
2559 ret = ctdb_ctrl_setreclock(ctdb, TIMELIMIT(), options.pnn, reclock);
2561 DEBUG(DEBUG_ERR, ("Unable to get reclock file from node %u\n", options.pnn));
2568 set the natgw state on/off
2570 static int control_setnatgwstate(struct ctdb_context *ctdb, int argc, const char **argv)
2573 uint32_t natgwstate;
2579 if (!strcmp(argv[0], "on")) {
2581 } else if (!strcmp(argv[0], "off")) {
2587 ret = ctdb_ctrl_setnatgwstate(ctdb, TIMELIMIT(), options.pnn, natgwstate);
2589 DEBUG(DEBUG_ERR, ("Unable to set the natgw state for node %u\n", options.pnn));
2597 set the lmaster role on/off
2599 static int control_setlmasterrole(struct ctdb_context *ctdb, int argc, const char **argv)
2602 uint32_t lmasterrole;
2608 if (!strcmp(argv[0], "on")) {
2610 } else if (!strcmp(argv[0], "off")) {
2616 ret = ctdb_ctrl_setlmasterrole(ctdb, TIMELIMIT(), options.pnn, lmasterrole);
2618 DEBUG(DEBUG_ERR, ("Unable to set the lmaster role for node %u\n", options.pnn));
2626 set the recmaster role on/off
2628 static int control_setrecmasterrole(struct ctdb_context *ctdb, int argc, const char **argv)
2631 uint32_t recmasterrole;
2637 if (!strcmp(argv[0], "on")) {
2639 } else if (!strcmp(argv[0], "off")) {
2645 ret = ctdb_ctrl_setrecmasterrole(ctdb, TIMELIMIT(), options.pnn, recmasterrole);
2647 DEBUG(DEBUG_ERR, ("Unable to set the recmaster role for node %u\n", options.pnn));
2655 set debug level on a node or all nodes
2657 static int control_setdebug(struct ctdb_context *ctdb, int argc, const char **argv)
2663 printf("You must specify the debug level. Valid levels are:\n");
2664 for (i=0; debug_levels[i].description != NULL; i++) {
2665 printf("%s (%d)\n", debug_levels[i].description, debug_levels[i].level);
2671 if (isalpha(argv[0][0]) || argv[0][0] == '-') {
2672 level = get_debug_by_desc(argv[0]);
2674 level = strtol(argv[0], NULL, 0);
2677 for (i=0; debug_levels[i].description != NULL; i++) {
2678 if (level == debug_levels[i].level) {
2682 if (debug_levels[i].description == NULL) {
2683 printf("Invalid debug level, must be one of\n");
2684 for (i=0; debug_levels[i].description != NULL; i++) {
2685 printf("%s (%d)\n", debug_levels[i].description, debug_levels[i].level);
2690 ret = ctdb_ctrl_set_debuglevel(ctdb, options.pnn, level);
2692 DEBUG(DEBUG_ERR, ("Unable to set debug level on node %u\n", options.pnn));
2701 static int control_freeze(struct ctdb_context *ctdb, int argc, const char **argv)
2705 ret = ctdb_ctrl_freeze(ctdb, TIMELIMIT(), options.pnn);
2707 DEBUG(DEBUG_ERR, ("Unable to freeze node %u\n", options.pnn));
2715 static int control_thaw(struct ctdb_context *ctdb, int argc, const char **argv)
2719 ret = ctdb_ctrl_thaw(ctdb, TIMELIMIT(), options.pnn);
2721 DEBUG(DEBUG_ERR, ("Unable to thaw node %u\n", options.pnn));
2728 attach to a database
2730 static int control_attach(struct ctdb_context *ctdb, int argc, const char **argv)
2732 const char *db_name;
2733 struct ctdb_db_context *ctdb_db;
2740 ctdb_db = ctdb_attach(ctdb, db_name, false, 0);
2741 if (ctdb_db == NULL) {
2742 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
2750 run an eventscript on a node
2752 static int control_eventscript(struct ctdb_context *ctdb, int argc, const char **argv)
2758 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2761 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
2765 data.dptr = (unsigned char *)discard_const(argv[0]);
2766 data.dsize = strlen((char *)data.dptr) + 1;
2768 DEBUG(DEBUG_ERR, ("Running eventscripts with arguments \"%s\" on node %u\n", data.dptr, options.pnn));
2770 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_RUN_EVENTSCRIPTS,
2771 0, data, tmp_ctx, NULL, &res, NULL, &errmsg);
2772 if (ret != 0 || res != 0) {
2773 DEBUG(DEBUG_ERR,("Failed to run eventscripts - %s\n", errmsg));
2774 talloc_free(tmp_ctx);
2777 talloc_free(tmp_ctx);
2781 #define DB_VERSION 1
2782 #define MAX_DB_NAME 64
2783 struct db_file_header {
2784 unsigned long version;
2786 unsigned long persistent;
2788 const char name[MAX_DB_NAME];
2791 struct backup_data {
2792 struct ctdb_marshall_buffer *records;
2795 bool traverse_error;
2798 static int backup_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *private)
2800 struct backup_data *bd = talloc_get_type(private, struct backup_data);
2801 struct ctdb_rec_data *rec;
2803 /* add the record */
2804 rec = ctdb_marshall_record(bd->records, 0, key, NULL, data);
2806 bd->traverse_error = true;
2807 DEBUG(DEBUG_ERR,("Failed to marshall record\n"));
2810 bd->records = talloc_realloc_size(NULL, bd->records, rec->length + bd->len);
2811 if (bd->records == NULL) {
2812 DEBUG(DEBUG_ERR,("Failed to expand marshalling buffer\n"));
2813 bd->traverse_error = true;
2816 bd->records->count++;
2817 memcpy(bd->len+(uint8_t *)bd->records, rec, rec->length);
2818 bd->len += rec->length;
2826 * backup a database to a file
2828 static int control_backupdb(struct ctdb_context *ctdb, int argc, const char **argv)
2831 struct ctdb_dbid_map *dbmap=NULL;
2832 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2833 struct db_file_header dbhdr;
2834 struct ctdb_db_context *ctdb_db;
2835 struct backup_data *bd;
2840 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
2844 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &dbmap);
2846 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
2850 for(i=0;i<dbmap->num;i++){
2853 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, tmp_ctx, &name);
2854 if(!strcmp(argv[0], name)){
2855 talloc_free(discard_const(name));
2858 talloc_free(discard_const(name));
2860 if (i == dbmap->num) {
2861 DEBUG(DEBUG_ERR,("No database with name '%s' found\n", argv[0]));
2862 talloc_free(tmp_ctx);
2867 ctdb_db = ctdb_attach(ctdb, argv[0], dbmap->dbs[i].persistent, 0);
2868 if (ctdb_db == NULL) {
2869 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", argv[0]));
2870 talloc_free(tmp_ctx);
2875 ret = tdb_transaction_start(ctdb_db->ltdb->tdb);
2877 DEBUG(DEBUG_ERR,("Failed to start transaction\n"));
2878 talloc_free(tmp_ctx);
2883 bd = talloc_zero(tmp_ctx, struct backup_data);
2885 DEBUG(DEBUG_ERR,("Failed to allocate backup_data\n"));
2886 talloc_free(tmp_ctx);
2890 bd->records = talloc_zero(bd, struct ctdb_marshall_buffer);
2891 if (bd->records == NULL) {
2892 DEBUG(DEBUG_ERR,("Failed to allocate ctdb_marshall_buffer\n"));
2893 talloc_free(tmp_ctx);
2897 bd->len = offsetof(struct ctdb_marshall_buffer, data);
2898 bd->records->db_id = ctdb_db->db_id;
2899 /* traverse the database collecting all records */
2900 if (tdb_traverse_read(ctdb_db->ltdb->tdb, backup_traverse, bd) == -1 ||
2901 bd->traverse_error) {
2902 DEBUG(DEBUG_ERR,("Traverse error\n"));
2903 talloc_free(tmp_ctx);
2907 tdb_transaction_cancel(ctdb_db->ltdb->tdb);
2910 fh = open(argv[1], O_RDWR|O_CREAT, 0600);
2912 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[1]));
2913 talloc_free(tmp_ctx);
2917 dbhdr.version = DB_VERSION;
2918 dbhdr.timestamp = time(NULL);
2919 dbhdr.persistent = dbmap->dbs[i].persistent;
2920 dbhdr.size = bd->len;
2921 if (strlen(argv[0]) >= MAX_DB_NAME) {
2922 DEBUG(DEBUG_ERR,("Too long dbname\n"));
2925 strncpy(discard_const(dbhdr.name), argv[0], MAX_DB_NAME);
2926 ret = write(fh, &dbhdr, sizeof(dbhdr));
2928 DEBUG(DEBUG_ERR,("write failed: %s\n", strerror(errno)));
2931 ret = write(fh, bd->records, bd->len);
2933 DEBUG(DEBUG_ERR,("write failed: %s\n", strerror(errno)));
2942 DEBUG(DEBUG_ERR,("close failed: %s\n", strerror(errno)));
2945 talloc_free(tmp_ctx);
2950 * restore a database from a file
2952 static int control_restoredb(struct ctdb_context *ctdb, int argc, const char **argv)
2955 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2958 struct db_file_header dbhdr;
2959 struct ctdb_db_context *ctdb_db;
2960 struct ctdb_node_map *nodemap=NULL;
2961 struct ctdb_vnn_map *vnnmap=NULL;
2963 struct ctdb_control_wipe_database w;
2965 uint32_t generation;
2970 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
2974 fh = open(argv[0], O_RDONLY);
2976 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[0]));
2977 talloc_free(tmp_ctx);
2981 read(fh, &dbhdr, sizeof(dbhdr));
2982 if (dbhdr.version != DB_VERSION) {
2983 DEBUG(DEBUG_ERR,("Invalid version of database dump. File is version %lu but expected version was %u\n", dbhdr.version, DB_VERSION));
2984 talloc_free(tmp_ctx);
2988 outdata.dsize = dbhdr.size;
2989 outdata.dptr = talloc_size(tmp_ctx, outdata.dsize);
2990 if (outdata.dptr == NULL) {
2991 DEBUG(DEBUG_ERR,("Failed to allocate data of size '%lu'\n", dbhdr.size));
2993 talloc_free(tmp_ctx);
2996 read(fh, outdata.dptr, outdata.dsize);
2999 tm = localtime(&dbhdr.timestamp);
3000 strftime(tbuf,sizeof(tbuf)-1,"%Y/%m/%d %H:%M:%S", tm);
3001 printf("Restoring database '%s' from backup @ %s\n",
3005 ctdb_db = ctdb_attach(ctdb, dbhdr.name, dbhdr.persistent, 0);
3006 if (ctdb_db == NULL) {
3007 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", dbhdr.name));
3008 talloc_free(tmp_ctx);
3012 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
3014 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
3015 talloc_free(tmp_ctx);
3020 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &vnnmap);
3022 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n", options.pnn));
3023 talloc_free(tmp_ctx);
3027 /* freeze all nodes */
3028 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3029 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_FREEZE,
3034 DEBUG(DEBUG_ERR, ("Unable to freeze nodes.\n"));
3035 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3036 talloc_free(tmp_ctx);
3040 generation = vnnmap->generation;
3041 data.dptr = (void *)&generation;
3042 data.dsize = sizeof(generation);
3044 /* start a cluster wide transaction */
3045 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3046 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_START,
3048 TIMELIMIT(), false, data,
3051 DEBUG(DEBUG_ERR, ("Unable to start cluster wide transactions.\n"));
3056 w.db_id = ctdb_db->db_id;
3057 w.transaction_id = generation;
3059 data.dptr = (void *)&w;
3060 data.dsize = sizeof(w);
3062 /* wipe all the remote databases. */
3063 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3064 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_WIPE_DATABASE,
3066 TIMELIMIT(), false, data,
3069 DEBUG(DEBUG_ERR, ("Unable to wipe database.\n"));
3070 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3071 talloc_free(tmp_ctx);
3075 /* push the database */
3076 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3077 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_PUSH_DB,
3079 TIMELIMIT(), false, outdata,
3082 DEBUG(DEBUG_ERR, ("Failed to push database.\n"));
3083 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3084 talloc_free(tmp_ctx);
3088 data.dptr = (void *)&generation;
3089 data.dsize = sizeof(generation);
3091 /* commit all the changes */
3092 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_COMMIT,
3094 TIMELIMIT(), false, data,
3097 DEBUG(DEBUG_ERR, ("Unable to commit databases.\n"));
3098 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3099 talloc_free(tmp_ctx);
3104 /* thaw all nodes */
3105 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3106 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_THAW,
3111 DEBUG(DEBUG_ERR, ("Unable to thaw nodes.\n"));
3112 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3113 talloc_free(tmp_ctx);
3118 talloc_free(tmp_ctx);
3123 * set flags of a node in the nodemap
3125 static int control_setflags(struct ctdb_context *ctdb, int argc, const char **argv)
3132 struct ctdb_node_flag_change c;
3139 if (sscanf(argv[0], "%d", &node) != 1) {
3140 DEBUG(DEBUG_ERR, ("Badly formed node\n"));
3144 if (sscanf(argv[1], "0x%x", &flags) != 1) {
3145 DEBUG(DEBUG_ERR, ("Badly formed flags\n"));
3152 c.new_flags = flags;
3154 data.dsize = sizeof(c);
3155 data.dptr = (unsigned char *)&c;
3157 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_MODIFY_FLAGS, 0,
3158 data, NULL, NULL, &status, NULL, NULL);
3159 if (ret != 0 || status != 0) {
3160 DEBUG(DEBUG_ERR,("Failed to modify flags\n"));
3169 static int control_dumpmemory(struct ctdb_context *ctdb, int argc, const char **argv)
3175 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3176 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_DUMP_MEMORY,
3177 0, tdb_null, tmp_ctx, &data, &res, NULL, &errmsg);
3178 if (ret != 0 || res != 0) {
3179 DEBUG(DEBUG_ERR,("Failed to dump memory - %s\n", errmsg));
3180 talloc_free(tmp_ctx);
3183 write(1, data.dptr, data.dsize);
3184 talloc_free(tmp_ctx);
3189 handler for memory dumps
3191 static void mem_dump_handler(struct ctdb_context *ctdb, uint64_t srvid,
3192 TDB_DATA data, void *private_data)
3194 write(1, data.dptr, data.dsize);
3199 dump memory usage on the recovery daemon
3201 static int control_rddumpmemory(struct ctdb_context *ctdb, int argc, const char **argv)
3205 struct rd_memdump_reply rd;
3207 rd.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
3209 DEBUG(DEBUG_ERR, ("Failed to get pnn of local node\n"));
3212 rd.srvid = getpid();
3214 /* register a message port for receiveing the reply so that we
3215 can receive the reply
3217 ctdb_set_message_handler(ctdb, rd.srvid, mem_dump_handler, NULL);
3220 data.dptr = (uint8_t *)&rd;
3221 data.dsize = sizeof(rd);
3223 ret = ctdb_send_message(ctdb, options.pnn, CTDB_SRVID_MEM_DUMP, data);
3225 DEBUG(DEBUG_ERR,("Failed to send memdump request message to %u\n", options.pnn));
3229 /* this loop will terminate when we have received the reply */
3231 event_loop_once(ctdb->ev);
3238 list all nodes in the cluster
3239 if the daemon is running, we read the data from the daemon.
3240 if the daemon is not running we parse the nodes file directly
3242 static int control_listnodes(struct ctdb_context *ctdb, int argc, const char **argv)
3245 struct ctdb_node_map *nodemap=NULL;
3248 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
3250 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
3254 for(i=0;i<nodemap->num;i++){
3255 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
3258 if (options.machinereadable){
3259 printf(":%d:%s:\n", nodemap->nodes[i].pnn, ctdb_addr_to_str(&nodemap->nodes[i].addr));
3261 printf("%s\n", ctdb_addr_to_str(&nodemap->nodes[i].addr));
3265 TALLOC_CTX *mem_ctx = talloc_new(NULL);
3266 struct pnn_node *pnn_nodes;
3267 struct pnn_node *pnn_node;
3269 pnn_nodes = read_nodes_file(mem_ctx);
3270 if (pnn_nodes == NULL) {
3271 DEBUG(DEBUG_ERR,("Failed to read nodes file\n"));
3272 talloc_free(mem_ctx);
3276 for(pnn_node=pnn_nodes;pnn_node;pnn_node=pnn_node->next) {
3277 ctdb_sock_addr addr;
3279 if (parse_ip(pnn_node->addr, NULL, 63999, &addr) == 0) {
3280 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s' in nodes file\n", pnn_node->addr));
3281 talloc_free(mem_ctx);
3285 if (options.machinereadable){
3286 printf(":%d:%s:\n", pnn_node->pnn, pnn_node->addr);
3288 printf("%s\n", pnn_node->addr);
3291 talloc_free(mem_ctx);
3298 reload the nodes file on the local node
3300 static int control_reload_nodes_file(struct ctdb_context *ctdb, int argc, const char **argv)
3304 struct ctdb_node_map *nodemap=NULL;
3306 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
3308 DEBUG(DEBUG_ERR, ("Failed to read pnn of local node\n"));
3312 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
3314 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
3318 /* reload the nodes file on all remote nodes */
3319 for (i=0;i<nodemap->num;i++) {
3320 if (nodemap->nodes[i].pnn == mypnn) {
3323 DEBUG(DEBUG_NOTICE, ("Reloading nodes file on node %u\n", nodemap->nodes[i].pnn));
3324 ret = ctdb_ctrl_reload_nodes_file(ctdb, TIMELIMIT(),
3325 nodemap->nodes[i].pnn);
3327 DEBUG(DEBUG_ERR, ("ERROR: Failed to reload nodes file on node %u. You MUST fix that node manually!\n", nodemap->nodes[i].pnn));
3331 /* reload the nodes file on the local node */
3332 DEBUG(DEBUG_NOTICE, ("Reloading nodes file on node %u\n", mypnn));
3333 ret = ctdb_ctrl_reload_nodes_file(ctdb, TIMELIMIT(), mypnn);
3335 DEBUG(DEBUG_ERR, ("ERROR: Failed to reload nodes file on node %u. You MUST fix that node manually!\n", mypnn));
3338 /* initiate a recovery */
3339 control_recover(ctdb, argc, argv);
3345 static const struct {
3347 int (*fn)(struct ctdb_context *, int, const char **);
3349 bool without_daemon; /* can be run without daemon running ? */
3352 } ctdb_commands[] = {
3354 { "version", control_version, true, false, "show version of ctdb" },
3356 { "status", control_status, true, false, "show node status" },
3357 { "uptime", control_uptime, true, false, "show node uptime" },
3358 { "ping", control_ping, true, false, "ping all nodes" },
3359 { "getvar", control_getvar, true, false, "get a tunable variable", "<name>"},
3360 { "setvar", control_setvar, true, false, "set a tunable variable", "<name> <value>"},
3361 { "listvars", control_listvars, true, false, "list tunable variables"},
3362 { "statistics", control_statistics, false, false, "show statistics" },
3363 { "statisticsreset", control_statistics_reset, true, false, "reset statistics"},
3364 { "ip", control_ip, false, false, "show which public ip's that ctdb manages" },
3365 { "process-exists", control_process_exists, true, false, "check if a process exists on a node", "<pid>"},
3366 { "getdbmap", control_getdbmap, true, false, "show the database map" },
3367 { "catdb", control_catdb, true, false, "dump a database" , "<dbname>"},
3368 { "getmonmode", control_getmonmode, true, false, "show monitoring mode" },
3369 { "getcapabilities", control_getcapabilities, true, false, "show node capabilities" },
3370 { "pnn", control_pnn, true, false, "show the pnn of the currnet node" },
3371 { "lvs", control_lvs, true, false, "show lvs configuration" },
3372 { "lvsmaster", control_lvsmaster, true, false, "show which node is the lvs master" },
3373 { "disablemonitor", control_disable_monmode,true, false, "set monitoring mode to DISABLE" },
3374 { "enablemonitor", control_enable_monmode, true, false, "set monitoring mode to ACTIVE" },
3375 { "setdebug", control_setdebug, true, false, "set debug level", "<EMERG|ALERT|CRIT|ERR|WARNING|NOTICE|INFO|DEBUG>" },
3376 { "getdebug", control_getdebug, true, false, "get debug level" },
3377 { "attach", control_attach, true, false, "attach to a database", "<dbname>" },
3378 { "dumpmemory", control_dumpmemory, true, false, "dump memory map to stdout" },
3379 { "rddumpmemory", control_rddumpmemory, true, false, "dump memory map from the recovery daemon to stdout" },
3380 { "getpid", control_getpid, true, false, "get ctdbd process ID" },
3381 { "disable", control_disable, true, false, "disable a nodes public IP" },
3382 { "enable", control_enable, true, false, "enable a nodes public IP" },
3383 { "stop", control_stop, true, false, "stop a node" },
3384 { "continue", control_continue, true, false, "re-start a stopped node" },
3385 { "ban", control_ban, true, false, "ban a node from the cluster", "<bantime|0>"},
3386 { "unban", control_unban, true, false, "unban a node" },
3387 { "showban", control_showban, true, false, "show ban information"},
3388 { "shutdown", control_shutdown, true, false, "shutdown ctdbd" },
3389 { "recover", control_recover, true, false, "force recovery" },
3390 { "ipreallocate", control_ipreallocate, true, false, "force the recovery daemon to perform a ip reallocation procedure" },
3391 { "freeze", control_freeze, true, false, "freeze all databases" },
3392 { "thaw", control_thaw, true, false, "thaw all databases" },
3393 { "isnotrecmaster", control_isnotrecmaster, false, false, "check if the local node is recmaster or not" },
3394 { "killtcp", kill_tcp, false, false, "kill a tcp connection.", "<srcip:port> <dstip:port>" },
3395 { "gratiousarp", control_gratious_arp, false, false, "send a gratious arp", "<ip> <interface>" },
3396 { "tickle", tickle_tcp, false, false, "send a tcp tickle ack", "<srcip:port> <dstip:port>" },
3397 { "gettickles", control_get_tickles, false, false, "get the list of tickles registered for this ip", "<ip>" },
3399 { "regsrvid", regsrvid, false, false, "register a server id", "<pnn> <type> <id>" },
3400 { "unregsrvid", unregsrvid, false, false, "unregister a server id", "<pnn> <type> <id>" },
3401 { "chksrvid", chksrvid, false, false, "check if a server id exists", "<pnn> <type> <id>" },
3402 { "getsrvids", getsrvids, false, false, "get a list of all server ids"},
3403 { "vacuum", ctdb_vacuum, false, false, "vacuum the databases of empty records", "[max_records]"},
3404 { "repack", ctdb_repack, false, false, "repack all databases", "[max_freelist]"},
3405 { "listnodes", control_listnodes, false, true, "list all nodes in the cluster"},
3406 { "reloadnodes", control_reload_nodes_file, false, false, "reload the nodes file and restart the transport on all nodes"},
3407 { "moveip", control_moveip, false, false, "move/failover an ip address to another node", "<ip> <node>"},
3408 { "addip", control_addip, true, false, "add a ip address to a node", "<ip/mask> <iface>"},
3409 { "delip", control_delip, false, false, "delete an ip address from a node", "<ip>"},
3410 { "eventscript", control_eventscript, true, false, "run the eventscript with the given parameters on a node", "<arguments>"},
3411 { "backupdb", control_backupdb, false, false, "backup the database into a file.", "<database> <file>"},
3412 { "restoredb", control_restoredb, false, false, "restore the database from a file.", "<file>"},
3413 { "recmaster", control_recmaster, false, false, "show the pnn for the recovery master."},
3414 { "setflags", control_setflags, false, false, "set flags for a node in the nodemap.", "<node> <flags>"},
3415 { "scriptstatus", control_scriptstatus, false, false, "show the status of the monitoring scripts"},
3416 { "enablescript", control_enablescript, false, false, "enable an eventscript", "<script>"},
3417 { "disablescript", control_disablescript, false, false, "disable an eventscript", "<script>"},
3418 { "natgwlist", control_natgwlist, false, false, "show the nodes belonging to this natgw configuration"},
3419 { "xpnn", control_xpnn, true, true, "find the pnn of the local node without talking to the daemon (unreliable)" },
3420 { "getreclock", control_getreclock, false, false, "Show the reclock file of a node"},
3421 { "setreclock", control_setreclock, false, false, "Set/clear the reclock file of a node", "[filename]"},
3422 { "setnatgwstate", control_setnatgwstate, false, false, "Set NATGW state to on/off", "{on|off}"},
3423 { "setlmasterrole", control_setlmasterrole, false, false, "Set LMASTER role to on/off", "{on|off}"},
3424 { "setrecmasterrole", control_setrecmasterrole, false, false, "Set RECMASTER role to on/off", "{on|off}"},
3430 static void usage(void)
3434 "Usage: ctdb [options] <control>\n" \
3436 " -n <node> choose node number, or 'all' (defaults to local node)\n"
3437 " -Y generate machinereadable output\n"
3438 " -t <timelimit> set timelimit for control in seconds (default %u)\n", options.timelimit);
3439 printf("Controls:\n");
3440 for (i=0;i<ARRAY_SIZE(ctdb_commands);i++) {
3441 printf(" %-15s %-27s %s\n",
3442 ctdb_commands[i].name,
3443 ctdb_commands[i].args?ctdb_commands[i].args:"",
3444 ctdb_commands[i].msg);
3450 static void ctdb_alarm(int sig)
3452 printf("Maximum runtime exceeded - exiting\n");
3459 int main(int argc, const char *argv[])
3461 struct ctdb_context *ctdb;
3462 char *nodestring = NULL;
3463 struct poptOption popt_options[] = {
3466 { "timelimit", 't', POPT_ARG_INT, &options.timelimit, 0, "timelimit", "integer" },
3467 { "node", 'n', POPT_ARG_STRING, &nodestring, 0, "node", "integer|all" },
3468 { "machinereadable", 'Y', POPT_ARG_NONE, &options.machinereadable, 0, "enable machinereadable output", NULL },
3469 { "maxruntime", 'T', POPT_ARG_INT, &options.maxruntime, 0, "die if runtime exceeds this limit (in seconds)", "integer" },
3473 const char **extra_argv;
3477 struct event_context *ev;
3478 const char *control;
3482 /* set some defaults */
3483 options.maxruntime = 0;
3484 options.timelimit = 3;
3485 options.pnn = CTDB_CURRENT_NODE;
3487 pc = poptGetContext(argv[0], argc, argv, popt_options, POPT_CONTEXT_KEEP_FIRST);
3489 while ((opt = poptGetNextOpt(pc)) != -1) {
3492 DEBUG(DEBUG_ERR, ("Invalid option %s: %s\n",
3493 poptBadOption(pc, 0), poptStrerror(opt)));
3498 /* setup the remaining options for the main program to use */
3499 extra_argv = poptGetArgs(pc);
3502 while (extra_argv[extra_argc]) extra_argc++;
3505 if (extra_argc < 1) {
3509 if (options.maxruntime == 0) {
3510 const char *ctdb_timeout;
3511 ctdb_timeout = getenv("CTDB_TIMEOUT");
3512 if (ctdb_timeout != NULL) {
3513 options.maxruntime = strtoul(ctdb_timeout, NULL, 0);
3515 /* default timeout is 120 seconds */
3516 options.maxruntime = 120;
3520 signal(SIGALRM, ctdb_alarm);
3521 alarm(options.maxruntime);
3523 /* setup the node number to contact */
3524 if (nodestring != NULL) {
3525 if (strcmp(nodestring, "all") == 0) {
3526 options.pnn = CTDB_BROADCAST_ALL;
3528 options.pnn = strtoul(nodestring, NULL, 0);
3532 control = extra_argv[0];
3534 ev = event_context_init(NULL);
3536 for (i=0;i<ARRAY_SIZE(ctdb_commands);i++) {
3537 if (strcmp(control, ctdb_commands[i].name) == 0) {
3540 if (ctdb_commands[i].without_daemon == true) {
3544 /* initialise ctdb */
3545 ctdb = ctdb_cmdline_client(ev);
3547 if (ctdb_commands[i].without_daemon == false) {
3549 DEBUG(DEBUG_ERR, ("Failed to init ctdb\n"));
3553 /* verify the node exists */
3556 if (options.pnn == CTDB_CURRENT_NODE) {
3558 pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
3566 if (ctdb_commands[i].auto_all &&
3567 options.pnn == CTDB_BROADCAST_ALL) {
3572 nodes = ctdb_get_connected_nodes(ctdb, TIMELIMIT(), ctdb, &num_nodes);
3573 CTDB_NO_MEMORY(ctdb, nodes);
3575 for (j=0;j<num_nodes;j++) {
3576 options.pnn = nodes[j];
3577 ret |= ctdb_commands[i].fn(ctdb, extra_argc-1, extra_argv+1);
3581 ret = ctdb_commands[i].fn(ctdb, extra_argc-1, extra_argv+1);
3587 if (i == ARRAY_SIZE(ctdb_commands)) {
3588 DEBUG(DEBUG_ERR, ("Unknown control '%s'\n", control));