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"
34 #define ERR_TIMEOUT 20 /* timed out trying to reach node */
35 #define ERR_NONODE 21 /* node does not exist */
36 #define ERR_DISNODE 22 /* node is disconnected */
38 static void usage(void);
47 #define TIMELIMIT() timeval_current_ofs(options.timelimit, 0)
50 static int control_version(struct ctdb_context *ctdb, int argc, const char **argv)
53 #define XSTR(x) STR(x)
54 printf("CTDB version: %s\n", XSTR(CTDB_VERS));
61 verify that a node exists and is reachable
63 static void verify_node(struct ctdb_context *ctdb)
66 struct ctdb_node_map *nodemap=NULL;
68 if (options.pnn == CTDB_CURRENT_NODE) {
71 if (options.pnn == CTDB_BROADCAST_ALL) {
75 /* verify the node exists */
76 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
77 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
80 if (options.pnn >= nodemap->num) {
81 DEBUG(DEBUG_ERR, ("Node %u does not exist\n", options.pnn));
84 if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_DELETED) {
85 DEBUG(DEBUG_ERR, ("Node %u is DELETED\n", options.pnn));
88 if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_DISCONNECTED) {
89 DEBUG(DEBUG_ERR, ("Node %u is DISCONNECTED\n", options.pnn));
93 /* verify we can access the node */
94 ret = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
96 DEBUG(DEBUG_ERR,("Can not ban node. Node is not operational.\n"));
102 check if a database exists
104 static int db_exists(struct ctdb_context *ctdb, const char *db_name)
107 struct ctdb_dbid_map *dbmap=NULL;
109 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
111 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
115 for(i=0;i<dbmap->num;i++){
118 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
119 if (!strcmp(name, db_name)) {
128 see if a process exists
130 static int control_process_exists(struct ctdb_context *ctdb, int argc, const char **argv)
138 if (sscanf(argv[0], "%u:%u", &pnn, &pid) != 2) {
139 DEBUG(DEBUG_ERR, ("Badly formed pnn:pid\n"));
143 ret = ctdb_ctrl_process_exists(ctdb, pnn, pid);
145 printf("%u:%u exists\n", pnn, pid);
147 printf("%u:%u does not exist\n", pnn, pid);
153 display statistics structure
155 static void show_statistics(struct ctdb_statistics *s)
157 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
159 const char *prefix=NULL;
165 #define STATISTICS_FIELD(n) { #n, offsetof(struct ctdb_statistics, n) }
166 STATISTICS_FIELD(num_clients),
167 STATISTICS_FIELD(frozen),
168 STATISTICS_FIELD(recovering),
169 STATISTICS_FIELD(client_packets_sent),
170 STATISTICS_FIELD(client_packets_recv),
171 STATISTICS_FIELD(node_packets_sent),
172 STATISTICS_FIELD(node_packets_recv),
173 STATISTICS_FIELD(keepalive_packets_sent),
174 STATISTICS_FIELD(keepalive_packets_recv),
175 STATISTICS_FIELD(node.req_call),
176 STATISTICS_FIELD(node.reply_call),
177 STATISTICS_FIELD(node.req_dmaster),
178 STATISTICS_FIELD(node.reply_dmaster),
179 STATISTICS_FIELD(node.reply_error),
180 STATISTICS_FIELD(node.req_message),
181 STATISTICS_FIELD(node.req_control),
182 STATISTICS_FIELD(node.reply_control),
183 STATISTICS_FIELD(client.req_call),
184 STATISTICS_FIELD(client.req_message),
185 STATISTICS_FIELD(client.req_control),
186 STATISTICS_FIELD(timeouts.call),
187 STATISTICS_FIELD(timeouts.control),
188 STATISTICS_FIELD(timeouts.traverse),
189 STATISTICS_FIELD(total_calls),
190 STATISTICS_FIELD(pending_calls),
191 STATISTICS_FIELD(lockwait_calls),
192 STATISTICS_FIELD(pending_lockwait_calls),
193 STATISTICS_FIELD(childwrite_calls),
194 STATISTICS_FIELD(pending_childwrite_calls),
195 STATISTICS_FIELD(memory_used),
196 STATISTICS_FIELD(max_hop_count),
198 printf("CTDB version %u\n", CTDB_VERSION);
199 for (i=0;i<ARRAY_SIZE(fields);i++) {
200 if (strchr(fields[i].name, '.')) {
201 preflen = strcspn(fields[i].name, ".")+1;
202 if (!prefix || strncmp(prefix, fields[i].name, preflen) != 0) {
203 prefix = fields[i].name;
204 printf(" %*.*s\n", preflen-1, preflen-1, fields[i].name);
209 printf(" %*s%-22s%*s%10u\n",
211 fields[i].name+preflen,
213 *(uint32_t *)(fields[i].offset+(uint8_t *)s));
215 printf(" %-30s %.6f sec\n", "max_reclock_ctdbd", s->reclock.ctdbd);
216 printf(" %-30s %.6f sec\n", "max_reclock_recd", s->reclock.recd);
218 printf(" %-30s %.6f sec\n", "max_call_latency", s->max_call_latency);
219 printf(" %-30s %.6f sec\n", "max_lockwait_latency", s->max_lockwait_latency);
220 printf(" %-30s %.6f sec\n", "max_childwrite_latency", s->max_childwrite_latency);
221 talloc_free(tmp_ctx);
225 display remote ctdb statistics combined from all nodes
227 static int control_statistics_all(struct ctdb_context *ctdb)
230 struct ctdb_statistics statistics;
234 nodes = ctdb_get_connected_nodes(ctdb, TIMELIMIT(), ctdb, &num_nodes);
235 CTDB_NO_MEMORY(ctdb, nodes);
237 ZERO_STRUCT(statistics);
239 for (i=0;i<num_nodes;i++) {
240 struct ctdb_statistics s1;
242 uint32_t *v1 = (uint32_t *)&s1;
243 uint32_t *v2 = (uint32_t *)&statistics;
245 offsetof(struct ctdb_statistics, __last_counter) / sizeof(uint32_t);
246 ret = ctdb_ctrl_statistics(ctdb, nodes[i], &s1);
248 DEBUG(DEBUG_ERR, ("Unable to get statistics from node %u\n", nodes[i]));
251 for (j=0;j<num_ints;j++) {
254 statistics.max_hop_count =
255 MAX(statistics.max_hop_count, s1.max_hop_count);
256 statistics.max_call_latency =
257 MAX(statistics.max_call_latency, s1.max_call_latency);
258 statistics.max_lockwait_latency =
259 MAX(statistics.max_lockwait_latency, s1.max_lockwait_latency);
262 printf("Gathered statistics for %u nodes\n", num_nodes);
263 show_statistics(&statistics);
268 display remote ctdb statistics
270 static int control_statistics(struct ctdb_context *ctdb, int argc, const char **argv)
273 struct ctdb_statistics statistics;
275 if (options.pnn == CTDB_BROADCAST_ALL) {
276 return control_statistics_all(ctdb);
279 ret = ctdb_ctrl_statistics(ctdb, options.pnn, &statistics);
281 DEBUG(DEBUG_ERR, ("Unable to get statistics from node %u\n", options.pnn));
284 show_statistics(&statistics);
290 reset remote ctdb statistics
292 static int control_statistics_reset(struct ctdb_context *ctdb, int argc, const char **argv)
296 ret = ctdb_statistics_reset(ctdb, options.pnn);
298 DEBUG(DEBUG_ERR, ("Unable to reset statistics on node %u\n", options.pnn));
306 display uptime of remote node
308 static int control_uptime(struct ctdb_context *ctdb, int argc, const char **argv)
311 struct ctdb_uptime *uptime = NULL;
312 int tmp, days, hours, minutes, seconds;
314 ret = ctdb_ctrl_uptime(ctdb, ctdb, TIMELIMIT(), options.pnn, &uptime);
316 DEBUG(DEBUG_ERR, ("Unable to get uptime from node %u\n", options.pnn));
320 if (options.machinereadable){
321 printf(":Current Node Time:Ctdb Start Time:Last Recovery/Failover Time:Last Recovery/IPFailover Duration:\n");
322 printf(":%u:%u:%u:%lf\n",
323 (unsigned int)uptime->current_time.tv_sec,
324 (unsigned int)uptime->ctdbd_start_time.tv_sec,
325 (unsigned int)uptime->last_recovery_finished.tv_sec,
326 timeval_delta(&uptime->last_recovery_finished,
327 &uptime->last_recovery_started)
332 printf("Current time of node : %s", ctime(&uptime->current_time.tv_sec));
334 tmp = uptime->current_time.tv_sec - uptime->ctdbd_start_time.tv_sec;
342 printf("Ctdbd start time : (%03d %02d:%02d:%02d) %s", days, hours, minutes, seconds, ctime(&uptime->ctdbd_start_time.tv_sec));
344 tmp = uptime->current_time.tv_sec - uptime->last_recovery_finished.tv_sec;
352 printf("Time of last recovery/failover: (%03d %02d:%02d:%02d) %s", days, hours, minutes, seconds, ctime(&uptime->last_recovery_finished.tv_sec));
354 printf("Duration of last recovery/failover: %lf seconds\n",
355 timeval_delta(&uptime->last_recovery_finished,
356 &uptime->last_recovery_started));
362 show the PNN of the current node
364 static int control_pnn(struct ctdb_context *ctdb, int argc, const char **argv)
368 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
370 DEBUG(DEBUG_ERR, ("Unable to get pnn from local node."));
374 printf("PNN:%d\n", mypnn);
380 struct pnn_node *next;
385 static struct pnn_node *read_nodes_file(TALLOC_CTX *mem_ctx)
387 const char *nodes_list;
391 struct pnn_node *pnn_nodes = NULL;
392 struct pnn_node *pnn_node;
393 struct pnn_node *tmp_node;
395 /* read the nodes file */
396 nodes_list = getenv("CTDB_NODES");
397 if (nodes_list == NULL) {
398 nodes_list = "/etc/ctdb/nodes";
400 lines = file_lines_load(nodes_list, &nlines, mem_ctx);
404 while (nlines > 0 && strcmp(lines[nlines-1], "") == 0) {
407 for (i=0, pnn=0; i<nlines; i++) {
411 /* strip leading spaces */
412 while((*node == ' ') || (*node == '\t')) {
419 if (strcmp(node, "") == 0) {
422 pnn_node = talloc(mem_ctx, struct pnn_node);
423 pnn_node->pnn = pnn++;
424 pnn_node->addr = talloc_strdup(pnn_node, node);
425 pnn_node->next = pnn_nodes;
426 pnn_nodes = pnn_node;
429 /* swap them around so we return them in incrementing order */
430 pnn_node = pnn_nodes;
434 pnn_node = pnn_node->next;
436 tmp_node->next = pnn_nodes;
437 pnn_nodes = tmp_node;
444 show the PNN of the current node
445 discover the pnn by loading the nodes file and try to bind to all
446 addresses one at a time until the ip address is found.
448 static int control_xpnn(struct ctdb_context *ctdb, int argc, const char **argv)
450 TALLOC_CTX *mem_ctx = talloc_new(NULL);
451 struct pnn_node *pnn_nodes;
452 struct pnn_node *pnn_node;
454 pnn_nodes = read_nodes_file(mem_ctx);
455 if (pnn_nodes == NULL) {
456 DEBUG(DEBUG_ERR,("Failed to read nodes file\n"));
457 talloc_free(mem_ctx);
461 for(pnn_node=pnn_nodes;pnn_node;pnn_node=pnn_node->next) {
464 if (parse_ip(pnn_node->addr, NULL, 63999, &addr) == 0) {
465 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s' in nodes file\n", pnn_node->addr));
466 talloc_free(mem_ctx);
470 if (ctdb_sys_have_ip(&addr)) {
471 printf("PNN:%d\n", pnn_node->pnn);
472 talloc_free(mem_ctx);
477 printf("Failed to detect which PNN this node is\n");
478 talloc_free(mem_ctx);
483 display remote ctdb status
485 static int control_status(struct ctdb_context *ctdb, int argc, const char **argv)
488 struct ctdb_vnn_map *vnnmap=NULL;
489 struct ctdb_node_map *nodemap=NULL;
490 uint32_t recmode, recmaster;
493 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
498 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
500 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
504 if(options.machinereadable){
505 printf(":Node:IP:Disconnected:Banned:Disabled:Unhealthy:Stopped:Inactive:PartiallyOnline:\n");
506 for(i=0;i<nodemap->num;i++){
507 int partially_online = 0;
510 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
513 if (nodemap->nodes[i].flags == 0) {
514 struct ctdb_control_get_ifaces *ifaces;
516 ret = ctdb_ctrl_get_ifaces(ctdb, TIMELIMIT(),
517 nodemap->nodes[i].pnn,
520 for (j=0; j < ifaces->num; j++) {
521 if (ifaces->ifaces[j].link_state != 0) {
524 partially_online = 1;
530 printf(":%d:%s:%d:%d:%d:%d:%d:%d:%d:\n", nodemap->nodes[i].pnn,
531 ctdb_addr_to_str(&nodemap->nodes[i].addr),
532 !!(nodemap->nodes[i].flags&NODE_FLAGS_DISCONNECTED),
533 !!(nodemap->nodes[i].flags&NODE_FLAGS_BANNED),
534 !!(nodemap->nodes[i].flags&NODE_FLAGS_PERMANENTLY_DISABLED),
535 !!(nodemap->nodes[i].flags&NODE_FLAGS_UNHEALTHY),
536 !!(nodemap->nodes[i].flags&NODE_FLAGS_STOPPED),
537 !!(nodemap->nodes[i].flags&NODE_FLAGS_INACTIVE),
543 printf("Number of nodes:%d\n", nodemap->num);
544 for(i=0;i<nodemap->num;i++){
545 static const struct {
549 { NODE_FLAGS_DISCONNECTED, "DISCONNECTED" },
550 { NODE_FLAGS_PERMANENTLY_DISABLED, "DISABLED" },
551 { NODE_FLAGS_BANNED, "BANNED" },
552 { NODE_FLAGS_UNHEALTHY, "UNHEALTHY" },
553 { NODE_FLAGS_DELETED, "DELETED" },
554 { NODE_FLAGS_STOPPED, "STOPPED" },
555 { NODE_FLAGS_INACTIVE, "INACTIVE" },
557 char *flags_str = NULL;
560 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
563 if (nodemap->nodes[i].flags == 0) {
564 struct ctdb_control_get_ifaces *ifaces;
566 ret = ctdb_ctrl_get_ifaces(ctdb, TIMELIMIT(),
567 nodemap->nodes[i].pnn,
570 for (j=0; j < ifaces->num; j++) {
571 if (ifaces->ifaces[j].link_state != 0) {
574 flags_str = talloc_strdup(ctdb, "PARTIALLYONLINE");
580 for (j=0;j<ARRAY_SIZE(flag_names);j++) {
581 if (nodemap->nodes[i].flags & flag_names[j].flag) {
582 if (flags_str == NULL) {
583 flags_str = talloc_strdup(ctdb, flag_names[j].name);
585 flags_str = talloc_asprintf_append(flags_str, "|%s",
588 CTDB_NO_MEMORY_FATAL(ctdb, flags_str);
591 if (flags_str == NULL) {
592 flags_str = talloc_strdup(ctdb, "OK");
593 CTDB_NO_MEMORY_FATAL(ctdb, flags_str);
595 printf("pnn:%d %-16s %s%s\n", nodemap->nodes[i].pnn,
596 ctdb_addr_to_str(&nodemap->nodes[i].addr),
598 nodemap->nodes[i].pnn == mypnn?" (THIS NODE)":"");
599 talloc_free(flags_str);
602 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &vnnmap);
604 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n", options.pnn));
607 if (vnnmap->generation == INVALID_GENERATION) {
608 printf("Generation:INVALID\n");
610 printf("Generation:%d\n",vnnmap->generation);
612 printf("Size:%d\n",vnnmap->size);
613 for(i=0;i<vnnmap->size;i++){
614 printf("hash:%d lmaster:%d\n", i, vnnmap->map[i]);
617 ret = ctdb_ctrl_getrecmode(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmode);
619 DEBUG(DEBUG_ERR, ("Unable to get recmode from node %u\n", options.pnn));
622 printf("Recovery mode:%s (%d)\n",recmode==CTDB_RECOVERY_NORMAL?"NORMAL":"RECOVERY",recmode);
624 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
626 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
629 printf("Recovery master:%d\n",recmaster);
636 struct natgw_node *next;
641 display the list of nodes belonging to this natgw configuration
643 static int control_natgwlist(struct ctdb_context *ctdb, int argc, const char **argv)
646 const char *natgw_list;
649 struct natgw_node *natgw_nodes = NULL;
650 struct natgw_node *natgw_node;
651 struct ctdb_node_map *nodemap=NULL;
654 /* read the natgw nodes file into a linked list */
655 natgw_list = getenv("NATGW_NODES");
656 if (natgw_list == NULL) {
657 natgw_list = "/etc/ctdb/natgw_nodes";
659 lines = file_lines_load(natgw_list, &nlines, ctdb);
661 ctdb_set_error(ctdb, "Failed to load natgw node list '%s'\n", natgw_list);
664 while (nlines > 0 && strcmp(lines[nlines-1], "") == 0) {
667 for (i=0;i<nlines;i++) {
671 /* strip leading spaces */
672 while((*node == ' ') || (*node == '\t')) {
678 if (strcmp(node, "") == 0) {
681 natgw_node = talloc(ctdb, struct natgw_node);
682 natgw_node->addr = talloc_strdup(natgw_node, node);
683 CTDB_NO_MEMORY(ctdb, natgw_node->addr);
684 natgw_node->next = natgw_nodes;
685 natgw_nodes = natgw_node;
688 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
690 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node.\n"));
695 while(i<nodemap->num) {
696 for(natgw_node=natgw_nodes;natgw_node;natgw_node=natgw_node->next) {
697 if (!strcmp(natgw_node->addr, ctdb_addr_to_str(&nodemap->nodes[i].addr))) {
702 /* this node was not in the natgw so we just remove it from
705 if ((natgw_node == NULL)
706 || (nodemap->nodes[i].flags & NODE_FLAGS_DISCONNECTED) ) {
709 for (j=i+1; j<nodemap->num; j++) {
710 nodemap->nodes[j-1] = nodemap->nodes[j];
719 /* pick a node to be natgwmaster
720 * we dont allow STOPPED, DELETED, BANNED or UNHEALTHY nodes to become the natgwmaster
722 for(i=0;i<nodemap->num;i++){
723 if (!(nodemap->nodes[i].flags & (NODE_FLAGS_DISCONNECTED|NODE_FLAGS_STOPPED|NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_UNHEALTHY))) {
724 printf("%d %s\n", nodemap->nodes[i].pnn,ctdb_addr_to_str(&nodemap->nodes[i].addr));
728 /* we couldnt find any healthy node, try unhealthy ones */
729 if (i == nodemap->num) {
730 for(i=0;i<nodemap->num;i++){
731 if (!(nodemap->nodes[i].flags & (NODE_FLAGS_DISCONNECTED|NODE_FLAGS_STOPPED|NODE_FLAGS_DELETED))) {
732 printf("%d %s\n", nodemap->nodes[i].pnn,ctdb_addr_to_str(&nodemap->nodes[i].addr));
737 /* unless all nodes are STOPPED, when we pick one anyway */
738 if (i == nodemap->num) {
739 for(i=0;i<nodemap->num;i++){
740 if (!(nodemap->nodes[i].flags & (NODE_FLAGS_DISCONNECTED|NODE_FLAGS_DELETED))) {
741 printf("%d %s\n", nodemap->nodes[i].pnn, ctdb_addr_to_str(&nodemap->nodes[i].addr));
745 /* or if we still can not find any */
746 if (i == nodemap->num) {
747 printf("-1 0.0.0.0\n");
751 /* print the pruned list of nodes belonging to this natgw list */
752 for(i=0;i<nodemap->num;i++){
753 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
756 printf(":%d:%s:%d:%d:%d:%d:%d\n", nodemap->nodes[i].pnn,
757 ctdb_addr_to_str(&nodemap->nodes[i].addr),
758 !!(nodemap->nodes[i].flags&NODE_FLAGS_DISCONNECTED),
759 !!(nodemap->nodes[i].flags&NODE_FLAGS_BANNED),
760 !!(nodemap->nodes[i].flags&NODE_FLAGS_PERMANENTLY_DISABLED),
761 !!(nodemap->nodes[i].flags&NODE_FLAGS_UNHEALTHY),
762 !!(nodemap->nodes[i].flags&NODE_FLAGS_STOPPED));
769 display the status of the scripts for monitoring (or other events)
771 static int control_one_scriptstatus(struct ctdb_context *ctdb,
772 enum ctdb_eventscript_call type)
774 struct ctdb_scripts_wire *script_status;
777 ret = ctdb_ctrl_getscriptstatus(ctdb, TIMELIMIT(), options.pnn, ctdb, type, &script_status);
779 DEBUG(DEBUG_ERR, ("Unable to get script status from node %u\n", options.pnn));
783 if (script_status == NULL) {
784 if (!options.machinereadable) {
785 printf("%s cycle never run\n",
786 ctdb_eventscript_call_names[type]);
791 if (!options.machinereadable) {
792 printf("%d scripts were executed last %s cycle\n",
793 script_status->num_scripts,
794 ctdb_eventscript_call_names[type]);
796 for (i=0; i<script_status->num_scripts; i++) {
797 const char *status = NULL;
799 switch (script_status->scripts[i].status) {
810 if (script_status->scripts[i].status > 0)
814 if (options.machinereadable) {
815 printf("%s:%s:%i:%s:%lu.%06lu:%lu.%06lu:%s:\n",
816 ctdb_eventscript_call_names[type],
817 script_status->scripts[i].name,
818 script_status->scripts[i].status,
820 (long)script_status->scripts[i].start.tv_sec,
821 (long)script_status->scripts[i].start.tv_usec,
822 (long)script_status->scripts[i].finished.tv_sec,
823 (long)script_status->scripts[i].finished.tv_usec,
824 script_status->scripts[i].output);
828 printf("%-20s Status:%s ",
829 script_status->scripts[i].name, status);
831 /* Some other error, eg from stat. */
832 printf("%-20s Status:CANNOT RUN (%s)",
833 script_status->scripts[i].name,
834 strerror(-script_status->scripts[i].status));
836 if (script_status->scripts[i].status >= 0) {
837 printf("Duration:%.3lf ",
838 timeval_delta(&script_status->scripts[i].finished,
839 &script_status->scripts[i].start));
841 if (script_status->scripts[i].status != -ENOEXEC) {
843 ctime(&script_status->scripts[i].start.tv_sec));
844 if (script_status->scripts[i].status != 0) {
845 printf(" OUTPUT:%s\n",
846 script_status->scripts[i].output);
856 static int control_scriptstatus(struct ctdb_context *ctdb,
857 int argc, const char **argv)
860 enum ctdb_eventscript_call type, min, max;
864 DEBUG(DEBUG_ERR, ("Unknown arguments to scriptstatus\n"));
869 arg = ctdb_eventscript_call_names[CTDB_EVENT_MONITOR];
873 for (type = 0; type < CTDB_EVENT_MAX; type++) {
874 if (strcmp(arg, ctdb_eventscript_call_names[type]) == 0) {
880 if (type == CTDB_EVENT_MAX) {
881 if (strcmp(arg, "all") == 0) {
883 max = CTDB_EVENT_MAX;
885 DEBUG(DEBUG_ERR, ("Unknown event type %s\n", argv[0]));
890 if (options.machinereadable) {
891 printf(":Type:Name:Code:Status:Start:End:Error Output...:\n");
894 for (type = min; type < max; type++) {
895 ret = control_one_scriptstatus(ctdb, type);
905 enable an eventscript
907 static int control_enablescript(struct ctdb_context *ctdb, int argc, const char **argv)
915 ret = ctdb_ctrl_enablescript(ctdb, TIMELIMIT(), options.pnn, argv[0]);
917 DEBUG(DEBUG_ERR, ("Unable to enable script %s on node %u\n", argv[0], options.pnn));
925 disable an eventscript
927 static int control_disablescript(struct ctdb_context *ctdb, int argc, const char **argv)
935 ret = ctdb_ctrl_disablescript(ctdb, TIMELIMIT(), options.pnn, argv[0]);
937 DEBUG(DEBUG_ERR, ("Unable to disable script %s on node %u\n", argv[0], options.pnn));
945 display the pnn of the recovery master
947 static int control_recmaster(struct ctdb_context *ctdb, int argc, const char **argv)
952 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
954 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
957 printf("%d\n",recmaster);
963 get a list of all tickles for this pnn
965 static int control_get_tickles(struct ctdb_context *ctdb, int argc, const char **argv)
967 struct ctdb_control_tcp_tickle_list *list;
975 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
976 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
980 ret = ctdb_ctrl_get_tcp_tickles(ctdb, TIMELIMIT(), options.pnn, ctdb, &addr, &list);
982 DEBUG(DEBUG_ERR, ("Unable to list tickles\n"));
986 printf("Tickles for ip:%s\n", ctdb_addr_to_str(&list->addr));
987 printf("Num tickles:%u\n", list->tickles.num);
988 for (i=0;i<list->tickles.num;i++) {
989 printf("SRC: %s:%u ", ctdb_addr_to_str(&list->tickles.connections[i].src_addr), ntohs(list->tickles.connections[i].src_addr.ip.sin_port));
990 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));
1000 static int move_ip(struct ctdb_context *ctdb, ctdb_sock_addr *addr, uint32_t pnn)
1002 struct ctdb_all_public_ips *ips;
1003 struct ctdb_public_ip ip;
1006 uint32_t disable_time;
1008 struct ctdb_node_map *nodemap=NULL;
1009 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1012 data.dptr = (uint8_t*)&disable_time;
1013 data.dsize = sizeof(disable_time);
1014 ret = ctdb_send_message(ctdb, CTDB_BROADCAST_CONNECTED, CTDB_SRVID_DISABLE_IP_CHECK, data);
1016 DEBUG(DEBUG_ERR,("Failed to send message to disable ipcheck\n"));
1022 /* read the public ip list from the node */
1023 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), pnn, ctdb, &ips);
1025 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", pnn));
1026 talloc_free(tmp_ctx);
1030 for (i=0;i<ips->num;i++) {
1031 if (ctdb_same_ip(addr, &ips->ips[i].addr)) {
1036 DEBUG(DEBUG_ERR, ("Node %u can not host ip address '%s'\n",
1037 pnn, ctdb_addr_to_str(addr)));
1038 talloc_free(tmp_ctx);
1045 data.dptr = (uint8_t *)&ip;
1046 data.dsize = sizeof(ip);
1048 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &nodemap);
1050 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1051 talloc_free(tmp_ctx);
1055 nodes = list_of_active_nodes_except_pnn(ctdb, nodemap, tmp_ctx, pnn);
1056 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_RELEASE_IP,
1063 DEBUG(DEBUG_ERR,("Failed to release IP on nodes\n"));
1064 talloc_free(tmp_ctx);
1068 ret = ctdb_ctrl_takeover_ip(ctdb, TIMELIMIT(), pnn, &ip);
1070 DEBUG(DEBUG_ERR,("Failed to take over IP on node %d\n", pnn));
1071 talloc_free(tmp_ctx);
1075 talloc_free(tmp_ctx);
1080 move/failover an ip address to a specific node
1082 static int control_moveip(struct ctdb_context *ctdb, int argc, const char **argv)
1085 ctdb_sock_addr addr;
1092 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1093 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1098 if (sscanf(argv[1], "%u", &pnn) != 1) {
1099 DEBUG(DEBUG_ERR, ("Badly formed pnn\n"));
1103 if (move_ip(ctdb, &addr, pnn) != 0) {
1104 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", pnn));
1111 void getips_store_callback(void *param, void *data)
1113 struct ctdb_public_ip *node_ip = (struct ctdb_public_ip *)data;
1114 struct ctdb_all_public_ips *ips = param;
1118 ips->ips[i].pnn = node_ip->pnn;
1119 ips->ips[i].addr = node_ip->addr;
1122 void getips_count_callback(void *param, void *data)
1124 uint32_t *count = param;
1130 static uint32_t *ip_key(ctdb_sock_addr *ip)
1132 static uint32_t key[IP_KEYLEN];
1134 bzero(key, sizeof(key));
1136 switch (ip->sa.sa_family) {
1138 key[0] = ip->ip.sin_addr.s_addr;
1141 key[0] = ip->ip6.sin6_addr.s6_addr32[3];
1142 key[1] = ip->ip6.sin6_addr.s6_addr32[2];
1143 key[2] = ip->ip6.sin6_addr.s6_addr32[1];
1144 key[3] = ip->ip6.sin6_addr.s6_addr32[0];
1147 DEBUG(DEBUG_ERR, (__location__ " ERROR, unknown family passed :%u\n", ip->sa.sa_family));
1154 static void *add_ip_callback(void *parm, void *data)
1160 control_get_all_public_ips(struct ctdb_context *ctdb, TALLOC_CTX *tmp_ctx, struct ctdb_all_public_ips **ips)
1162 struct ctdb_all_public_ips *tmp_ips;
1163 struct ctdb_node_map *nodemap=NULL;
1164 trbt_tree_t *ip_tree;
1168 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1170 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1174 ip_tree = trbt_create(tmp_ctx, 0);
1176 for(i=0;i<nodemap->num;i++){
1177 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
1180 if (nodemap->nodes[i].flags & NODE_FLAGS_DISCONNECTED) {
1184 /* read the public ip list from this node */
1185 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &tmp_ips);
1187 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", nodemap->nodes[i].pnn));
1191 for (j=0; j<tmp_ips->num;j++) {
1192 struct ctdb_public_ip *node_ip;
1194 node_ip = talloc(tmp_ctx, struct ctdb_public_ip);
1195 node_ip->pnn = tmp_ips->ips[j].pnn;
1196 node_ip->addr = tmp_ips->ips[j].addr;
1198 trbt_insertarray32_callback(ip_tree,
1199 IP_KEYLEN, ip_key(&tmp_ips->ips[j].addr),
1203 talloc_free(tmp_ips);
1208 trbt_traversearray32(ip_tree, IP_KEYLEN, getips_count_callback, &count);
1210 len = offsetof(struct ctdb_all_public_ips, ips) +
1211 count*sizeof(struct ctdb_public_ip);
1212 tmp_ips = talloc_zero_size(tmp_ctx, len);
1213 trbt_traversearray32(ip_tree, IP_KEYLEN, getips_store_callback, tmp_ips);
1222 * scans all other nodes and returns a pnn for another node that can host this
1226 find_other_host_for_public_ip(struct ctdb_context *ctdb, ctdb_sock_addr *addr)
1228 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1229 struct ctdb_all_public_ips *ips;
1230 struct ctdb_node_map *nodemap=NULL;
1233 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1235 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1236 talloc_free(tmp_ctx);
1240 for(i=0;i<nodemap->num;i++){
1241 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1244 if (nodemap->nodes[i].pnn == options.pnn) {
1248 /* read the public ip list from this node */
1249 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips);
1251 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", nodemap->nodes[i].pnn));
1255 for (j=0;j<ips->num;j++) {
1256 if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1257 talloc_free(tmp_ctx);
1258 return nodemap->nodes[i].pnn;
1264 talloc_free(tmp_ctx);
1269 add a public ip address to a node
1271 static int control_addip(struct ctdb_context *ctdb, int argc, const char **argv)
1277 ctdb_sock_addr addr;
1278 struct ctdb_control_ip_iface *pub;
1279 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1280 struct ctdb_all_public_ips *ips;
1284 talloc_free(tmp_ctx);
1288 if (!parse_ip_mask(argv[0], argv[1], &addr, &mask)) {
1289 DEBUG(DEBUG_ERR, ("Badly formed ip/mask : %s\n", argv[0]));
1290 talloc_free(tmp_ctx);
1294 ret = control_get_all_public_ips(ctdb, tmp_ctx, &ips);
1296 DEBUG(DEBUG_ERR, ("Unable to get public ip list from cluster\n"));
1297 talloc_free(tmp_ctx);
1302 /* check if some other node is already serving this ip, if not,
1305 for (i=0;i<ips->num;i++) {
1306 if (ctdb_same_ip(&addr, &ips->ips[i].addr)) {
1311 len = offsetof(struct ctdb_control_ip_iface, iface) + strlen(argv[1]) + 1;
1312 pub = talloc_size(tmp_ctx, len);
1313 CTDB_NO_MEMORY(ctdb, pub);
1317 pub->len = strlen(argv[1])+1;
1318 memcpy(&pub->iface[0], argv[1], strlen(argv[1])+1);
1320 ret = ctdb_ctrl_add_public_ip(ctdb, TIMELIMIT(), options.pnn, pub);
1322 DEBUG(DEBUG_ERR, ("Unable to add public ip to node %u\n", options.pnn));
1323 talloc_free(tmp_ctx);
1327 if (i == ips->num) {
1328 /* no one has this ip so we claim it */
1331 pnn = ips->ips[i].pnn;
1334 if (move_ip(ctdb, &addr, pnn) != 0) {
1335 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", pnn));
1339 talloc_free(tmp_ctx);
1343 static int control_delip(struct ctdb_context *ctdb, int argc, const char **argv);
1345 static int control_delip_all(struct ctdb_context *ctdb, int argc, const char **argv, ctdb_sock_addr *addr)
1347 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1348 struct ctdb_node_map *nodemap=NULL;
1349 struct ctdb_all_public_ips *ips;
1352 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1354 DEBUG(DEBUG_ERR, ("Unable to get nodemap from current node\n"));
1358 /* remove it from the nodes that are not hosting the ip currently */
1359 for(i=0;i<nodemap->num;i++){
1360 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1363 if (ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips) != 0) {
1364 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %d\n", nodemap->nodes[i].pnn));
1368 for (j=0;j<ips->num;j++) {
1369 if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1377 if (ips->ips[j].pnn == nodemap->nodes[i].pnn) {
1381 options.pnn = nodemap->nodes[i].pnn;
1382 control_delip(ctdb, argc, argv);
1386 /* remove it from every node (also the one hosting it) */
1387 for(i=0;i<nodemap->num;i++){
1388 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1391 if (ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips) != 0) {
1392 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %d\n", nodemap->nodes[i].pnn));
1396 for (j=0;j<ips->num;j++) {
1397 if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1405 options.pnn = nodemap->nodes[i].pnn;
1406 control_delip(ctdb, argc, argv);
1409 talloc_free(tmp_ctx);
1414 delete a public ip address from a node
1416 static int control_delip(struct ctdb_context *ctdb, int argc, const char **argv)
1419 ctdb_sock_addr addr;
1420 struct ctdb_control_ip_iface pub;
1421 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1422 struct ctdb_all_public_ips *ips;
1425 talloc_free(tmp_ctx);
1429 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1430 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1434 if (options.pnn == CTDB_BROADCAST_ALL) {
1435 return control_delip_all(ctdb, argc, argv, &addr);
1442 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &ips);
1444 DEBUG(DEBUG_ERR, ("Unable to get public ip list from cluster\n"));
1445 talloc_free(tmp_ctx);
1449 for (i=0;i<ips->num;i++) {
1450 if (ctdb_same_ip(&addr, &ips->ips[i].addr)) {
1456 DEBUG(DEBUG_ERR, ("This node does not support this public address '%s'\n",
1457 ctdb_addr_to_str(&addr)));
1458 talloc_free(tmp_ctx);
1462 if (ips->ips[i].pnn == options.pnn) {
1463 ret = find_other_host_for_public_ip(ctdb, &addr);
1465 if (move_ip(ctdb, &addr, ret) != 0) {
1466 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", ret));
1472 ret = ctdb_ctrl_del_public_ip(ctdb, TIMELIMIT(), options.pnn, &pub);
1474 DEBUG(DEBUG_ERR, ("Unable to del public ip from node %u\n", options.pnn));
1475 talloc_free(tmp_ctx);
1479 talloc_free(tmp_ctx);
1484 kill a tcp connection
1486 static int kill_tcp(struct ctdb_context *ctdb, int argc, const char **argv)
1489 struct ctdb_control_killtcp killtcp;
1495 if (!parse_ip_port(argv[0], &killtcp.src_addr)) {
1496 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[0]));
1500 if (!parse_ip_port(argv[1], &killtcp.dst_addr)) {
1501 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[1]));
1505 ret = ctdb_ctrl_killtcp(ctdb, TIMELIMIT(), options.pnn, &killtcp);
1507 DEBUG(DEBUG_ERR, ("Unable to killtcp from node %u\n", options.pnn));
1518 static int control_gratious_arp(struct ctdb_context *ctdb, int argc, const char **argv)
1521 ctdb_sock_addr addr;
1527 if (!parse_ip(argv[0], NULL, 0, &addr)) {
1528 DEBUG(DEBUG_ERR, ("Bad IP '%s'\n", argv[0]));
1532 ret = ctdb_ctrl_gratious_arp(ctdb, TIMELIMIT(), options.pnn, &addr, argv[1]);
1534 DEBUG(DEBUG_ERR, ("Unable to send gratious_arp from node %u\n", options.pnn));
1542 register a server id
1544 static int regsrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1547 struct ctdb_server_id server_id;
1553 server_id.pnn = strtoul(argv[0], NULL, 0);
1554 server_id.type = strtoul(argv[1], NULL, 0);
1555 server_id.server_id = strtoul(argv[2], NULL, 0);
1557 ret = ctdb_ctrl_register_server_id(ctdb, TIMELIMIT(), &server_id);
1559 DEBUG(DEBUG_ERR, ("Unable to register server_id from node %u\n", options.pnn));
1566 unregister a server id
1568 static int unregsrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1571 struct ctdb_server_id server_id;
1577 server_id.pnn = strtoul(argv[0], NULL, 0);
1578 server_id.type = strtoul(argv[1], NULL, 0);
1579 server_id.server_id = strtoul(argv[2], NULL, 0);
1581 ret = ctdb_ctrl_unregister_server_id(ctdb, TIMELIMIT(), &server_id);
1583 DEBUG(DEBUG_ERR, ("Unable to unregister server_id from node %u\n", options.pnn));
1590 check if a server id exists
1592 static int chksrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1596 struct ctdb_server_id server_id;
1602 server_id.pnn = strtoul(argv[0], NULL, 0);
1603 server_id.type = strtoul(argv[1], NULL, 0);
1604 server_id.server_id = strtoul(argv[2], NULL, 0);
1606 ret = ctdb_ctrl_check_server_id(ctdb, TIMELIMIT(), options.pnn, &server_id, &status);
1608 DEBUG(DEBUG_ERR, ("Unable to check server_id from node %u\n", options.pnn));
1613 printf("Server id %d:%d:%d EXISTS\n", server_id.pnn, server_id.type, server_id.server_id);
1615 printf("Server id %d:%d:%d does NOT exist\n", server_id.pnn, server_id.type, server_id.server_id);
1621 get a list of all server ids that are registered on a node
1623 static int getsrvids(struct ctdb_context *ctdb, int argc, const char **argv)
1626 struct ctdb_server_id_list *server_ids;
1628 ret = ctdb_ctrl_get_server_id_list(ctdb, ctdb, TIMELIMIT(), options.pnn, &server_ids);
1630 DEBUG(DEBUG_ERR, ("Unable to get server_id list from node %u\n", options.pnn));
1634 for (i=0; i<server_ids->num; i++) {
1635 printf("Server id %d:%d:%d\n",
1636 server_ids->server_ids[i].pnn,
1637 server_ids->server_ids[i].type,
1638 server_ids->server_ids[i].server_id);
1645 send a tcp tickle ack
1647 static int tickle_tcp(struct ctdb_context *ctdb, int argc, const char **argv)
1650 ctdb_sock_addr src, dst;
1656 if (!parse_ip_port(argv[0], &src)) {
1657 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[0]));
1661 if (!parse_ip_port(argv[1], &dst)) {
1662 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[1]));
1666 ret = ctdb_sys_send_tcp(&src, &dst, 0, 0, 0);
1670 DEBUG(DEBUG_ERR, ("Error while sending tickle ack\n"));
1677 display public ip status
1679 static int control_ip(struct ctdb_context *ctdb, int argc, const char **argv)
1682 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1683 struct ctdb_all_public_ips *ips;
1685 if (options.pnn == CTDB_BROADCAST_ALL) {
1686 /* read the list of public ips from all nodes */
1687 ret = control_get_all_public_ips(ctdb, tmp_ctx, &ips);
1689 /* read the public ip list from this node */
1690 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &ips);
1693 DEBUG(DEBUG_ERR, ("Unable to get public ips from node %u\n", options.pnn));
1694 talloc_free(tmp_ctx);
1698 if (options.machinereadable){
1699 printf(":Public IP:Node:ActiveInterface:AvailableInterfaces:ConfiguredInterfaces:\n");
1701 if (options.pnn == CTDB_BROADCAST_ALL) {
1702 printf("Public IPs on ALL nodes\n");
1704 printf("Public IPs on node %u\n", options.pnn);
1708 for (i=1;i<=ips->num;i++) {
1709 struct ctdb_control_public_ip_info *info = NULL;
1711 char *aciface = NULL;
1712 char *avifaces = NULL;
1713 char *cifaces = NULL;
1715 if (options.pnn == CTDB_BROADCAST_ALL) {
1716 pnn = ips->ips[ips->num-i].pnn;
1722 ret = ctdb_ctrl_get_public_ip_info(ctdb, TIMELIMIT(), pnn, ctdb,
1723 &ips->ips[ips->num-i].addr, &info);
1730 for (j=0; j < info->num; j++) {
1731 if (cifaces == NULL) {
1732 cifaces = talloc_strdup(info,
1733 info->ifaces[j].name);
1735 cifaces = talloc_asprintf_append(cifaces,
1737 info->ifaces[j].name);
1740 if (info->active_idx == j) {
1741 aciface = info->ifaces[j].name;
1744 if (info->ifaces[j].link_state == 0) {
1748 if (avifaces == NULL) {
1749 avifaces = talloc_strdup(info, info->ifaces[j].name);
1751 avifaces = talloc_asprintf_append(avifaces,
1753 info->ifaces[j].name);
1758 if (options.machinereadable){
1759 printf(":%s:%d:%s:%s:%s:\n",
1760 ctdb_addr_to_str(&ips->ips[ips->num-i].addr),
1761 ips->ips[ips->num-i].pnn,
1763 avifaces?avifaces:"",
1764 cifaces?cifaces:"");
1766 printf("%s node[%d] active[%s] available[%s] configured[%s]\n",
1767 ctdb_addr_to_str(&ips->ips[ips->num-i].addr),
1768 ips->ips[ips->num-i].pnn,
1770 avifaces?avifaces:"",
1771 cifaces?cifaces:"");
1776 talloc_free(tmp_ctx);
1783 static int control_ipinfo(struct ctdb_context *ctdb, int argc, const char **argv)
1786 ctdb_sock_addr addr;
1787 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1788 struct ctdb_control_public_ip_info *info;
1791 talloc_free(tmp_ctx);
1795 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1796 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1800 /* read the public ip info from this node */
1801 ret = ctdb_ctrl_get_public_ip_info(ctdb, TIMELIMIT(), options.pnn,
1802 tmp_ctx, &addr, &info);
1804 DEBUG(DEBUG_ERR, ("Unable to get public ip[%s]info from node %u\n",
1805 argv[0], options.pnn));
1806 talloc_free(tmp_ctx);
1810 printf("Public IP[%s] info on node %u\n",
1811 ctdb_addr_to_str(&info->ip.addr),
1814 printf("IP:%s\nCurrentNode:%d\nNumInterfaces:%u\n",
1815 ctdb_addr_to_str(&info->ip.addr),
1816 info->ip.pnn, info->num);
1818 for (i=0; i<info->num; i++) {
1819 info->ifaces[i].name[CTDB_IFACE_SIZE] = '\0';
1821 printf("Interface[%u]: Name:%s Link:%s References:%u%s\n",
1822 i+1, info->ifaces[i].name,
1823 info->ifaces[i].link_state?"up":"down",
1824 (unsigned int)info->ifaces[i].references,
1825 (i==info->active_idx)?" (active)":"");
1828 talloc_free(tmp_ctx);
1833 display interfaces status
1835 static int control_ifaces(struct ctdb_context *ctdb, int argc, const char **argv)
1838 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1839 struct ctdb_control_get_ifaces *ifaces;
1841 /* read the public ip list from this node */
1842 ret = ctdb_ctrl_get_ifaces(ctdb, TIMELIMIT(), options.pnn,
1845 DEBUG(DEBUG_ERR, ("Unable to get interfaces from node %u\n",
1847 talloc_free(tmp_ctx);
1851 if (options.machinereadable){
1852 printf(":Name:LinkStatus:References:\n");
1854 printf("Interfaces on node %u\n", options.pnn);
1857 for (i=0; i<ifaces->num; i++) {
1858 if (options.machinereadable){
1859 printf(":%s:%s:%u\n",
1860 ifaces->ifaces[i].name,
1861 ifaces->ifaces[i].link_state?"1":"0",
1862 (unsigned int)ifaces->ifaces[i].references);
1864 printf("name:%s link:%s references:%u\n",
1865 ifaces->ifaces[i].name,
1866 ifaces->ifaces[i].link_state?"up":"down",
1867 (unsigned int)ifaces->ifaces[i].references);
1871 talloc_free(tmp_ctx);
1877 set link status of an interface
1879 static int control_setifacelink(struct ctdb_context *ctdb, int argc, const char **argv)
1882 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1883 struct ctdb_control_iface_info info;
1891 if (strlen(argv[0]) > CTDB_IFACE_SIZE) {
1892 DEBUG(DEBUG_ERR, ("interfaces name '%s' too long\n",
1894 talloc_free(tmp_ctx);
1897 strcpy(info.name, argv[0]);
1899 if (strcmp(argv[1], "up") == 0) {
1900 info.link_state = 1;
1901 } else if (strcmp(argv[1], "down") == 0) {
1902 info.link_state = 0;
1904 DEBUG(DEBUG_ERR, ("link state invalid '%s' should be 'up' or 'down'\n",
1906 talloc_free(tmp_ctx);
1910 /* read the public ip list from this node */
1911 ret = ctdb_ctrl_set_iface_link(ctdb, TIMELIMIT(), options.pnn,
1914 DEBUG(DEBUG_ERR, ("Unable to set link state for interfaces %s node %u\n",
1915 argv[0], options.pnn));
1916 talloc_free(tmp_ctx);
1920 talloc_free(tmp_ctx);
1925 display pid of a ctdb daemon
1927 static int control_getpid(struct ctdb_context *ctdb, int argc, const char **argv)
1932 ret = ctdb_ctrl_getpid(ctdb, TIMELIMIT(), options.pnn, &pid);
1934 DEBUG(DEBUG_ERR, ("Unable to get daemon pid from node %u\n", options.pnn));
1937 printf("Pid:%d\n", pid);
1943 handler for receiving the response to ipreallocate
1945 static void ip_reallocate_handler(struct ctdb_context *ctdb, uint64_t srvid,
1946 TDB_DATA data, void *private_data)
1951 static void ctdb_every_second(struct event_context *ev, struct timed_event *te, struct timeval t, void *p)
1953 struct ctdb_context *ctdb = talloc_get_type(p, struct ctdb_context);
1955 event_add_timed(ctdb->ev, ctdb,
1956 timeval_current_ofs(1, 0),
1957 ctdb_every_second, ctdb);
1961 ask the recovery daemon on the recovery master to perform a ip reallocation
1963 static int control_ipreallocate(struct ctdb_context *ctdb, int argc, const char **argv)
1967 struct takeover_run_reply rd;
1969 struct ctdb_node_map *nodemap=NULL;
1971 struct timeval tv = timeval_current();
1973 /* we need some events to trigger so we can timeout and restart
1976 event_add_timed(ctdb->ev, ctdb,
1977 timeval_current_ofs(1, 0),
1978 ctdb_every_second, ctdb);
1980 rd.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
1982 DEBUG(DEBUG_ERR, ("Failed to get pnn of local node\n"));
1985 rd.srvid = getpid();
1987 /* register a message port for receiveing the reply so that we
1988 can receive the reply
1990 ctdb_set_message_handler(ctdb, rd.srvid, ip_reallocate_handler, NULL);
1992 data.dptr = (uint8_t *)&rd;
1993 data.dsize = sizeof(rd);
1997 DEBUG(DEBUG_ERR,("Failed waiting for cluster convergense\n"));
2001 /* check that there are valid nodes available */
2002 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap) != 0) {
2003 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2006 for (i=0; i<nodemap->num;i++) {
2007 if ((nodemap->nodes[i].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) == 0) {
2011 if (i==nodemap->num) {
2012 DEBUG(DEBUG_ERR,("No recmaster available, no need to wait for cluster convergence\n"));
2017 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
2019 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
2023 /* verify the node exists */
2024 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), recmaster, ctdb, &nodemap) != 0) {
2025 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2030 /* check tha there are nodes available that can act as a recmaster */
2031 for (i=0; i<nodemap->num; i++) {
2032 if (nodemap->nodes[i].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
2037 if (i == nodemap->num) {
2038 DEBUG(DEBUG_ERR,("No possible nodes to host addresses.\n"));
2042 /* verify the recovery master is not STOPPED, nor BANNED */
2043 if (nodemap->nodes[recmaster].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
2044 DEBUG(DEBUG_ERR,("No suitable recmaster found. Try again\n"));
2051 /* verify the recovery master is not STOPPED, nor BANNED */
2052 if (nodemap->nodes[recmaster].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
2053 DEBUG(DEBUG_ERR,("No suitable recmaster found. Try again\n"));
2059 ret = ctdb_send_message(ctdb, recmaster, CTDB_SRVID_TAKEOVER_RUN, data);
2061 DEBUG(DEBUG_ERR,("Failed to send ip takeover run request message to %u\n", options.pnn));
2065 tv = timeval_current();
2066 /* this loop will terminate when we have received the reply */
2067 while (timeval_elapsed(&tv) < 3.0) {
2068 event_loop_once(ctdb->ev);
2071 DEBUG(DEBUG_INFO,("Timed out waiting for recmaster ipreallocate. Trying again\n"));
2081 disable a remote node
2083 static int control_disable(struct ctdb_context *ctdb, int argc, const char **argv)
2086 struct ctdb_node_map *nodemap=NULL;
2089 ret = ctdb_ctrl_modflags(ctdb, TIMELIMIT(), options.pnn, NODE_FLAGS_PERMANENTLY_DISABLED, 0);
2091 DEBUG(DEBUG_ERR, ("Unable to disable node %u\n", options.pnn));
2097 /* read the nodemap and verify the change took effect */
2098 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2099 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2103 } while (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED));
2104 ret = control_ipreallocate(ctdb, argc, argv);
2106 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2114 enable a disabled remote node
2116 static int control_enable(struct ctdb_context *ctdb, int argc, const char **argv)
2120 struct ctdb_node_map *nodemap=NULL;
2123 ret = ctdb_ctrl_modflags(ctdb, TIMELIMIT(), options.pnn, 0, NODE_FLAGS_PERMANENTLY_DISABLED);
2125 DEBUG(DEBUG_ERR, ("Unable to enable node %u\n", options.pnn));
2131 /* read the nodemap and verify the change took effect */
2132 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2133 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2137 } while (nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED);
2138 ret = control_ipreallocate(ctdb, argc, argv);
2140 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2150 static int control_stop(struct ctdb_context *ctdb, int argc, const char **argv)
2153 struct ctdb_node_map *nodemap=NULL;
2156 ret = ctdb_ctrl_stop_node(ctdb, TIMELIMIT(), options.pnn);
2158 DEBUG(DEBUG_ERR, ("Unable to stop node %u try again\n", options.pnn));
2163 /* read the nodemap and verify the change took effect */
2164 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2165 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2169 } while (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_STOPPED));
2170 ret = control_ipreallocate(ctdb, argc, argv);
2172 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2180 restart a stopped remote node
2182 static int control_continue(struct ctdb_context *ctdb, int argc, const char **argv)
2186 struct ctdb_node_map *nodemap=NULL;
2189 ret = ctdb_ctrl_continue_node(ctdb, TIMELIMIT(), options.pnn);
2191 DEBUG(DEBUG_ERR, ("Unable to continue node %u\n", options.pnn));
2197 /* read the nodemap and verify the change took effect */
2198 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2199 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2203 } while (nodemap->nodes[options.pnn].flags & NODE_FLAGS_STOPPED);
2204 ret = control_ipreallocate(ctdb, argc, argv);
2206 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2213 static uint32_t get_generation(struct ctdb_context *ctdb)
2215 struct ctdb_vnn_map *vnnmap=NULL;
2218 /* wait until the recmaster is not in recovery mode */
2220 uint32_t recmode, recmaster;
2222 if (vnnmap != NULL) {
2223 talloc_free(vnnmap);
2227 /* get the recmaster */
2228 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, &recmaster);
2230 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
2234 /* get recovery mode */
2235 ret = ctdb_ctrl_getrecmode(ctdb, ctdb, TIMELIMIT(), recmaster, &recmode);
2237 DEBUG(DEBUG_ERR, ("Unable to get recmode from node %u\n", options.pnn));
2241 /* get the current generation number */
2242 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), recmaster, ctdb, &vnnmap);
2244 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from recmaster (%u)\n", recmaster));
2248 if ((recmode == CTDB_RECOVERY_NORMAL)
2249 && (vnnmap->generation != 1)){
2250 return vnnmap->generation;
2257 ban a node from the cluster
2259 static int control_ban(struct ctdb_context *ctdb, int argc, const char **argv)
2262 struct ctdb_node_map *nodemap=NULL;
2263 struct ctdb_ban_time bantime;
2269 /* verify the node exists */
2270 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
2272 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2276 if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_BANNED) {
2277 DEBUG(DEBUG_ERR,("Node %u is already banned.\n", options.pnn));
2281 bantime.pnn = options.pnn;
2282 bantime.time = strtoul(argv[0], NULL, 0);
2284 ret = ctdb_ctrl_set_ban(ctdb, TIMELIMIT(), options.pnn, &bantime);
2286 DEBUG(DEBUG_ERR,("Banning node %d for %d seconds failed.\n", bantime.pnn, bantime.time));
2290 ret = control_ipreallocate(ctdb, argc, argv);
2292 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2301 unban a node from the cluster
2303 static int control_unban(struct ctdb_context *ctdb, int argc, const char **argv)
2306 struct ctdb_node_map *nodemap=NULL;
2307 struct ctdb_ban_time bantime;
2309 /* verify the node exists */
2310 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
2312 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2316 if (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_BANNED)) {
2317 DEBUG(DEBUG_ERR,("Node %u is not banned.\n", options.pnn));
2321 bantime.pnn = options.pnn;
2324 ret = ctdb_ctrl_set_ban(ctdb, TIMELIMIT(), options.pnn, &bantime);
2326 DEBUG(DEBUG_ERR,("Unbanning node %d failed.\n", bantime.pnn));
2330 ret = control_ipreallocate(ctdb, argc, argv);
2332 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2341 show ban information for a node
2343 static int control_showban(struct ctdb_context *ctdb, int argc, const char **argv)
2346 struct ctdb_node_map *nodemap=NULL;
2347 struct ctdb_ban_time *bantime;
2349 /* verify the node exists */
2350 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
2352 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2356 ret = ctdb_ctrl_get_ban(ctdb, TIMELIMIT(), options.pnn, ctdb, &bantime);
2358 DEBUG(DEBUG_ERR,("Showing ban info for node %d failed.\n", options.pnn));
2362 if (bantime->time == 0) {
2363 printf("Node %u is not banned\n", bantime->pnn);
2365 printf("Node %u is banned banned for %d seconds\n", bantime->pnn, bantime->time);
2374 static int control_shutdown(struct ctdb_context *ctdb, int argc, const char **argv)
2378 ret = ctdb_ctrl_shutdown(ctdb, TIMELIMIT(), options.pnn);
2380 DEBUG(DEBUG_ERR, ("Unable to shutdown node %u\n", options.pnn));
2390 static int control_recover(struct ctdb_context *ctdb, int argc, const char **argv)
2393 uint32_t generation, next_generation;
2395 /* record the current generation number */
2396 generation = get_generation(ctdb);
2398 ret = ctdb_ctrl_freeze_priority(ctdb, TIMELIMIT(), options.pnn, 1);
2400 DEBUG(DEBUG_ERR, ("Unable to freeze node\n"));
2404 ret = ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
2406 DEBUG(DEBUG_ERR, ("Unable to set recovery mode\n"));
2410 /* wait until we are in a new generation */
2412 next_generation = get_generation(ctdb);
2413 if (next_generation != generation) {
2424 display monitoring mode of a remote node
2426 static int control_getmonmode(struct ctdb_context *ctdb, int argc, const char **argv)
2431 ret = ctdb_ctrl_getmonmode(ctdb, TIMELIMIT(), options.pnn, &monmode);
2433 DEBUG(DEBUG_ERR, ("Unable to get monmode from node %u\n", options.pnn));
2436 if (!options.machinereadable){
2437 printf("Monitoring mode:%s (%d)\n",monmode==CTDB_MONITORING_ACTIVE?"ACTIVE":"DISABLED",monmode);
2440 printf(":%d:\n",monmode);
2447 display capabilities of a remote node
2449 static int control_getcapabilities(struct ctdb_context *ctdb, int argc, const char **argv)
2451 uint32_t capabilities;
2454 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), options.pnn, &capabilities);
2456 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", options.pnn));
2460 if (!options.machinereadable){
2461 printf("RECMASTER: %s\n", (capabilities&CTDB_CAP_RECMASTER)?"YES":"NO");
2462 printf("LMASTER: %s\n", (capabilities&CTDB_CAP_LMASTER)?"YES":"NO");
2463 printf("LVS: %s\n", (capabilities&CTDB_CAP_LVS)?"YES":"NO");
2464 printf("NATGW: %s\n", (capabilities&CTDB_CAP_NATGW)?"YES":"NO");
2466 printf(":RECMASTER:LMASTER:LVS:NATGW:\n");
2467 printf(":%d:%d:%d:%d:\n",
2468 !!(capabilities&CTDB_CAP_RECMASTER),
2469 !!(capabilities&CTDB_CAP_LMASTER),
2470 !!(capabilities&CTDB_CAP_LVS),
2471 !!(capabilities&CTDB_CAP_NATGW));
2477 display lvs configuration
2479 static int control_lvs(struct ctdb_context *ctdb, int argc, const char **argv)
2481 uint32_t *capabilities;
2482 struct ctdb_node_map *nodemap=NULL;
2484 int healthy_count = 0;
2486 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
2488 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
2492 capabilities = talloc_array(ctdb, uint32_t, nodemap->num);
2493 CTDB_NO_MEMORY(ctdb, capabilities);
2495 /* collect capabilities for all connected nodes */
2496 for (i=0; i<nodemap->num; i++) {
2497 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2500 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2504 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), i, &capabilities[i]);
2506 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", i));
2510 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2514 if (!(nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY)) {
2519 /* Print all LVS nodes */
2520 for (i=0; i<nodemap->num; i++) {
2521 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2524 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2527 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2531 if (healthy_count != 0) {
2532 if (nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY) {
2537 printf("%d:%s\n", i,
2538 ctdb_addr_to_str(&nodemap->nodes[i].addr));
2545 display who is the lvs master
2547 static int control_lvsmaster(struct ctdb_context *ctdb, int argc, const char **argv)
2549 uint32_t *capabilities;
2550 struct ctdb_node_map *nodemap=NULL;
2552 int healthy_count = 0;
2554 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
2556 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
2560 capabilities = talloc_array(ctdb, uint32_t, nodemap->num);
2561 CTDB_NO_MEMORY(ctdb, capabilities);
2563 /* collect capabilities for all connected nodes */
2564 for (i=0; i<nodemap->num; i++) {
2565 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2568 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2572 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), i, &capabilities[i]);
2574 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", i));
2578 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2582 if (!(nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY)) {
2587 /* find and show the lvsmaster */
2588 for (i=0; i<nodemap->num; i++) {
2589 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2592 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2595 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2599 if (healthy_count != 0) {
2600 if (nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY) {
2605 if (options.machinereadable){
2608 printf("Node %d is LVS master\n", i);
2613 printf("There is no LVS master\n");
2618 disable monitoring on a node
2620 static int control_disable_monmode(struct ctdb_context *ctdb, int argc, const char **argv)
2625 ret = ctdb_ctrl_disable_monmode(ctdb, TIMELIMIT(), options.pnn);
2627 DEBUG(DEBUG_ERR, ("Unable to disable monmode on node %u\n", options.pnn));
2630 printf("Monitoring mode:%s\n","DISABLED");
2636 enable monitoring on a node
2638 static int control_enable_monmode(struct ctdb_context *ctdb, int argc, const char **argv)
2643 ret = ctdb_ctrl_enable_monmode(ctdb, TIMELIMIT(), options.pnn);
2645 DEBUG(DEBUG_ERR, ("Unable to enable monmode on node %u\n", options.pnn));
2648 printf("Monitoring mode:%s\n","ACTIVE");
2654 display remote list of keys/data for a db
2656 static int control_catdb(struct ctdb_context *ctdb, int argc, const char **argv)
2658 const char *db_name;
2659 struct ctdb_db_context *ctdb_db;
2669 if (db_exists(ctdb, db_name)) {
2670 DEBUG(DEBUG_ERR,("Database '%s' does not exist\n", db_name));
2674 ctdb_db = ctdb_attach(ctdb, db_name, false, 0);
2676 if (ctdb_db == NULL) {
2677 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
2681 /* traverse and dump the cluster tdb */
2682 ret = ctdb_dump_db(ctdb_db, stdout);
2684 DEBUG(DEBUG_ERR, ("Unable to dump database\n"));
2685 DEBUG(DEBUG_ERR, ("Maybe try 'ctdb getdbstatus %s'"
2686 " and 'ctdb getvar AllowUnhealthyDBRead'\n",
2690 talloc_free(ctdb_db);
2692 printf("Dumped %d records\n", ret);
2697 static void log_handler(struct ctdb_context *ctdb, uint64_t srvid,
2698 TDB_DATA data, void *private_data)
2700 DEBUG(DEBUG_ERR,("Log data received\n"));
2701 if (data.dsize > 0) {
2702 printf("%s", data.dptr);
2709 display a list of log messages from the in memory ringbuffer
2711 static int control_getlog(struct ctdb_context *ctdb, int argc, const char **argv)
2715 struct ctdb_get_log_addr log_addr;
2717 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2722 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
2723 talloc_free(tmp_ctx);
2727 log_addr.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
2728 log_addr.srvid = getpid();
2729 if (isalpha(argv[0][0]) || argv[0][0] == '-') {
2730 log_addr.level = get_debug_by_desc(argv[0]);
2732 log_addr.level = strtol(argv[0], NULL, 0);
2736 data.dptr = (unsigned char *)&log_addr;
2737 data.dsize = sizeof(log_addr);
2739 DEBUG(DEBUG_ERR, ("Pulling logs from node %u\n", options.pnn));
2741 ctdb_set_message_handler(ctdb, log_addr.srvid, log_handler, NULL);
2744 DEBUG(DEBUG_ERR,("Listen for response on %d\n", (int)log_addr.srvid));
2746 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_GET_LOG,
2747 0, data, tmp_ctx, NULL, &res, NULL, &errmsg);
2748 if (ret != 0 || res != 0) {
2749 DEBUG(DEBUG_ERR,("Failed to get logs - %s\n", errmsg));
2750 talloc_free(tmp_ctx);
2755 tv = timeval_current();
2756 /* this loop will terminate when we have received the reply */
2757 while (timeval_elapsed(&tv) < 3.0) {
2758 event_loop_once(ctdb->ev);
2761 DEBUG(DEBUG_INFO,("Timed out waiting for log data.\n"));
2763 talloc_free(tmp_ctx);
2768 clear the in memory log area
2770 static int control_clearlog(struct ctdb_context *ctdb, int argc, const char **argv)
2775 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2777 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_CLEAR_LOG,
2778 0, tdb_null, tmp_ctx, NULL, &res, NULL, &errmsg);
2779 if (ret != 0 || res != 0) {
2780 DEBUG(DEBUG_ERR,("Failed to clear logs\n"));
2781 talloc_free(tmp_ctx);
2785 talloc_free(tmp_ctx);
2792 display a list of the databases on a remote ctdb
2794 static int control_getdbmap(struct ctdb_context *ctdb, int argc, const char **argv)
2797 struct ctdb_dbid_map *dbmap=NULL;
2799 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
2801 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
2805 if(options.machinereadable){
2806 printf(":ID:Name:Path:Persistent:Unhealthy:\n");
2807 for(i=0;i<dbmap->num;i++){
2813 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn,
2814 dbmap->dbs[i].dbid, ctdb, &path);
2815 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn,
2816 dbmap->dbs[i].dbid, ctdb, &name);
2817 ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn,
2818 dbmap->dbs[i].dbid, ctdb, &health);
2819 persistent = dbmap->dbs[i].persistent;
2820 printf(":0x%08X:%s:%s:%d:%d:\n",
2821 dbmap->dbs[i].dbid, name, path,
2822 !!(persistent), !!(health));
2827 printf("Number of databases:%d\n", dbmap->num);
2828 for(i=0;i<dbmap->num;i++){
2834 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &path);
2835 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
2836 ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &health);
2837 persistent = dbmap->dbs[i].persistent;
2838 printf("dbid:0x%08x name:%s path:%s%s%s\n",
2839 dbmap->dbs[i].dbid, name, path,
2840 persistent?" PERSISTENT":"",
2841 health?" UNHEALTHY":"");
2848 display the status of a database on a remote ctdb
2850 static int control_getdbstatus(struct ctdb_context *ctdb, int argc, const char **argv)
2853 struct ctdb_dbid_map *dbmap=NULL;
2854 const char *db_name;
2862 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
2864 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
2868 for(i=0;i<dbmap->num;i++){
2874 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
2875 if (strcmp(name, db_name) != 0) {
2879 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &path);
2880 ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &health);
2881 persistent = dbmap->dbs[i].persistent;
2882 printf("dbid: 0x%08x\nname: %s\npath: %s\nPERSISTENT: %s\nHEALTH: %s\n",
2883 dbmap->dbs[i].dbid, name, path,
2884 persistent?"yes":"no",
2885 health?health:"OK");
2889 DEBUG(DEBUG_ERR, ("db %s doesn't exist on node %u\n", db_name, options.pnn));
2894 check if the local node is recmaster or not
2895 it will return 1 if this node is the recmaster and 0 if it is not
2896 or if the local ctdb daemon could not be contacted
2898 static int control_isnotrecmaster(struct ctdb_context *ctdb, int argc, const char **argv)
2900 uint32_t mypnn, recmaster;
2903 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
2905 printf("Failed to get pnn of node\n");
2909 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
2911 printf("Failed to get the recmaster\n");
2915 if (recmaster != mypnn) {
2916 printf("this node is not the recmaster\n");
2920 printf("this node is the recmaster\n");
2927 static int control_ping(struct ctdb_context *ctdb, int argc, const char **argv)
2930 struct timeval tv = timeval_current();
2931 ret = ctdb_ctrl_ping(ctdb, options.pnn);
2933 printf("Unable to get ping response from node %u\n", options.pnn);
2936 printf("response from %u time=%.6f sec (%d clients)\n",
2937 options.pnn, timeval_elapsed(&tv), ret);
2946 static int control_getvar(struct ctdb_context *ctdb, int argc, const char **argv)
2957 ret = ctdb_ctrl_get_tunable(ctdb, TIMELIMIT(), options.pnn, name, &value);
2959 DEBUG(DEBUG_ERR, ("Unable to get tunable variable '%s'\n", name));
2963 printf("%-19s = %u\n", name, value);
2970 static int control_setvar(struct ctdb_context *ctdb, int argc, const char **argv)
2981 value = strtoul(argv[1], NULL, 0);
2983 ret = ctdb_ctrl_set_tunable(ctdb, TIMELIMIT(), options.pnn, name, value);
2985 DEBUG(DEBUG_ERR, ("Unable to set tunable variable '%s'\n", name));
2994 static int control_listvars(struct ctdb_context *ctdb, int argc, const char **argv)
3000 ret = ctdb_ctrl_list_tunables(ctdb, TIMELIMIT(), options.pnn, ctdb, &list, &count);
3002 DEBUG(DEBUG_ERR, ("Unable to list tunable variables\n"));
3006 for (i=0;i<count;i++) {
3007 control_getvar(ctdb, 1, &list[i]);
3016 display debug level on a node
3018 static int control_getdebug(struct ctdb_context *ctdb, int argc, const char **argv)
3023 ret = ctdb_ctrl_get_debuglevel(ctdb, options.pnn, &level);
3025 DEBUG(DEBUG_ERR, ("Unable to get debuglevel response from node %u\n", options.pnn));
3028 if (options.machinereadable){
3029 printf(":Name:Level:\n");
3030 printf(":%s:%d:\n",get_debug_by_level(level),level);
3032 printf("Node %u is at debug level %s (%d)\n", options.pnn, get_debug_by_level(level), level);
3039 display reclock file of a node
3041 static int control_getreclock(struct ctdb_context *ctdb, int argc, const char **argv)
3044 const char *reclock;
3046 ret = ctdb_ctrl_getreclock(ctdb, TIMELIMIT(), options.pnn, ctdb, &reclock);
3048 DEBUG(DEBUG_ERR, ("Unable to get reclock file from node %u\n", options.pnn));
3051 if (options.machinereadable){
3052 if (reclock != NULL) {
3053 printf("%s", reclock);
3056 if (reclock == NULL) {
3057 printf("No reclock file used.\n");
3059 printf("Reclock file:%s\n", reclock);
3067 set the reclock file of a node
3069 static int control_setreclock(struct ctdb_context *ctdb, int argc, const char **argv)
3072 const char *reclock;
3076 } else if (argc == 1) {
3082 ret = ctdb_ctrl_setreclock(ctdb, TIMELIMIT(), options.pnn, reclock);
3084 DEBUG(DEBUG_ERR, ("Unable to get reclock file from node %u\n", options.pnn));
3091 set the natgw state on/off
3093 static int control_setnatgwstate(struct ctdb_context *ctdb, int argc, const char **argv)
3096 uint32_t natgwstate;
3102 if (!strcmp(argv[0], "on")) {
3104 } else if (!strcmp(argv[0], "off")) {
3110 ret = ctdb_ctrl_setnatgwstate(ctdb, TIMELIMIT(), options.pnn, natgwstate);
3112 DEBUG(DEBUG_ERR, ("Unable to set the natgw state for node %u\n", options.pnn));
3120 set the lmaster role on/off
3122 static int control_setlmasterrole(struct ctdb_context *ctdb, int argc, const char **argv)
3125 uint32_t lmasterrole;
3131 if (!strcmp(argv[0], "on")) {
3133 } else if (!strcmp(argv[0], "off")) {
3139 ret = ctdb_ctrl_setlmasterrole(ctdb, TIMELIMIT(), options.pnn, lmasterrole);
3141 DEBUG(DEBUG_ERR, ("Unable to set the lmaster role for node %u\n", options.pnn));
3149 set the recmaster role on/off
3151 static int control_setrecmasterrole(struct ctdb_context *ctdb, int argc, const char **argv)
3154 uint32_t recmasterrole;
3160 if (!strcmp(argv[0], "on")) {
3162 } else if (!strcmp(argv[0], "off")) {
3168 ret = ctdb_ctrl_setrecmasterrole(ctdb, TIMELIMIT(), options.pnn, recmasterrole);
3170 DEBUG(DEBUG_ERR, ("Unable to set the recmaster role for node %u\n", options.pnn));
3178 set debug level on a node or all nodes
3180 static int control_setdebug(struct ctdb_context *ctdb, int argc, const char **argv)
3186 printf("You must specify the debug level. Valid levels are:\n");
3187 for (i=0; debug_levels[i].description != NULL; i++) {
3188 printf("%s (%d)\n", debug_levels[i].description, debug_levels[i].level);
3194 if (isalpha(argv[0][0]) || argv[0][0] == '-') {
3195 level = get_debug_by_desc(argv[0]);
3197 level = strtol(argv[0], NULL, 0);
3200 for (i=0; debug_levels[i].description != NULL; i++) {
3201 if (level == debug_levels[i].level) {
3205 if (debug_levels[i].description == NULL) {
3206 printf("Invalid debug level, must be one of\n");
3207 for (i=0; debug_levels[i].description != NULL; i++) {
3208 printf("%s (%d)\n", debug_levels[i].description, debug_levels[i].level);
3213 ret = ctdb_ctrl_set_debuglevel(ctdb, options.pnn, level);
3215 DEBUG(DEBUG_ERR, ("Unable to set debug level on node %u\n", options.pnn));
3224 static int control_freeze(struct ctdb_context *ctdb, int argc, const char **argv)
3230 priority = strtol(argv[0], NULL, 0);
3234 DEBUG(DEBUG_ERR,("Freeze by priority %u\n", priority));
3236 ret = ctdb_ctrl_freeze_priority(ctdb, TIMELIMIT(), options.pnn, priority);
3238 DEBUG(DEBUG_ERR, ("Unable to freeze node %u\n", options.pnn));
3246 static int control_thaw(struct ctdb_context *ctdb, int argc, const char **argv)
3252 priority = strtol(argv[0], NULL, 0);
3256 DEBUG(DEBUG_ERR,("Thaw by priority %u\n", priority));
3258 ret = ctdb_ctrl_thaw_priority(ctdb, TIMELIMIT(), options.pnn, priority);
3260 DEBUG(DEBUG_ERR, ("Unable to thaw node %u\n", options.pnn));
3267 attach to a database
3269 static int control_attach(struct ctdb_context *ctdb, int argc, const char **argv)
3271 const char *db_name;
3272 struct ctdb_db_context *ctdb_db;
3279 ctdb_db = ctdb_attach(ctdb, db_name, false, 0);
3280 if (ctdb_db == NULL) {
3281 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
3291 static int control_setdbprio(struct ctdb_context *ctdb, int argc, const char **argv)
3293 struct ctdb_db_priority db_prio;
3300 db_prio.db_id = strtoul(argv[0], NULL, 0);
3301 db_prio.priority = strtoul(argv[1], NULL, 0);
3303 ret = ctdb_ctrl_set_db_priority(ctdb, TIMELIMIT(), options.pnn, &db_prio);
3305 DEBUG(DEBUG_ERR,("Unable to set db prio\n"));
3315 static int control_getdbprio(struct ctdb_context *ctdb, int argc, const char **argv)
3317 uint32_t db_id, priority;
3324 db_id = strtoul(argv[0], NULL, 0);
3326 ret = ctdb_ctrl_get_db_priority(ctdb, TIMELIMIT(), options.pnn, db_id, &priority);
3328 DEBUG(DEBUG_ERR,("Unable to get db prio\n"));
3332 DEBUG(DEBUG_ERR,("Priority:%u\n", priority));
3338 run an eventscript on a node
3340 static int control_eventscript(struct ctdb_context *ctdb, int argc, const char **argv)
3346 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3349 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3353 data.dptr = (unsigned char *)discard_const(argv[0]);
3354 data.dsize = strlen((char *)data.dptr) + 1;
3356 DEBUG(DEBUG_ERR, ("Running eventscripts with arguments \"%s\" on node %u\n", data.dptr, options.pnn));
3358 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_RUN_EVENTSCRIPTS,
3359 0, data, tmp_ctx, NULL, &res, NULL, &errmsg);
3360 if (ret != 0 || res != 0) {
3361 DEBUG(DEBUG_ERR,("Failed to run eventscripts - %s\n", errmsg));
3362 talloc_free(tmp_ctx);
3365 talloc_free(tmp_ctx);
3369 #define DB_VERSION 1
3370 #define MAX_DB_NAME 64
3371 struct db_file_header {
3372 unsigned long version;
3374 unsigned long persistent;
3376 const char name[MAX_DB_NAME];
3379 struct backup_data {
3380 struct ctdb_marshall_buffer *records;
3383 bool traverse_error;
3386 static int backup_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *private)
3388 struct backup_data *bd = talloc_get_type(private, struct backup_data);
3389 struct ctdb_rec_data *rec;
3391 /* add the record */
3392 rec = ctdb_marshall_record(bd->records, 0, key, NULL, data);
3394 bd->traverse_error = true;
3395 DEBUG(DEBUG_ERR,("Failed to marshall record\n"));
3398 bd->records = talloc_realloc_size(NULL, bd->records, rec->length + bd->len);
3399 if (bd->records == NULL) {
3400 DEBUG(DEBUG_ERR,("Failed to expand marshalling buffer\n"));
3401 bd->traverse_error = true;
3404 bd->records->count++;
3405 memcpy(bd->len+(uint8_t *)bd->records, rec, rec->length);
3406 bd->len += rec->length;
3414 * backup a database to a file
3416 static int control_backupdb(struct ctdb_context *ctdb, int argc, const char **argv)
3419 struct ctdb_dbid_map *dbmap=NULL;
3420 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3421 struct db_file_header dbhdr;
3422 struct ctdb_db_context *ctdb_db;
3423 struct backup_data *bd;
3426 const char *reason = NULL;
3429 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3433 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &dbmap);
3435 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
3439 for(i=0;i<dbmap->num;i++){
3442 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, tmp_ctx, &name);
3443 if(!strcmp(argv[0], name)){
3444 talloc_free(discard_const(name));
3447 talloc_free(discard_const(name));
3449 if (i == dbmap->num) {
3450 DEBUG(DEBUG_ERR,("No database with name '%s' found\n", argv[0]));
3451 talloc_free(tmp_ctx);
3455 ret = ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn,
3456 dbmap->dbs[i].dbid, tmp_ctx, &reason);
3458 DEBUG(DEBUG_ERR,("Unable to get dbhealth for database '%s'\n",
3460 talloc_free(tmp_ctx);
3464 uint32_t allow_unhealthy = 0;
3466 ctdb_ctrl_get_tunable(ctdb, TIMELIMIT(), options.pnn,
3467 "AllowUnhealthyDBRead",
3470 if (allow_unhealthy != 1) {
3471 DEBUG(DEBUG_ERR,("database '%s' is unhealthy: %s\n",
3474 DEBUG(DEBUG_ERR,("disallow backup : tunnable AllowUnhealthyDBRead = %u\n",
3476 talloc_free(tmp_ctx);
3480 DEBUG(DEBUG_WARNING,("WARNING database '%s' is unhealthy - see 'ctdb getdbstatus %s'\n",
3482 DEBUG(DEBUG_WARNING,("WARNING! allow backup of unhealthy database: "
3483 "tunnable AllowUnhealthyDBRead = %u\n",
3487 ctdb_db = ctdb_attach(ctdb, argv[0], dbmap->dbs[i].persistent, 0);
3488 if (ctdb_db == NULL) {
3489 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", argv[0]));
3490 talloc_free(tmp_ctx);
3495 ret = tdb_transaction_start(ctdb_db->ltdb->tdb);
3497 DEBUG(DEBUG_ERR,("Failed to start transaction\n"));
3498 talloc_free(tmp_ctx);
3503 bd = talloc_zero(tmp_ctx, struct backup_data);
3505 DEBUG(DEBUG_ERR,("Failed to allocate backup_data\n"));
3506 talloc_free(tmp_ctx);
3510 bd->records = talloc_zero(bd, struct ctdb_marshall_buffer);
3511 if (bd->records == NULL) {
3512 DEBUG(DEBUG_ERR,("Failed to allocate ctdb_marshall_buffer\n"));
3513 talloc_free(tmp_ctx);
3517 bd->len = offsetof(struct ctdb_marshall_buffer, data);
3518 bd->records->db_id = ctdb_db->db_id;
3519 /* traverse the database collecting all records */
3520 if (tdb_traverse_read(ctdb_db->ltdb->tdb, backup_traverse, bd) == -1 ||
3521 bd->traverse_error) {
3522 DEBUG(DEBUG_ERR,("Traverse error\n"));
3523 talloc_free(tmp_ctx);
3527 tdb_transaction_cancel(ctdb_db->ltdb->tdb);
3530 fh = open(argv[1], O_RDWR|O_CREAT, 0600);
3532 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[1]));
3533 talloc_free(tmp_ctx);
3537 dbhdr.version = DB_VERSION;
3538 dbhdr.timestamp = time(NULL);
3539 dbhdr.persistent = dbmap->dbs[i].persistent;
3540 dbhdr.size = bd->len;
3541 if (strlen(argv[0]) >= MAX_DB_NAME) {
3542 DEBUG(DEBUG_ERR,("Too long dbname\n"));
3545 strncpy(discard_const(dbhdr.name), argv[0], MAX_DB_NAME);
3546 ret = write(fh, &dbhdr, sizeof(dbhdr));
3548 DEBUG(DEBUG_ERR,("write failed: %s\n", strerror(errno)));
3551 ret = write(fh, bd->records, bd->len);
3553 DEBUG(DEBUG_ERR,("write failed: %s\n", strerror(errno)));
3562 DEBUG(DEBUG_ERR,("close failed: %s\n", strerror(errno)));
3565 talloc_free(tmp_ctx);
3570 * restore a database from a file
3572 static int control_restoredb(struct ctdb_context *ctdb, int argc, const char **argv)
3575 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3578 struct db_file_header dbhdr;
3579 struct ctdb_db_context *ctdb_db;
3580 struct ctdb_node_map *nodemap=NULL;
3581 struct ctdb_vnn_map *vnnmap=NULL;
3583 struct ctdb_control_wipe_database w;
3585 uint32_t generation;
3590 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3594 fh = open(argv[0], O_RDONLY);
3596 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[0]));
3597 talloc_free(tmp_ctx);
3601 read(fh, &dbhdr, sizeof(dbhdr));
3602 if (dbhdr.version != DB_VERSION) {
3603 DEBUG(DEBUG_ERR,("Invalid version of database dump. File is version %lu but expected version was %u\n", dbhdr.version, DB_VERSION));
3604 talloc_free(tmp_ctx);
3608 outdata.dsize = dbhdr.size;
3609 outdata.dptr = talloc_size(tmp_ctx, outdata.dsize);
3610 if (outdata.dptr == NULL) {
3611 DEBUG(DEBUG_ERR,("Failed to allocate data of size '%lu'\n", dbhdr.size));
3613 talloc_free(tmp_ctx);
3616 read(fh, outdata.dptr, outdata.dsize);
3619 tm = localtime(&dbhdr.timestamp);
3620 strftime(tbuf,sizeof(tbuf)-1,"%Y/%m/%d %H:%M:%S", tm);
3621 printf("Restoring database '%s' from backup @ %s\n",
3625 ctdb_db = ctdb_attach(ctdb, dbhdr.name, dbhdr.persistent, 0);
3626 if (ctdb_db == NULL) {
3627 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", dbhdr.name));
3628 talloc_free(tmp_ctx);
3632 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
3634 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
3635 talloc_free(tmp_ctx);
3640 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &vnnmap);
3642 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n", options.pnn));
3643 talloc_free(tmp_ctx);
3647 /* freeze all nodes */
3648 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3649 for (i=1; i<=NUM_DB_PRIORITIES; i++) {
3650 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_FREEZE,
3656 DEBUG(DEBUG_ERR, ("Unable to freeze nodes.\n"));
3657 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3658 talloc_free(tmp_ctx);
3663 generation = vnnmap->generation;
3664 data.dptr = (void *)&generation;
3665 data.dsize = sizeof(generation);
3667 /* start a cluster wide transaction */
3668 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3669 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_START,
3671 TIMELIMIT(), false, data,
3674 DEBUG(DEBUG_ERR, ("Unable to start cluster wide transactions.\n"));
3679 w.db_id = ctdb_db->db_id;
3680 w.transaction_id = generation;
3682 data.dptr = (void *)&w;
3683 data.dsize = sizeof(w);
3685 /* wipe all the remote databases. */
3686 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3687 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_WIPE_DATABASE,
3689 TIMELIMIT(), false, data,
3692 DEBUG(DEBUG_ERR, ("Unable to wipe database.\n"));
3693 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3694 talloc_free(tmp_ctx);
3698 /* push the database */
3699 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3700 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_PUSH_DB,
3702 TIMELIMIT(), false, outdata,
3705 DEBUG(DEBUG_ERR, ("Failed to push database.\n"));
3706 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3707 talloc_free(tmp_ctx);
3711 data.dptr = (void *)&ctdb_db->db_id;
3712 data.dsize = sizeof(ctdb_db->db_id);
3714 /* mark the database as healthy */
3715 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3716 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_DB_SET_HEALTHY,
3718 TIMELIMIT(), false, data,
3721 DEBUG(DEBUG_ERR, ("Failed to mark database as healthy.\n"));
3722 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3723 talloc_free(tmp_ctx);
3727 data.dptr = (void *)&generation;
3728 data.dsize = sizeof(generation);
3730 /* commit all the changes */
3731 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_COMMIT,
3733 TIMELIMIT(), false, data,
3736 DEBUG(DEBUG_ERR, ("Unable to commit databases.\n"));
3737 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3738 talloc_free(tmp_ctx);
3743 /* thaw all nodes */
3744 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3745 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_THAW,
3751 DEBUG(DEBUG_ERR, ("Unable to thaw nodes.\n"));
3752 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3753 talloc_free(tmp_ctx);
3758 talloc_free(tmp_ctx);
3763 * dump a database backup from a file
3765 static int control_dumpdbbackup(struct ctdb_context *ctdb, int argc, const char **argv)
3767 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3769 struct db_file_header dbhdr;
3773 struct ctdb_rec_data *rec = NULL;
3774 struct ctdb_marshall_buffer *m;
3777 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3781 fh = open(argv[0], O_RDONLY);
3783 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[0]));
3784 talloc_free(tmp_ctx);
3788 read(fh, &dbhdr, sizeof(dbhdr));
3789 if (dbhdr.version != DB_VERSION) {
3790 DEBUG(DEBUG_ERR,("Invalid version of database dump. File is version %lu but expected version was %u\n", dbhdr.version, DB_VERSION));
3791 talloc_free(tmp_ctx);
3795 outdata.dsize = dbhdr.size;
3796 outdata.dptr = talloc_size(tmp_ctx, outdata.dsize);
3797 if (outdata.dptr == NULL) {
3798 DEBUG(DEBUG_ERR,("Failed to allocate data of size '%lu'\n", dbhdr.size));
3800 talloc_free(tmp_ctx);
3803 read(fh, outdata.dptr, outdata.dsize);
3805 m = (struct ctdb_marshall_buffer *)outdata.dptr;
3807 tm = localtime(&dbhdr.timestamp);
3808 strftime(tbuf,sizeof(tbuf)-1,"%Y/%m/%d %H:%M:%S", tm);
3809 printf("Backup of database name:'%s' dbid:0x%x08x from @ %s\n",
3810 dbhdr.name, m->db_id, tbuf);
3812 for (i=0; i < m->count; i++) {
3816 /* we do not want the header splitted, so we pass NULL*/
3817 rec = ctdb_marshall_loop_next(m, rec, &reqid,
3820 ctdb_dumpdb_record(ctdb, key, data, stdout);
3823 printf("Dumped %d records\n", i);
3824 talloc_free(tmp_ctx);
3829 * wipe a database from a file
3831 static int control_wipedb(struct ctdb_context *ctdb, int argc,
3835 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3837 struct ctdb_db_context *ctdb_db;
3838 struct ctdb_node_map *nodemap = NULL;
3839 struct ctdb_vnn_map *vnnmap = NULL;
3841 struct ctdb_control_wipe_database w;
3843 uint32_t generation;
3844 struct ctdb_dbid_map *dbmap = NULL;
3847 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3851 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx,
3854 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n",
3859 for(i=0;i<dbmap->num;i++){
3862 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn,
3863 dbmap->dbs[i].dbid, tmp_ctx, &name);
3864 if(!strcmp(argv[0], name)){
3865 talloc_free(discard_const(name));
3868 talloc_free(discard_const(name));
3870 if (i == dbmap->num) {
3871 DEBUG(DEBUG_ERR, ("No database with name '%s' found\n",
3873 talloc_free(tmp_ctx);
3877 ctdb_db = ctdb_attach(ctdb, argv[0], dbmap->dbs[i].persistent, 0);
3878 if (ctdb_db == NULL) {
3879 DEBUG(DEBUG_ERR, ("Unable to attach to database '%s'\n",
3881 talloc_free(tmp_ctx);
3885 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb,
3888 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n",
3890 talloc_free(tmp_ctx);
3894 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx,
3897 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n",
3899 talloc_free(tmp_ctx);
3903 /* freeze all nodes */
3904 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3905 for (i=1; i<=NUM_DB_PRIORITIES; i++) {
3906 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_FREEZE,
3913 DEBUG(DEBUG_ERR, ("Unable to freeze nodes.\n"));
3914 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn,
3915 CTDB_RECOVERY_ACTIVE);
3916 talloc_free(tmp_ctx);
3921 generation = vnnmap->generation;
3922 data.dptr = (void *)&generation;
3923 data.dsize = sizeof(generation);
3925 /* start a cluster wide transaction */
3926 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3927 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_START,
3929 TIMELIMIT(), false, data,
3933 DEBUG(DEBUG_ERR, ("Unable to start cluster wide "
3934 "transactions.\n"));
3938 w.db_id = ctdb_db->db_id;
3939 w.transaction_id = generation;
3941 data.dptr = (void *)&w;
3942 data.dsize = sizeof(w);
3944 /* wipe all the remote databases. */
3945 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3946 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_WIPE_DATABASE,
3948 TIMELIMIT(), false, data,
3951 DEBUG(DEBUG_ERR, ("Unable to wipe database.\n"));
3952 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3953 talloc_free(tmp_ctx);
3957 data.dptr = (void *)&ctdb_db->db_id;
3958 data.dsize = sizeof(ctdb_db->db_id);
3960 /* mark the database as healthy */
3961 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3962 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_DB_SET_HEALTHY,
3964 TIMELIMIT(), false, data,
3967 DEBUG(DEBUG_ERR, ("Failed to mark database as healthy.\n"));
3968 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3969 talloc_free(tmp_ctx);
3973 data.dptr = (void *)&generation;
3974 data.dsize = sizeof(generation);
3976 /* commit all the changes */
3977 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_COMMIT,
3979 TIMELIMIT(), false, data,
3982 DEBUG(DEBUG_ERR, ("Unable to commit databases.\n"));
3983 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3984 talloc_free(tmp_ctx);
3988 /* thaw all nodes */
3989 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3990 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_THAW,
3996 DEBUG(DEBUG_ERR, ("Unable to thaw nodes.\n"));
3997 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3998 talloc_free(tmp_ctx);
4002 talloc_free(tmp_ctx);
4007 * set flags of a node in the nodemap
4009 static int control_setflags(struct ctdb_context *ctdb, int argc, const char **argv)
4016 struct ctdb_node_flag_change c;
4023 if (sscanf(argv[0], "%d", &node) != 1) {
4024 DEBUG(DEBUG_ERR, ("Badly formed node\n"));
4028 if (sscanf(argv[1], "0x%x", &flags) != 1) {
4029 DEBUG(DEBUG_ERR, ("Badly formed flags\n"));
4036 c.new_flags = flags;
4038 data.dsize = sizeof(c);
4039 data.dptr = (unsigned char *)&c;
4041 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_MODIFY_FLAGS, 0,
4042 data, NULL, NULL, &status, NULL, NULL);
4043 if (ret != 0 || status != 0) {
4044 DEBUG(DEBUG_ERR,("Failed to modify flags\n"));
4053 static int control_dumpmemory(struct ctdb_context *ctdb, int argc, const char **argv)
4059 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
4060 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_DUMP_MEMORY,
4061 0, tdb_null, tmp_ctx, &data, &res, NULL, &errmsg);
4062 if (ret != 0 || res != 0) {
4063 DEBUG(DEBUG_ERR,("Failed to dump memory - %s\n", errmsg));
4064 talloc_free(tmp_ctx);
4067 write(1, data.dptr, data.dsize);
4068 talloc_free(tmp_ctx);
4073 handler for memory dumps
4075 static void mem_dump_handler(struct ctdb_context *ctdb, uint64_t srvid,
4076 TDB_DATA data, void *private_data)
4078 write(1, data.dptr, data.dsize);
4083 dump memory usage on the recovery daemon
4085 static int control_rddumpmemory(struct ctdb_context *ctdb, int argc, const char **argv)
4089 struct rd_memdump_reply rd;
4091 rd.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
4093 DEBUG(DEBUG_ERR, ("Failed to get pnn of local node\n"));
4096 rd.srvid = getpid();
4098 /* register a message port for receiveing the reply so that we
4099 can receive the reply
4101 ctdb_set_message_handler(ctdb, rd.srvid, mem_dump_handler, NULL);
4104 data.dptr = (uint8_t *)&rd;
4105 data.dsize = sizeof(rd);
4107 ret = ctdb_send_message(ctdb, options.pnn, CTDB_SRVID_MEM_DUMP, data);
4109 DEBUG(DEBUG_ERR,("Failed to send memdump request message to %u\n", options.pnn));
4113 /* this loop will terminate when we have received the reply */
4115 event_loop_once(ctdb->ev);
4122 send a message to a srvid
4124 static int control_msgsend(struct ctdb_context *ctdb, int argc, const char **argv)
4126 unsigned long srvid;
4134 srvid = strtoul(argv[0], NULL, 0);
4136 data.dptr = (uint8_t *)discard_const(argv[1]);
4137 data.dsize= strlen(argv[1]);
4139 ret = ctdb_send_message(ctdb, CTDB_BROADCAST_CONNECTED, srvid, data);
4141 DEBUG(DEBUG_ERR,("Failed to send memdump request message to %u\n", options.pnn));
4149 handler for msglisten
4151 static void msglisten_handler(struct ctdb_context *ctdb, uint64_t srvid,
4152 TDB_DATA data, void *private_data)
4156 printf("Message received: ");
4157 for (i=0;i<data.dsize;i++) {
4158 printf("%c", data.dptr[i]);
4164 listen for messages on a messageport
4166 static int control_msglisten(struct ctdb_context *ctdb, int argc, const char **argv)
4172 /* register a message port and listen for messages
4174 ctdb_set_message_handler(ctdb, srvid, msglisten_handler, NULL);
4175 printf("Listening for messages on srvid:%d\n", (int)srvid);
4178 event_loop_once(ctdb->ev);
4185 list all nodes in the cluster
4186 if the daemon is running, we read the data from the daemon.
4187 if the daemon is not running we parse the nodes file directly
4189 static int control_listnodes(struct ctdb_context *ctdb, int argc, const char **argv)
4192 struct ctdb_node_map *nodemap=NULL;
4195 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
4197 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
4201 for(i=0;i<nodemap->num;i++){
4202 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
4205 if (options.machinereadable){
4206 printf(":%d:%s:\n", nodemap->nodes[i].pnn, ctdb_addr_to_str(&nodemap->nodes[i].addr));
4208 printf("%s\n", ctdb_addr_to_str(&nodemap->nodes[i].addr));
4212 TALLOC_CTX *mem_ctx = talloc_new(NULL);
4213 struct pnn_node *pnn_nodes;
4214 struct pnn_node *pnn_node;
4216 pnn_nodes = read_nodes_file(mem_ctx);
4217 if (pnn_nodes == NULL) {
4218 DEBUG(DEBUG_ERR,("Failed to read nodes file\n"));
4219 talloc_free(mem_ctx);
4223 for(pnn_node=pnn_nodes;pnn_node;pnn_node=pnn_node->next) {
4224 ctdb_sock_addr addr;
4226 if (parse_ip(pnn_node->addr, NULL, 63999, &addr) == 0) {
4227 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s' in nodes file\n", pnn_node->addr));
4228 talloc_free(mem_ctx);
4232 if (options.machinereadable){
4233 printf(":%d:%s:\n", pnn_node->pnn, pnn_node->addr);
4235 printf("%s\n", pnn_node->addr);
4238 talloc_free(mem_ctx);
4245 reload the nodes file on the local node
4247 static int control_reload_nodes_file(struct ctdb_context *ctdb, int argc, const char **argv)
4251 struct ctdb_node_map *nodemap=NULL;
4253 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
4255 DEBUG(DEBUG_ERR, ("Failed to read pnn of local node\n"));
4259 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
4261 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
4265 /* reload the nodes file on all remote nodes */
4266 for (i=0;i<nodemap->num;i++) {
4267 if (nodemap->nodes[i].pnn == mypnn) {
4270 DEBUG(DEBUG_NOTICE, ("Reloading nodes file on node %u\n", nodemap->nodes[i].pnn));
4271 ret = ctdb_ctrl_reload_nodes_file(ctdb, TIMELIMIT(),
4272 nodemap->nodes[i].pnn);
4274 DEBUG(DEBUG_ERR, ("ERROR: Failed to reload nodes file on node %u. You MUST fix that node manually!\n", nodemap->nodes[i].pnn));
4278 /* reload the nodes file on the local node */
4279 DEBUG(DEBUG_NOTICE, ("Reloading nodes file on node %u\n", mypnn));
4280 ret = ctdb_ctrl_reload_nodes_file(ctdb, TIMELIMIT(), mypnn);
4282 DEBUG(DEBUG_ERR, ("ERROR: Failed to reload nodes file on node %u. You MUST fix that node manually!\n", mypnn));
4285 /* initiate a recovery */
4286 control_recover(ctdb, argc, argv);
4292 static const struct {
4294 int (*fn)(struct ctdb_context *, int, const char **);
4296 bool without_daemon; /* can be run without daemon running ? */
4299 } ctdb_commands[] = {
4301 { "version", control_version, true, false, "show version of ctdb" },
4303 { "status", control_status, true, false, "show node status" },
4304 { "uptime", control_uptime, true, false, "show node uptime" },
4305 { "ping", control_ping, true, false, "ping all nodes" },
4306 { "getvar", control_getvar, true, false, "get a tunable variable", "<name>"},
4307 { "setvar", control_setvar, true, false, "set a tunable variable", "<name> <value>"},
4308 { "listvars", control_listvars, true, false, "list tunable variables"},
4309 { "statistics", control_statistics, false, false, "show statistics" },
4310 { "statisticsreset", control_statistics_reset, true, false, "reset statistics"},
4311 { "ip", control_ip, false, false, "show which public ip's that ctdb manages" },
4312 { "ipinfo", control_ipinfo, true, false, "show details about a public ip that ctdb manages", "<ip>" },
4313 { "ifaces", control_ifaces, true, false, "show which interfaces that ctdb manages" },
4314 { "setifacelink", control_setifacelink, true, false, "set interface link status", "<iface> <status>" },
4315 { "process-exists", control_process_exists, true, false, "check if a process exists on a node", "<pid>"},
4316 { "getdbmap", control_getdbmap, true, false, "show the database map" },
4317 { "getdbstatus", control_getdbstatus, true, false, "show the status of a database", "<dbname>" },
4318 { "catdb", control_catdb, true, false, "dump a database" , "<dbname>"},
4319 { "getmonmode", control_getmonmode, true, false, "show monitoring mode" },
4320 { "getcapabilities", control_getcapabilities, true, false, "show node capabilities" },
4321 { "pnn", control_pnn, true, false, "show the pnn of the currnet node" },
4322 { "lvs", control_lvs, true, false, "show lvs configuration" },
4323 { "lvsmaster", control_lvsmaster, true, false, "show which node is the lvs master" },
4324 { "disablemonitor", control_disable_monmode,true, false, "set monitoring mode to DISABLE" },
4325 { "enablemonitor", control_enable_monmode, true, false, "set monitoring mode to ACTIVE" },
4326 { "setdebug", control_setdebug, true, false, "set debug level", "<EMERG|ALERT|CRIT|ERR|WARNING|NOTICE|INFO|DEBUG>" },
4327 { "getdebug", control_getdebug, true, false, "get debug level" },
4328 { "getlog", control_getlog, true, false, "get the log data from the in memory ringbuffer", "<level>" },
4329 { "clearlog", control_clearlog, true, false, "clear the log data from the in memory ringbuffer" },
4330 { "attach", control_attach, true, false, "attach to a database", "<dbname>" },
4331 { "dumpmemory", control_dumpmemory, true, false, "dump memory map to stdout" },
4332 { "rddumpmemory", control_rddumpmemory, true, false, "dump memory map from the recovery daemon to stdout" },
4333 { "getpid", control_getpid, true, false, "get ctdbd process ID" },
4334 { "disable", control_disable, true, false, "disable a nodes public IP" },
4335 { "enable", control_enable, true, false, "enable a nodes public IP" },
4336 { "stop", control_stop, true, false, "stop a node" },
4337 { "continue", control_continue, true, false, "re-start a stopped node" },
4338 { "ban", control_ban, true, false, "ban a node from the cluster", "<bantime|0>"},
4339 { "unban", control_unban, true, false, "unban a node" },
4340 { "showban", control_showban, true, false, "show ban information"},
4341 { "shutdown", control_shutdown, true, false, "shutdown ctdbd" },
4342 { "recover", control_recover, true, false, "force recovery" },
4343 { "ipreallocate", control_ipreallocate, true, false, "force the recovery daemon to perform a ip reallocation procedure" },
4344 { "freeze", control_freeze, true, false, "freeze databases", "[priority:1-3]" },
4345 { "thaw", control_thaw, true, false, "thaw databases", "[priority:1-3]" },
4346 { "isnotrecmaster", control_isnotrecmaster, false, false, "check if the local node is recmaster or not" },
4347 { "killtcp", kill_tcp, false, false, "kill a tcp connection.", "<srcip:port> <dstip:port>" },
4348 { "gratiousarp", control_gratious_arp, false, false, "send a gratious arp", "<ip> <interface>" },
4349 { "tickle", tickle_tcp, false, false, "send a tcp tickle ack", "<srcip:port> <dstip:port>" },
4350 { "gettickles", control_get_tickles, false, false, "get the list of tickles registered for this ip", "<ip>" },
4352 { "regsrvid", regsrvid, false, false, "register a server id", "<pnn> <type> <id>" },
4353 { "unregsrvid", unregsrvid, false, false, "unregister a server id", "<pnn> <type> <id>" },
4354 { "chksrvid", chksrvid, false, false, "check if a server id exists", "<pnn> <type> <id>" },
4355 { "getsrvids", getsrvids, false, false, "get a list of all server ids"},
4356 { "vacuum", ctdb_vacuum, false, false, "vacuum the databases of empty records", "[max_records]"},
4357 { "repack", ctdb_repack, false, false, "repack all databases", "[max_freelist]"},
4358 { "listnodes", control_listnodes, false, true, "list all nodes in the cluster"},
4359 { "reloadnodes", control_reload_nodes_file, false, false, "reload the nodes file and restart the transport on all nodes"},
4360 { "moveip", control_moveip, false, false, "move/failover an ip address to another node", "<ip> <node>"},
4361 { "addip", control_addip, true, false, "add a ip address to a node", "<ip/mask> <iface>"},
4362 { "delip", control_delip, false, false, "delete an ip address from a node", "<ip>"},
4363 { "eventscript", control_eventscript, true, false, "run the eventscript with the given parameters on a node", "<arguments>"},
4364 { "backupdb", control_backupdb, false, false, "backup the database into a file.", "<database> <file>"},
4365 { "restoredb", control_restoredb, false, false, "restore the database from a file.", "<file>"},
4366 { "dumpdbbackup", control_dumpdbbackup, false, true, "dump database backup from a file.", "<file>"},
4367 { "wipedb", control_wipedb, false, false, "wipe the contents of a database.", "<dbname>"},
4368 { "recmaster", control_recmaster, false, false, "show the pnn for the recovery master."},
4369 { "setflags", control_setflags, false, false, "set flags for a node in the nodemap.", "<node> <flags>"},
4370 { "scriptstatus", control_scriptstatus, false, false, "show the status of the monitoring scripts (or all scripts)", "[all]"},
4371 { "enablescript", control_enablescript, false, false, "enable an eventscript", "<script>"},
4372 { "disablescript", control_disablescript, false, false, "disable an eventscript", "<script>"},
4373 { "natgwlist", control_natgwlist, false, false, "show the nodes belonging to this natgw configuration"},
4374 { "xpnn", control_xpnn, true, true, "find the pnn of the local node without talking to the daemon (unreliable)" },
4375 { "getreclock", control_getreclock, false, false, "Show the reclock file of a node"},
4376 { "setreclock", control_setreclock, false, false, "Set/clear the reclock file of a node", "[filename]"},
4377 { "setnatgwstate", control_setnatgwstate, false, false, "Set NATGW state to on/off", "{on|off}"},
4378 { "setlmasterrole", control_setlmasterrole, false, false, "Set LMASTER role to on/off", "{on|off}"},
4379 { "setrecmasterrole", control_setrecmasterrole, false, false, "Set RECMASTER role to on/off", "{on|off}"},
4380 { "setdbprio", control_setdbprio, false, false, "Set DB priority", "<dbid> <prio:1-3>"},
4381 { "getdbprio", control_getdbprio, false, false, "Get DB priority", "<dbid>"},
4382 { "msglisten", control_msglisten, false, false, "Listen on a srvid port for messages", "<msg srvid>"},
4383 { "msgsend", control_msgsend, false, false, "Send a message to srvid", "<srvid> <message>"},
4389 static void usage(void)
4393 "Usage: ctdb [options] <control>\n" \
4395 " -n <node> choose node number, or 'all' (defaults to local node)\n"
4396 " -Y generate machinereadable output\n"
4397 " -t <timelimit> set timelimit for control in seconds (default %u)\n", options.timelimit);
4398 printf("Controls:\n");
4399 for (i=0;i<ARRAY_SIZE(ctdb_commands);i++) {
4400 printf(" %-15s %-27s %s\n",
4401 ctdb_commands[i].name,
4402 ctdb_commands[i].args?ctdb_commands[i].args:"",
4403 ctdb_commands[i].msg);
4409 static void ctdb_alarm(int sig)
4411 printf("Maximum runtime exceeded - exiting\n");
4418 int main(int argc, const char *argv[])
4420 struct ctdb_context *ctdb;
4421 char *nodestring = NULL;
4422 struct poptOption popt_options[] = {
4425 { "timelimit", 't', POPT_ARG_INT, &options.timelimit, 0, "timelimit", "integer" },
4426 { "node", 'n', POPT_ARG_STRING, &nodestring, 0, "node", "integer|all" },
4427 { "machinereadable", 'Y', POPT_ARG_NONE, &options.machinereadable, 0, "enable machinereadable output", NULL },
4428 { "maxruntime", 'T', POPT_ARG_INT, &options.maxruntime, 0, "die if runtime exceeds this limit (in seconds)", "integer" },
4432 const char **extra_argv;
4436 struct event_context *ev;
4437 const char *control;
4441 /* set some defaults */
4442 options.maxruntime = 0;
4443 options.timelimit = 3;
4444 options.pnn = CTDB_CURRENT_NODE;
4446 pc = poptGetContext(argv[0], argc, argv, popt_options, POPT_CONTEXT_KEEP_FIRST);
4448 while ((opt = poptGetNextOpt(pc)) != -1) {
4451 DEBUG(DEBUG_ERR, ("Invalid option %s: %s\n",
4452 poptBadOption(pc, 0), poptStrerror(opt)));
4457 /* setup the remaining options for the main program to use */
4458 extra_argv = poptGetArgs(pc);
4461 while (extra_argv[extra_argc]) extra_argc++;
4464 if (extra_argc < 1) {
4468 if (options.maxruntime == 0) {
4469 const char *ctdb_timeout;
4470 ctdb_timeout = getenv("CTDB_TIMEOUT");
4471 if (ctdb_timeout != NULL) {
4472 options.maxruntime = strtoul(ctdb_timeout, NULL, 0);
4474 /* default timeout is 120 seconds */
4475 options.maxruntime = 120;
4479 signal(SIGALRM, ctdb_alarm);
4480 alarm(options.maxruntime);
4482 /* setup the node number to contact */
4483 if (nodestring != NULL) {
4484 if (strcmp(nodestring, "all") == 0) {
4485 options.pnn = CTDB_BROADCAST_ALL;
4487 options.pnn = strtoul(nodestring, NULL, 0);
4491 control = extra_argv[0];
4493 ev = event_context_init(NULL);
4495 for (i=0;i<ARRAY_SIZE(ctdb_commands);i++) {
4496 if (strcmp(control, ctdb_commands[i].name) == 0) {
4499 if (ctdb_commands[i].without_daemon == true) {
4503 /* initialise ctdb */
4504 ctdb = ctdb_cmdline_client(ev);
4506 if (ctdb_commands[i].without_daemon == false) {
4508 DEBUG(DEBUG_ERR, ("Failed to init ctdb\n"));
4512 /* verify the node exists */
4515 if (options.pnn == CTDB_CURRENT_NODE) {
4517 pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
4525 if (ctdb_commands[i].auto_all &&
4526 options.pnn == CTDB_BROADCAST_ALL) {
4531 nodes = ctdb_get_connected_nodes(ctdb, TIMELIMIT(), ctdb, &num_nodes);
4532 CTDB_NO_MEMORY(ctdb, nodes);
4534 for (j=0;j<num_nodes;j++) {
4535 options.pnn = nodes[j];
4536 ret |= ctdb_commands[i].fn(ctdb, extra_argc-1, extra_argv+1);
4540 ret = ctdb_commands[i].fn(ctdb, extra_argc-1, extra_argv+1);
4546 if (i == ARRAY_SIZE(ctdb_commands)) {
4547 DEBUG(DEBUG_ERR, ("Unknown control '%s'\n", control));