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:\n");
506 for(i=0;i<nodemap->num;i++){
507 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
510 printf(":%d:%s:%d:%d:%d:%d:%d:%d:\n", nodemap->nodes[i].pnn,
511 ctdb_addr_to_str(&nodemap->nodes[i].addr),
512 !!(nodemap->nodes[i].flags&NODE_FLAGS_DISCONNECTED),
513 !!(nodemap->nodes[i].flags&NODE_FLAGS_BANNED),
514 !!(nodemap->nodes[i].flags&NODE_FLAGS_PERMANENTLY_DISABLED),
515 !!(nodemap->nodes[i].flags&NODE_FLAGS_UNHEALTHY),
516 !!(nodemap->nodes[i].flags&NODE_FLAGS_STOPPED),
517 !!(nodemap->nodes[i].flags&NODE_FLAGS_INACTIVE));
522 printf("Number of nodes:%d\n", nodemap->num);
523 for(i=0;i<nodemap->num;i++){
524 static const struct {
528 { NODE_FLAGS_DISCONNECTED, "DISCONNECTED" },
529 { NODE_FLAGS_PERMANENTLY_DISABLED, "DISABLED" },
530 { NODE_FLAGS_BANNED, "BANNED" },
531 { NODE_FLAGS_UNHEALTHY, "UNHEALTHY" },
532 { NODE_FLAGS_DELETED, "DELETED" },
533 { NODE_FLAGS_STOPPED, "STOPPED" },
534 { NODE_FLAGS_INACTIVE, "INACTIVE" },
536 char *flags_str = NULL;
539 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
542 for (j=0;j<ARRAY_SIZE(flag_names);j++) {
543 if (nodemap->nodes[i].flags & flag_names[j].flag) {
544 if (flags_str == NULL) {
545 flags_str = talloc_strdup(ctdb, flag_names[j].name);
547 flags_str = talloc_asprintf_append(flags_str, "|%s",
550 CTDB_NO_MEMORY_FATAL(ctdb, flags_str);
553 if (flags_str == NULL) {
554 flags_str = talloc_strdup(ctdb, "OK");
555 CTDB_NO_MEMORY_FATAL(ctdb, flags_str);
557 printf("pnn:%d %-16s %s%s\n", nodemap->nodes[i].pnn,
558 ctdb_addr_to_str(&nodemap->nodes[i].addr),
560 nodemap->nodes[i].pnn == mypnn?" (THIS NODE)":"");
561 talloc_free(flags_str);
564 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &vnnmap);
566 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n", options.pnn));
569 if (vnnmap->generation == INVALID_GENERATION) {
570 printf("Generation:INVALID\n");
572 printf("Generation:%d\n",vnnmap->generation);
574 printf("Size:%d\n",vnnmap->size);
575 for(i=0;i<vnnmap->size;i++){
576 printf("hash:%d lmaster:%d\n", i, vnnmap->map[i]);
579 ret = ctdb_ctrl_getrecmode(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmode);
581 DEBUG(DEBUG_ERR, ("Unable to get recmode from node %u\n", options.pnn));
584 printf("Recovery mode:%s (%d)\n",recmode==CTDB_RECOVERY_NORMAL?"NORMAL":"RECOVERY",recmode);
586 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
588 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
591 printf("Recovery master:%d\n",recmaster);
598 struct natgw_node *next;
603 display the list of nodes belonging to this natgw configuration
605 static int control_natgwlist(struct ctdb_context *ctdb, int argc, const char **argv)
608 const char *natgw_list;
611 struct natgw_node *natgw_nodes = NULL;
612 struct natgw_node *natgw_node;
613 struct ctdb_node_map *nodemap=NULL;
616 /* read the natgw nodes file into a linked list */
617 natgw_list = getenv("NATGW_NODES");
618 if (natgw_list == NULL) {
619 natgw_list = "/etc/ctdb/natgw_nodes";
621 lines = file_lines_load(natgw_list, &nlines, ctdb);
623 ctdb_set_error(ctdb, "Failed to load natgw node list '%s'\n", natgw_list);
626 while (nlines > 0 && strcmp(lines[nlines-1], "") == 0) {
629 for (i=0;i<nlines;i++) {
633 /* strip leading spaces */
634 while((*node == ' ') || (*node == '\t')) {
640 if (strcmp(node, "") == 0) {
643 natgw_node = talloc(ctdb, struct natgw_node);
644 natgw_node->addr = talloc_strdup(natgw_node, node);
645 CTDB_NO_MEMORY(ctdb, natgw_node->addr);
646 natgw_node->next = natgw_nodes;
647 natgw_nodes = natgw_node;
650 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
652 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node.\n"));
657 while(i<nodemap->num) {
658 for(natgw_node=natgw_nodes;natgw_node;natgw_node=natgw_node->next) {
659 if (!strcmp(natgw_node->addr, ctdb_addr_to_str(&nodemap->nodes[i].addr))) {
664 /* this node was not in the natgw so we just remove it from
667 if ((natgw_node == NULL)
668 || (nodemap->nodes[i].flags & NODE_FLAGS_DISCONNECTED) ) {
671 for (j=i+1; j<nodemap->num; j++) {
672 nodemap->nodes[j-1] = nodemap->nodes[j];
681 /* pick a node to be natgwmaster
682 * we dont allow STOPPED, DELETED, BANNED or UNHEALTHY nodes to become the natgwmaster
684 for(i=0;i<nodemap->num;i++){
685 if (!(nodemap->nodes[i].flags & (NODE_FLAGS_DISCONNECTED|NODE_FLAGS_STOPPED|NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_UNHEALTHY))) {
686 printf("%d %s\n", nodemap->nodes[i].pnn,ctdb_addr_to_str(&nodemap->nodes[i].addr));
690 /* we couldnt find any healthy node, try unhealthy ones */
691 if (i == nodemap->num) {
692 for(i=0;i<nodemap->num;i++){
693 if (!(nodemap->nodes[i].flags & (NODE_FLAGS_DISCONNECTED|NODE_FLAGS_STOPPED|NODE_FLAGS_DELETED))) {
694 printf("%d %s\n", nodemap->nodes[i].pnn,ctdb_addr_to_str(&nodemap->nodes[i].addr));
699 /* unless all nodes are STOPPED, when we pick one anyway */
700 if (i == nodemap->num) {
701 for(i=0;i<nodemap->num;i++){
702 if (!(nodemap->nodes[i].flags & (NODE_FLAGS_DISCONNECTED|NODE_FLAGS_DELETED))) {
703 printf("%d %s\n", nodemap->nodes[i].pnn, ctdb_addr_to_str(&nodemap->nodes[i].addr));
707 /* or if we still can not find any */
708 if (i == nodemap->num) {
709 printf("-1 0.0.0.0\n");
713 /* print the pruned list of nodes belonging to this natgw list */
714 for(i=0;i<nodemap->num;i++){
715 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
718 printf(":%d:%s:%d:%d:%d:%d:%d\n", nodemap->nodes[i].pnn,
719 ctdb_addr_to_str(&nodemap->nodes[i].addr),
720 !!(nodemap->nodes[i].flags&NODE_FLAGS_DISCONNECTED),
721 !!(nodemap->nodes[i].flags&NODE_FLAGS_BANNED),
722 !!(nodemap->nodes[i].flags&NODE_FLAGS_PERMANENTLY_DISABLED),
723 !!(nodemap->nodes[i].flags&NODE_FLAGS_UNHEALTHY),
724 !!(nodemap->nodes[i].flags&NODE_FLAGS_STOPPED));
731 display the status of the scripts for monitoring (or other events)
733 static int control_one_scriptstatus(struct ctdb_context *ctdb,
734 enum ctdb_eventscript_call type)
736 struct ctdb_scripts_wire *script_status;
739 ret = ctdb_ctrl_getscriptstatus(ctdb, TIMELIMIT(), options.pnn, ctdb, type, &script_status);
741 DEBUG(DEBUG_ERR, ("Unable to get script status from node %u\n", options.pnn));
745 if (script_status == NULL) {
746 if (!options.machinereadable) {
747 printf("%s cycle never run\n",
748 ctdb_eventscript_call_names[type]);
753 if (!options.machinereadable) {
754 printf("%d scripts were executed last %s cycle\n",
755 script_status->num_scripts,
756 ctdb_eventscript_call_names[type]);
758 for (i=0; i<script_status->num_scripts; i++) {
759 const char *status = NULL;
761 switch (script_status->scripts[i].status) {
772 if (script_status->scripts[i].status > 0)
776 if (options.machinereadable) {
777 printf("%s:%s:%i:%s:%lu.%06lu:%lu.%06lu:%s:\n",
778 ctdb_eventscript_call_names[type],
779 script_status->scripts[i].name,
780 script_status->scripts[i].status,
782 (long)script_status->scripts[i].start.tv_sec,
783 (long)script_status->scripts[i].start.tv_usec,
784 (long)script_status->scripts[i].finished.tv_sec,
785 (long)script_status->scripts[i].finished.tv_usec,
786 script_status->scripts[i].output);
790 printf("%-20s Status:%s ",
791 script_status->scripts[i].name, status);
793 /* Some other error, eg from stat. */
794 printf("%-20s Status:CANNOT RUN (%s)",
795 script_status->scripts[i].name,
796 strerror(-script_status->scripts[i].status));
798 if (script_status->scripts[i].status >= 0) {
799 printf("Duration:%.3lf ",
800 timeval_delta(&script_status->scripts[i].finished,
801 &script_status->scripts[i].start));
803 if (script_status->scripts[i].status != -ENOEXEC) {
805 ctime(&script_status->scripts[i].start.tv_sec));
806 if (script_status->scripts[i].status != 0) {
807 printf(" OUTPUT:%s\n",
808 script_status->scripts[i].output);
818 static int control_scriptstatus(struct ctdb_context *ctdb,
819 int argc, const char **argv)
822 enum ctdb_eventscript_call type, min, max;
826 DEBUG(DEBUG_ERR, ("Unknown arguments to scriptstatus\n"));
831 arg = ctdb_eventscript_call_names[CTDB_EVENT_MONITOR];
835 for (type = 0; type < CTDB_EVENT_MAX; type++) {
836 if (strcmp(arg, ctdb_eventscript_call_names[type]) == 0) {
842 if (type == CTDB_EVENT_MAX) {
843 if (strcmp(arg, "all") == 0) {
845 max = CTDB_EVENT_MAX;
847 DEBUG(DEBUG_ERR, ("Unknown event type %s\n", argv[0]));
852 if (options.machinereadable) {
853 printf(":Type:Name:Code:Status:Start:End:Error Output...:\n");
856 for (type = min; type < max; type++) {
857 ret = control_one_scriptstatus(ctdb, type);
867 enable an eventscript
869 static int control_enablescript(struct ctdb_context *ctdb, int argc, const char **argv)
877 ret = ctdb_ctrl_enablescript(ctdb, TIMELIMIT(), options.pnn, argv[0]);
879 DEBUG(DEBUG_ERR, ("Unable to enable script %s on node %u\n", argv[0], options.pnn));
887 disable an eventscript
889 static int control_disablescript(struct ctdb_context *ctdb, int argc, const char **argv)
897 ret = ctdb_ctrl_disablescript(ctdb, TIMELIMIT(), options.pnn, argv[0]);
899 DEBUG(DEBUG_ERR, ("Unable to disable script %s on node %u\n", argv[0], options.pnn));
907 display the pnn of the recovery master
909 static int control_recmaster(struct ctdb_context *ctdb, int argc, const char **argv)
914 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
916 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
919 printf("%d\n",recmaster);
925 get a list of all tickles for this pnn
927 static int control_get_tickles(struct ctdb_context *ctdb, int argc, const char **argv)
929 struct ctdb_control_tcp_tickle_list *list;
937 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
938 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
942 ret = ctdb_ctrl_get_tcp_tickles(ctdb, TIMELIMIT(), options.pnn, ctdb, &addr, &list);
944 DEBUG(DEBUG_ERR, ("Unable to list tickles\n"));
948 printf("Tickles for ip:%s\n", ctdb_addr_to_str(&list->addr));
949 printf("Num tickles:%u\n", list->tickles.num);
950 for (i=0;i<list->tickles.num;i++) {
951 printf("SRC: %s:%u ", ctdb_addr_to_str(&list->tickles.connections[i].src_addr), ntohs(list->tickles.connections[i].src_addr.ip.sin_port));
952 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));
962 static int move_ip(struct ctdb_context *ctdb, ctdb_sock_addr *addr, uint32_t pnn)
964 struct ctdb_all_public_ips *ips;
965 struct ctdb_public_ip ip;
968 uint32_t disable_time;
970 struct ctdb_node_map *nodemap=NULL;
971 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
974 data.dptr = (uint8_t*)&disable_time;
975 data.dsize = sizeof(disable_time);
976 ret = ctdb_send_message(ctdb, CTDB_BROADCAST_CONNECTED, CTDB_SRVID_DISABLE_IP_CHECK, data);
978 DEBUG(DEBUG_ERR,("Failed to send message to disable ipcheck\n"));
984 /* read the public ip list from the node */
985 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), pnn, ctdb, &ips);
987 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", pnn));
988 talloc_free(tmp_ctx);
992 for (i=0;i<ips->num;i++) {
993 if (ctdb_same_ip(addr, &ips->ips[i].addr)) {
998 DEBUG(DEBUG_ERR, ("Node %u can not host ip address '%s'\n",
999 pnn, ctdb_addr_to_str(addr)));
1000 talloc_free(tmp_ctx);
1007 data.dptr = (uint8_t *)&ip;
1008 data.dsize = sizeof(ip);
1010 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &nodemap);
1012 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1013 talloc_free(tmp_ctx);
1017 nodes = list_of_active_nodes_except_pnn(ctdb, nodemap, tmp_ctx, pnn);
1018 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_RELEASE_IP,
1025 DEBUG(DEBUG_ERR,("Failed to release IP on nodes\n"));
1026 talloc_free(tmp_ctx);
1030 ret = ctdb_ctrl_takeover_ip(ctdb, TIMELIMIT(), pnn, &ip);
1032 DEBUG(DEBUG_ERR,("Failed to take over IP on node %d\n", pnn));
1033 talloc_free(tmp_ctx);
1037 talloc_free(tmp_ctx);
1042 move/failover an ip address to a specific node
1044 static int control_moveip(struct ctdb_context *ctdb, int argc, const char **argv)
1047 ctdb_sock_addr addr;
1054 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1055 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1060 if (sscanf(argv[1], "%u", &pnn) != 1) {
1061 DEBUG(DEBUG_ERR, ("Badly formed pnn\n"));
1065 if (move_ip(ctdb, &addr, pnn) != 0) {
1066 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", pnn));
1073 void getips_store_callback(void *param, void *data)
1075 struct ctdb_public_ip *node_ip = (struct ctdb_public_ip *)data;
1076 struct ctdb_all_public_ips *ips = param;
1080 ips->ips[i].pnn = node_ip->pnn;
1081 ips->ips[i].addr = node_ip->addr;
1084 void getips_count_callback(void *param, void *data)
1086 uint32_t *count = param;
1092 static uint32_t *ip_key(ctdb_sock_addr *ip)
1094 static uint32_t key[IP_KEYLEN];
1096 bzero(key, sizeof(key));
1098 switch (ip->sa.sa_family) {
1100 key[0] = ip->ip.sin_addr.s_addr;
1103 key[0] = ip->ip6.sin6_addr.s6_addr32[3];
1104 key[1] = ip->ip6.sin6_addr.s6_addr32[2];
1105 key[2] = ip->ip6.sin6_addr.s6_addr32[1];
1106 key[3] = ip->ip6.sin6_addr.s6_addr32[0];
1109 DEBUG(DEBUG_ERR, (__location__ " ERROR, unknown family passed :%u\n", ip->sa.sa_family));
1116 static void *add_ip_callback(void *parm, void *data)
1122 control_get_all_public_ips(struct ctdb_context *ctdb, TALLOC_CTX *tmp_ctx, struct ctdb_all_public_ips **ips)
1124 struct ctdb_all_public_ips *tmp_ips;
1125 struct ctdb_node_map *nodemap=NULL;
1126 trbt_tree_t *ip_tree;
1130 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1132 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1136 ip_tree = trbt_create(tmp_ctx, 0);
1138 for(i=0;i<nodemap->num;i++){
1139 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
1142 if (nodemap->nodes[i].flags & NODE_FLAGS_DISCONNECTED) {
1146 /* read the public ip list from this node */
1147 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &tmp_ips);
1149 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", nodemap->nodes[i].pnn));
1153 for (j=0; j<tmp_ips->num;j++) {
1154 struct ctdb_public_ip *node_ip;
1156 node_ip = talloc(tmp_ctx, struct ctdb_public_ip);
1157 node_ip->pnn = tmp_ips->ips[j].pnn;
1158 node_ip->addr = tmp_ips->ips[j].addr;
1160 trbt_insertarray32_callback(ip_tree,
1161 IP_KEYLEN, ip_key(&tmp_ips->ips[j].addr),
1165 talloc_free(tmp_ips);
1170 trbt_traversearray32(ip_tree, IP_KEYLEN, getips_count_callback, &count);
1172 len = offsetof(struct ctdb_all_public_ips, ips) +
1173 count*sizeof(struct ctdb_public_ip);
1174 tmp_ips = talloc_zero_size(tmp_ctx, len);
1175 trbt_traversearray32(ip_tree, IP_KEYLEN, getips_store_callback, tmp_ips);
1184 * scans all other nodes and returns a pnn for another node that can host this
1188 find_other_host_for_public_ip(struct ctdb_context *ctdb, ctdb_sock_addr *addr)
1190 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1191 struct ctdb_all_public_ips *ips;
1192 struct ctdb_node_map *nodemap=NULL;
1195 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1197 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1198 talloc_free(tmp_ctx);
1202 for(i=0;i<nodemap->num;i++){
1203 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1206 if (nodemap->nodes[i].pnn == options.pnn) {
1210 /* read the public ip list from this node */
1211 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips);
1213 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", nodemap->nodes[i].pnn));
1217 for (j=0;j<ips->num;j++) {
1218 if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1219 talloc_free(tmp_ctx);
1220 return nodemap->nodes[i].pnn;
1226 talloc_free(tmp_ctx);
1231 add a public ip address to a node
1233 static int control_addip(struct ctdb_context *ctdb, int argc, const char **argv)
1239 ctdb_sock_addr addr;
1240 struct ctdb_control_ip_iface *pub;
1241 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1242 struct ctdb_all_public_ips *ips;
1246 talloc_free(tmp_ctx);
1250 if (!parse_ip_mask(argv[0], argv[1], &addr, &mask)) {
1251 DEBUG(DEBUG_ERR, ("Badly formed ip/mask : %s\n", argv[0]));
1252 talloc_free(tmp_ctx);
1256 ret = control_get_all_public_ips(ctdb, tmp_ctx, &ips);
1258 DEBUG(DEBUG_ERR, ("Unable to get public ip list from cluster\n"));
1259 talloc_free(tmp_ctx);
1264 /* check if some other node is already serving this ip, if not,
1267 for (i=0;i<ips->num;i++) {
1268 if (ctdb_same_ip(&addr, &ips->ips[i].addr)) {
1273 len = offsetof(struct ctdb_control_ip_iface, iface) + strlen(argv[1]) + 1;
1274 pub = talloc_size(tmp_ctx, len);
1275 CTDB_NO_MEMORY(ctdb, pub);
1279 pub->len = strlen(argv[1])+1;
1280 memcpy(&pub->iface[0], argv[1], strlen(argv[1])+1);
1282 ret = ctdb_ctrl_add_public_ip(ctdb, TIMELIMIT(), options.pnn, pub);
1284 DEBUG(DEBUG_ERR, ("Unable to add public ip to node %u\n", options.pnn));
1285 talloc_free(tmp_ctx);
1289 if (i == ips->num) {
1290 /* no one has this ip so we claim it */
1293 pnn = ips->ips[i].pnn;
1296 if (move_ip(ctdb, &addr, pnn) != 0) {
1297 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", pnn));
1301 talloc_free(tmp_ctx);
1305 static int control_delip(struct ctdb_context *ctdb, int argc, const char **argv);
1307 static int control_delip_all(struct ctdb_context *ctdb, int argc, const char **argv, ctdb_sock_addr *addr)
1309 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1310 struct ctdb_node_map *nodemap=NULL;
1311 struct ctdb_all_public_ips *ips;
1314 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1316 DEBUG(DEBUG_ERR, ("Unable to get nodemap from current node\n"));
1320 /* remove it from the nodes that are not hosting the ip currently */
1321 for(i=0;i<nodemap->num;i++){
1322 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1325 if (ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips) != 0) {
1326 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %d\n", nodemap->nodes[i].pnn));
1330 for (j=0;j<ips->num;j++) {
1331 if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1339 if (ips->ips[j].pnn == nodemap->nodes[i].pnn) {
1343 options.pnn = nodemap->nodes[i].pnn;
1344 control_delip(ctdb, argc, argv);
1348 /* remove it from every node (also the one hosting it) */
1349 for(i=0;i<nodemap->num;i++){
1350 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1353 if (ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips) != 0) {
1354 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %d\n", nodemap->nodes[i].pnn));
1358 for (j=0;j<ips->num;j++) {
1359 if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1367 options.pnn = nodemap->nodes[i].pnn;
1368 control_delip(ctdb, argc, argv);
1371 talloc_free(tmp_ctx);
1376 delete a public ip address from a node
1378 static int control_delip(struct ctdb_context *ctdb, int argc, const char **argv)
1381 ctdb_sock_addr addr;
1382 struct ctdb_control_ip_iface pub;
1383 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1384 struct ctdb_all_public_ips *ips;
1387 talloc_free(tmp_ctx);
1391 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1392 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1396 if (options.pnn == CTDB_BROADCAST_ALL) {
1397 return control_delip_all(ctdb, argc, argv, &addr);
1404 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &ips);
1406 DEBUG(DEBUG_ERR, ("Unable to get public ip list from cluster\n"));
1407 talloc_free(tmp_ctx);
1411 for (i=0;i<ips->num;i++) {
1412 if (ctdb_same_ip(&addr, &ips->ips[i].addr)) {
1418 DEBUG(DEBUG_ERR, ("This node does not support this public address '%s'\n",
1419 ctdb_addr_to_str(&addr)));
1420 talloc_free(tmp_ctx);
1424 if (ips->ips[i].pnn == options.pnn) {
1425 ret = find_other_host_for_public_ip(ctdb, &addr);
1427 if (move_ip(ctdb, &addr, ret) != 0) {
1428 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", ret));
1434 ret = ctdb_ctrl_del_public_ip(ctdb, TIMELIMIT(), options.pnn, &pub);
1436 DEBUG(DEBUG_ERR, ("Unable to del public ip from node %u\n", options.pnn));
1437 talloc_free(tmp_ctx);
1441 talloc_free(tmp_ctx);
1446 kill a tcp connection
1448 static int kill_tcp(struct ctdb_context *ctdb, int argc, const char **argv)
1451 struct ctdb_control_killtcp killtcp;
1457 if (!parse_ip_port(argv[0], &killtcp.src_addr)) {
1458 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[0]));
1462 if (!parse_ip_port(argv[1], &killtcp.dst_addr)) {
1463 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[1]));
1467 ret = ctdb_ctrl_killtcp(ctdb, TIMELIMIT(), options.pnn, &killtcp);
1469 DEBUG(DEBUG_ERR, ("Unable to killtcp from node %u\n", options.pnn));
1480 static int control_gratious_arp(struct ctdb_context *ctdb, int argc, const char **argv)
1483 ctdb_sock_addr addr;
1489 if (!parse_ip(argv[0], NULL, 0, &addr)) {
1490 DEBUG(DEBUG_ERR, ("Bad IP '%s'\n", argv[0]));
1494 ret = ctdb_ctrl_gratious_arp(ctdb, TIMELIMIT(), options.pnn, &addr, argv[1]);
1496 DEBUG(DEBUG_ERR, ("Unable to send gratious_arp from node %u\n", options.pnn));
1504 register a server id
1506 static int regsrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1509 struct ctdb_server_id server_id;
1515 server_id.pnn = strtoul(argv[0], NULL, 0);
1516 server_id.type = strtoul(argv[1], NULL, 0);
1517 server_id.server_id = strtoul(argv[2], NULL, 0);
1519 ret = ctdb_ctrl_register_server_id(ctdb, TIMELIMIT(), &server_id);
1521 DEBUG(DEBUG_ERR, ("Unable to register server_id from node %u\n", options.pnn));
1528 unregister a server id
1530 static int unregsrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1533 struct ctdb_server_id server_id;
1539 server_id.pnn = strtoul(argv[0], NULL, 0);
1540 server_id.type = strtoul(argv[1], NULL, 0);
1541 server_id.server_id = strtoul(argv[2], NULL, 0);
1543 ret = ctdb_ctrl_unregister_server_id(ctdb, TIMELIMIT(), &server_id);
1545 DEBUG(DEBUG_ERR, ("Unable to unregister server_id from node %u\n", options.pnn));
1552 check if a server id exists
1554 static int chksrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1558 struct ctdb_server_id server_id;
1564 server_id.pnn = strtoul(argv[0], NULL, 0);
1565 server_id.type = strtoul(argv[1], NULL, 0);
1566 server_id.server_id = strtoul(argv[2], NULL, 0);
1568 ret = ctdb_ctrl_check_server_id(ctdb, TIMELIMIT(), options.pnn, &server_id, &status);
1570 DEBUG(DEBUG_ERR, ("Unable to check server_id from node %u\n", options.pnn));
1575 printf("Server id %d:%d:%d EXISTS\n", server_id.pnn, server_id.type, server_id.server_id);
1577 printf("Server id %d:%d:%d does NOT exist\n", server_id.pnn, server_id.type, server_id.server_id);
1583 get a list of all server ids that are registered on a node
1585 static int getsrvids(struct ctdb_context *ctdb, int argc, const char **argv)
1588 struct ctdb_server_id_list *server_ids;
1590 ret = ctdb_ctrl_get_server_id_list(ctdb, ctdb, TIMELIMIT(), options.pnn, &server_ids);
1592 DEBUG(DEBUG_ERR, ("Unable to get server_id list from node %u\n", options.pnn));
1596 for (i=0; i<server_ids->num; i++) {
1597 printf("Server id %d:%d:%d\n",
1598 server_ids->server_ids[i].pnn,
1599 server_ids->server_ids[i].type,
1600 server_ids->server_ids[i].server_id);
1607 send a tcp tickle ack
1609 static int tickle_tcp(struct ctdb_context *ctdb, int argc, const char **argv)
1612 ctdb_sock_addr src, dst;
1618 if (!parse_ip_port(argv[0], &src)) {
1619 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[0]));
1623 if (!parse_ip_port(argv[1], &dst)) {
1624 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[1]));
1628 ret = ctdb_sys_send_tcp(&src, &dst, 0, 0, 0);
1632 DEBUG(DEBUG_ERR, ("Error while sending tickle ack\n"));
1639 display public ip status
1641 static int control_ip(struct ctdb_context *ctdb, int argc, const char **argv)
1644 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1645 struct ctdb_all_public_ips *ips;
1647 if (options.pnn == CTDB_BROADCAST_ALL) {
1648 /* read the list of public ips from all nodes */
1649 ret = control_get_all_public_ips(ctdb, tmp_ctx, &ips);
1651 /* read the public ip list from this node */
1652 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &ips);
1655 DEBUG(DEBUG_ERR, ("Unable to get public ips from node %u\n", options.pnn));
1656 talloc_free(tmp_ctx);
1660 if (options.machinereadable){
1661 printf(":Public IP:Node:\n");
1663 if (options.pnn == CTDB_BROADCAST_ALL) {
1664 printf("Public IPs on ALL nodes\n");
1666 printf("Public IPs on node %u\n", options.pnn);
1670 for (i=1;i<=ips->num;i++) {
1671 if (options.machinereadable){
1672 printf(":%s:%d:\n", ctdb_addr_to_str(&ips->ips[ips->num-i].addr), ips->ips[ips->num-i].pnn);
1674 printf("%s %d\n", ctdb_addr_to_str(&ips->ips[ips->num-i].addr), ips->ips[ips->num-i].pnn);
1678 talloc_free(tmp_ctx);
1685 static int control_ipinfo(struct ctdb_context *ctdb, int argc, const char **argv)
1688 ctdb_sock_addr addr;
1689 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1690 struct ctdb_control_public_ip_info *info;
1693 talloc_free(tmp_ctx);
1697 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1698 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1702 /* read the public ip info from this node */
1703 ret = ctdb_ctrl_get_public_ip_info(ctdb, TIMELIMIT(), options.pnn,
1704 tmp_ctx, &addr, &info);
1706 DEBUG(DEBUG_ERR, ("Unable to get public ip[%s]info from node %u\n",
1707 argv[0], options.pnn));
1708 talloc_free(tmp_ctx);
1712 printf("Public IP[%s] info on node %u\n",
1713 ctdb_addr_to_str(&info->ip.addr),
1716 printf("IP:%s\nCurrentNode:%d\nNumInterfaces:%u\n",
1717 ctdb_addr_to_str(&info->ip.addr),
1718 info->ip.pnn, info->num);
1720 for (i=0; i<info->num; i++) {
1721 info->ifaces[i].name[CTDB_IFACE_SIZE] = '\0';
1723 printf("Interface[%u]: Name:%s Link:%s References:%u%s\n",
1724 i+1, info->ifaces[i].name,
1725 info->ifaces[i].link_state?"up":"down",
1726 (unsigned int)info->ifaces[i].references,
1727 (i==info->active_idx)?" (active)":"");
1730 talloc_free(tmp_ctx);
1735 display interfaces status
1737 static int control_ifaces(struct ctdb_context *ctdb, int argc, const char **argv)
1740 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1741 struct ctdb_control_get_ifaces *ifaces;
1743 /* read the public ip list from this node */
1744 ret = ctdb_ctrl_get_ifaces(ctdb, TIMELIMIT(), options.pnn,
1747 DEBUG(DEBUG_ERR, ("Unable to get interfaces from node %u\n",
1749 talloc_free(tmp_ctx);
1753 if (options.machinereadable){
1754 printf(":Name:LinkStatus:References:\n");
1756 printf("Interfaces on node %u\n", options.pnn);
1759 for (i=0; i<ifaces->num; i++) {
1760 if (options.machinereadable){
1761 printf(":%s:%s:%u\n",
1762 ifaces->ifaces[i].name,
1763 ifaces->ifaces[i].link_state?"1":"0",
1764 (unsigned int)ifaces->ifaces[i].references);
1766 printf("name:%s link:%s references:%u\n",
1767 ifaces->ifaces[i].name,
1768 ifaces->ifaces[i].link_state?"up":"down",
1769 (unsigned int)ifaces->ifaces[i].references);
1773 talloc_free(tmp_ctx);
1779 set link status of an interface
1781 static int control_setifacelink(struct ctdb_context *ctdb, int argc, const char **argv)
1784 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1785 struct ctdb_control_iface_info info;
1793 if (strlen(argv[0]) > CTDB_IFACE_SIZE) {
1794 DEBUG(DEBUG_ERR, ("interfaces name '%s' too long\n",
1796 talloc_free(tmp_ctx);
1799 strcpy(info.name, argv[0]);
1801 if (strcmp(argv[1], "up") == 0) {
1802 info.link_state = 1;
1803 } else if (strcmp(argv[1], "down") == 0) {
1804 info.link_state = 0;
1806 DEBUG(DEBUG_ERR, ("link state invalid '%s' should be 'up' or 'down'\n",
1808 talloc_free(tmp_ctx);
1812 /* read the public ip list from this node */
1813 ret = ctdb_ctrl_set_iface_link(ctdb, TIMELIMIT(), options.pnn,
1816 DEBUG(DEBUG_ERR, ("Unable to set link state for interfaces %s node %u\n",
1817 argv[0], options.pnn));
1818 talloc_free(tmp_ctx);
1822 talloc_free(tmp_ctx);
1827 display pid of a ctdb daemon
1829 static int control_getpid(struct ctdb_context *ctdb, int argc, const char **argv)
1834 ret = ctdb_ctrl_getpid(ctdb, TIMELIMIT(), options.pnn, &pid);
1836 DEBUG(DEBUG_ERR, ("Unable to get daemon pid from node %u\n", options.pnn));
1839 printf("Pid:%d\n", pid);
1845 handler for receiving the response to ipreallocate
1847 static void ip_reallocate_handler(struct ctdb_context *ctdb, uint64_t srvid,
1848 TDB_DATA data, void *private_data)
1853 static void ctdb_every_second(struct event_context *ev, struct timed_event *te, struct timeval t, void *p)
1855 struct ctdb_context *ctdb = talloc_get_type(p, struct ctdb_context);
1857 event_add_timed(ctdb->ev, ctdb,
1858 timeval_current_ofs(1, 0),
1859 ctdb_every_second, ctdb);
1863 ask the recovery daemon on the recovery master to perform a ip reallocation
1865 static int control_ipreallocate(struct ctdb_context *ctdb, int argc, const char **argv)
1869 struct takeover_run_reply rd;
1871 struct ctdb_node_map *nodemap=NULL;
1873 struct timeval tv = timeval_current();
1875 /* we need some events to trigger so we can timeout and restart
1878 event_add_timed(ctdb->ev, ctdb,
1879 timeval_current_ofs(1, 0),
1880 ctdb_every_second, ctdb);
1882 rd.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
1884 DEBUG(DEBUG_ERR, ("Failed to get pnn of local node\n"));
1887 rd.srvid = getpid();
1889 /* register a message port for receiveing the reply so that we
1890 can receive the reply
1892 ctdb_set_message_handler(ctdb, rd.srvid, ip_reallocate_handler, NULL);
1894 data.dptr = (uint8_t *)&rd;
1895 data.dsize = sizeof(rd);
1899 DEBUG(DEBUG_ERR,("Failed waiting for cluster convergense\n"));
1903 /* check that there are valid nodes available */
1904 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap) != 0) {
1905 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
1908 for (i=0; i<nodemap->num;i++) {
1909 if ((nodemap->nodes[i].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) == 0) {
1913 if (i==nodemap->num) {
1914 DEBUG(DEBUG_ERR,("No recmaster available, no need to wait for cluster convergence\n"));
1919 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
1921 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
1925 /* verify the node exists */
1926 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), recmaster, ctdb, &nodemap) != 0) {
1927 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
1932 /* check tha there are nodes available that can act as a recmaster */
1933 for (i=0; i<nodemap->num; i++) {
1934 if (nodemap->nodes[i].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
1939 if (i == nodemap->num) {
1940 DEBUG(DEBUG_ERR,("No possible nodes to host addresses.\n"));
1944 /* verify the recovery master is not STOPPED, nor BANNED */
1945 if (nodemap->nodes[recmaster].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
1946 DEBUG(DEBUG_ERR,("No suitable recmaster found. Try again\n"));
1953 /* verify the recovery master is not STOPPED, nor BANNED */
1954 if (nodemap->nodes[recmaster].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
1955 DEBUG(DEBUG_ERR,("No suitable recmaster found. Try again\n"));
1961 ret = ctdb_send_message(ctdb, recmaster, CTDB_SRVID_TAKEOVER_RUN, data);
1963 DEBUG(DEBUG_ERR,("Failed to send ip takeover run request message to %u\n", options.pnn));
1967 tv = timeval_current();
1968 /* this loop will terminate when we have received the reply */
1969 while (timeval_elapsed(&tv) < 3.0) {
1970 event_loop_once(ctdb->ev);
1973 DEBUG(DEBUG_INFO,("Timed out waiting for recmaster ipreallocate. Trying again\n"));
1983 disable a remote node
1985 static int control_disable(struct ctdb_context *ctdb, int argc, const char **argv)
1988 struct ctdb_node_map *nodemap=NULL;
1991 ret = ctdb_ctrl_modflags(ctdb, TIMELIMIT(), options.pnn, NODE_FLAGS_PERMANENTLY_DISABLED, 0);
1993 DEBUG(DEBUG_ERR, ("Unable to disable node %u\n", options.pnn));
1999 /* read the nodemap and verify the change took effect */
2000 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2001 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2005 } while (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED));
2006 ret = control_ipreallocate(ctdb, argc, argv);
2008 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2016 enable a disabled remote node
2018 static int control_enable(struct ctdb_context *ctdb, int argc, const char **argv)
2022 struct ctdb_node_map *nodemap=NULL;
2025 ret = ctdb_ctrl_modflags(ctdb, TIMELIMIT(), options.pnn, 0, NODE_FLAGS_PERMANENTLY_DISABLED);
2027 DEBUG(DEBUG_ERR, ("Unable to enable node %u\n", options.pnn));
2033 /* read the nodemap and verify the change took effect */
2034 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2035 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2039 } while (nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED);
2040 ret = control_ipreallocate(ctdb, argc, argv);
2042 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2052 static int control_stop(struct ctdb_context *ctdb, int argc, const char **argv)
2055 struct ctdb_node_map *nodemap=NULL;
2058 ret = ctdb_ctrl_stop_node(ctdb, TIMELIMIT(), options.pnn);
2060 DEBUG(DEBUG_ERR, ("Unable to stop node %u try again\n", options.pnn));
2065 /* read the nodemap and verify the change took effect */
2066 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2067 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2071 } while (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_STOPPED));
2072 ret = control_ipreallocate(ctdb, argc, argv);
2074 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2082 restart a stopped remote node
2084 static int control_continue(struct ctdb_context *ctdb, int argc, const char **argv)
2088 struct ctdb_node_map *nodemap=NULL;
2091 ret = ctdb_ctrl_continue_node(ctdb, TIMELIMIT(), options.pnn);
2093 DEBUG(DEBUG_ERR, ("Unable to continue node %u\n", options.pnn));
2099 /* read the nodemap and verify the change took effect */
2100 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2101 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2105 } while (nodemap->nodes[options.pnn].flags & NODE_FLAGS_STOPPED);
2106 ret = control_ipreallocate(ctdb, argc, argv);
2108 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2115 static uint32_t get_generation(struct ctdb_context *ctdb)
2117 struct ctdb_vnn_map *vnnmap=NULL;
2120 /* wait until the recmaster is not in recovery mode */
2122 uint32_t recmode, recmaster;
2124 if (vnnmap != NULL) {
2125 talloc_free(vnnmap);
2129 /* get the recmaster */
2130 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, &recmaster);
2132 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
2136 /* get recovery mode */
2137 ret = ctdb_ctrl_getrecmode(ctdb, ctdb, TIMELIMIT(), recmaster, &recmode);
2139 DEBUG(DEBUG_ERR, ("Unable to get recmode from node %u\n", options.pnn));
2143 /* get the current generation number */
2144 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), recmaster, ctdb, &vnnmap);
2146 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from recmaster (%u)\n", recmaster));
2150 if ((recmode == CTDB_RECOVERY_NORMAL)
2151 && (vnnmap->generation != 1)){
2152 return vnnmap->generation;
2159 ban a node from the cluster
2161 static int control_ban(struct ctdb_context *ctdb, int argc, const char **argv)
2164 struct ctdb_node_map *nodemap=NULL;
2165 struct ctdb_ban_time bantime;
2171 /* verify the node exists */
2172 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
2174 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2178 if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_BANNED) {
2179 DEBUG(DEBUG_ERR,("Node %u is already banned.\n", options.pnn));
2183 bantime.pnn = options.pnn;
2184 bantime.time = strtoul(argv[0], NULL, 0);
2186 ret = ctdb_ctrl_set_ban(ctdb, TIMELIMIT(), options.pnn, &bantime);
2188 DEBUG(DEBUG_ERR,("Banning node %d for %d seconds failed.\n", bantime.pnn, bantime.time));
2192 ret = control_ipreallocate(ctdb, argc, argv);
2194 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2203 unban a node from the cluster
2205 static int control_unban(struct ctdb_context *ctdb, int argc, const char **argv)
2208 struct ctdb_node_map *nodemap=NULL;
2209 struct ctdb_ban_time bantime;
2211 /* verify the node exists */
2212 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
2214 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2218 if (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_BANNED)) {
2219 DEBUG(DEBUG_ERR,("Node %u is not banned.\n", options.pnn));
2223 bantime.pnn = options.pnn;
2226 ret = ctdb_ctrl_set_ban(ctdb, TIMELIMIT(), options.pnn, &bantime);
2228 DEBUG(DEBUG_ERR,("Unbanning node %d failed.\n", bantime.pnn));
2232 ret = control_ipreallocate(ctdb, argc, argv);
2234 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2243 show ban information for a node
2245 static int control_showban(struct ctdb_context *ctdb, int argc, const char **argv)
2248 struct ctdb_node_map *nodemap=NULL;
2249 struct ctdb_ban_time *bantime;
2251 /* verify the node exists */
2252 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
2254 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2258 ret = ctdb_ctrl_get_ban(ctdb, TIMELIMIT(), options.pnn, ctdb, &bantime);
2260 DEBUG(DEBUG_ERR,("Showing ban info for node %d failed.\n", options.pnn));
2264 if (bantime->time == 0) {
2265 printf("Node %u is not banned\n", bantime->pnn);
2267 printf("Node %u is banned banned for %d seconds\n", bantime->pnn, bantime->time);
2276 static int control_shutdown(struct ctdb_context *ctdb, int argc, const char **argv)
2280 ret = ctdb_ctrl_shutdown(ctdb, TIMELIMIT(), options.pnn);
2282 DEBUG(DEBUG_ERR, ("Unable to shutdown node %u\n", options.pnn));
2292 static int control_recover(struct ctdb_context *ctdb, int argc, const char **argv)
2295 uint32_t generation, next_generation;
2297 /* record the current generation number */
2298 generation = get_generation(ctdb);
2300 ret = ctdb_ctrl_freeze_priority(ctdb, TIMELIMIT(), options.pnn, 1);
2302 DEBUG(DEBUG_ERR, ("Unable to freeze node\n"));
2306 ret = ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
2308 DEBUG(DEBUG_ERR, ("Unable to set recovery mode\n"));
2312 /* wait until we are in a new generation */
2314 next_generation = get_generation(ctdb);
2315 if (next_generation != generation) {
2326 display monitoring mode of a remote node
2328 static int control_getmonmode(struct ctdb_context *ctdb, int argc, const char **argv)
2333 ret = ctdb_ctrl_getmonmode(ctdb, TIMELIMIT(), options.pnn, &monmode);
2335 DEBUG(DEBUG_ERR, ("Unable to get monmode from node %u\n", options.pnn));
2338 if (!options.machinereadable){
2339 printf("Monitoring mode:%s (%d)\n",monmode==CTDB_MONITORING_ACTIVE?"ACTIVE":"DISABLED",monmode);
2342 printf(":%d:\n",monmode);
2349 display capabilities of a remote node
2351 static int control_getcapabilities(struct ctdb_context *ctdb, int argc, const char **argv)
2353 uint32_t capabilities;
2356 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), options.pnn, &capabilities);
2358 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", options.pnn));
2362 if (!options.machinereadable){
2363 printf("RECMASTER: %s\n", (capabilities&CTDB_CAP_RECMASTER)?"YES":"NO");
2364 printf("LMASTER: %s\n", (capabilities&CTDB_CAP_LMASTER)?"YES":"NO");
2365 printf("LVS: %s\n", (capabilities&CTDB_CAP_LVS)?"YES":"NO");
2366 printf("NATGW: %s\n", (capabilities&CTDB_CAP_NATGW)?"YES":"NO");
2368 printf(":RECMASTER:LMASTER:LVS:NATGW:\n");
2369 printf(":%d:%d:%d:%d:\n",
2370 !!(capabilities&CTDB_CAP_RECMASTER),
2371 !!(capabilities&CTDB_CAP_LMASTER),
2372 !!(capabilities&CTDB_CAP_LVS),
2373 !!(capabilities&CTDB_CAP_NATGW));
2379 display lvs configuration
2381 static int control_lvs(struct ctdb_context *ctdb, int argc, const char **argv)
2383 uint32_t *capabilities;
2384 struct ctdb_node_map *nodemap=NULL;
2386 int healthy_count = 0;
2388 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
2390 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
2394 capabilities = talloc_array(ctdb, uint32_t, nodemap->num);
2395 CTDB_NO_MEMORY(ctdb, capabilities);
2397 /* collect capabilities for all connected nodes */
2398 for (i=0; i<nodemap->num; i++) {
2399 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2402 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2406 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), i, &capabilities[i]);
2408 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", i));
2412 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2416 if (!(nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY)) {
2421 /* Print all LVS nodes */
2422 for (i=0; i<nodemap->num; i++) {
2423 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2426 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2429 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2433 if (healthy_count != 0) {
2434 if (nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY) {
2439 printf("%d:%s\n", i,
2440 ctdb_addr_to_str(&nodemap->nodes[i].addr));
2447 display who is the lvs master
2449 static int control_lvsmaster(struct ctdb_context *ctdb, int argc, const char **argv)
2451 uint32_t *capabilities;
2452 struct ctdb_node_map *nodemap=NULL;
2454 int healthy_count = 0;
2456 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
2458 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
2462 capabilities = talloc_array(ctdb, uint32_t, nodemap->num);
2463 CTDB_NO_MEMORY(ctdb, capabilities);
2465 /* collect capabilities for all connected nodes */
2466 for (i=0; i<nodemap->num; i++) {
2467 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2470 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2474 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), i, &capabilities[i]);
2476 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", i));
2480 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2484 if (!(nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY)) {
2489 /* find and show the lvsmaster */
2490 for (i=0; i<nodemap->num; i++) {
2491 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2494 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2497 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2501 if (healthy_count != 0) {
2502 if (nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY) {
2507 if (options.machinereadable){
2510 printf("Node %d is LVS master\n", i);
2515 printf("There is no LVS master\n");
2520 disable monitoring on a node
2522 static int control_disable_monmode(struct ctdb_context *ctdb, int argc, const char **argv)
2527 ret = ctdb_ctrl_disable_monmode(ctdb, TIMELIMIT(), options.pnn);
2529 DEBUG(DEBUG_ERR, ("Unable to disable monmode on node %u\n", options.pnn));
2532 printf("Monitoring mode:%s\n","DISABLED");
2538 enable monitoring on a node
2540 static int control_enable_monmode(struct ctdb_context *ctdb, int argc, const char **argv)
2545 ret = ctdb_ctrl_enable_monmode(ctdb, TIMELIMIT(), options.pnn);
2547 DEBUG(DEBUG_ERR, ("Unable to enable monmode on node %u\n", options.pnn));
2550 printf("Monitoring mode:%s\n","ACTIVE");
2556 display remote list of keys/data for a db
2558 static int control_catdb(struct ctdb_context *ctdb, int argc, const char **argv)
2560 const char *db_name;
2561 struct ctdb_db_context *ctdb_db;
2571 if (db_exists(ctdb, db_name)) {
2572 DEBUG(DEBUG_ERR,("Database '%s' does not exist\n", db_name));
2576 ctdb_db = ctdb_attach(ctdb, db_name, false, 0);
2578 if (ctdb_db == NULL) {
2579 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
2583 /* traverse and dump the cluster tdb */
2584 ret = ctdb_dump_db(ctdb_db, stdout);
2586 DEBUG(DEBUG_ERR, ("Unable to dump database\n"));
2587 DEBUG(DEBUG_ERR, ("Maybe try 'ctdb getdbstatus %s'"
2588 " and 'ctdb getvar AllowUnhealthyDBRead'\n",
2592 talloc_free(ctdb_db);
2594 printf("Dumped %d records\n", ret);
2599 static void log_handler(struct ctdb_context *ctdb, uint64_t srvid,
2600 TDB_DATA data, void *private_data)
2602 DEBUG(DEBUG_ERR,("Log data received\n"));
2603 if (data.dsize > 0) {
2604 printf("%s", data.dptr);
2611 display a list of log messages from the in memory ringbuffer
2613 static int control_getlog(struct ctdb_context *ctdb, int argc, const char **argv)
2617 struct ctdb_get_log_addr log_addr;
2619 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2624 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
2625 talloc_free(tmp_ctx);
2629 log_addr.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
2630 log_addr.srvid = getpid();
2631 if (isalpha(argv[0][0]) || argv[0][0] == '-') {
2632 log_addr.level = get_debug_by_desc(argv[0]);
2634 log_addr.level = strtol(argv[0], NULL, 0);
2638 data.dptr = (unsigned char *)&log_addr;
2639 data.dsize = sizeof(log_addr);
2641 DEBUG(DEBUG_ERR, ("Pulling logs from node %u\n", options.pnn));
2643 ctdb_set_message_handler(ctdb, log_addr.srvid, log_handler, NULL);
2646 DEBUG(DEBUG_ERR,("Listen for response on %d\n", (int)log_addr.srvid));
2648 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_GET_LOG,
2649 0, data, tmp_ctx, NULL, &res, NULL, &errmsg);
2650 if (ret != 0 || res != 0) {
2651 DEBUG(DEBUG_ERR,("Failed to get logs - %s\n", errmsg));
2652 talloc_free(tmp_ctx);
2657 tv = timeval_current();
2658 /* this loop will terminate when we have received the reply */
2659 while (timeval_elapsed(&tv) < 3.0) {
2660 event_loop_once(ctdb->ev);
2663 DEBUG(DEBUG_INFO,("Timed out waiting for log data.\n"));
2665 talloc_free(tmp_ctx);
2670 clear the in memory log area
2672 static int control_clearlog(struct ctdb_context *ctdb, int argc, const char **argv)
2677 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2679 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_CLEAR_LOG,
2680 0, tdb_null, tmp_ctx, NULL, &res, NULL, &errmsg);
2681 if (ret != 0 || res != 0) {
2682 DEBUG(DEBUG_ERR,("Failed to clear logs\n"));
2683 talloc_free(tmp_ctx);
2687 talloc_free(tmp_ctx);
2694 display a list of the databases on a remote ctdb
2696 static int control_getdbmap(struct ctdb_context *ctdb, int argc, const char **argv)
2699 struct ctdb_dbid_map *dbmap=NULL;
2701 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
2703 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
2707 if(options.machinereadable){
2708 printf(":ID:Name:Path:Persistent:Unhealthy:\n");
2709 for(i=0;i<dbmap->num;i++){
2715 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn,
2716 dbmap->dbs[i].dbid, ctdb, &path);
2717 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn,
2718 dbmap->dbs[i].dbid, ctdb, &name);
2719 ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn,
2720 dbmap->dbs[i].dbid, ctdb, &health);
2721 persistent = dbmap->dbs[i].persistent;
2722 printf(":0x%08X:%s:%s:%d:%d:\n",
2723 dbmap->dbs[i].dbid, name, path,
2724 !!(persistent), !!(health));
2729 printf("Number of databases:%d\n", dbmap->num);
2730 for(i=0;i<dbmap->num;i++){
2736 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &path);
2737 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
2738 ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &health);
2739 persistent = dbmap->dbs[i].persistent;
2740 printf("dbid:0x%08x name:%s path:%s%s%s\n",
2741 dbmap->dbs[i].dbid, name, path,
2742 persistent?" PERSISTENT":"",
2743 health?" UNHEALTHY":"");
2750 display the status of a database on a remote ctdb
2752 static int control_getdbstatus(struct ctdb_context *ctdb, int argc, const char **argv)
2755 struct ctdb_dbid_map *dbmap=NULL;
2756 const char *db_name;
2764 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
2766 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
2770 for(i=0;i<dbmap->num;i++){
2776 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
2777 if (strcmp(name, db_name) != 0) {
2781 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &path);
2782 ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &health);
2783 persistent = dbmap->dbs[i].persistent;
2784 printf("dbid: 0x%08x\nname: %s\npath: %s\nPERSISTENT: %s\nHEALTH: %s\n",
2785 dbmap->dbs[i].dbid, name, path,
2786 persistent?"yes":"no",
2787 health?health:"OK");
2791 DEBUG(DEBUG_ERR, ("db %s doesn't exist on node %u\n", db_name, options.pnn));
2796 check if the local node is recmaster or not
2797 it will return 1 if this node is the recmaster and 0 if it is not
2798 or if the local ctdb daemon could not be contacted
2800 static int control_isnotrecmaster(struct ctdb_context *ctdb, int argc, const char **argv)
2802 uint32_t mypnn, recmaster;
2805 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
2807 printf("Failed to get pnn of node\n");
2811 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
2813 printf("Failed to get the recmaster\n");
2817 if (recmaster != mypnn) {
2818 printf("this node is not the recmaster\n");
2822 printf("this node is the recmaster\n");
2829 static int control_ping(struct ctdb_context *ctdb, int argc, const char **argv)
2832 struct timeval tv = timeval_current();
2833 ret = ctdb_ctrl_ping(ctdb, options.pnn);
2835 printf("Unable to get ping response from node %u\n", options.pnn);
2838 printf("response from %u time=%.6f sec (%d clients)\n",
2839 options.pnn, timeval_elapsed(&tv), ret);
2848 static int control_getvar(struct ctdb_context *ctdb, int argc, const char **argv)
2859 ret = ctdb_ctrl_get_tunable(ctdb, TIMELIMIT(), options.pnn, name, &value);
2861 DEBUG(DEBUG_ERR, ("Unable to get tunable variable '%s'\n", name));
2865 printf("%-19s = %u\n", name, value);
2872 static int control_setvar(struct ctdb_context *ctdb, int argc, const char **argv)
2883 value = strtoul(argv[1], NULL, 0);
2885 ret = ctdb_ctrl_set_tunable(ctdb, TIMELIMIT(), options.pnn, name, value);
2887 DEBUG(DEBUG_ERR, ("Unable to set tunable variable '%s'\n", name));
2896 static int control_listvars(struct ctdb_context *ctdb, int argc, const char **argv)
2902 ret = ctdb_ctrl_list_tunables(ctdb, TIMELIMIT(), options.pnn, ctdb, &list, &count);
2904 DEBUG(DEBUG_ERR, ("Unable to list tunable variables\n"));
2908 for (i=0;i<count;i++) {
2909 control_getvar(ctdb, 1, &list[i]);
2918 display debug level on a node
2920 static int control_getdebug(struct ctdb_context *ctdb, int argc, const char **argv)
2925 ret = ctdb_ctrl_get_debuglevel(ctdb, options.pnn, &level);
2927 DEBUG(DEBUG_ERR, ("Unable to get debuglevel response from node %u\n", options.pnn));
2930 if (options.machinereadable){
2931 printf(":Name:Level:\n");
2932 printf(":%s:%d:\n",get_debug_by_level(level),level);
2934 printf("Node %u is at debug level %s (%d)\n", options.pnn, get_debug_by_level(level), level);
2941 display reclock file of a node
2943 static int control_getreclock(struct ctdb_context *ctdb, int argc, const char **argv)
2946 const char *reclock;
2948 ret = ctdb_ctrl_getreclock(ctdb, TIMELIMIT(), options.pnn, ctdb, &reclock);
2950 DEBUG(DEBUG_ERR, ("Unable to get reclock file from node %u\n", options.pnn));
2953 if (options.machinereadable){
2954 if (reclock != NULL) {
2955 printf("%s", reclock);
2958 if (reclock == NULL) {
2959 printf("No reclock file used.\n");
2961 printf("Reclock file:%s\n", reclock);
2969 set the reclock file of a node
2971 static int control_setreclock(struct ctdb_context *ctdb, int argc, const char **argv)
2974 const char *reclock;
2978 } else if (argc == 1) {
2984 ret = ctdb_ctrl_setreclock(ctdb, TIMELIMIT(), options.pnn, reclock);
2986 DEBUG(DEBUG_ERR, ("Unable to get reclock file from node %u\n", options.pnn));
2993 set the natgw state on/off
2995 static int control_setnatgwstate(struct ctdb_context *ctdb, int argc, const char **argv)
2998 uint32_t natgwstate;
3004 if (!strcmp(argv[0], "on")) {
3006 } else if (!strcmp(argv[0], "off")) {
3012 ret = ctdb_ctrl_setnatgwstate(ctdb, TIMELIMIT(), options.pnn, natgwstate);
3014 DEBUG(DEBUG_ERR, ("Unable to set the natgw state for node %u\n", options.pnn));
3022 set the lmaster role on/off
3024 static int control_setlmasterrole(struct ctdb_context *ctdb, int argc, const char **argv)
3027 uint32_t lmasterrole;
3033 if (!strcmp(argv[0], "on")) {
3035 } else if (!strcmp(argv[0], "off")) {
3041 ret = ctdb_ctrl_setlmasterrole(ctdb, TIMELIMIT(), options.pnn, lmasterrole);
3043 DEBUG(DEBUG_ERR, ("Unable to set the lmaster role for node %u\n", options.pnn));
3051 set the recmaster role on/off
3053 static int control_setrecmasterrole(struct ctdb_context *ctdb, int argc, const char **argv)
3056 uint32_t recmasterrole;
3062 if (!strcmp(argv[0], "on")) {
3064 } else if (!strcmp(argv[0], "off")) {
3070 ret = ctdb_ctrl_setrecmasterrole(ctdb, TIMELIMIT(), options.pnn, recmasterrole);
3072 DEBUG(DEBUG_ERR, ("Unable to set the recmaster role for node %u\n", options.pnn));
3080 set debug level on a node or all nodes
3082 static int control_setdebug(struct ctdb_context *ctdb, int argc, const char **argv)
3088 printf("You must specify the debug level. Valid levels are:\n");
3089 for (i=0; debug_levels[i].description != NULL; i++) {
3090 printf("%s (%d)\n", debug_levels[i].description, debug_levels[i].level);
3096 if (isalpha(argv[0][0]) || argv[0][0] == '-') {
3097 level = get_debug_by_desc(argv[0]);
3099 level = strtol(argv[0], NULL, 0);
3102 for (i=0; debug_levels[i].description != NULL; i++) {
3103 if (level == debug_levels[i].level) {
3107 if (debug_levels[i].description == NULL) {
3108 printf("Invalid debug level, must be one of\n");
3109 for (i=0; debug_levels[i].description != NULL; i++) {
3110 printf("%s (%d)\n", debug_levels[i].description, debug_levels[i].level);
3115 ret = ctdb_ctrl_set_debuglevel(ctdb, options.pnn, level);
3117 DEBUG(DEBUG_ERR, ("Unable to set debug level on node %u\n", options.pnn));
3126 static int control_freeze(struct ctdb_context *ctdb, int argc, const char **argv)
3132 priority = strtol(argv[0], NULL, 0);
3136 DEBUG(DEBUG_ERR,("Freeze by priority %u\n", priority));
3138 ret = ctdb_ctrl_freeze_priority(ctdb, TIMELIMIT(), options.pnn, priority);
3140 DEBUG(DEBUG_ERR, ("Unable to freeze node %u\n", options.pnn));
3148 static int control_thaw(struct ctdb_context *ctdb, int argc, const char **argv)
3154 priority = strtol(argv[0], NULL, 0);
3158 DEBUG(DEBUG_ERR,("Thaw by priority %u\n", priority));
3160 ret = ctdb_ctrl_thaw_priority(ctdb, TIMELIMIT(), options.pnn, priority);
3162 DEBUG(DEBUG_ERR, ("Unable to thaw node %u\n", options.pnn));
3169 attach to a database
3171 static int control_attach(struct ctdb_context *ctdb, int argc, const char **argv)
3173 const char *db_name;
3174 struct ctdb_db_context *ctdb_db;
3181 ctdb_db = ctdb_attach(ctdb, db_name, false, 0);
3182 if (ctdb_db == NULL) {
3183 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
3193 static int control_setdbprio(struct ctdb_context *ctdb, int argc, const char **argv)
3195 struct ctdb_db_priority db_prio;
3202 db_prio.db_id = strtoul(argv[0], NULL, 0);
3203 db_prio.priority = strtoul(argv[1], NULL, 0);
3205 ret = ctdb_ctrl_set_db_priority(ctdb, TIMELIMIT(), options.pnn, &db_prio);
3207 DEBUG(DEBUG_ERR,("Unable to set db prio\n"));
3217 static int control_getdbprio(struct ctdb_context *ctdb, int argc, const char **argv)
3219 uint32_t db_id, priority;
3226 db_id = strtoul(argv[0], NULL, 0);
3228 ret = ctdb_ctrl_get_db_priority(ctdb, TIMELIMIT(), options.pnn, db_id, &priority);
3230 DEBUG(DEBUG_ERR,("Unable to get db prio\n"));
3234 DEBUG(DEBUG_ERR,("Priority:%u\n", priority));
3240 run an eventscript on a node
3242 static int control_eventscript(struct ctdb_context *ctdb, int argc, const char **argv)
3248 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3251 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3255 data.dptr = (unsigned char *)discard_const(argv[0]);
3256 data.dsize = strlen((char *)data.dptr) + 1;
3258 DEBUG(DEBUG_ERR, ("Running eventscripts with arguments \"%s\" on node %u\n", data.dptr, options.pnn));
3260 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_RUN_EVENTSCRIPTS,
3261 0, data, tmp_ctx, NULL, &res, NULL, &errmsg);
3262 if (ret != 0 || res != 0) {
3263 DEBUG(DEBUG_ERR,("Failed to run eventscripts - %s\n", errmsg));
3264 talloc_free(tmp_ctx);
3267 talloc_free(tmp_ctx);
3271 #define DB_VERSION 1
3272 #define MAX_DB_NAME 64
3273 struct db_file_header {
3274 unsigned long version;
3276 unsigned long persistent;
3278 const char name[MAX_DB_NAME];
3281 struct backup_data {
3282 struct ctdb_marshall_buffer *records;
3285 bool traverse_error;
3288 static int backup_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *private)
3290 struct backup_data *bd = talloc_get_type(private, struct backup_data);
3291 struct ctdb_rec_data *rec;
3293 /* add the record */
3294 rec = ctdb_marshall_record(bd->records, 0, key, NULL, data);
3296 bd->traverse_error = true;
3297 DEBUG(DEBUG_ERR,("Failed to marshall record\n"));
3300 bd->records = talloc_realloc_size(NULL, bd->records, rec->length + bd->len);
3301 if (bd->records == NULL) {
3302 DEBUG(DEBUG_ERR,("Failed to expand marshalling buffer\n"));
3303 bd->traverse_error = true;
3306 bd->records->count++;
3307 memcpy(bd->len+(uint8_t *)bd->records, rec, rec->length);
3308 bd->len += rec->length;
3316 * backup a database to a file
3318 static int control_backupdb(struct ctdb_context *ctdb, int argc, const char **argv)
3321 struct ctdb_dbid_map *dbmap=NULL;
3322 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3323 struct db_file_header dbhdr;
3324 struct ctdb_db_context *ctdb_db;
3325 struct backup_data *bd;
3328 const char *reason = NULL;
3331 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3335 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &dbmap);
3337 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
3341 for(i=0;i<dbmap->num;i++){
3344 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, tmp_ctx, &name);
3345 if(!strcmp(argv[0], name)){
3346 talloc_free(discard_const(name));
3349 talloc_free(discard_const(name));
3351 if (i == dbmap->num) {
3352 DEBUG(DEBUG_ERR,("No database with name '%s' found\n", argv[0]));
3353 talloc_free(tmp_ctx);
3357 ret = ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn,
3358 dbmap->dbs[i].dbid, tmp_ctx, &reason);
3360 DEBUG(DEBUG_ERR,("Unable to get dbhealth for database '%s'\n",
3362 talloc_free(tmp_ctx);
3366 uint32_t allow_unhealthy = 0;
3368 ctdb_ctrl_get_tunable(ctdb, TIMELIMIT(), options.pnn,
3369 "AllowUnhealthyDBRead",
3372 if (allow_unhealthy != 1) {
3373 DEBUG(DEBUG_ERR,("database '%s' is unhealthy: %s\n",
3376 DEBUG(DEBUG_ERR,("disallow backup : tunnable AllowUnhealthyDBRead = %u\n",
3378 talloc_free(tmp_ctx);
3382 DEBUG(DEBUG_WARNING,("WARNING database '%s' is unhealthy - see 'ctdb getdbstatus %s'\n",
3384 DEBUG(DEBUG_WARNING,("WARNING! allow backup of unhealthy database: "
3385 "tunnable AllowUnhealthyDBRead = %u\n",
3389 ctdb_db = ctdb_attach(ctdb, argv[0], dbmap->dbs[i].persistent, 0);
3390 if (ctdb_db == NULL) {
3391 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", argv[0]));
3392 talloc_free(tmp_ctx);
3397 ret = tdb_transaction_start(ctdb_db->ltdb->tdb);
3399 DEBUG(DEBUG_ERR,("Failed to start transaction\n"));
3400 talloc_free(tmp_ctx);
3405 bd = talloc_zero(tmp_ctx, struct backup_data);
3407 DEBUG(DEBUG_ERR,("Failed to allocate backup_data\n"));
3408 talloc_free(tmp_ctx);
3412 bd->records = talloc_zero(bd, struct ctdb_marshall_buffer);
3413 if (bd->records == NULL) {
3414 DEBUG(DEBUG_ERR,("Failed to allocate ctdb_marshall_buffer\n"));
3415 talloc_free(tmp_ctx);
3419 bd->len = offsetof(struct ctdb_marshall_buffer, data);
3420 bd->records->db_id = ctdb_db->db_id;
3421 /* traverse the database collecting all records */
3422 if (tdb_traverse_read(ctdb_db->ltdb->tdb, backup_traverse, bd) == -1 ||
3423 bd->traverse_error) {
3424 DEBUG(DEBUG_ERR,("Traverse error\n"));
3425 talloc_free(tmp_ctx);
3429 tdb_transaction_cancel(ctdb_db->ltdb->tdb);
3432 fh = open(argv[1], O_RDWR|O_CREAT, 0600);
3434 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[1]));
3435 talloc_free(tmp_ctx);
3439 dbhdr.version = DB_VERSION;
3440 dbhdr.timestamp = time(NULL);
3441 dbhdr.persistent = dbmap->dbs[i].persistent;
3442 dbhdr.size = bd->len;
3443 if (strlen(argv[0]) >= MAX_DB_NAME) {
3444 DEBUG(DEBUG_ERR,("Too long dbname\n"));
3447 strncpy(discard_const(dbhdr.name), argv[0], MAX_DB_NAME);
3448 ret = write(fh, &dbhdr, sizeof(dbhdr));
3450 DEBUG(DEBUG_ERR,("write failed: %s\n", strerror(errno)));
3453 ret = write(fh, bd->records, bd->len);
3455 DEBUG(DEBUG_ERR,("write failed: %s\n", strerror(errno)));
3464 DEBUG(DEBUG_ERR,("close failed: %s\n", strerror(errno)));
3467 talloc_free(tmp_ctx);
3472 * restore a database from a file
3474 static int control_restoredb(struct ctdb_context *ctdb, int argc, const char **argv)
3477 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3480 struct db_file_header dbhdr;
3481 struct ctdb_db_context *ctdb_db;
3482 struct ctdb_node_map *nodemap=NULL;
3483 struct ctdb_vnn_map *vnnmap=NULL;
3485 struct ctdb_control_wipe_database w;
3487 uint32_t generation;
3492 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3496 fh = open(argv[0], O_RDONLY);
3498 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[0]));
3499 talloc_free(tmp_ctx);
3503 read(fh, &dbhdr, sizeof(dbhdr));
3504 if (dbhdr.version != DB_VERSION) {
3505 DEBUG(DEBUG_ERR,("Invalid version of database dump. File is version %lu but expected version was %u\n", dbhdr.version, DB_VERSION));
3506 talloc_free(tmp_ctx);
3510 outdata.dsize = dbhdr.size;
3511 outdata.dptr = talloc_size(tmp_ctx, outdata.dsize);
3512 if (outdata.dptr == NULL) {
3513 DEBUG(DEBUG_ERR,("Failed to allocate data of size '%lu'\n", dbhdr.size));
3515 talloc_free(tmp_ctx);
3518 read(fh, outdata.dptr, outdata.dsize);
3521 tm = localtime(&dbhdr.timestamp);
3522 strftime(tbuf,sizeof(tbuf)-1,"%Y/%m/%d %H:%M:%S", tm);
3523 printf("Restoring database '%s' from backup @ %s\n",
3527 ctdb_db = ctdb_attach(ctdb, dbhdr.name, dbhdr.persistent, 0);
3528 if (ctdb_db == NULL) {
3529 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", dbhdr.name));
3530 talloc_free(tmp_ctx);
3534 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
3536 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
3537 talloc_free(tmp_ctx);
3542 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &vnnmap);
3544 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n", options.pnn));
3545 talloc_free(tmp_ctx);
3549 /* freeze all nodes */
3550 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3551 for (i=1; i<=NUM_DB_PRIORITIES; i++) {
3552 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_FREEZE,
3558 DEBUG(DEBUG_ERR, ("Unable to freeze nodes.\n"));
3559 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3560 talloc_free(tmp_ctx);
3565 generation = vnnmap->generation;
3566 data.dptr = (void *)&generation;
3567 data.dsize = sizeof(generation);
3569 /* start a cluster wide transaction */
3570 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3571 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_START,
3573 TIMELIMIT(), false, data,
3576 DEBUG(DEBUG_ERR, ("Unable to start cluster wide transactions.\n"));
3581 w.db_id = ctdb_db->db_id;
3582 w.transaction_id = generation;
3584 data.dptr = (void *)&w;
3585 data.dsize = sizeof(w);
3587 /* wipe all the remote databases. */
3588 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3589 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_WIPE_DATABASE,
3591 TIMELIMIT(), false, data,
3594 DEBUG(DEBUG_ERR, ("Unable to wipe database.\n"));
3595 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3596 talloc_free(tmp_ctx);
3600 /* push the database */
3601 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3602 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_PUSH_DB,
3604 TIMELIMIT(), false, outdata,
3607 DEBUG(DEBUG_ERR, ("Failed to push database.\n"));
3608 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3609 talloc_free(tmp_ctx);
3613 data.dptr = (void *)&ctdb_db->db_id;
3614 data.dsize = sizeof(ctdb_db->db_id);
3616 /* mark the database as healthy */
3617 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3618 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_DB_SET_HEALTHY,
3620 TIMELIMIT(), false, data,
3623 DEBUG(DEBUG_ERR, ("Failed to mark database as healthy.\n"));
3624 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3625 talloc_free(tmp_ctx);
3629 data.dptr = (void *)&generation;
3630 data.dsize = sizeof(generation);
3632 /* commit all the changes */
3633 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_COMMIT,
3635 TIMELIMIT(), false, data,
3638 DEBUG(DEBUG_ERR, ("Unable to commit databases.\n"));
3639 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3640 talloc_free(tmp_ctx);
3645 /* thaw all nodes */
3646 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3647 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_THAW,
3653 DEBUG(DEBUG_ERR, ("Unable to thaw nodes.\n"));
3654 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3655 talloc_free(tmp_ctx);
3660 talloc_free(tmp_ctx);
3665 * dump a database backup from a file
3667 static int control_dumpdbbackup(struct ctdb_context *ctdb, int argc, const char **argv)
3669 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3671 struct db_file_header dbhdr;
3675 struct ctdb_rec_data *rec = NULL;
3676 struct ctdb_marshall_buffer *m;
3679 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3683 fh = open(argv[0], O_RDONLY);
3685 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[0]));
3686 talloc_free(tmp_ctx);
3690 read(fh, &dbhdr, sizeof(dbhdr));
3691 if (dbhdr.version != DB_VERSION) {
3692 DEBUG(DEBUG_ERR,("Invalid version of database dump. File is version %lu but expected version was %u\n", dbhdr.version, DB_VERSION));
3693 talloc_free(tmp_ctx);
3697 outdata.dsize = dbhdr.size;
3698 outdata.dptr = talloc_size(tmp_ctx, outdata.dsize);
3699 if (outdata.dptr == NULL) {
3700 DEBUG(DEBUG_ERR,("Failed to allocate data of size '%lu'\n", dbhdr.size));
3702 talloc_free(tmp_ctx);
3705 read(fh, outdata.dptr, outdata.dsize);
3707 m = (struct ctdb_marshall_buffer *)outdata.dptr;
3709 tm = localtime(&dbhdr.timestamp);
3710 strftime(tbuf,sizeof(tbuf)-1,"%Y/%m/%d %H:%M:%S", tm);
3711 printf("Backup of database name:'%s' dbid:0x%x08x from @ %s\n",
3712 dbhdr.name, m->db_id, tbuf);
3714 for (i=0; i < m->count; i++) {
3718 /* we do not want the header splitted, so we pass NULL*/
3719 rec = ctdb_marshall_loop_next(m, rec, &reqid,
3722 ctdb_dumpdb_record(ctdb, key, data, stdout);
3725 printf("Dumped %d records\n", i);
3726 talloc_free(tmp_ctx);
3731 * wipe a database from a file
3733 static int control_wipedb(struct ctdb_context *ctdb, int argc,
3737 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3739 struct ctdb_db_context *ctdb_db;
3740 struct ctdb_node_map *nodemap = NULL;
3741 struct ctdb_vnn_map *vnnmap = NULL;
3743 struct ctdb_control_wipe_database w;
3745 uint32_t generation;
3746 struct ctdb_dbid_map *dbmap = NULL;
3749 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3753 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx,
3756 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n",
3761 for(i=0;i<dbmap->num;i++){
3764 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn,
3765 dbmap->dbs[i].dbid, tmp_ctx, &name);
3766 if(!strcmp(argv[0], name)){
3767 talloc_free(discard_const(name));
3770 talloc_free(discard_const(name));
3772 if (i == dbmap->num) {
3773 DEBUG(DEBUG_ERR, ("No database with name '%s' found\n",
3775 talloc_free(tmp_ctx);
3779 ctdb_db = ctdb_attach(ctdb, argv[0], dbmap->dbs[i].persistent, 0);
3780 if (ctdb_db == NULL) {
3781 DEBUG(DEBUG_ERR, ("Unable to attach to database '%s'\n",
3783 talloc_free(tmp_ctx);
3787 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb,
3790 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n",
3792 talloc_free(tmp_ctx);
3796 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx,
3799 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n",
3801 talloc_free(tmp_ctx);
3805 /* freeze all nodes */
3806 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3807 for (i=1; i<=NUM_DB_PRIORITIES; i++) {
3808 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_FREEZE,
3815 DEBUG(DEBUG_ERR, ("Unable to freeze nodes.\n"));
3816 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn,
3817 CTDB_RECOVERY_ACTIVE);
3818 talloc_free(tmp_ctx);
3823 generation = vnnmap->generation;
3824 data.dptr = (void *)&generation;
3825 data.dsize = sizeof(generation);
3827 /* start a cluster wide transaction */
3828 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3829 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_START,
3831 TIMELIMIT(), false, data,
3835 DEBUG(DEBUG_ERR, ("Unable to start cluster wide "
3836 "transactions.\n"));
3840 w.db_id = ctdb_db->db_id;
3841 w.transaction_id = generation;
3843 data.dptr = (void *)&w;
3844 data.dsize = sizeof(w);
3846 /* wipe all the remote databases. */
3847 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3848 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_WIPE_DATABASE,
3850 TIMELIMIT(), false, data,
3853 DEBUG(DEBUG_ERR, ("Unable to wipe database.\n"));
3854 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3855 talloc_free(tmp_ctx);
3859 data.dptr = (void *)&ctdb_db->db_id;
3860 data.dsize = sizeof(ctdb_db->db_id);
3862 /* mark the database as healthy */
3863 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3864 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_DB_SET_HEALTHY,
3866 TIMELIMIT(), false, data,
3869 DEBUG(DEBUG_ERR, ("Failed to mark database as healthy.\n"));
3870 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3871 talloc_free(tmp_ctx);
3875 data.dptr = (void *)&generation;
3876 data.dsize = sizeof(generation);
3878 /* commit all the changes */
3879 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_COMMIT,
3881 TIMELIMIT(), false, data,
3884 DEBUG(DEBUG_ERR, ("Unable to commit databases.\n"));
3885 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3886 talloc_free(tmp_ctx);
3890 /* thaw all nodes */
3891 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3892 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_THAW,
3898 DEBUG(DEBUG_ERR, ("Unable to thaw nodes.\n"));
3899 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3900 talloc_free(tmp_ctx);
3904 talloc_free(tmp_ctx);
3909 * set flags of a node in the nodemap
3911 static int control_setflags(struct ctdb_context *ctdb, int argc, const char **argv)
3918 struct ctdb_node_flag_change c;
3925 if (sscanf(argv[0], "%d", &node) != 1) {
3926 DEBUG(DEBUG_ERR, ("Badly formed node\n"));
3930 if (sscanf(argv[1], "0x%x", &flags) != 1) {
3931 DEBUG(DEBUG_ERR, ("Badly formed flags\n"));
3938 c.new_flags = flags;
3940 data.dsize = sizeof(c);
3941 data.dptr = (unsigned char *)&c;
3943 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_MODIFY_FLAGS, 0,
3944 data, NULL, NULL, &status, NULL, NULL);
3945 if (ret != 0 || status != 0) {
3946 DEBUG(DEBUG_ERR,("Failed to modify flags\n"));
3955 static int control_dumpmemory(struct ctdb_context *ctdb, int argc, const char **argv)
3961 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3962 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_DUMP_MEMORY,
3963 0, tdb_null, tmp_ctx, &data, &res, NULL, &errmsg);
3964 if (ret != 0 || res != 0) {
3965 DEBUG(DEBUG_ERR,("Failed to dump memory - %s\n", errmsg));
3966 talloc_free(tmp_ctx);
3969 write(1, data.dptr, data.dsize);
3970 talloc_free(tmp_ctx);
3975 handler for memory dumps
3977 static void mem_dump_handler(struct ctdb_context *ctdb, uint64_t srvid,
3978 TDB_DATA data, void *private_data)
3980 write(1, data.dptr, data.dsize);
3985 dump memory usage on the recovery daemon
3987 static int control_rddumpmemory(struct ctdb_context *ctdb, int argc, const char **argv)
3991 struct rd_memdump_reply rd;
3993 rd.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
3995 DEBUG(DEBUG_ERR, ("Failed to get pnn of local node\n"));
3998 rd.srvid = getpid();
4000 /* register a message port for receiveing the reply so that we
4001 can receive the reply
4003 ctdb_set_message_handler(ctdb, rd.srvid, mem_dump_handler, NULL);
4006 data.dptr = (uint8_t *)&rd;
4007 data.dsize = sizeof(rd);
4009 ret = ctdb_send_message(ctdb, options.pnn, CTDB_SRVID_MEM_DUMP, data);
4011 DEBUG(DEBUG_ERR,("Failed to send memdump request message to %u\n", options.pnn));
4015 /* this loop will terminate when we have received the reply */
4017 event_loop_once(ctdb->ev);
4024 list all nodes in the cluster
4025 if the daemon is running, we read the data from the daemon.
4026 if the daemon is not running we parse the nodes file directly
4028 static int control_listnodes(struct ctdb_context *ctdb, int argc, const char **argv)
4031 struct ctdb_node_map *nodemap=NULL;
4034 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
4036 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
4040 for(i=0;i<nodemap->num;i++){
4041 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
4044 if (options.machinereadable){
4045 printf(":%d:%s:\n", nodemap->nodes[i].pnn, ctdb_addr_to_str(&nodemap->nodes[i].addr));
4047 printf("%s\n", ctdb_addr_to_str(&nodemap->nodes[i].addr));
4051 TALLOC_CTX *mem_ctx = talloc_new(NULL);
4052 struct pnn_node *pnn_nodes;
4053 struct pnn_node *pnn_node;
4055 pnn_nodes = read_nodes_file(mem_ctx);
4056 if (pnn_nodes == NULL) {
4057 DEBUG(DEBUG_ERR,("Failed to read nodes file\n"));
4058 talloc_free(mem_ctx);
4062 for(pnn_node=pnn_nodes;pnn_node;pnn_node=pnn_node->next) {
4063 ctdb_sock_addr addr;
4065 if (parse_ip(pnn_node->addr, NULL, 63999, &addr) == 0) {
4066 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s' in nodes file\n", pnn_node->addr));
4067 talloc_free(mem_ctx);
4071 if (options.machinereadable){
4072 printf(":%d:%s:\n", pnn_node->pnn, pnn_node->addr);
4074 printf("%s\n", pnn_node->addr);
4077 talloc_free(mem_ctx);
4084 reload the nodes file on the local node
4086 static int control_reload_nodes_file(struct ctdb_context *ctdb, int argc, const char **argv)
4090 struct ctdb_node_map *nodemap=NULL;
4092 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
4094 DEBUG(DEBUG_ERR, ("Failed to read pnn of local node\n"));
4098 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
4100 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
4104 /* reload the nodes file on all remote nodes */
4105 for (i=0;i<nodemap->num;i++) {
4106 if (nodemap->nodes[i].pnn == mypnn) {
4109 DEBUG(DEBUG_NOTICE, ("Reloading nodes file on node %u\n", nodemap->nodes[i].pnn));
4110 ret = ctdb_ctrl_reload_nodes_file(ctdb, TIMELIMIT(),
4111 nodemap->nodes[i].pnn);
4113 DEBUG(DEBUG_ERR, ("ERROR: Failed to reload nodes file on node %u. You MUST fix that node manually!\n", nodemap->nodes[i].pnn));
4117 /* reload the nodes file on the local node */
4118 DEBUG(DEBUG_NOTICE, ("Reloading nodes file on node %u\n", mypnn));
4119 ret = ctdb_ctrl_reload_nodes_file(ctdb, TIMELIMIT(), mypnn);
4121 DEBUG(DEBUG_ERR, ("ERROR: Failed to reload nodes file on node %u. You MUST fix that node manually!\n", mypnn));
4124 /* initiate a recovery */
4125 control_recover(ctdb, argc, argv);
4131 static const struct {
4133 int (*fn)(struct ctdb_context *, int, const char **);
4135 bool without_daemon; /* can be run without daemon running ? */
4138 } ctdb_commands[] = {
4140 { "version", control_version, true, false, "show version of ctdb" },
4142 { "status", control_status, true, false, "show node status" },
4143 { "uptime", control_uptime, true, false, "show node uptime" },
4144 { "ping", control_ping, true, false, "ping all nodes" },
4145 { "getvar", control_getvar, true, false, "get a tunable variable", "<name>"},
4146 { "setvar", control_setvar, true, false, "set a tunable variable", "<name> <value>"},
4147 { "listvars", control_listvars, true, false, "list tunable variables"},
4148 { "statistics", control_statistics, false, false, "show statistics" },
4149 { "statisticsreset", control_statistics_reset, true, false, "reset statistics"},
4150 { "ip", control_ip, false, false, "show which public ip's that ctdb manages" },
4151 { "ipinfo", control_ipinfo, true, false, "show details about a public ip that ctdb manages", "<ip>" },
4152 { "ifaces", control_ifaces, true, false, "show which interfaces that ctdb manages" },
4153 { "setifacelink", control_setifacelink, true, false, "set interface link status", "<iface> <status>" },
4154 { "process-exists", control_process_exists, true, false, "check if a process exists on a node", "<pid>"},
4155 { "getdbmap", control_getdbmap, true, false, "show the database map" },
4156 { "getdbstatus", control_getdbstatus, true, false, "show the status of a database", "<dbname>" },
4157 { "catdb", control_catdb, true, false, "dump a database" , "<dbname>"},
4158 { "getmonmode", control_getmonmode, true, false, "show monitoring mode" },
4159 { "getcapabilities", control_getcapabilities, true, false, "show node capabilities" },
4160 { "pnn", control_pnn, true, false, "show the pnn of the currnet node" },
4161 { "lvs", control_lvs, true, false, "show lvs configuration" },
4162 { "lvsmaster", control_lvsmaster, true, false, "show which node is the lvs master" },
4163 { "disablemonitor", control_disable_monmode,true, false, "set monitoring mode to DISABLE" },
4164 { "enablemonitor", control_enable_monmode, true, false, "set monitoring mode to ACTIVE" },
4165 { "setdebug", control_setdebug, true, false, "set debug level", "<EMERG|ALERT|CRIT|ERR|WARNING|NOTICE|INFO|DEBUG>" },
4166 { "getdebug", control_getdebug, true, false, "get debug level" },
4167 { "getlog", control_getlog, true, false, "get the log data from the in memory ringbuffer", "<level>" },
4168 { "clearlog", control_clearlog, true, false, "clear the log data from the in memory ringbuffer" },
4169 { "attach", control_attach, true, false, "attach to a database", "<dbname>" },
4170 { "dumpmemory", control_dumpmemory, true, false, "dump memory map to stdout" },
4171 { "rddumpmemory", control_rddumpmemory, true, false, "dump memory map from the recovery daemon to stdout" },
4172 { "getpid", control_getpid, true, false, "get ctdbd process ID" },
4173 { "disable", control_disable, true, false, "disable a nodes public IP" },
4174 { "enable", control_enable, true, false, "enable a nodes public IP" },
4175 { "stop", control_stop, true, false, "stop a node" },
4176 { "continue", control_continue, true, false, "re-start a stopped node" },
4177 { "ban", control_ban, true, false, "ban a node from the cluster", "<bantime|0>"},
4178 { "unban", control_unban, true, false, "unban a node" },
4179 { "showban", control_showban, true, false, "show ban information"},
4180 { "shutdown", control_shutdown, true, false, "shutdown ctdbd" },
4181 { "recover", control_recover, true, false, "force recovery" },
4182 { "ipreallocate", control_ipreallocate, true, false, "force the recovery daemon to perform a ip reallocation procedure" },
4183 { "freeze", control_freeze, true, false, "freeze databases", "[priority:1-3]" },
4184 { "thaw", control_thaw, true, false, "thaw databases", "[priority:1-3]" },
4185 { "isnotrecmaster", control_isnotrecmaster, false, false, "check if the local node is recmaster or not" },
4186 { "killtcp", kill_tcp, false, false, "kill a tcp connection.", "<srcip:port> <dstip:port>" },
4187 { "gratiousarp", control_gratious_arp, false, false, "send a gratious arp", "<ip> <interface>" },
4188 { "tickle", tickle_tcp, false, false, "send a tcp tickle ack", "<srcip:port> <dstip:port>" },
4189 { "gettickles", control_get_tickles, false, false, "get the list of tickles registered for this ip", "<ip>" },
4191 { "regsrvid", regsrvid, false, false, "register a server id", "<pnn> <type> <id>" },
4192 { "unregsrvid", unregsrvid, false, false, "unregister a server id", "<pnn> <type> <id>" },
4193 { "chksrvid", chksrvid, false, false, "check if a server id exists", "<pnn> <type> <id>" },
4194 { "getsrvids", getsrvids, false, false, "get a list of all server ids"},
4195 { "vacuum", ctdb_vacuum, false, false, "vacuum the databases of empty records", "[max_records]"},
4196 { "repack", ctdb_repack, false, false, "repack all databases", "[max_freelist]"},
4197 { "listnodes", control_listnodes, false, true, "list all nodes in the cluster"},
4198 { "reloadnodes", control_reload_nodes_file, false, false, "reload the nodes file and restart the transport on all nodes"},
4199 { "moveip", control_moveip, false, false, "move/failover an ip address to another node", "<ip> <node>"},
4200 { "addip", control_addip, true, false, "add a ip address to a node", "<ip/mask> <iface>"},
4201 { "delip", control_delip, false, false, "delete an ip address from a node", "<ip>"},
4202 { "eventscript", control_eventscript, true, false, "run the eventscript with the given parameters on a node", "<arguments>"},
4203 { "backupdb", control_backupdb, false, false, "backup the database into a file.", "<database> <file>"},
4204 { "restoredb", control_restoredb, false, false, "restore the database from a file.", "<file>"},
4205 { "dumpdbbackup", control_dumpdbbackup, false, true, "dump database backup from a file.", "<file>"},
4206 { "wipedb", control_wipedb, false, false, "wipe the contents of a database.", "<dbname>"},
4207 { "recmaster", control_recmaster, false, false, "show the pnn for the recovery master."},
4208 { "setflags", control_setflags, false, false, "set flags for a node in the nodemap.", "<node> <flags>"},
4209 { "scriptstatus", control_scriptstatus, false, false, "show the status of the monitoring scripts (or all scripts)", "[all]"},
4210 { "enablescript", control_enablescript, false, false, "enable an eventscript", "<script>"},
4211 { "disablescript", control_disablescript, false, false, "disable an eventscript", "<script>"},
4212 { "natgwlist", control_natgwlist, false, false, "show the nodes belonging to this natgw configuration"},
4213 { "xpnn", control_xpnn, true, true, "find the pnn of the local node without talking to the daemon (unreliable)" },
4214 { "getreclock", control_getreclock, false, false, "Show the reclock file of a node"},
4215 { "setreclock", control_setreclock, false, false, "Set/clear the reclock file of a node", "[filename]"},
4216 { "setnatgwstate", control_setnatgwstate, false, false, "Set NATGW state to on/off", "{on|off}"},
4217 { "setlmasterrole", control_setlmasterrole, false, false, "Set LMASTER role to on/off", "{on|off}"},
4218 { "setrecmasterrole", control_setrecmasterrole, false, false, "Set RECMASTER role to on/off", "{on|off}"},
4219 { "setdbprio", control_setdbprio, false, false, "Set DB priority", "<dbid> <prio:1-3>"},
4220 { "getdbprio", control_getdbprio, false, false, "Get DB priority", "<dbid>"},
4226 static void usage(void)
4230 "Usage: ctdb [options] <control>\n" \
4232 " -n <node> choose node number, or 'all' (defaults to local node)\n"
4233 " -Y generate machinereadable output\n"
4234 " -t <timelimit> set timelimit for control in seconds (default %u)\n", options.timelimit);
4235 printf("Controls:\n");
4236 for (i=0;i<ARRAY_SIZE(ctdb_commands);i++) {
4237 printf(" %-15s %-27s %s\n",
4238 ctdb_commands[i].name,
4239 ctdb_commands[i].args?ctdb_commands[i].args:"",
4240 ctdb_commands[i].msg);
4246 static void ctdb_alarm(int sig)
4248 printf("Maximum runtime exceeded - exiting\n");
4255 int main(int argc, const char *argv[])
4257 struct ctdb_context *ctdb;
4258 char *nodestring = NULL;
4259 struct poptOption popt_options[] = {
4262 { "timelimit", 't', POPT_ARG_INT, &options.timelimit, 0, "timelimit", "integer" },
4263 { "node", 'n', POPT_ARG_STRING, &nodestring, 0, "node", "integer|all" },
4264 { "machinereadable", 'Y', POPT_ARG_NONE, &options.machinereadable, 0, "enable machinereadable output", NULL },
4265 { "maxruntime", 'T', POPT_ARG_INT, &options.maxruntime, 0, "die if runtime exceeds this limit (in seconds)", "integer" },
4269 const char **extra_argv;
4273 struct event_context *ev;
4274 const char *control;
4278 /* set some defaults */
4279 options.maxruntime = 0;
4280 options.timelimit = 3;
4281 options.pnn = CTDB_CURRENT_NODE;
4283 pc = poptGetContext(argv[0], argc, argv, popt_options, POPT_CONTEXT_KEEP_FIRST);
4285 while ((opt = poptGetNextOpt(pc)) != -1) {
4288 DEBUG(DEBUG_ERR, ("Invalid option %s: %s\n",
4289 poptBadOption(pc, 0), poptStrerror(opt)));
4294 /* setup the remaining options for the main program to use */
4295 extra_argv = poptGetArgs(pc);
4298 while (extra_argv[extra_argc]) extra_argc++;
4301 if (extra_argc < 1) {
4305 if (options.maxruntime == 0) {
4306 const char *ctdb_timeout;
4307 ctdb_timeout = getenv("CTDB_TIMEOUT");
4308 if (ctdb_timeout != NULL) {
4309 options.maxruntime = strtoul(ctdb_timeout, NULL, 0);
4311 /* default timeout is 120 seconds */
4312 options.maxruntime = 120;
4316 signal(SIGALRM, ctdb_alarm);
4317 alarm(options.maxruntime);
4319 /* setup the node number to contact */
4320 if (nodestring != NULL) {
4321 if (strcmp(nodestring, "all") == 0) {
4322 options.pnn = CTDB_BROADCAST_ALL;
4324 options.pnn = strtoul(nodestring, NULL, 0);
4328 control = extra_argv[0];
4330 ev = event_context_init(NULL);
4332 for (i=0;i<ARRAY_SIZE(ctdb_commands);i++) {
4333 if (strcmp(control, ctdb_commands[i].name) == 0) {
4336 if (ctdb_commands[i].without_daemon == true) {
4340 /* initialise ctdb */
4341 ctdb = ctdb_cmdline_client(ev);
4343 if (ctdb_commands[i].without_daemon == false) {
4345 DEBUG(DEBUG_ERR, ("Failed to init ctdb\n"));
4349 /* verify the node exists */
4352 if (options.pnn == CTDB_CURRENT_NODE) {
4354 pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
4362 if (ctdb_commands[i].auto_all &&
4363 options.pnn == CTDB_BROADCAST_ALL) {
4368 nodes = ctdb_get_connected_nodes(ctdb, TIMELIMIT(), ctdb, &num_nodes);
4369 CTDB_NO_MEMORY(ctdb, nodes);
4371 for (j=0;j<num_nodes;j++) {
4372 options.pnn = nodes[j];
4373 ret |= ctdb_commands[i].fn(ctdb, extra_argc-1, extra_argv+1);
4377 ret = ctdb_commands[i].fn(ctdb, extra_argc-1, extra_argv+1);
4383 if (i == ARRAY_SIZE(ctdb_commands)) {
4384 DEBUG(DEBUG_ERR, ("Unknown control '%s'\n", control));