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)
48 #define LONGTIMELIMIT() timeval_current_ofs(options.timelimit*10, 0)
51 static int control_version(struct ctdb_context *ctdb, int argc, const char **argv)
54 #define XSTR(x) STR(x)
55 printf("CTDB version: %s\n", XSTR(CTDB_VERS));
62 verify that a node exists and is reachable
64 static void verify_node(struct ctdb_context *ctdb)
67 struct ctdb_node_map *nodemap=NULL;
69 if (options.pnn == CTDB_CURRENT_NODE) {
72 if (options.pnn == CTDB_BROADCAST_ALL) {
76 /* verify the node exists */
77 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
78 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
81 if (options.pnn >= nodemap->num) {
82 DEBUG(DEBUG_ERR, ("Node %u does not exist\n", options.pnn));
85 if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_DELETED) {
86 DEBUG(DEBUG_ERR, ("Node %u is DELETED\n", options.pnn));
89 if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_DISCONNECTED) {
90 DEBUG(DEBUG_ERR, ("Node %u is DISCONNECTED\n", options.pnn));
94 /* verify we can access the node */
95 ret = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
97 DEBUG(DEBUG_ERR,("Can not ban node. Node is not operational.\n"));
103 check if a database exists
105 static int db_exists(struct ctdb_context *ctdb, const char *db_name)
108 struct ctdb_dbid_map *dbmap=NULL;
110 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
112 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
116 for(i=0;i<dbmap->num;i++){
119 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
120 if (!strcmp(name, db_name)) {
129 see if a process exists
131 static int control_process_exists(struct ctdb_context *ctdb, int argc, const char **argv)
139 if (sscanf(argv[0], "%u:%u", &pnn, &pid) != 2) {
140 DEBUG(DEBUG_ERR, ("Badly formed pnn:pid\n"));
144 ret = ctdb_ctrl_process_exists(ctdb, pnn, pid);
146 printf("%u:%u exists\n", pnn, pid);
148 printf("%u:%u does not exist\n", pnn, pid);
154 display statistics structure
156 static void show_statistics(struct ctdb_statistics *s)
158 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
160 const char *prefix=NULL;
166 #define STATISTICS_FIELD(n) { #n, offsetof(struct ctdb_statistics, n) }
167 STATISTICS_FIELD(num_clients),
168 STATISTICS_FIELD(frozen),
169 STATISTICS_FIELD(recovering),
170 STATISTICS_FIELD(num_recoveries),
171 STATISTICS_FIELD(client_packets_sent),
172 STATISTICS_FIELD(client_packets_recv),
173 STATISTICS_FIELD(node_packets_sent),
174 STATISTICS_FIELD(node_packets_recv),
175 STATISTICS_FIELD(keepalive_packets_sent),
176 STATISTICS_FIELD(keepalive_packets_recv),
177 STATISTICS_FIELD(node.req_call),
178 STATISTICS_FIELD(node.reply_call),
179 STATISTICS_FIELD(node.req_dmaster),
180 STATISTICS_FIELD(node.reply_dmaster),
181 STATISTICS_FIELD(node.reply_error),
182 STATISTICS_FIELD(node.req_message),
183 STATISTICS_FIELD(node.req_control),
184 STATISTICS_FIELD(node.reply_control),
185 STATISTICS_FIELD(client.req_call),
186 STATISTICS_FIELD(client.req_message),
187 STATISTICS_FIELD(client.req_control),
188 STATISTICS_FIELD(timeouts.call),
189 STATISTICS_FIELD(timeouts.control),
190 STATISTICS_FIELD(timeouts.traverse),
191 STATISTICS_FIELD(total_calls),
192 STATISTICS_FIELD(pending_calls),
193 STATISTICS_FIELD(lockwait_calls),
194 STATISTICS_FIELD(pending_lockwait_calls),
195 STATISTICS_FIELD(childwrite_calls),
196 STATISTICS_FIELD(pending_childwrite_calls),
197 STATISTICS_FIELD(memory_used),
198 STATISTICS_FIELD(max_hop_count),
200 printf("CTDB version %u\n", CTDB_VERSION);
201 for (i=0;i<ARRAY_SIZE(fields);i++) {
202 if (strchr(fields[i].name, '.')) {
203 preflen = strcspn(fields[i].name, ".")+1;
204 if (!prefix || strncmp(prefix, fields[i].name, preflen) != 0) {
205 prefix = fields[i].name;
206 printf(" %*.*s\n", preflen-1, preflen-1, fields[i].name);
211 printf(" %*s%-22s%*s%10u\n",
213 fields[i].name+preflen,
215 *(uint32_t *)(fields[i].offset+(uint8_t *)s));
217 printf(" %-30s %.6f sec\n", "max_reclock_ctdbd", s->reclock.ctdbd);
218 printf(" %-30s %.6f sec\n", "max_reclock_recd", s->reclock.recd);
220 printf(" %-30s %.6f sec\n", "max_call_latency", s->max_call_latency);
221 printf(" %-30s %.6f sec\n", "max_lockwait_latency", s->max_lockwait_latency);
222 printf(" %-30s %.6f sec\n", "max_childwrite_latency", s->max_childwrite_latency);
223 talloc_free(tmp_ctx);
227 display remote ctdb statistics combined from all nodes
229 static int control_statistics_all(struct ctdb_context *ctdb)
232 struct ctdb_statistics statistics;
236 nodes = ctdb_get_connected_nodes(ctdb, TIMELIMIT(), ctdb, &num_nodes);
237 CTDB_NO_MEMORY(ctdb, nodes);
239 ZERO_STRUCT(statistics);
241 for (i=0;i<num_nodes;i++) {
242 struct ctdb_statistics s1;
244 uint32_t *v1 = (uint32_t *)&s1;
245 uint32_t *v2 = (uint32_t *)&statistics;
247 offsetof(struct ctdb_statistics, __last_counter) / sizeof(uint32_t);
248 ret = ctdb_ctrl_statistics(ctdb, nodes[i], &s1);
250 DEBUG(DEBUG_ERR, ("Unable to get statistics from node %u\n", nodes[i]));
253 for (j=0;j<num_ints;j++) {
256 statistics.max_hop_count =
257 MAX(statistics.max_hop_count, s1.max_hop_count);
258 statistics.max_call_latency =
259 MAX(statistics.max_call_latency, s1.max_call_latency);
260 statistics.max_lockwait_latency =
261 MAX(statistics.max_lockwait_latency, s1.max_lockwait_latency);
264 printf("Gathered statistics for %u nodes\n", num_nodes);
265 show_statistics(&statistics);
270 display remote ctdb statistics
272 static int control_statistics(struct ctdb_context *ctdb, int argc, const char **argv)
275 struct ctdb_statistics statistics;
277 if (options.pnn == CTDB_BROADCAST_ALL) {
278 return control_statistics_all(ctdb);
281 ret = ctdb_ctrl_statistics(ctdb, options.pnn, &statistics);
283 DEBUG(DEBUG_ERR, ("Unable to get statistics from node %u\n", options.pnn));
286 show_statistics(&statistics);
292 reset remote ctdb statistics
294 static int control_statistics_reset(struct ctdb_context *ctdb, int argc, const char **argv)
298 ret = ctdb_statistics_reset(ctdb, options.pnn);
300 DEBUG(DEBUG_ERR, ("Unable to reset statistics on node %u\n", options.pnn));
308 display uptime of remote node
310 static int control_uptime(struct ctdb_context *ctdb, int argc, const char **argv)
313 struct ctdb_uptime *uptime = NULL;
314 int tmp, days, hours, minutes, seconds;
316 ret = ctdb_ctrl_uptime(ctdb, ctdb, TIMELIMIT(), options.pnn, &uptime);
318 DEBUG(DEBUG_ERR, ("Unable to get uptime from node %u\n", options.pnn));
322 if (options.machinereadable){
323 printf(":Current Node Time:Ctdb Start Time:Last Recovery/Failover Time:Last Recovery/IPFailover Duration:\n");
324 printf(":%u:%u:%u:%lf\n",
325 (unsigned int)uptime->current_time.tv_sec,
326 (unsigned int)uptime->ctdbd_start_time.tv_sec,
327 (unsigned int)uptime->last_recovery_finished.tv_sec,
328 timeval_delta(&uptime->last_recovery_finished,
329 &uptime->last_recovery_started)
334 printf("Current time of node : %s", ctime(&uptime->current_time.tv_sec));
336 tmp = uptime->current_time.tv_sec - uptime->ctdbd_start_time.tv_sec;
344 printf("Ctdbd start time : (%03d %02d:%02d:%02d) %s", days, hours, minutes, seconds, ctime(&uptime->ctdbd_start_time.tv_sec));
346 tmp = uptime->current_time.tv_sec - uptime->last_recovery_finished.tv_sec;
354 printf("Time of last recovery/failover: (%03d %02d:%02d:%02d) %s", days, hours, minutes, seconds, ctime(&uptime->last_recovery_finished.tv_sec));
356 printf("Duration of last recovery/failover: %lf seconds\n",
357 timeval_delta(&uptime->last_recovery_finished,
358 &uptime->last_recovery_started));
364 show the PNN of the current node
366 static int control_pnn(struct ctdb_context *ctdb, int argc, const char **argv)
370 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
372 DEBUG(DEBUG_ERR, ("Unable to get pnn from local node."));
376 printf("PNN:%d\n", mypnn);
382 struct pnn_node *next;
387 static struct pnn_node *read_nodes_file(TALLOC_CTX *mem_ctx)
389 const char *nodes_list;
393 struct pnn_node *pnn_nodes = NULL;
394 struct pnn_node *pnn_node;
395 struct pnn_node *tmp_node;
397 /* read the nodes file */
398 nodes_list = getenv("CTDB_NODES");
399 if (nodes_list == NULL) {
400 nodes_list = "/etc/ctdb/nodes";
402 lines = file_lines_load(nodes_list, &nlines, mem_ctx);
406 while (nlines > 0 && strcmp(lines[nlines-1], "") == 0) {
409 for (i=0, pnn=0; i<nlines; i++) {
413 /* strip leading spaces */
414 while((*node == ' ') || (*node == '\t')) {
421 if (strcmp(node, "") == 0) {
424 pnn_node = talloc(mem_ctx, struct pnn_node);
425 pnn_node->pnn = pnn++;
426 pnn_node->addr = talloc_strdup(pnn_node, node);
427 pnn_node->next = pnn_nodes;
428 pnn_nodes = pnn_node;
431 /* swap them around so we return them in incrementing order */
432 pnn_node = pnn_nodes;
436 pnn_node = pnn_node->next;
438 tmp_node->next = pnn_nodes;
439 pnn_nodes = tmp_node;
446 show the PNN of the current node
447 discover the pnn by loading the nodes file and try to bind to all
448 addresses one at a time until the ip address is found.
450 static int control_xpnn(struct ctdb_context *ctdb, int argc, const char **argv)
452 TALLOC_CTX *mem_ctx = talloc_new(NULL);
453 struct pnn_node *pnn_nodes;
454 struct pnn_node *pnn_node;
456 pnn_nodes = read_nodes_file(mem_ctx);
457 if (pnn_nodes == NULL) {
458 DEBUG(DEBUG_ERR,("Failed to read nodes file\n"));
459 talloc_free(mem_ctx);
463 for(pnn_node=pnn_nodes;pnn_node;pnn_node=pnn_node->next) {
466 if (parse_ip(pnn_node->addr, NULL, 63999, &addr) == 0) {
467 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s' in nodes file\n", pnn_node->addr));
468 talloc_free(mem_ctx);
472 if (ctdb_sys_have_ip(&addr)) {
473 printf("PNN:%d\n", pnn_node->pnn);
474 talloc_free(mem_ctx);
479 printf("Failed to detect which PNN this node is\n");
480 talloc_free(mem_ctx);
485 display remote ctdb status
487 static int control_status(struct ctdb_context *ctdb, int argc, const char **argv)
490 struct ctdb_vnn_map *vnnmap=NULL;
491 struct ctdb_node_map *nodemap=NULL;
492 uint32_t recmode, recmaster;
495 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
500 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
502 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
506 if(options.machinereadable){
507 printf(":Node:IP:Disconnected:Banned:Disabled:Unhealthy:Stopped:Inactive:PartiallyOnline:\n");
508 for(i=0;i<nodemap->num;i++){
509 int partially_online = 0;
512 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
515 if (nodemap->nodes[i].flags == 0) {
516 struct ctdb_control_get_ifaces *ifaces;
518 ret = ctdb_ctrl_get_ifaces(ctdb, TIMELIMIT(),
519 nodemap->nodes[i].pnn,
522 for (j=0; j < ifaces->num; j++) {
523 if (ifaces->ifaces[j].link_state != 0) {
526 partially_online = 1;
532 printf(":%d:%s:%d:%d:%d:%d:%d:%d:%d:\n", nodemap->nodes[i].pnn,
533 ctdb_addr_to_str(&nodemap->nodes[i].addr),
534 !!(nodemap->nodes[i].flags&NODE_FLAGS_DISCONNECTED),
535 !!(nodemap->nodes[i].flags&NODE_FLAGS_BANNED),
536 !!(nodemap->nodes[i].flags&NODE_FLAGS_PERMANENTLY_DISABLED),
537 !!(nodemap->nodes[i].flags&NODE_FLAGS_UNHEALTHY),
538 !!(nodemap->nodes[i].flags&NODE_FLAGS_STOPPED),
539 !!(nodemap->nodes[i].flags&NODE_FLAGS_INACTIVE),
545 printf("Number of nodes:%d\n", nodemap->num);
546 for(i=0;i<nodemap->num;i++){
547 static const struct {
551 { NODE_FLAGS_DISCONNECTED, "DISCONNECTED" },
552 { NODE_FLAGS_PERMANENTLY_DISABLED, "DISABLED" },
553 { NODE_FLAGS_BANNED, "BANNED" },
554 { NODE_FLAGS_UNHEALTHY, "UNHEALTHY" },
555 { NODE_FLAGS_DELETED, "DELETED" },
556 { NODE_FLAGS_STOPPED, "STOPPED" },
557 { NODE_FLAGS_INACTIVE, "INACTIVE" },
559 char *flags_str = NULL;
562 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
565 if (nodemap->nodes[i].flags == 0) {
566 struct ctdb_control_get_ifaces *ifaces;
568 ret = ctdb_ctrl_get_ifaces(ctdb, TIMELIMIT(),
569 nodemap->nodes[i].pnn,
572 for (j=0; j < ifaces->num; j++) {
573 if (ifaces->ifaces[j].link_state != 0) {
576 flags_str = talloc_strdup(ctdb, "PARTIALLYONLINE");
582 for (j=0;j<ARRAY_SIZE(flag_names);j++) {
583 if (nodemap->nodes[i].flags & flag_names[j].flag) {
584 if (flags_str == NULL) {
585 flags_str = talloc_strdup(ctdb, flag_names[j].name);
587 flags_str = talloc_asprintf_append(flags_str, "|%s",
590 CTDB_NO_MEMORY_FATAL(ctdb, flags_str);
593 if (flags_str == NULL) {
594 flags_str = talloc_strdup(ctdb, "OK");
595 CTDB_NO_MEMORY_FATAL(ctdb, flags_str);
597 printf("pnn:%d %-16s %s%s\n", nodemap->nodes[i].pnn,
598 ctdb_addr_to_str(&nodemap->nodes[i].addr),
600 nodemap->nodes[i].pnn == mypnn?" (THIS NODE)":"");
601 talloc_free(flags_str);
604 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &vnnmap);
606 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n", options.pnn));
609 if (vnnmap->generation == INVALID_GENERATION) {
610 printf("Generation:INVALID\n");
612 printf("Generation:%d\n",vnnmap->generation);
614 printf("Size:%d\n",vnnmap->size);
615 for(i=0;i<vnnmap->size;i++){
616 printf("hash:%d lmaster:%d\n", i, vnnmap->map[i]);
619 ret = ctdb_ctrl_getrecmode(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmode);
621 DEBUG(DEBUG_ERR, ("Unable to get recmode from node %u\n", options.pnn));
624 printf("Recovery mode:%s (%d)\n",recmode==CTDB_RECOVERY_NORMAL?"NORMAL":"RECOVERY",recmode);
626 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
628 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
631 printf("Recovery master:%d\n",recmaster);
638 struct natgw_node *next;
643 display the list of nodes belonging to this natgw configuration
645 static int control_natgwlist(struct ctdb_context *ctdb, int argc, const char **argv)
648 const char *natgw_list;
651 struct natgw_node *natgw_nodes = NULL;
652 struct natgw_node *natgw_node;
653 struct ctdb_node_map *nodemap=NULL;
656 /* read the natgw nodes file into a linked list */
657 natgw_list = getenv("NATGW_NODES");
658 if (natgw_list == NULL) {
659 natgw_list = "/etc/ctdb/natgw_nodes";
661 lines = file_lines_load(natgw_list, &nlines, ctdb);
663 ctdb_set_error(ctdb, "Failed to load natgw node list '%s'\n", natgw_list);
666 while (nlines > 0 && strcmp(lines[nlines-1], "") == 0) {
669 for (i=0;i<nlines;i++) {
673 /* strip leading spaces */
674 while((*node == ' ') || (*node == '\t')) {
680 if (strcmp(node, "") == 0) {
683 natgw_node = talloc(ctdb, struct natgw_node);
684 natgw_node->addr = talloc_strdup(natgw_node, node);
685 CTDB_NO_MEMORY(ctdb, natgw_node->addr);
686 natgw_node->next = natgw_nodes;
687 natgw_nodes = natgw_node;
690 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
692 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node.\n"));
697 while(i<nodemap->num) {
698 for(natgw_node=natgw_nodes;natgw_node;natgw_node=natgw_node->next) {
699 if (!strcmp(natgw_node->addr, ctdb_addr_to_str(&nodemap->nodes[i].addr))) {
704 /* this node was not in the natgw so we just remove it from
707 if ((natgw_node == NULL)
708 || (nodemap->nodes[i].flags & NODE_FLAGS_DISCONNECTED) ) {
711 for (j=i+1; j<nodemap->num; j++) {
712 nodemap->nodes[j-1] = nodemap->nodes[j];
721 /* pick a node to be natgwmaster
722 * we dont allow STOPPED, DELETED, BANNED or UNHEALTHY nodes to become the natgwmaster
724 for(i=0;i<nodemap->num;i++){
725 if (!(nodemap->nodes[i].flags & (NODE_FLAGS_DISCONNECTED|NODE_FLAGS_STOPPED|NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_UNHEALTHY))) {
726 printf("%d %s\n", nodemap->nodes[i].pnn,ctdb_addr_to_str(&nodemap->nodes[i].addr));
730 /* we couldnt find any healthy node, try unhealthy ones */
731 if (i == nodemap->num) {
732 for(i=0;i<nodemap->num;i++){
733 if (!(nodemap->nodes[i].flags & (NODE_FLAGS_DISCONNECTED|NODE_FLAGS_STOPPED|NODE_FLAGS_DELETED))) {
734 printf("%d %s\n", nodemap->nodes[i].pnn,ctdb_addr_to_str(&nodemap->nodes[i].addr));
739 /* unless all nodes are STOPPED, when we pick one anyway */
740 if (i == nodemap->num) {
741 for(i=0;i<nodemap->num;i++){
742 if (!(nodemap->nodes[i].flags & (NODE_FLAGS_DISCONNECTED|NODE_FLAGS_DELETED))) {
743 printf("%d %s\n", nodemap->nodes[i].pnn, ctdb_addr_to_str(&nodemap->nodes[i].addr));
747 /* or if we still can not find any */
748 if (i == nodemap->num) {
749 printf("-1 0.0.0.0\n");
753 /* print the pruned list of nodes belonging to this natgw list */
754 for(i=0;i<nodemap->num;i++){
755 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
758 printf(":%d:%s:%d:%d:%d:%d:%d\n", nodemap->nodes[i].pnn,
759 ctdb_addr_to_str(&nodemap->nodes[i].addr),
760 !!(nodemap->nodes[i].flags&NODE_FLAGS_DISCONNECTED),
761 !!(nodemap->nodes[i].flags&NODE_FLAGS_BANNED),
762 !!(nodemap->nodes[i].flags&NODE_FLAGS_PERMANENTLY_DISABLED),
763 !!(nodemap->nodes[i].flags&NODE_FLAGS_UNHEALTHY),
764 !!(nodemap->nodes[i].flags&NODE_FLAGS_STOPPED));
771 display the status of the scripts for monitoring (or other events)
773 static int control_one_scriptstatus(struct ctdb_context *ctdb,
774 enum ctdb_eventscript_call type)
776 struct ctdb_scripts_wire *script_status;
779 ret = ctdb_ctrl_getscriptstatus(ctdb, TIMELIMIT(), options.pnn, ctdb, type, &script_status);
781 DEBUG(DEBUG_ERR, ("Unable to get script status from node %u\n", options.pnn));
785 if (script_status == NULL) {
786 if (!options.machinereadable) {
787 printf("%s cycle never run\n",
788 ctdb_eventscript_call_names[type]);
793 if (!options.machinereadable) {
794 printf("%d scripts were executed last %s cycle\n",
795 script_status->num_scripts,
796 ctdb_eventscript_call_names[type]);
798 for (i=0; i<script_status->num_scripts; i++) {
799 const char *status = NULL;
801 switch (script_status->scripts[i].status) {
812 if (script_status->scripts[i].status > 0)
816 if (options.machinereadable) {
817 printf("%s:%s:%i:%s:%lu.%06lu:%lu.%06lu:%s:\n",
818 ctdb_eventscript_call_names[type],
819 script_status->scripts[i].name,
820 script_status->scripts[i].status,
822 (long)script_status->scripts[i].start.tv_sec,
823 (long)script_status->scripts[i].start.tv_usec,
824 (long)script_status->scripts[i].finished.tv_sec,
825 (long)script_status->scripts[i].finished.tv_usec,
826 script_status->scripts[i].output);
830 printf("%-20s Status:%s ",
831 script_status->scripts[i].name, status);
833 /* Some other error, eg from stat. */
834 printf("%-20s Status:CANNOT RUN (%s)",
835 script_status->scripts[i].name,
836 strerror(-script_status->scripts[i].status));
838 if (script_status->scripts[i].status >= 0) {
839 printf("Duration:%.3lf ",
840 timeval_delta(&script_status->scripts[i].finished,
841 &script_status->scripts[i].start));
843 if (script_status->scripts[i].status != -ENOEXEC) {
845 ctime(&script_status->scripts[i].start.tv_sec));
846 if (script_status->scripts[i].status != 0) {
847 printf(" OUTPUT:%s\n",
848 script_status->scripts[i].output);
858 static int control_scriptstatus(struct ctdb_context *ctdb,
859 int argc, const char **argv)
862 enum ctdb_eventscript_call type, min, max;
866 DEBUG(DEBUG_ERR, ("Unknown arguments to scriptstatus\n"));
871 arg = ctdb_eventscript_call_names[CTDB_EVENT_MONITOR];
875 for (type = 0; type < CTDB_EVENT_MAX; type++) {
876 if (strcmp(arg, ctdb_eventscript_call_names[type]) == 0) {
882 if (type == CTDB_EVENT_MAX) {
883 if (strcmp(arg, "all") == 0) {
885 max = CTDB_EVENT_MAX;
887 DEBUG(DEBUG_ERR, ("Unknown event type %s\n", argv[0]));
892 if (options.machinereadable) {
893 printf(":Type:Name:Code:Status:Start:End:Error Output...:\n");
896 for (type = min; type < max; type++) {
897 ret = control_one_scriptstatus(ctdb, type);
907 enable an eventscript
909 static int control_enablescript(struct ctdb_context *ctdb, int argc, const char **argv)
917 ret = ctdb_ctrl_enablescript(ctdb, TIMELIMIT(), options.pnn, argv[0]);
919 DEBUG(DEBUG_ERR, ("Unable to enable script %s on node %u\n", argv[0], options.pnn));
927 disable an eventscript
929 static int control_disablescript(struct ctdb_context *ctdb, int argc, const char **argv)
937 ret = ctdb_ctrl_disablescript(ctdb, TIMELIMIT(), options.pnn, argv[0]);
939 DEBUG(DEBUG_ERR, ("Unable to disable script %s on node %u\n", argv[0], options.pnn));
947 display the pnn of the recovery master
949 static int control_recmaster(struct ctdb_context *ctdb, int argc, const char **argv)
954 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
956 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
959 printf("%d\n",recmaster);
965 get a list of all tickles for this pnn
967 static int control_get_tickles(struct ctdb_context *ctdb, int argc, const char **argv)
969 struct ctdb_control_tcp_tickle_list *list;
977 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
978 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
982 ret = ctdb_ctrl_get_tcp_tickles(ctdb, TIMELIMIT(), options.pnn, ctdb, &addr, &list);
984 DEBUG(DEBUG_ERR, ("Unable to list tickles\n"));
988 printf("Tickles for ip:%s\n", ctdb_addr_to_str(&list->addr));
989 printf("Num tickles:%u\n", list->tickles.num);
990 for (i=0;i<list->tickles.num;i++) {
991 printf("SRC: %s:%u ", ctdb_addr_to_str(&list->tickles.connections[i].src_addr), ntohs(list->tickles.connections[i].src_addr.ip.sin_port));
992 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));
1001 static int move_ip(struct ctdb_context *ctdb, ctdb_sock_addr *addr, uint32_t pnn)
1003 struct ctdb_all_public_ips *ips;
1004 struct ctdb_public_ip ip;
1007 uint32_t disable_time;
1009 struct ctdb_node_map *nodemap=NULL;
1010 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1013 data.dptr = (uint8_t*)&disable_time;
1014 data.dsize = sizeof(disable_time);
1015 ret = ctdb_send_message(ctdb, CTDB_BROADCAST_CONNECTED, CTDB_SRVID_DISABLE_IP_CHECK, data);
1017 DEBUG(DEBUG_ERR,("Failed to send message to disable ipcheck\n"));
1023 /* read the public ip list from the node */
1024 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), pnn, ctdb, &ips);
1026 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", pnn));
1027 talloc_free(tmp_ctx);
1031 for (i=0;i<ips->num;i++) {
1032 if (ctdb_same_ip(addr, &ips->ips[i].addr)) {
1037 DEBUG(DEBUG_ERR, ("Node %u can not host ip address '%s'\n",
1038 pnn, ctdb_addr_to_str(addr)));
1039 talloc_free(tmp_ctx);
1046 data.dptr = (uint8_t *)&ip;
1047 data.dsize = sizeof(ip);
1049 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &nodemap);
1051 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1052 talloc_free(tmp_ctx);
1056 nodes = list_of_active_nodes_except_pnn(ctdb, nodemap, tmp_ctx, pnn);
1057 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_RELEASE_IP,
1064 DEBUG(DEBUG_ERR,("Failed to release IP on nodes\n"));
1065 talloc_free(tmp_ctx);
1069 ret = ctdb_ctrl_takeover_ip(ctdb, LONGTIMELIMIT(), pnn, &ip);
1071 DEBUG(DEBUG_ERR,("Failed to take over IP on node %d\n", pnn));
1072 talloc_free(tmp_ctx);
1076 /* update the recovery daemon so it now knows to expect the new
1077 node assignment for this ip.
1079 ret = ctdb_send_message(ctdb, CTDB_BROADCAST_CONNECTED, CTDB_SRVID_RECD_UPDATE_IP, data);
1081 DEBUG(DEBUG_ERR,("Failed to send message to update the ip on the recovery master.\n"));
1085 talloc_free(tmp_ctx);
1090 move/failover an ip address to a specific node
1092 static int control_moveip(struct ctdb_context *ctdb, int argc, const char **argv)
1095 ctdb_sock_addr addr;
1102 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1103 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1108 if (sscanf(argv[1], "%u", &pnn) != 1) {
1109 DEBUG(DEBUG_ERR, ("Badly formed pnn\n"));
1113 if (move_ip(ctdb, &addr, pnn) != 0) {
1114 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", pnn));
1121 void getips_store_callback(void *param, void *data)
1123 struct ctdb_public_ip *node_ip = (struct ctdb_public_ip *)data;
1124 struct ctdb_all_public_ips *ips = param;
1128 ips->ips[i].pnn = node_ip->pnn;
1129 ips->ips[i].addr = node_ip->addr;
1132 void getips_count_callback(void *param, void *data)
1134 uint32_t *count = param;
1140 static uint32_t *ip_key(ctdb_sock_addr *ip)
1142 static uint32_t key[IP_KEYLEN];
1144 bzero(key, sizeof(key));
1146 switch (ip->sa.sa_family) {
1148 key[0] = ip->ip.sin_addr.s_addr;
1151 key[0] = ip->ip6.sin6_addr.s6_addr32[3];
1152 key[1] = ip->ip6.sin6_addr.s6_addr32[2];
1153 key[2] = ip->ip6.sin6_addr.s6_addr32[1];
1154 key[3] = ip->ip6.sin6_addr.s6_addr32[0];
1157 DEBUG(DEBUG_ERR, (__location__ " ERROR, unknown family passed :%u\n", ip->sa.sa_family));
1164 static void *add_ip_callback(void *parm, void *data)
1170 control_get_all_public_ips(struct ctdb_context *ctdb, TALLOC_CTX *tmp_ctx, struct ctdb_all_public_ips **ips)
1172 struct ctdb_all_public_ips *tmp_ips;
1173 struct ctdb_node_map *nodemap=NULL;
1174 trbt_tree_t *ip_tree;
1178 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1180 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1184 ip_tree = trbt_create(tmp_ctx, 0);
1186 for(i=0;i<nodemap->num;i++){
1187 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
1190 if (nodemap->nodes[i].flags & NODE_FLAGS_DISCONNECTED) {
1194 /* read the public ip list from this node */
1195 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &tmp_ips);
1197 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", nodemap->nodes[i].pnn));
1201 for (j=0; j<tmp_ips->num;j++) {
1202 struct ctdb_public_ip *node_ip;
1204 node_ip = talloc(tmp_ctx, struct ctdb_public_ip);
1205 node_ip->pnn = tmp_ips->ips[j].pnn;
1206 node_ip->addr = tmp_ips->ips[j].addr;
1208 trbt_insertarray32_callback(ip_tree,
1209 IP_KEYLEN, ip_key(&tmp_ips->ips[j].addr),
1213 talloc_free(tmp_ips);
1218 trbt_traversearray32(ip_tree, IP_KEYLEN, getips_count_callback, &count);
1220 len = offsetof(struct ctdb_all_public_ips, ips) +
1221 count*sizeof(struct ctdb_public_ip);
1222 tmp_ips = talloc_zero_size(tmp_ctx, len);
1223 trbt_traversearray32(ip_tree, IP_KEYLEN, getips_store_callback, tmp_ips);
1232 * scans all other nodes and returns a pnn for another node that can host this
1236 find_other_host_for_public_ip(struct ctdb_context *ctdb, ctdb_sock_addr *addr)
1238 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1239 struct ctdb_all_public_ips *ips;
1240 struct ctdb_node_map *nodemap=NULL;
1243 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1245 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1246 talloc_free(tmp_ctx);
1250 for(i=0;i<nodemap->num;i++){
1251 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1254 if (nodemap->nodes[i].pnn == options.pnn) {
1258 /* read the public ip list from this node */
1259 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips);
1261 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", nodemap->nodes[i].pnn));
1265 for (j=0;j<ips->num;j++) {
1266 if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1267 talloc_free(tmp_ctx);
1268 return nodemap->nodes[i].pnn;
1274 talloc_free(tmp_ctx);
1279 add a public ip address to a node
1281 static int control_addip(struct ctdb_context *ctdb, int argc, const char **argv)
1287 ctdb_sock_addr addr;
1288 struct ctdb_control_ip_iface *pub;
1289 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1290 struct ctdb_all_public_ips *ips;
1294 talloc_free(tmp_ctx);
1298 if (!parse_ip_mask(argv[0], argv[1], &addr, &mask)) {
1299 DEBUG(DEBUG_ERR, ("Badly formed ip/mask : %s\n", argv[0]));
1300 talloc_free(tmp_ctx);
1304 ret = control_get_all_public_ips(ctdb, tmp_ctx, &ips);
1306 DEBUG(DEBUG_ERR, ("Unable to get public ip list from cluster\n"));
1307 talloc_free(tmp_ctx);
1312 /* check if some other node is already serving this ip, if not,
1315 for (i=0;i<ips->num;i++) {
1316 if (ctdb_same_ip(&addr, &ips->ips[i].addr)) {
1321 len = offsetof(struct ctdb_control_ip_iface, iface) + strlen(argv[1]) + 1;
1322 pub = talloc_size(tmp_ctx, len);
1323 CTDB_NO_MEMORY(ctdb, pub);
1327 pub->len = strlen(argv[1])+1;
1328 memcpy(&pub->iface[0], argv[1], strlen(argv[1])+1);
1330 ret = ctdb_ctrl_add_public_ip(ctdb, TIMELIMIT(), options.pnn, pub);
1332 DEBUG(DEBUG_ERR, ("Unable to add public ip to node %u\n", options.pnn));
1333 talloc_free(tmp_ctx);
1337 if (i == ips->num) {
1338 /* no one has this ip so we claim it */
1341 pnn = ips->ips[i].pnn;
1344 if (move_ip(ctdb, &addr, pnn) != 0) {
1345 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", pnn));
1349 talloc_free(tmp_ctx);
1353 static int control_delip(struct ctdb_context *ctdb, int argc, const char **argv);
1355 static int control_delip_all(struct ctdb_context *ctdb, int argc, const char **argv, ctdb_sock_addr *addr)
1357 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1358 struct ctdb_node_map *nodemap=NULL;
1359 struct ctdb_all_public_ips *ips;
1362 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1364 DEBUG(DEBUG_ERR, ("Unable to get nodemap from current node\n"));
1368 /* remove it from the nodes that are not hosting the ip currently */
1369 for(i=0;i<nodemap->num;i++){
1370 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1373 if (ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips) != 0) {
1374 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %d\n", nodemap->nodes[i].pnn));
1378 for (j=0;j<ips->num;j++) {
1379 if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1387 if (ips->ips[j].pnn == nodemap->nodes[i].pnn) {
1391 options.pnn = nodemap->nodes[i].pnn;
1392 control_delip(ctdb, argc, argv);
1396 /* remove it from every node (also the one hosting it) */
1397 for(i=0;i<nodemap->num;i++){
1398 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1401 if (ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips) != 0) {
1402 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %d\n", nodemap->nodes[i].pnn));
1406 for (j=0;j<ips->num;j++) {
1407 if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1415 options.pnn = nodemap->nodes[i].pnn;
1416 control_delip(ctdb, argc, argv);
1419 talloc_free(tmp_ctx);
1424 delete a public ip address from a node
1426 static int control_delip(struct ctdb_context *ctdb, int argc, const char **argv)
1429 ctdb_sock_addr addr;
1430 struct ctdb_control_ip_iface pub;
1431 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1432 struct ctdb_all_public_ips *ips;
1435 talloc_free(tmp_ctx);
1439 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1440 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1444 if (options.pnn == CTDB_BROADCAST_ALL) {
1445 return control_delip_all(ctdb, argc, argv, &addr);
1452 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &ips);
1454 DEBUG(DEBUG_ERR, ("Unable to get public ip list from cluster\n"));
1455 talloc_free(tmp_ctx);
1459 for (i=0;i<ips->num;i++) {
1460 if (ctdb_same_ip(&addr, &ips->ips[i].addr)) {
1466 DEBUG(DEBUG_ERR, ("This node does not support this public address '%s'\n",
1467 ctdb_addr_to_str(&addr)));
1468 talloc_free(tmp_ctx);
1472 if (ips->ips[i].pnn == options.pnn) {
1473 ret = find_other_host_for_public_ip(ctdb, &addr);
1475 if (move_ip(ctdb, &addr, ret) != 0) {
1476 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", ret));
1482 ret = ctdb_ctrl_del_public_ip(ctdb, TIMELIMIT(), options.pnn, &pub);
1484 DEBUG(DEBUG_ERR, ("Unable to del public ip from node %u\n", options.pnn));
1485 talloc_free(tmp_ctx);
1489 talloc_free(tmp_ctx);
1494 kill a tcp connection
1496 static int kill_tcp(struct ctdb_context *ctdb, int argc, const char **argv)
1499 struct ctdb_control_killtcp killtcp;
1505 if (!parse_ip_port(argv[0], &killtcp.src_addr)) {
1506 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[0]));
1510 if (!parse_ip_port(argv[1], &killtcp.dst_addr)) {
1511 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[1]));
1515 ret = ctdb_ctrl_killtcp(ctdb, TIMELIMIT(), options.pnn, &killtcp);
1517 DEBUG(DEBUG_ERR, ("Unable to killtcp from node %u\n", options.pnn));
1528 static int control_gratious_arp(struct ctdb_context *ctdb, int argc, const char **argv)
1531 ctdb_sock_addr addr;
1537 if (!parse_ip(argv[0], NULL, 0, &addr)) {
1538 DEBUG(DEBUG_ERR, ("Bad IP '%s'\n", argv[0]));
1542 ret = ctdb_ctrl_gratious_arp(ctdb, TIMELIMIT(), options.pnn, &addr, argv[1]);
1544 DEBUG(DEBUG_ERR, ("Unable to send gratious_arp from node %u\n", options.pnn));
1552 register a server id
1554 static int regsrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1557 struct ctdb_server_id server_id;
1563 server_id.pnn = strtoul(argv[0], NULL, 0);
1564 server_id.type = strtoul(argv[1], NULL, 0);
1565 server_id.server_id = strtoul(argv[2], NULL, 0);
1567 ret = ctdb_ctrl_register_server_id(ctdb, TIMELIMIT(), &server_id);
1569 DEBUG(DEBUG_ERR, ("Unable to register server_id from node %u\n", options.pnn));
1572 DEBUG(DEBUG_ERR,("Srvid registered. Sleeping for 999 seconds\n"));
1578 unregister a server id
1580 static int unregsrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1583 struct ctdb_server_id server_id;
1589 server_id.pnn = strtoul(argv[0], NULL, 0);
1590 server_id.type = strtoul(argv[1], NULL, 0);
1591 server_id.server_id = strtoul(argv[2], NULL, 0);
1593 ret = ctdb_ctrl_unregister_server_id(ctdb, TIMELIMIT(), &server_id);
1595 DEBUG(DEBUG_ERR, ("Unable to unregister server_id from node %u\n", options.pnn));
1602 check if a server id exists
1604 static int chksrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1608 struct ctdb_server_id server_id;
1614 server_id.pnn = strtoul(argv[0], NULL, 0);
1615 server_id.type = strtoul(argv[1], NULL, 0);
1616 server_id.server_id = strtoul(argv[2], NULL, 0);
1618 ret = ctdb_ctrl_check_server_id(ctdb, TIMELIMIT(), options.pnn, &server_id, &status);
1620 DEBUG(DEBUG_ERR, ("Unable to check server_id from node %u\n", options.pnn));
1625 printf("Server id %d:%d:%d EXISTS\n", server_id.pnn, server_id.type, server_id.server_id);
1627 printf("Server id %d:%d:%d does NOT exist\n", server_id.pnn, server_id.type, server_id.server_id);
1633 get a list of all server ids that are registered on a node
1635 static int getsrvids(struct ctdb_context *ctdb, int argc, const char **argv)
1638 struct ctdb_server_id_list *server_ids;
1640 ret = ctdb_ctrl_get_server_id_list(ctdb, ctdb, TIMELIMIT(), options.pnn, &server_ids);
1642 DEBUG(DEBUG_ERR, ("Unable to get server_id list from node %u\n", options.pnn));
1646 for (i=0; i<server_ids->num; i++) {
1647 printf("Server id %d:%d:%d\n",
1648 server_ids->server_ids[i].pnn,
1649 server_ids->server_ids[i].type,
1650 server_ids->server_ids[i].server_id);
1657 send a tcp tickle ack
1659 static int tickle_tcp(struct ctdb_context *ctdb, int argc, const char **argv)
1662 ctdb_sock_addr src, dst;
1668 if (!parse_ip_port(argv[0], &src)) {
1669 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[0]));
1673 if (!parse_ip_port(argv[1], &dst)) {
1674 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[1]));
1678 ret = ctdb_sys_send_tcp(&src, &dst, 0, 0, 0);
1682 DEBUG(DEBUG_ERR, ("Error while sending tickle ack\n"));
1689 display public ip status
1691 static int control_ip(struct ctdb_context *ctdb, int argc, const char **argv)
1694 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1695 struct ctdb_all_public_ips *ips;
1697 if (options.pnn == CTDB_BROADCAST_ALL) {
1698 /* read the list of public ips from all nodes */
1699 ret = control_get_all_public_ips(ctdb, tmp_ctx, &ips);
1701 /* read the public ip list from this node */
1702 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &ips);
1705 DEBUG(DEBUG_ERR, ("Unable to get public ips from node %u\n", options.pnn));
1706 talloc_free(tmp_ctx);
1710 if (options.machinereadable){
1711 printf(":Public IP:Node:ActiveInterface:AvailableInterfaces:ConfiguredInterfaces:\n");
1713 if (options.pnn == CTDB_BROADCAST_ALL) {
1714 printf("Public IPs on ALL nodes\n");
1716 printf("Public IPs on node %u\n", options.pnn);
1720 for (i=1;i<=ips->num;i++) {
1721 struct ctdb_control_public_ip_info *info = NULL;
1723 char *aciface = NULL;
1724 char *avifaces = NULL;
1725 char *cifaces = NULL;
1727 if (options.pnn == CTDB_BROADCAST_ALL) {
1728 pnn = ips->ips[ips->num-i].pnn;
1734 ret = ctdb_ctrl_get_public_ip_info(ctdb, TIMELIMIT(), pnn, ctdb,
1735 &ips->ips[ips->num-i].addr, &info);
1742 for (j=0; j < info->num; j++) {
1743 if (cifaces == NULL) {
1744 cifaces = talloc_strdup(info,
1745 info->ifaces[j].name);
1747 cifaces = talloc_asprintf_append(cifaces,
1749 info->ifaces[j].name);
1752 if (info->active_idx == j) {
1753 aciface = info->ifaces[j].name;
1756 if (info->ifaces[j].link_state == 0) {
1760 if (avifaces == NULL) {
1761 avifaces = talloc_strdup(info, info->ifaces[j].name);
1763 avifaces = talloc_asprintf_append(avifaces,
1765 info->ifaces[j].name);
1770 if (options.machinereadable){
1771 printf(":%s:%d:%s:%s:%s:\n",
1772 ctdb_addr_to_str(&ips->ips[ips->num-i].addr),
1773 ips->ips[ips->num-i].pnn,
1775 avifaces?avifaces:"",
1776 cifaces?cifaces:"");
1778 printf("%s node[%d] active[%s] available[%s] configured[%s]\n",
1779 ctdb_addr_to_str(&ips->ips[ips->num-i].addr),
1780 ips->ips[ips->num-i].pnn,
1782 avifaces?avifaces:"",
1783 cifaces?cifaces:"");
1788 talloc_free(tmp_ctx);
1795 static int control_ipinfo(struct ctdb_context *ctdb, int argc, const char **argv)
1798 ctdb_sock_addr addr;
1799 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1800 struct ctdb_control_public_ip_info *info;
1803 talloc_free(tmp_ctx);
1807 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1808 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1812 /* read the public ip info from this node */
1813 ret = ctdb_ctrl_get_public_ip_info(ctdb, TIMELIMIT(), options.pnn,
1814 tmp_ctx, &addr, &info);
1816 DEBUG(DEBUG_ERR, ("Unable to get public ip[%s]info from node %u\n",
1817 argv[0], options.pnn));
1818 talloc_free(tmp_ctx);
1822 printf("Public IP[%s] info on node %u\n",
1823 ctdb_addr_to_str(&info->ip.addr),
1826 printf("IP:%s\nCurrentNode:%d\nNumInterfaces:%u\n",
1827 ctdb_addr_to_str(&info->ip.addr),
1828 info->ip.pnn, info->num);
1830 for (i=0; i<info->num; i++) {
1831 info->ifaces[i].name[CTDB_IFACE_SIZE] = '\0';
1833 printf("Interface[%u]: Name:%s Link:%s References:%u%s\n",
1834 i+1, info->ifaces[i].name,
1835 info->ifaces[i].link_state?"up":"down",
1836 (unsigned int)info->ifaces[i].references,
1837 (i==info->active_idx)?" (active)":"");
1840 talloc_free(tmp_ctx);
1845 display interfaces status
1847 static int control_ifaces(struct ctdb_context *ctdb, int argc, const char **argv)
1850 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1851 struct ctdb_control_get_ifaces *ifaces;
1853 /* read the public ip list from this node */
1854 ret = ctdb_ctrl_get_ifaces(ctdb, TIMELIMIT(), options.pnn,
1857 DEBUG(DEBUG_ERR, ("Unable to get interfaces from node %u\n",
1859 talloc_free(tmp_ctx);
1863 if (options.machinereadable){
1864 printf(":Name:LinkStatus:References:\n");
1866 printf("Interfaces on node %u\n", options.pnn);
1869 for (i=0; i<ifaces->num; i++) {
1870 if (options.machinereadable){
1871 printf(":%s:%s:%u\n",
1872 ifaces->ifaces[i].name,
1873 ifaces->ifaces[i].link_state?"1":"0",
1874 (unsigned int)ifaces->ifaces[i].references);
1876 printf("name:%s link:%s references:%u\n",
1877 ifaces->ifaces[i].name,
1878 ifaces->ifaces[i].link_state?"up":"down",
1879 (unsigned int)ifaces->ifaces[i].references);
1883 talloc_free(tmp_ctx);
1889 set link status of an interface
1891 static int control_setifacelink(struct ctdb_context *ctdb, int argc, const char **argv)
1894 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1895 struct ctdb_control_iface_info info;
1903 if (strlen(argv[0]) > CTDB_IFACE_SIZE) {
1904 DEBUG(DEBUG_ERR, ("interfaces name '%s' too long\n",
1906 talloc_free(tmp_ctx);
1909 strcpy(info.name, argv[0]);
1911 if (strcmp(argv[1], "up") == 0) {
1912 info.link_state = 1;
1913 } else if (strcmp(argv[1], "down") == 0) {
1914 info.link_state = 0;
1916 DEBUG(DEBUG_ERR, ("link state invalid '%s' should be 'up' or 'down'\n",
1918 talloc_free(tmp_ctx);
1922 /* read the public ip list from this node */
1923 ret = ctdb_ctrl_set_iface_link(ctdb, TIMELIMIT(), options.pnn,
1926 DEBUG(DEBUG_ERR, ("Unable to set link state for interfaces %s node %u\n",
1927 argv[0], options.pnn));
1928 talloc_free(tmp_ctx);
1932 talloc_free(tmp_ctx);
1937 display pid of a ctdb daemon
1939 static int control_getpid(struct ctdb_context *ctdb, int argc, const char **argv)
1944 ret = ctdb_ctrl_getpid(ctdb, TIMELIMIT(), options.pnn, &pid);
1946 DEBUG(DEBUG_ERR, ("Unable to get daemon pid from node %u\n", options.pnn));
1949 printf("Pid:%d\n", pid);
1954 static uint32_t ipreallocate_finished;
1957 handler for receiving the response to ipreallocate
1959 static void ip_reallocate_handler(struct ctdb_context *ctdb, uint64_t srvid,
1960 TDB_DATA data, void *private_data)
1962 ipreallocate_finished = 1;
1965 static void ctdb_every_second(struct event_context *ev, struct timed_event *te, struct timeval t, void *p)
1967 struct ctdb_context *ctdb = talloc_get_type(p, struct ctdb_context);
1969 event_add_timed(ctdb->ev, ctdb,
1970 timeval_current_ofs(1, 0),
1971 ctdb_every_second, ctdb);
1975 ask the recovery daemon on the recovery master to perform a ip reallocation
1977 static int control_ipreallocate(struct ctdb_context *ctdb, int argc, const char **argv)
1981 struct takeover_run_reply rd;
1983 struct ctdb_node_map *nodemap=NULL;
1985 struct timeval tv = timeval_current();
1987 /* we need some events to trigger so we can timeout and restart
1990 event_add_timed(ctdb->ev, ctdb,
1991 timeval_current_ofs(1, 0),
1992 ctdb_every_second, ctdb);
1994 rd.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
1996 DEBUG(DEBUG_ERR, ("Failed to get pnn of local node\n"));
1999 rd.srvid = getpid();
2001 /* register a message port for receiveing the reply so that we
2002 can receive the reply
2004 ctdb_set_message_handler(ctdb, rd.srvid, ip_reallocate_handler, NULL);
2006 data.dptr = (uint8_t *)&rd;
2007 data.dsize = sizeof(rd);
2010 /* check that there are valid nodes available */
2011 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap) != 0) {
2012 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2015 for (i=0; i<nodemap->num;i++) {
2016 if ((nodemap->nodes[i].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) == 0) {
2020 if (i==nodemap->num) {
2021 DEBUG(DEBUG_ERR,("No recmaster available, no need to wait for cluster convergence\n"));
2026 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
2028 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
2032 /* verify the node exists */
2033 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), recmaster, ctdb, &nodemap) != 0) {
2034 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2039 /* check tha there are nodes available that can act as a recmaster */
2040 for (i=0; i<nodemap->num; i++) {
2041 if (nodemap->nodes[i].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
2046 if (i == nodemap->num) {
2047 DEBUG(DEBUG_ERR,("No possible nodes to host addresses.\n"));
2051 /* verify the recovery master is not STOPPED, nor BANNED */
2052 if (nodemap->nodes[recmaster].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
2053 DEBUG(DEBUG_ERR,("No suitable recmaster found. Try again\n"));
2060 /* verify the recovery master is not STOPPED, nor BANNED */
2061 if (nodemap->nodes[recmaster].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
2062 DEBUG(DEBUG_ERR,("No suitable recmaster found. Try again\n"));
2068 ipreallocate_finished = 0;
2069 ret = ctdb_send_message(ctdb, recmaster, CTDB_SRVID_TAKEOVER_RUN, data);
2071 DEBUG(DEBUG_ERR,("Failed to send ip takeover run request message to %u\n", options.pnn));
2075 tv = timeval_current();
2076 /* this loop will terminate when we have received the reply */
2077 while (timeval_elapsed(&tv) < 3.0) {
2078 event_loop_once(ctdb->ev);
2080 if (ipreallocate_finished == 1) {
2084 DEBUG(DEBUG_ERR,("Timed out waiting for recmaster ipreallocate. Trying again\n"));
2094 disable a remote node
2096 static int control_disable(struct ctdb_context *ctdb, int argc, const char **argv)
2099 struct ctdb_node_map *nodemap=NULL;
2101 /* check if the node is already disabled */
2102 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2103 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2106 if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2107 DEBUG(DEBUG_ERR,("Node %d is already disabled.\n", options.pnn));
2112 ret = ctdb_ctrl_modflags(ctdb, TIMELIMIT(), options.pnn, NODE_FLAGS_PERMANENTLY_DISABLED, 0);
2114 DEBUG(DEBUG_ERR, ("Unable to disable node %u\n", options.pnn));
2120 /* read the nodemap and verify the change took effect */
2121 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2122 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2126 } while (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED));
2127 ret = control_ipreallocate(ctdb, argc, argv);
2129 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2137 enable a disabled remote node
2139 static int control_enable(struct ctdb_context *ctdb, int argc, const char **argv)
2143 struct ctdb_node_map *nodemap=NULL;
2146 /* check if the node is already enabled */
2147 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2148 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2151 if (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED)) {
2152 DEBUG(DEBUG_ERR,("Node %d is already enabled.\n", options.pnn));
2157 ret = ctdb_ctrl_modflags(ctdb, TIMELIMIT(), options.pnn, 0, NODE_FLAGS_PERMANENTLY_DISABLED);
2159 DEBUG(DEBUG_ERR, ("Unable to enable node %u\n", options.pnn));
2165 /* read the nodemap and verify the change took effect */
2166 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2167 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2171 } while (nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED);
2173 ret = control_ipreallocate(ctdb, argc, argv);
2175 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2185 static int control_stop(struct ctdb_context *ctdb, int argc, const char **argv)
2188 struct ctdb_node_map *nodemap=NULL;
2191 ret = ctdb_ctrl_stop_node(ctdb, TIMELIMIT(), options.pnn);
2193 DEBUG(DEBUG_ERR, ("Unable to stop node %u try again\n", options.pnn));
2198 /* read the nodemap and verify the change took effect */
2199 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2200 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2204 } while (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_STOPPED));
2205 ret = control_ipreallocate(ctdb, argc, argv);
2207 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2215 restart a stopped remote node
2217 static int control_continue(struct ctdb_context *ctdb, int argc, const char **argv)
2221 struct ctdb_node_map *nodemap=NULL;
2224 ret = ctdb_ctrl_continue_node(ctdb, TIMELIMIT(), options.pnn);
2226 DEBUG(DEBUG_ERR, ("Unable to continue node %u\n", options.pnn));
2232 /* read the nodemap and verify the change took effect */
2233 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2234 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2238 } while (nodemap->nodes[options.pnn].flags & NODE_FLAGS_STOPPED);
2239 ret = control_ipreallocate(ctdb, argc, argv);
2241 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2248 static uint32_t get_generation(struct ctdb_context *ctdb)
2250 struct ctdb_vnn_map *vnnmap=NULL;
2253 /* wait until the recmaster is not in recovery mode */
2255 uint32_t recmode, recmaster;
2257 if (vnnmap != NULL) {
2258 talloc_free(vnnmap);
2262 /* get the recmaster */
2263 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, &recmaster);
2265 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
2269 /* get recovery mode */
2270 ret = ctdb_ctrl_getrecmode(ctdb, ctdb, TIMELIMIT(), recmaster, &recmode);
2272 DEBUG(DEBUG_ERR, ("Unable to get recmode from node %u\n", options.pnn));
2276 /* get the current generation number */
2277 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), recmaster, ctdb, &vnnmap);
2279 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from recmaster (%u)\n", recmaster));
2283 if ((recmode == CTDB_RECOVERY_NORMAL)
2284 && (vnnmap->generation != 1)){
2285 return vnnmap->generation;
2292 ban a node from the cluster
2294 static int control_ban(struct ctdb_context *ctdb, int argc, const char **argv)
2297 struct ctdb_node_map *nodemap=NULL;
2298 struct ctdb_ban_time bantime;
2304 /* verify the node exists */
2305 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
2307 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2311 if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_BANNED) {
2312 DEBUG(DEBUG_ERR,("Node %u is already banned.\n", options.pnn));
2316 bantime.pnn = options.pnn;
2317 bantime.time = strtoul(argv[0], NULL, 0);
2319 ret = ctdb_ctrl_set_ban(ctdb, TIMELIMIT(), options.pnn, &bantime);
2321 DEBUG(DEBUG_ERR,("Banning node %d for %d seconds failed.\n", bantime.pnn, bantime.time));
2325 ret = control_ipreallocate(ctdb, argc, argv);
2327 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2336 unban a node from the cluster
2338 static int control_unban(struct ctdb_context *ctdb, int argc, const char **argv)
2341 struct ctdb_node_map *nodemap=NULL;
2342 struct ctdb_ban_time bantime;
2344 /* verify the node exists */
2345 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
2347 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2351 if (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_BANNED)) {
2352 DEBUG(DEBUG_ERR,("Node %u is not banned.\n", options.pnn));
2356 bantime.pnn = options.pnn;
2359 ret = ctdb_ctrl_set_ban(ctdb, TIMELIMIT(), options.pnn, &bantime);
2361 DEBUG(DEBUG_ERR,("Unbanning node %d failed.\n", bantime.pnn));
2365 ret = control_ipreallocate(ctdb, argc, argv);
2367 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2376 show ban information for a node
2378 static int control_showban(struct ctdb_context *ctdb, int argc, const char **argv)
2381 struct ctdb_node_map *nodemap=NULL;
2382 struct ctdb_ban_time *bantime;
2384 /* verify the node exists */
2385 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
2387 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2391 ret = ctdb_ctrl_get_ban(ctdb, TIMELIMIT(), options.pnn, ctdb, &bantime);
2393 DEBUG(DEBUG_ERR,("Showing ban info for node %d failed.\n", options.pnn));
2397 if (bantime->time == 0) {
2398 printf("Node %u is not banned\n", bantime->pnn);
2400 printf("Node %u is banned banned for %d seconds\n", bantime->pnn, bantime->time);
2409 static int control_shutdown(struct ctdb_context *ctdb, int argc, const char **argv)
2413 ret = ctdb_ctrl_shutdown(ctdb, TIMELIMIT(), options.pnn);
2415 DEBUG(DEBUG_ERR, ("Unable to shutdown node %u\n", options.pnn));
2425 static int control_recover(struct ctdb_context *ctdb, int argc, const char **argv)
2428 uint32_t generation, next_generation;
2430 /* record the current generation number */
2431 generation = get_generation(ctdb);
2433 ret = ctdb_ctrl_freeze_priority(ctdb, TIMELIMIT(), options.pnn, 1);
2435 DEBUG(DEBUG_ERR, ("Unable to freeze node\n"));
2439 ret = ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
2441 DEBUG(DEBUG_ERR, ("Unable to set recovery mode\n"));
2445 /* wait until we are in a new generation */
2447 next_generation = get_generation(ctdb);
2448 if (next_generation != generation) {
2459 display monitoring mode of a remote node
2461 static int control_getmonmode(struct ctdb_context *ctdb, int argc, const char **argv)
2466 ret = ctdb_ctrl_getmonmode(ctdb, TIMELIMIT(), options.pnn, &monmode);
2468 DEBUG(DEBUG_ERR, ("Unable to get monmode from node %u\n", options.pnn));
2471 if (!options.machinereadable){
2472 printf("Monitoring mode:%s (%d)\n",monmode==CTDB_MONITORING_ACTIVE?"ACTIVE":"DISABLED",monmode);
2475 printf(":%d:\n",monmode);
2482 display capabilities of a remote node
2484 static int control_getcapabilities(struct ctdb_context *ctdb, int argc, const char **argv)
2486 uint32_t capabilities;
2489 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), options.pnn, &capabilities);
2491 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", options.pnn));
2495 if (!options.machinereadable){
2496 printf("RECMASTER: %s\n", (capabilities&CTDB_CAP_RECMASTER)?"YES":"NO");
2497 printf("LMASTER: %s\n", (capabilities&CTDB_CAP_LMASTER)?"YES":"NO");
2498 printf("LVS: %s\n", (capabilities&CTDB_CAP_LVS)?"YES":"NO");
2499 printf("NATGW: %s\n", (capabilities&CTDB_CAP_NATGW)?"YES":"NO");
2501 printf(":RECMASTER:LMASTER:LVS:NATGW:\n");
2502 printf(":%d:%d:%d:%d:\n",
2503 !!(capabilities&CTDB_CAP_RECMASTER),
2504 !!(capabilities&CTDB_CAP_LMASTER),
2505 !!(capabilities&CTDB_CAP_LVS),
2506 !!(capabilities&CTDB_CAP_NATGW));
2512 display lvs configuration
2514 static int control_lvs(struct ctdb_context *ctdb, int argc, const char **argv)
2516 uint32_t *capabilities;
2517 struct ctdb_node_map *nodemap=NULL;
2519 int healthy_count = 0;
2521 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
2523 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
2527 capabilities = talloc_array(ctdb, uint32_t, nodemap->num);
2528 CTDB_NO_MEMORY(ctdb, capabilities);
2530 /* collect capabilities for all connected nodes */
2531 for (i=0; i<nodemap->num; i++) {
2532 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2535 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2539 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), i, &capabilities[i]);
2541 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", i));
2545 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2549 if (!(nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY)) {
2554 /* Print all LVS nodes */
2555 for (i=0; i<nodemap->num; i++) {
2556 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2559 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2562 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2566 if (healthy_count != 0) {
2567 if (nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY) {
2572 printf("%d:%s\n", i,
2573 ctdb_addr_to_str(&nodemap->nodes[i].addr));
2580 display who is the lvs master
2582 static int control_lvsmaster(struct ctdb_context *ctdb, int argc, const char **argv)
2584 uint32_t *capabilities;
2585 struct ctdb_node_map *nodemap=NULL;
2587 int healthy_count = 0;
2589 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
2591 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
2595 capabilities = talloc_array(ctdb, uint32_t, nodemap->num);
2596 CTDB_NO_MEMORY(ctdb, capabilities);
2598 /* collect capabilities for all connected nodes */
2599 for (i=0; i<nodemap->num; i++) {
2600 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2603 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2607 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), i, &capabilities[i]);
2609 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", i));
2613 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2617 if (!(nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY)) {
2622 /* find and show the lvsmaster */
2623 for (i=0; i<nodemap->num; i++) {
2624 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2627 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2630 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2634 if (healthy_count != 0) {
2635 if (nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY) {
2640 if (options.machinereadable){
2643 printf("Node %d is LVS master\n", i);
2648 printf("There is no LVS master\n");
2653 disable monitoring on a node
2655 static int control_disable_monmode(struct ctdb_context *ctdb, int argc, const char **argv)
2660 ret = ctdb_ctrl_disable_monmode(ctdb, TIMELIMIT(), options.pnn);
2662 DEBUG(DEBUG_ERR, ("Unable to disable monmode on node %u\n", options.pnn));
2665 printf("Monitoring mode:%s\n","DISABLED");
2671 enable monitoring on a node
2673 static int control_enable_monmode(struct ctdb_context *ctdb, int argc, const char **argv)
2678 ret = ctdb_ctrl_enable_monmode(ctdb, TIMELIMIT(), options.pnn);
2680 DEBUG(DEBUG_ERR, ("Unable to enable monmode on node %u\n", options.pnn));
2683 printf("Monitoring mode:%s\n","ACTIVE");
2689 display remote list of keys/data for a db
2691 static int control_catdb(struct ctdb_context *ctdb, int argc, const char **argv)
2693 const char *db_name;
2694 struct ctdb_db_context *ctdb_db;
2704 if (db_exists(ctdb, db_name)) {
2705 DEBUG(DEBUG_ERR,("Database '%s' does not exist\n", db_name));
2709 ctdb_db = ctdb_attach(ctdb, db_name, false, 0);
2711 if (ctdb_db == NULL) {
2712 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
2716 /* traverse and dump the cluster tdb */
2717 ret = ctdb_dump_db(ctdb_db, stdout);
2719 DEBUG(DEBUG_ERR, ("Unable to dump database\n"));
2720 DEBUG(DEBUG_ERR, ("Maybe try 'ctdb getdbstatus %s'"
2721 " and 'ctdb getvar AllowUnhealthyDBRead'\n",
2725 talloc_free(ctdb_db);
2727 printf("Dumped %d records\n", ret);
2732 static void log_handler(struct ctdb_context *ctdb, uint64_t srvid,
2733 TDB_DATA data, void *private_data)
2735 DEBUG(DEBUG_ERR,("Log data received\n"));
2736 if (data.dsize > 0) {
2737 printf("%s", data.dptr);
2744 display a list of log messages from the in memory ringbuffer
2746 static int control_getlog(struct ctdb_context *ctdb, int argc, const char **argv)
2750 struct ctdb_get_log_addr log_addr;
2752 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2757 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
2758 talloc_free(tmp_ctx);
2762 log_addr.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
2763 log_addr.srvid = getpid();
2764 if (isalpha(argv[0][0]) || argv[0][0] == '-') {
2765 log_addr.level = get_debug_by_desc(argv[0]);
2767 log_addr.level = strtol(argv[0], NULL, 0);
2771 data.dptr = (unsigned char *)&log_addr;
2772 data.dsize = sizeof(log_addr);
2774 DEBUG(DEBUG_ERR, ("Pulling logs from node %u\n", options.pnn));
2776 ctdb_set_message_handler(ctdb, log_addr.srvid, log_handler, NULL);
2779 DEBUG(DEBUG_ERR,("Listen for response on %d\n", (int)log_addr.srvid));
2781 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_GET_LOG,
2782 0, data, tmp_ctx, NULL, &res, NULL, &errmsg);
2783 if (ret != 0 || res != 0) {
2784 DEBUG(DEBUG_ERR,("Failed to get logs - %s\n", errmsg));
2785 talloc_free(tmp_ctx);
2790 tv = timeval_current();
2791 /* this loop will terminate when we have received the reply */
2792 while (timeval_elapsed(&tv) < 3.0) {
2793 event_loop_once(ctdb->ev);
2796 DEBUG(DEBUG_INFO,("Timed out waiting for log data.\n"));
2798 talloc_free(tmp_ctx);
2803 clear the in memory log area
2805 static int control_clearlog(struct ctdb_context *ctdb, int argc, const char **argv)
2810 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2812 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_CLEAR_LOG,
2813 0, tdb_null, tmp_ctx, NULL, &res, NULL, &errmsg);
2814 if (ret != 0 || res != 0) {
2815 DEBUG(DEBUG_ERR,("Failed to clear logs\n"));
2816 talloc_free(tmp_ctx);
2820 talloc_free(tmp_ctx);
2827 display a list of the databases on a remote ctdb
2829 static int control_getdbmap(struct ctdb_context *ctdb, int argc, const char **argv)
2832 struct ctdb_dbid_map *dbmap=NULL;
2834 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
2836 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
2840 if(options.machinereadable){
2841 printf(":ID:Name:Path:Persistent:Unhealthy:\n");
2842 for(i=0;i<dbmap->num;i++){
2848 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn,
2849 dbmap->dbs[i].dbid, ctdb, &path);
2850 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn,
2851 dbmap->dbs[i].dbid, ctdb, &name);
2852 ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn,
2853 dbmap->dbs[i].dbid, ctdb, &health);
2854 persistent = dbmap->dbs[i].persistent;
2855 printf(":0x%08X:%s:%s:%d:%d:\n",
2856 dbmap->dbs[i].dbid, name, path,
2857 !!(persistent), !!(health));
2862 printf("Number of databases:%d\n", dbmap->num);
2863 for(i=0;i<dbmap->num;i++){
2869 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &path);
2870 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
2871 ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &health);
2872 persistent = dbmap->dbs[i].persistent;
2873 printf("dbid:0x%08x name:%s path:%s%s%s\n",
2874 dbmap->dbs[i].dbid, name, path,
2875 persistent?" PERSISTENT":"",
2876 health?" UNHEALTHY":"");
2883 display the status of a database on a remote ctdb
2885 static int control_getdbstatus(struct ctdb_context *ctdb, int argc, const char **argv)
2888 struct ctdb_dbid_map *dbmap=NULL;
2889 const char *db_name;
2897 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
2899 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
2903 for(i=0;i<dbmap->num;i++){
2909 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
2910 if (strcmp(name, db_name) != 0) {
2914 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &path);
2915 ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &health);
2916 persistent = dbmap->dbs[i].persistent;
2917 printf("dbid: 0x%08x\nname: %s\npath: %s\nPERSISTENT: %s\nHEALTH: %s\n",
2918 dbmap->dbs[i].dbid, name, path,
2919 persistent?"yes":"no",
2920 health?health:"OK");
2924 DEBUG(DEBUG_ERR, ("db %s doesn't exist on node %u\n", db_name, options.pnn));
2929 check if the local node is recmaster or not
2930 it will return 1 if this node is the recmaster and 0 if it is not
2931 or if the local ctdb daemon could not be contacted
2933 static int control_isnotrecmaster(struct ctdb_context *ctdb, int argc, const char **argv)
2935 uint32_t mypnn, recmaster;
2938 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
2940 printf("Failed to get pnn of node\n");
2944 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
2946 printf("Failed to get the recmaster\n");
2950 if (recmaster != mypnn) {
2951 printf("this node is not the recmaster\n");
2955 printf("this node is the recmaster\n");
2962 static int control_ping(struct ctdb_context *ctdb, int argc, const char **argv)
2965 struct timeval tv = timeval_current();
2966 ret = ctdb_ctrl_ping(ctdb, options.pnn);
2968 printf("Unable to get ping response from node %u\n", options.pnn);
2971 printf("response from %u time=%.6f sec (%d clients)\n",
2972 options.pnn, timeval_elapsed(&tv), ret);
2981 static int control_getvar(struct ctdb_context *ctdb, int argc, const char **argv)
2992 ret = ctdb_ctrl_get_tunable(ctdb, TIMELIMIT(), options.pnn, name, &value);
2994 DEBUG(DEBUG_ERR, ("Unable to get tunable variable '%s'\n", name));
2998 printf("%-19s = %u\n", name, value);
3005 static int control_setvar(struct ctdb_context *ctdb, int argc, const char **argv)
3016 value = strtoul(argv[1], NULL, 0);
3018 ret = ctdb_ctrl_set_tunable(ctdb, TIMELIMIT(), options.pnn, name, value);
3020 DEBUG(DEBUG_ERR, ("Unable to set tunable variable '%s'\n", name));
3029 static int control_listvars(struct ctdb_context *ctdb, int argc, const char **argv)
3035 ret = ctdb_ctrl_list_tunables(ctdb, TIMELIMIT(), options.pnn, ctdb, &list, &count);
3037 DEBUG(DEBUG_ERR, ("Unable to list tunable variables\n"));
3041 for (i=0;i<count;i++) {
3042 control_getvar(ctdb, 1, &list[i]);
3051 display debug level on a node
3053 static int control_getdebug(struct ctdb_context *ctdb, int argc, const char **argv)
3058 ret = ctdb_ctrl_get_debuglevel(ctdb, options.pnn, &level);
3060 DEBUG(DEBUG_ERR, ("Unable to get debuglevel response from node %u\n", options.pnn));
3063 if (options.machinereadable){
3064 printf(":Name:Level:\n");
3065 printf(":%s:%d:\n",get_debug_by_level(level),level);
3067 printf("Node %u is at debug level %s (%d)\n", options.pnn, get_debug_by_level(level), level);
3074 display reclock file of a node
3076 static int control_getreclock(struct ctdb_context *ctdb, int argc, const char **argv)
3079 const char *reclock;
3081 ret = ctdb_ctrl_getreclock(ctdb, TIMELIMIT(), options.pnn, ctdb, &reclock);
3083 DEBUG(DEBUG_ERR, ("Unable to get reclock file from node %u\n", options.pnn));
3086 if (options.machinereadable){
3087 if (reclock != NULL) {
3088 printf("%s", reclock);
3091 if (reclock == NULL) {
3092 printf("No reclock file used.\n");
3094 printf("Reclock file:%s\n", reclock);
3102 set the reclock file of a node
3104 static int control_setreclock(struct ctdb_context *ctdb, int argc, const char **argv)
3107 const char *reclock;
3111 } else if (argc == 1) {
3117 ret = ctdb_ctrl_setreclock(ctdb, TIMELIMIT(), options.pnn, reclock);
3119 DEBUG(DEBUG_ERR, ("Unable to get reclock file from node %u\n", options.pnn));
3126 set the natgw state on/off
3128 static int control_setnatgwstate(struct ctdb_context *ctdb, int argc, const char **argv)
3131 uint32_t natgwstate;
3137 if (!strcmp(argv[0], "on")) {
3139 } else if (!strcmp(argv[0], "off")) {
3145 ret = ctdb_ctrl_setnatgwstate(ctdb, TIMELIMIT(), options.pnn, natgwstate);
3147 DEBUG(DEBUG_ERR, ("Unable to set the natgw state for node %u\n", options.pnn));
3155 set the lmaster role on/off
3157 static int control_setlmasterrole(struct ctdb_context *ctdb, int argc, const char **argv)
3160 uint32_t lmasterrole;
3166 if (!strcmp(argv[0], "on")) {
3168 } else if (!strcmp(argv[0], "off")) {
3174 ret = ctdb_ctrl_setlmasterrole(ctdb, TIMELIMIT(), options.pnn, lmasterrole);
3176 DEBUG(DEBUG_ERR, ("Unable to set the lmaster role for node %u\n", options.pnn));
3184 set the recmaster role on/off
3186 static int control_setrecmasterrole(struct ctdb_context *ctdb, int argc, const char **argv)
3189 uint32_t recmasterrole;
3195 if (!strcmp(argv[0], "on")) {
3197 } else if (!strcmp(argv[0], "off")) {
3203 ret = ctdb_ctrl_setrecmasterrole(ctdb, TIMELIMIT(), options.pnn, recmasterrole);
3205 DEBUG(DEBUG_ERR, ("Unable to set the recmaster role for node %u\n", options.pnn));
3213 set debug level on a node or all nodes
3215 static int control_setdebug(struct ctdb_context *ctdb, int argc, const char **argv)
3221 printf("You must specify the debug level. Valid levels are:\n");
3222 for (i=0; debug_levels[i].description != NULL; i++) {
3223 printf("%s (%d)\n", debug_levels[i].description, debug_levels[i].level);
3229 if (isalpha(argv[0][0]) || argv[0][0] == '-') {
3230 level = get_debug_by_desc(argv[0]);
3232 level = strtol(argv[0], NULL, 0);
3235 for (i=0; debug_levels[i].description != NULL; i++) {
3236 if (level == debug_levels[i].level) {
3240 if (debug_levels[i].description == NULL) {
3241 printf("Invalid debug level, must be one of\n");
3242 for (i=0; debug_levels[i].description != NULL; i++) {
3243 printf("%s (%d)\n", debug_levels[i].description, debug_levels[i].level);
3248 ret = ctdb_ctrl_set_debuglevel(ctdb, options.pnn, level);
3250 DEBUG(DEBUG_ERR, ("Unable to set debug level on node %u\n", options.pnn));
3259 static int control_freeze(struct ctdb_context *ctdb, int argc, const char **argv)
3265 priority = strtol(argv[0], NULL, 0);
3269 DEBUG(DEBUG_ERR,("Freeze by priority %u\n", priority));
3271 ret = ctdb_ctrl_freeze_priority(ctdb, TIMELIMIT(), options.pnn, priority);
3273 DEBUG(DEBUG_ERR, ("Unable to freeze node %u\n", options.pnn));
3281 static int control_thaw(struct ctdb_context *ctdb, int argc, const char **argv)
3287 priority = strtol(argv[0], NULL, 0);
3291 DEBUG(DEBUG_ERR,("Thaw by priority %u\n", priority));
3293 ret = ctdb_ctrl_thaw_priority(ctdb, TIMELIMIT(), options.pnn, priority);
3295 DEBUG(DEBUG_ERR, ("Unable to thaw node %u\n", options.pnn));
3302 attach to a database
3304 static int control_attach(struct ctdb_context *ctdb, int argc, const char **argv)
3306 const char *db_name;
3307 struct ctdb_db_context *ctdb_db;
3314 ctdb_db = ctdb_attach(ctdb, db_name, false, 0);
3315 if (ctdb_db == NULL) {
3316 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
3326 static int control_setdbprio(struct ctdb_context *ctdb, int argc, const char **argv)
3328 struct ctdb_db_priority db_prio;
3335 db_prio.db_id = strtoul(argv[0], NULL, 0);
3336 db_prio.priority = strtoul(argv[1], NULL, 0);
3338 ret = ctdb_ctrl_set_db_priority(ctdb, TIMELIMIT(), options.pnn, &db_prio);
3340 DEBUG(DEBUG_ERR,("Unable to set db prio\n"));
3350 static int control_getdbprio(struct ctdb_context *ctdb, int argc, const char **argv)
3352 uint32_t db_id, priority;
3359 db_id = strtoul(argv[0], NULL, 0);
3361 ret = ctdb_ctrl_get_db_priority(ctdb, TIMELIMIT(), options.pnn, db_id, &priority);
3363 DEBUG(DEBUG_ERR,("Unable to get db prio\n"));
3367 DEBUG(DEBUG_ERR,("Priority:%u\n", priority));
3373 run an eventscript on a node
3375 static int control_eventscript(struct ctdb_context *ctdb, int argc, const char **argv)
3381 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3384 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3388 data.dptr = (unsigned char *)discard_const(argv[0]);
3389 data.dsize = strlen((char *)data.dptr) + 1;
3391 DEBUG(DEBUG_ERR, ("Running eventscripts with arguments \"%s\" on node %u\n", data.dptr, options.pnn));
3393 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_RUN_EVENTSCRIPTS,
3394 0, data, tmp_ctx, NULL, &res, NULL, &errmsg);
3395 if (ret != 0 || res != 0) {
3396 DEBUG(DEBUG_ERR,("Failed to run eventscripts - %s\n", errmsg));
3397 talloc_free(tmp_ctx);
3400 talloc_free(tmp_ctx);
3404 #define DB_VERSION 1
3405 #define MAX_DB_NAME 64
3406 struct db_file_header {
3407 unsigned long version;
3409 unsigned long persistent;
3411 const char name[MAX_DB_NAME];
3414 struct backup_data {
3415 struct ctdb_marshall_buffer *records;
3418 bool traverse_error;
3421 static int backup_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *private)
3423 struct backup_data *bd = talloc_get_type(private, struct backup_data);
3424 struct ctdb_rec_data *rec;
3426 /* add the record */
3427 rec = ctdb_marshall_record(bd->records, 0, key, NULL, data);
3429 bd->traverse_error = true;
3430 DEBUG(DEBUG_ERR,("Failed to marshall record\n"));
3433 bd->records = talloc_realloc_size(NULL, bd->records, rec->length + bd->len);
3434 if (bd->records == NULL) {
3435 DEBUG(DEBUG_ERR,("Failed to expand marshalling buffer\n"));
3436 bd->traverse_error = true;
3439 bd->records->count++;
3440 memcpy(bd->len+(uint8_t *)bd->records, rec, rec->length);
3441 bd->len += rec->length;
3449 * backup a database to a file
3451 static int control_backupdb(struct ctdb_context *ctdb, int argc, const char **argv)
3454 struct ctdb_dbid_map *dbmap=NULL;
3455 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3456 struct db_file_header dbhdr;
3457 struct ctdb_db_context *ctdb_db;
3458 struct backup_data *bd;
3461 const char *reason = NULL;
3464 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3468 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &dbmap);
3470 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
3474 for(i=0;i<dbmap->num;i++){
3477 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, tmp_ctx, &name);
3478 if(!strcmp(argv[0], name)){
3479 talloc_free(discard_const(name));
3482 talloc_free(discard_const(name));
3484 if (i == dbmap->num) {
3485 DEBUG(DEBUG_ERR,("No database with name '%s' found\n", argv[0]));
3486 talloc_free(tmp_ctx);
3490 ret = ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn,
3491 dbmap->dbs[i].dbid, tmp_ctx, &reason);
3493 DEBUG(DEBUG_ERR,("Unable to get dbhealth for database '%s'\n",
3495 talloc_free(tmp_ctx);
3499 uint32_t allow_unhealthy = 0;
3501 ctdb_ctrl_get_tunable(ctdb, TIMELIMIT(), options.pnn,
3502 "AllowUnhealthyDBRead",
3505 if (allow_unhealthy != 1) {
3506 DEBUG(DEBUG_ERR,("database '%s' is unhealthy: %s\n",
3509 DEBUG(DEBUG_ERR,("disallow backup : tunnable AllowUnhealthyDBRead = %u\n",
3511 talloc_free(tmp_ctx);
3515 DEBUG(DEBUG_WARNING,("WARNING database '%s' is unhealthy - see 'ctdb getdbstatus %s'\n",
3517 DEBUG(DEBUG_WARNING,("WARNING! allow backup of unhealthy database: "
3518 "tunnable AllowUnhealthyDBRead = %u\n",
3522 ctdb_db = ctdb_attach(ctdb, argv[0], dbmap->dbs[i].persistent, 0);
3523 if (ctdb_db == NULL) {
3524 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", argv[0]));
3525 talloc_free(tmp_ctx);
3530 ret = tdb_transaction_start(ctdb_db->ltdb->tdb);
3532 DEBUG(DEBUG_ERR,("Failed to start transaction\n"));
3533 talloc_free(tmp_ctx);
3538 bd = talloc_zero(tmp_ctx, struct backup_data);
3540 DEBUG(DEBUG_ERR,("Failed to allocate backup_data\n"));
3541 talloc_free(tmp_ctx);
3545 bd->records = talloc_zero(bd, struct ctdb_marshall_buffer);
3546 if (bd->records == NULL) {
3547 DEBUG(DEBUG_ERR,("Failed to allocate ctdb_marshall_buffer\n"));
3548 talloc_free(tmp_ctx);
3552 bd->len = offsetof(struct ctdb_marshall_buffer, data);
3553 bd->records->db_id = ctdb_db->db_id;
3554 /* traverse the database collecting all records */
3555 if (tdb_traverse_read(ctdb_db->ltdb->tdb, backup_traverse, bd) == -1 ||
3556 bd->traverse_error) {
3557 DEBUG(DEBUG_ERR,("Traverse error\n"));
3558 talloc_free(tmp_ctx);
3562 tdb_transaction_cancel(ctdb_db->ltdb->tdb);
3565 fh = open(argv[1], O_RDWR|O_CREAT, 0600);
3567 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[1]));
3568 talloc_free(tmp_ctx);
3572 dbhdr.version = DB_VERSION;
3573 dbhdr.timestamp = time(NULL);
3574 dbhdr.persistent = dbmap->dbs[i].persistent;
3575 dbhdr.size = bd->len;
3576 if (strlen(argv[0]) >= MAX_DB_NAME) {
3577 DEBUG(DEBUG_ERR,("Too long dbname\n"));
3580 strncpy(discard_const(dbhdr.name), argv[0], MAX_DB_NAME);
3581 ret = write(fh, &dbhdr, sizeof(dbhdr));
3583 DEBUG(DEBUG_ERR,("write failed: %s\n", strerror(errno)));
3586 ret = write(fh, bd->records, bd->len);
3588 DEBUG(DEBUG_ERR,("write failed: %s\n", strerror(errno)));
3597 DEBUG(DEBUG_ERR,("close failed: %s\n", strerror(errno)));
3600 talloc_free(tmp_ctx);
3605 * restore a database from a file
3607 static int control_restoredb(struct ctdb_context *ctdb, int argc, const char **argv)
3610 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3613 struct db_file_header dbhdr;
3614 struct ctdb_db_context *ctdb_db;
3615 struct ctdb_node_map *nodemap=NULL;
3616 struct ctdb_vnn_map *vnnmap=NULL;
3618 struct ctdb_control_wipe_database w;
3620 uint32_t generation;
3625 if (argc < 1 || argc > 2) {
3626 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3630 fh = open(argv[0], O_RDONLY);
3632 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[0]));
3633 talloc_free(tmp_ctx);
3637 read(fh, &dbhdr, sizeof(dbhdr));
3638 if (dbhdr.version != DB_VERSION) {
3639 DEBUG(DEBUG_ERR,("Invalid version of database dump. File is version %lu but expected version was %u\n", dbhdr.version, DB_VERSION));
3640 talloc_free(tmp_ctx);
3644 dbname = dbhdr.name;
3649 outdata.dsize = dbhdr.size;
3650 outdata.dptr = talloc_size(tmp_ctx, outdata.dsize);
3651 if (outdata.dptr == NULL) {
3652 DEBUG(DEBUG_ERR,("Failed to allocate data of size '%lu'\n", dbhdr.size));
3654 talloc_free(tmp_ctx);
3657 read(fh, outdata.dptr, outdata.dsize);
3660 tm = localtime(&dbhdr.timestamp);
3661 strftime(tbuf,sizeof(tbuf)-1,"%Y/%m/%d %H:%M:%S", tm);
3662 printf("Restoring database '%s' from backup @ %s\n",
3666 ctdb_db = ctdb_attach(ctdb, dbname, dbhdr.persistent, 0);
3667 if (ctdb_db == NULL) {
3668 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", dbname));
3669 talloc_free(tmp_ctx);
3673 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
3675 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
3676 talloc_free(tmp_ctx);
3681 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &vnnmap);
3683 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n", options.pnn));
3684 talloc_free(tmp_ctx);
3688 /* freeze all nodes */
3689 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3690 for (i=1; i<=NUM_DB_PRIORITIES; i++) {
3691 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_FREEZE,
3697 DEBUG(DEBUG_ERR, ("Unable to freeze nodes.\n"));
3698 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3699 talloc_free(tmp_ctx);
3704 generation = vnnmap->generation;
3705 data.dptr = (void *)&generation;
3706 data.dsize = sizeof(generation);
3708 /* start a cluster wide transaction */
3709 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3710 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_START,
3712 TIMELIMIT(), false, data,
3715 DEBUG(DEBUG_ERR, ("Unable to start cluster wide transactions.\n"));
3720 w.db_id = ctdb_db->db_id;
3721 w.transaction_id = generation;
3723 data.dptr = (void *)&w;
3724 data.dsize = sizeof(w);
3726 /* wipe all the remote databases. */
3727 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3728 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_WIPE_DATABASE,
3730 TIMELIMIT(), false, data,
3733 DEBUG(DEBUG_ERR, ("Unable to wipe database.\n"));
3734 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3735 talloc_free(tmp_ctx);
3739 /* push the database */
3740 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3741 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_PUSH_DB,
3743 TIMELIMIT(), false, outdata,
3746 DEBUG(DEBUG_ERR, ("Failed to push database.\n"));
3747 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3748 talloc_free(tmp_ctx);
3752 data.dptr = (void *)&ctdb_db->db_id;
3753 data.dsize = sizeof(ctdb_db->db_id);
3755 /* mark the database as healthy */
3756 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3757 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_DB_SET_HEALTHY,
3759 TIMELIMIT(), false, data,
3762 DEBUG(DEBUG_ERR, ("Failed to mark database as healthy.\n"));
3763 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3764 talloc_free(tmp_ctx);
3768 data.dptr = (void *)&generation;
3769 data.dsize = sizeof(generation);
3771 /* commit all the changes */
3772 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_COMMIT,
3774 TIMELIMIT(), false, data,
3777 DEBUG(DEBUG_ERR, ("Unable to commit databases.\n"));
3778 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3779 talloc_free(tmp_ctx);
3784 /* thaw all nodes */
3785 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3786 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_THAW,
3792 DEBUG(DEBUG_ERR, ("Unable to thaw nodes.\n"));
3793 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3794 talloc_free(tmp_ctx);
3799 talloc_free(tmp_ctx);
3804 * dump a database backup from a file
3806 static int control_dumpdbbackup(struct ctdb_context *ctdb, int argc, const char **argv)
3808 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3810 struct db_file_header dbhdr;
3814 struct ctdb_rec_data *rec = NULL;
3815 struct ctdb_marshall_buffer *m;
3818 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3822 fh = open(argv[0], O_RDONLY);
3824 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[0]));
3825 talloc_free(tmp_ctx);
3829 read(fh, &dbhdr, sizeof(dbhdr));
3830 if (dbhdr.version != DB_VERSION) {
3831 DEBUG(DEBUG_ERR,("Invalid version of database dump. File is version %lu but expected version was %u\n", dbhdr.version, DB_VERSION));
3832 talloc_free(tmp_ctx);
3836 outdata.dsize = dbhdr.size;
3837 outdata.dptr = talloc_size(tmp_ctx, outdata.dsize);
3838 if (outdata.dptr == NULL) {
3839 DEBUG(DEBUG_ERR,("Failed to allocate data of size '%lu'\n", dbhdr.size));
3841 talloc_free(tmp_ctx);
3844 read(fh, outdata.dptr, outdata.dsize);
3846 m = (struct ctdb_marshall_buffer *)outdata.dptr;
3848 tm = localtime(&dbhdr.timestamp);
3849 strftime(tbuf,sizeof(tbuf)-1,"%Y/%m/%d %H:%M:%S", tm);
3850 printf("Backup of database name:'%s' dbid:0x%x08x from @ %s\n",
3851 dbhdr.name, m->db_id, tbuf);
3853 for (i=0; i < m->count; i++) {
3857 /* we do not want the header splitted, so we pass NULL*/
3858 rec = ctdb_marshall_loop_next(m, rec, &reqid,
3861 ctdb_dumpdb_record(ctdb, key, data, stdout);
3864 printf("Dumped %d records\n", i);
3865 talloc_free(tmp_ctx);
3870 * wipe a database from a file
3872 static int control_wipedb(struct ctdb_context *ctdb, int argc,
3876 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3878 struct ctdb_db_context *ctdb_db;
3879 struct ctdb_node_map *nodemap = NULL;
3880 struct ctdb_vnn_map *vnnmap = NULL;
3882 struct ctdb_control_wipe_database w;
3884 uint32_t generation;
3885 struct ctdb_dbid_map *dbmap = NULL;
3888 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3892 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx,
3895 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n",
3900 for(i=0;i<dbmap->num;i++){
3903 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn,
3904 dbmap->dbs[i].dbid, tmp_ctx, &name);
3905 if(!strcmp(argv[0], name)){
3906 talloc_free(discard_const(name));
3909 talloc_free(discard_const(name));
3911 if (i == dbmap->num) {
3912 DEBUG(DEBUG_ERR, ("No database with name '%s' found\n",
3914 talloc_free(tmp_ctx);
3918 ctdb_db = ctdb_attach(ctdb, argv[0], dbmap->dbs[i].persistent, 0);
3919 if (ctdb_db == NULL) {
3920 DEBUG(DEBUG_ERR, ("Unable to attach to database '%s'\n",
3922 talloc_free(tmp_ctx);
3926 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb,
3929 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n",
3931 talloc_free(tmp_ctx);
3935 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx,
3938 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n",
3940 talloc_free(tmp_ctx);
3944 /* freeze all nodes */
3945 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3946 for (i=1; i<=NUM_DB_PRIORITIES; i++) {
3947 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_FREEZE,
3954 DEBUG(DEBUG_ERR, ("Unable to freeze nodes.\n"));
3955 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn,
3956 CTDB_RECOVERY_ACTIVE);
3957 talloc_free(tmp_ctx);
3962 generation = vnnmap->generation;
3963 data.dptr = (void *)&generation;
3964 data.dsize = sizeof(generation);
3966 /* start a cluster wide transaction */
3967 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3968 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_START,
3970 TIMELIMIT(), false, data,
3974 DEBUG(DEBUG_ERR, ("Unable to start cluster wide "
3975 "transactions.\n"));
3979 w.db_id = ctdb_db->db_id;
3980 w.transaction_id = generation;
3982 data.dptr = (void *)&w;
3983 data.dsize = sizeof(w);
3985 /* wipe all the remote databases. */
3986 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3987 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_WIPE_DATABASE,
3989 TIMELIMIT(), false, data,
3992 DEBUG(DEBUG_ERR, ("Unable to wipe database.\n"));
3993 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3994 talloc_free(tmp_ctx);
3998 data.dptr = (void *)&ctdb_db->db_id;
3999 data.dsize = sizeof(ctdb_db->db_id);
4001 /* mark the database as healthy */
4002 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4003 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_DB_SET_HEALTHY,
4005 TIMELIMIT(), false, data,
4008 DEBUG(DEBUG_ERR, ("Failed to mark database as healthy.\n"));
4009 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4010 talloc_free(tmp_ctx);
4014 data.dptr = (void *)&generation;
4015 data.dsize = sizeof(generation);
4017 /* commit all the changes */
4018 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_COMMIT,
4020 TIMELIMIT(), false, data,
4023 DEBUG(DEBUG_ERR, ("Unable to commit databases.\n"));
4024 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4025 talloc_free(tmp_ctx);
4029 /* thaw all nodes */
4030 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4031 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_THAW,
4037 DEBUG(DEBUG_ERR, ("Unable to thaw nodes.\n"));
4038 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4039 talloc_free(tmp_ctx);
4043 talloc_free(tmp_ctx);
4048 * set flags of a node in the nodemap
4050 static int control_setflags(struct ctdb_context *ctdb, int argc, const char **argv)
4057 struct ctdb_node_flag_change c;
4064 if (sscanf(argv[0], "%d", &node) != 1) {
4065 DEBUG(DEBUG_ERR, ("Badly formed node\n"));
4069 if (sscanf(argv[1], "0x%x", &flags) != 1) {
4070 DEBUG(DEBUG_ERR, ("Badly formed flags\n"));
4077 c.new_flags = flags;
4079 data.dsize = sizeof(c);
4080 data.dptr = (unsigned char *)&c;
4082 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_MODIFY_FLAGS, 0,
4083 data, NULL, NULL, &status, NULL, NULL);
4084 if (ret != 0 || status != 0) {
4085 DEBUG(DEBUG_ERR,("Failed to modify flags\n"));
4094 static int control_dumpmemory(struct ctdb_context *ctdb, int argc, const char **argv)
4100 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
4101 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_DUMP_MEMORY,
4102 0, tdb_null, tmp_ctx, &data, &res, NULL, &errmsg);
4103 if (ret != 0 || res != 0) {
4104 DEBUG(DEBUG_ERR,("Failed to dump memory - %s\n", errmsg));
4105 talloc_free(tmp_ctx);
4108 write(1, data.dptr, data.dsize);
4109 talloc_free(tmp_ctx);
4114 handler for memory dumps
4116 static void mem_dump_handler(struct ctdb_context *ctdb, uint64_t srvid,
4117 TDB_DATA data, void *private_data)
4119 write(1, data.dptr, data.dsize);
4124 dump memory usage on the recovery daemon
4126 static int control_rddumpmemory(struct ctdb_context *ctdb, int argc, const char **argv)
4130 struct rd_memdump_reply rd;
4132 rd.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
4134 DEBUG(DEBUG_ERR, ("Failed to get pnn of local node\n"));
4137 rd.srvid = getpid();
4139 /* register a message port for receiveing the reply so that we
4140 can receive the reply
4142 ctdb_set_message_handler(ctdb, rd.srvid, mem_dump_handler, NULL);
4145 data.dptr = (uint8_t *)&rd;
4146 data.dsize = sizeof(rd);
4148 ret = ctdb_send_message(ctdb, options.pnn, CTDB_SRVID_MEM_DUMP, data);
4150 DEBUG(DEBUG_ERR,("Failed to send memdump request message to %u\n", options.pnn));
4154 /* this loop will terminate when we have received the reply */
4156 event_loop_once(ctdb->ev);
4163 send a message to a srvid
4165 static int control_msgsend(struct ctdb_context *ctdb, int argc, const char **argv)
4167 unsigned long srvid;
4175 srvid = strtoul(argv[0], NULL, 0);
4177 data.dptr = (uint8_t *)discard_const(argv[1]);
4178 data.dsize= strlen(argv[1]);
4180 ret = ctdb_send_message(ctdb, CTDB_BROADCAST_CONNECTED, srvid, data);
4182 DEBUG(DEBUG_ERR,("Failed to send memdump request message to %u\n", options.pnn));
4190 handler for msglisten
4192 static void msglisten_handler(struct ctdb_context *ctdb, uint64_t srvid,
4193 TDB_DATA data, void *private_data)
4197 printf("Message received: ");
4198 for (i=0;i<data.dsize;i++) {
4199 printf("%c", data.dptr[i]);
4205 listen for messages on a messageport
4207 static int control_msglisten(struct ctdb_context *ctdb, int argc, const char **argv)
4213 /* register a message port and listen for messages
4215 ctdb_set_message_handler(ctdb, srvid, msglisten_handler, NULL);
4216 printf("Listening for messages on srvid:%d\n", (int)srvid);
4219 event_loop_once(ctdb->ev);
4226 list all nodes in the cluster
4227 if the daemon is running, we read the data from the daemon.
4228 if the daemon is not running we parse the nodes file directly
4230 static int control_listnodes(struct ctdb_context *ctdb, int argc, const char **argv)
4233 struct ctdb_node_map *nodemap=NULL;
4236 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
4238 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
4242 for(i=0;i<nodemap->num;i++){
4243 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
4246 if (options.machinereadable){
4247 printf(":%d:%s:\n", nodemap->nodes[i].pnn, ctdb_addr_to_str(&nodemap->nodes[i].addr));
4249 printf("%s\n", ctdb_addr_to_str(&nodemap->nodes[i].addr));
4253 TALLOC_CTX *mem_ctx = talloc_new(NULL);
4254 struct pnn_node *pnn_nodes;
4255 struct pnn_node *pnn_node;
4257 pnn_nodes = read_nodes_file(mem_ctx);
4258 if (pnn_nodes == NULL) {
4259 DEBUG(DEBUG_ERR,("Failed to read nodes file\n"));
4260 talloc_free(mem_ctx);
4264 for(pnn_node=pnn_nodes;pnn_node;pnn_node=pnn_node->next) {
4265 ctdb_sock_addr addr;
4267 if (parse_ip(pnn_node->addr, NULL, 63999, &addr) == 0) {
4268 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s' in nodes file\n", pnn_node->addr));
4269 talloc_free(mem_ctx);
4273 if (options.machinereadable){
4274 printf(":%d:%s:\n", pnn_node->pnn, pnn_node->addr);
4276 printf("%s\n", pnn_node->addr);
4279 talloc_free(mem_ctx);
4286 reload the nodes file on the local node
4288 static int control_reload_nodes_file(struct ctdb_context *ctdb, int argc, const char **argv)
4292 struct ctdb_node_map *nodemap=NULL;
4294 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
4296 DEBUG(DEBUG_ERR, ("Failed to read pnn of local node\n"));
4300 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
4302 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
4306 /* reload the nodes file on all remote nodes */
4307 for (i=0;i<nodemap->num;i++) {
4308 if (nodemap->nodes[i].pnn == mypnn) {
4311 DEBUG(DEBUG_NOTICE, ("Reloading nodes file on node %u\n", nodemap->nodes[i].pnn));
4312 ret = ctdb_ctrl_reload_nodes_file(ctdb, TIMELIMIT(),
4313 nodemap->nodes[i].pnn);
4315 DEBUG(DEBUG_ERR, ("ERROR: Failed to reload nodes file on node %u. You MUST fix that node manually!\n", nodemap->nodes[i].pnn));
4319 /* reload the nodes file on the local node */
4320 DEBUG(DEBUG_NOTICE, ("Reloading nodes file on node %u\n", mypnn));
4321 ret = ctdb_ctrl_reload_nodes_file(ctdb, TIMELIMIT(), mypnn);
4323 DEBUG(DEBUG_ERR, ("ERROR: Failed to reload nodes file on node %u. You MUST fix that node manually!\n", mypnn));
4326 /* initiate a recovery */
4327 control_recover(ctdb, argc, argv);
4333 static const struct {
4335 int (*fn)(struct ctdb_context *, int, const char **);
4337 bool without_daemon; /* can be run without daemon running ? */
4340 } ctdb_commands[] = {
4342 { "version", control_version, true, false, "show version of ctdb" },
4344 { "status", control_status, true, false, "show node status" },
4345 { "uptime", control_uptime, true, false, "show node uptime" },
4346 { "ping", control_ping, true, false, "ping all nodes" },
4347 { "getvar", control_getvar, true, false, "get a tunable variable", "<name>"},
4348 { "setvar", control_setvar, true, false, "set a tunable variable", "<name> <value>"},
4349 { "listvars", control_listvars, true, false, "list tunable variables"},
4350 { "statistics", control_statistics, false, false, "show statistics" },
4351 { "statisticsreset", control_statistics_reset, true, false, "reset statistics"},
4352 { "ip", control_ip, false, false, "show which public ip's that ctdb manages" },
4353 { "ipinfo", control_ipinfo, true, false, "show details about a public ip that ctdb manages", "<ip>" },
4354 { "ifaces", control_ifaces, true, false, "show which interfaces that ctdb manages" },
4355 { "setifacelink", control_setifacelink, true, false, "set interface link status", "<iface> <status>" },
4356 { "process-exists", control_process_exists, true, false, "check if a process exists on a node", "<pid>"},
4357 { "getdbmap", control_getdbmap, true, false, "show the database map" },
4358 { "getdbstatus", control_getdbstatus, true, false, "show the status of a database", "<dbname>" },
4359 { "catdb", control_catdb, true, false, "dump a database" , "<dbname>"},
4360 { "getmonmode", control_getmonmode, true, false, "show monitoring mode" },
4361 { "getcapabilities", control_getcapabilities, true, false, "show node capabilities" },
4362 { "pnn", control_pnn, true, false, "show the pnn of the currnet node" },
4363 { "lvs", control_lvs, true, false, "show lvs configuration" },
4364 { "lvsmaster", control_lvsmaster, true, false, "show which node is the lvs master" },
4365 { "disablemonitor", control_disable_monmode,true, false, "set monitoring mode to DISABLE" },
4366 { "enablemonitor", control_enable_monmode, true, false, "set monitoring mode to ACTIVE" },
4367 { "setdebug", control_setdebug, true, false, "set debug level", "<EMERG|ALERT|CRIT|ERR|WARNING|NOTICE|INFO|DEBUG>" },
4368 { "getdebug", control_getdebug, true, false, "get debug level" },
4369 { "getlog", control_getlog, true, false, "get the log data from the in memory ringbuffer", "<level>" },
4370 { "clearlog", control_clearlog, true, false, "clear the log data from the in memory ringbuffer" },
4371 { "attach", control_attach, true, false, "attach to a database", "<dbname>" },
4372 { "dumpmemory", control_dumpmemory, true, false, "dump memory map to stdout" },
4373 { "rddumpmemory", control_rddumpmemory, true, false, "dump memory map from the recovery daemon to stdout" },
4374 { "getpid", control_getpid, true, false, "get ctdbd process ID" },
4375 { "disable", control_disable, true, false, "disable a nodes public IP" },
4376 { "enable", control_enable, true, false, "enable a nodes public IP" },
4377 { "stop", control_stop, true, false, "stop a node" },
4378 { "continue", control_continue, true, false, "re-start a stopped node" },
4379 { "ban", control_ban, true, false, "ban a node from the cluster", "<bantime|0>"},
4380 { "unban", control_unban, true, false, "unban a node" },
4381 { "showban", control_showban, true, false, "show ban information"},
4382 { "shutdown", control_shutdown, true, false, "shutdown ctdbd" },
4383 { "recover", control_recover, true, false, "force recovery" },
4384 { "ipreallocate", control_ipreallocate, true, false, "force the recovery daemon to perform a ip reallocation procedure" },
4385 { "freeze", control_freeze, true, false, "freeze databases", "[priority:1-3]" },
4386 { "thaw", control_thaw, true, false, "thaw databases", "[priority:1-3]" },
4387 { "isnotrecmaster", control_isnotrecmaster, false, false, "check if the local node is recmaster or not" },
4388 { "killtcp", kill_tcp, false, false, "kill a tcp connection.", "<srcip:port> <dstip:port>" },
4389 { "gratiousarp", control_gratious_arp, false, false, "send a gratious arp", "<ip> <interface>" },
4390 { "tickle", tickle_tcp, false, false, "send a tcp tickle ack", "<srcip:port> <dstip:port>" },
4391 { "gettickles", control_get_tickles, false, false, "get the list of tickles registered for this ip", "<ip>" },
4393 { "regsrvid", regsrvid, false, false, "register a server id", "<pnn> <type> <id>" },
4394 { "unregsrvid", unregsrvid, false, false, "unregister a server id", "<pnn> <type> <id>" },
4395 { "chksrvid", chksrvid, false, false, "check if a server id exists", "<pnn> <type> <id>" },
4396 { "getsrvids", getsrvids, false, false, "get a list of all server ids"},
4397 { "vacuum", ctdb_vacuum, false, false, "vacuum the databases of empty records", "[max_records]"},
4398 { "repack", ctdb_repack, false, false, "repack all databases", "[max_freelist]"},
4399 { "listnodes", control_listnodes, false, true, "list all nodes in the cluster"},
4400 { "reloadnodes", control_reload_nodes_file, false, false, "reload the nodes file and restart the transport on all nodes"},
4401 { "moveip", control_moveip, false, false, "move/failover an ip address to another node", "<ip> <node>"},
4402 { "addip", control_addip, true, false, "add a ip address to a node", "<ip/mask> <iface>"},
4403 { "delip", control_delip, false, false, "delete an ip address from a node", "<ip>"},
4404 { "eventscript", control_eventscript, true, false, "run the eventscript with the given parameters on a node", "<arguments>"},
4405 { "backupdb", control_backupdb, false, false, "backup the database into a file.", "<database> <file>"},
4406 { "restoredb", control_restoredb, false, false, "restore the database from a file.", "<file> [dbname]"},
4407 { "dumpdbbackup", control_dumpdbbackup, false, true, "dump database backup from a file.", "<file>"},
4408 { "wipedb", control_wipedb, false, false, "wipe the contents of a database.", "<dbname>"},
4409 { "recmaster", control_recmaster, false, false, "show the pnn for the recovery master."},
4410 { "setflags", control_setflags, false, false, "set flags for a node in the nodemap.", "<node> <flags>"},
4411 { "scriptstatus", control_scriptstatus, false, false, "show the status of the monitoring scripts (or all scripts)", "[all]"},
4412 { "enablescript", control_enablescript, false, false, "enable an eventscript", "<script>"},
4413 { "disablescript", control_disablescript, false, false, "disable an eventscript", "<script>"},
4414 { "natgwlist", control_natgwlist, false, false, "show the nodes belonging to this natgw configuration"},
4415 { "xpnn", control_xpnn, true, true, "find the pnn of the local node without talking to the daemon (unreliable)" },
4416 { "getreclock", control_getreclock, false, false, "Show the reclock file of a node"},
4417 { "setreclock", control_setreclock, false, false, "Set/clear the reclock file of a node", "[filename]"},
4418 { "setnatgwstate", control_setnatgwstate, false, false, "Set NATGW state to on/off", "{on|off}"},
4419 { "setlmasterrole", control_setlmasterrole, false, false, "Set LMASTER role to on/off", "{on|off}"},
4420 { "setrecmasterrole", control_setrecmasterrole, false, false, "Set RECMASTER role to on/off", "{on|off}"},
4421 { "setdbprio", control_setdbprio, false, false, "Set DB priority", "<dbid> <prio:1-3>"},
4422 { "getdbprio", control_getdbprio, false, false, "Get DB priority", "<dbid>"},
4423 { "msglisten", control_msglisten, false, false, "Listen on a srvid port for messages", "<msg srvid>"},
4424 { "msgsend", control_msgsend, false, false, "Send a message to srvid", "<srvid> <message>"},
4430 static void usage(void)
4434 "Usage: ctdb [options] <control>\n" \
4436 " -n <node> choose node number, or 'all' (defaults to local node)\n"
4437 " -Y generate machinereadable output\n"
4438 " -t <timelimit> set timelimit for control in seconds (default %u)\n", options.timelimit);
4439 printf("Controls:\n");
4440 for (i=0;i<ARRAY_SIZE(ctdb_commands);i++) {
4441 printf(" %-15s %-27s %s\n",
4442 ctdb_commands[i].name,
4443 ctdb_commands[i].args?ctdb_commands[i].args:"",
4444 ctdb_commands[i].msg);
4450 static void ctdb_alarm(int sig)
4452 printf("Maximum runtime exceeded - exiting\n");
4459 int main(int argc, const char *argv[])
4461 struct ctdb_context *ctdb;
4462 char *nodestring = NULL;
4463 struct poptOption popt_options[] = {
4466 { "timelimit", 't', POPT_ARG_INT, &options.timelimit, 0, "timelimit", "integer" },
4467 { "node", 'n', POPT_ARG_STRING, &nodestring, 0, "node", "integer|all" },
4468 { "machinereadable", 'Y', POPT_ARG_NONE, &options.machinereadable, 0, "enable machinereadable output", NULL },
4469 { "maxruntime", 'T', POPT_ARG_INT, &options.maxruntime, 0, "die if runtime exceeds this limit (in seconds)", "integer" },
4473 const char **extra_argv;
4477 struct event_context *ev;
4478 const char *control;
4482 /* set some defaults */
4483 options.maxruntime = 0;
4484 options.timelimit = 3;
4485 options.pnn = CTDB_CURRENT_NODE;
4487 pc = poptGetContext(argv[0], argc, argv, popt_options, POPT_CONTEXT_KEEP_FIRST);
4489 while ((opt = poptGetNextOpt(pc)) != -1) {
4492 DEBUG(DEBUG_ERR, ("Invalid option %s: %s\n",
4493 poptBadOption(pc, 0), poptStrerror(opt)));
4498 /* setup the remaining options for the main program to use */
4499 extra_argv = poptGetArgs(pc);
4502 while (extra_argv[extra_argc]) extra_argc++;
4505 if (extra_argc < 1) {
4509 if (options.maxruntime == 0) {
4510 const char *ctdb_timeout;
4511 ctdb_timeout = getenv("CTDB_TIMEOUT");
4512 if (ctdb_timeout != NULL) {
4513 options.maxruntime = strtoul(ctdb_timeout, NULL, 0);
4515 /* default timeout is 120 seconds */
4516 options.maxruntime = 120;
4520 signal(SIGALRM, ctdb_alarm);
4521 alarm(options.maxruntime);
4523 /* setup the node number to contact */
4524 if (nodestring != NULL) {
4525 if (strcmp(nodestring, "all") == 0) {
4526 options.pnn = CTDB_BROADCAST_ALL;
4528 options.pnn = strtoul(nodestring, NULL, 0);
4532 control = extra_argv[0];
4534 ev = event_context_init(NULL);
4536 for (i=0;i<ARRAY_SIZE(ctdb_commands);i++) {
4537 if (strcmp(control, ctdb_commands[i].name) == 0) {
4540 if (ctdb_commands[i].without_daemon == true) {
4544 /* initialise ctdb */
4545 ctdb = ctdb_cmdline_client(ev);
4547 if (ctdb_commands[i].without_daemon == false) {
4549 DEBUG(DEBUG_ERR, ("Failed to init ctdb\n"));
4553 /* verify the node exists */
4556 if (options.pnn == CTDB_CURRENT_NODE) {
4558 pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
4566 if (ctdb_commands[i].auto_all &&
4567 options.pnn == CTDB_BROADCAST_ALL) {
4572 nodes = ctdb_get_connected_nodes(ctdb, TIMELIMIT(), ctdb, &num_nodes);
4573 CTDB_NO_MEMORY(ctdb, nodes);
4575 for (j=0;j<num_nodes;j++) {
4576 options.pnn = nodes[j];
4577 ret |= ctdb_commands[i].fn(ctdb, extra_argc-1, extra_argv+1);
4581 ret = ctdb_commands[i].fn(ctdb, extra_argc-1, extra_argv+1);
4587 if (i == ARRAY_SIZE(ctdb_commands)) {
4588 DEBUG(DEBUG_ERR, ("Unknown control '%s'\n", control));