4 Copyright (C) Andrew Tridgell 2007
5 Copyright (C) Ronnie Sahlberg 2007
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, see <http://www.gnu.org/licenses/>.
22 #include "lib/events/events.h"
23 #include "system/time.h"
24 #include "system/filesys.h"
25 #include "system/network.h"
26 #include "system/locale.h"
29 #include "../include/ctdb.h"
30 #include "../include/ctdb_private.h"
31 #include "../common/rb_tree.h"
34 #define ERR_TIMEOUT 20 /* timed out trying to reach node */
35 #define ERR_NONODE 21 /* node does not exist */
36 #define ERR_DISNODE 22 /* node is disconnected */
38 static void usage(void);
47 #define TIMELIMIT() timeval_current_ofs(options.timelimit, 0)
50 static int control_version(struct ctdb_context *ctdb, int argc, const char **argv)
53 #define XSTR(x) STR(x)
54 printf("CTDB version: %s\n", XSTR(CTDB_VERS));
61 verify that a node exists and is reachable
63 static void verify_node(struct ctdb_context *ctdb)
66 struct ctdb_node_map *nodemap=NULL;
68 if (options.pnn == CTDB_CURRENT_NODE) {
71 if (options.pnn == CTDB_BROADCAST_ALL) {
75 /* verify the node exists */
76 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
77 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
80 if (options.pnn >= nodemap->num) {
81 DEBUG(DEBUG_ERR, ("Node %u does not exist\n", options.pnn));
84 if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_DELETED) {
85 DEBUG(DEBUG_ERR, ("Node %u is DELETED\n", options.pnn));
88 if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_DISCONNECTED) {
89 DEBUG(DEBUG_ERR, ("Node %u is DISCONNECTED\n", options.pnn));
93 /* verify we can access the node */
94 ret = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
96 DEBUG(DEBUG_ERR,("Can not ban node. Node is not operational.\n"));
102 check if a database exists
104 static int db_exists(struct ctdb_context *ctdb, const char *db_name)
107 struct ctdb_dbid_map *dbmap=NULL;
109 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
111 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
115 for(i=0;i<dbmap->num;i++){
118 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
119 if (!strcmp(name, db_name)) {
128 see if a process exists
130 static int control_process_exists(struct ctdb_context *ctdb, int argc, const char **argv)
138 if (sscanf(argv[0], "%u:%u", &pnn, &pid) != 2) {
139 DEBUG(DEBUG_ERR, ("Badly formed pnn:pid\n"));
143 ret = ctdb_ctrl_process_exists(ctdb, pnn, pid);
145 printf("%u:%u exists\n", pnn, pid);
147 printf("%u:%u does not exist\n", pnn, pid);
153 display statistics structure
155 static void show_statistics(struct ctdb_statistics *s)
157 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
159 const char *prefix=NULL;
165 #define STATISTICS_FIELD(n) { #n, offsetof(struct ctdb_statistics, n) }
166 STATISTICS_FIELD(num_clients),
167 STATISTICS_FIELD(frozen),
168 STATISTICS_FIELD(recovering),
169 STATISTICS_FIELD(client_packets_sent),
170 STATISTICS_FIELD(client_packets_recv),
171 STATISTICS_FIELD(node_packets_sent),
172 STATISTICS_FIELD(node_packets_recv),
173 STATISTICS_FIELD(keepalive_packets_sent),
174 STATISTICS_FIELD(keepalive_packets_recv),
175 STATISTICS_FIELD(node.req_call),
176 STATISTICS_FIELD(node.reply_call),
177 STATISTICS_FIELD(node.req_dmaster),
178 STATISTICS_FIELD(node.reply_dmaster),
179 STATISTICS_FIELD(node.reply_error),
180 STATISTICS_FIELD(node.req_message),
181 STATISTICS_FIELD(node.req_control),
182 STATISTICS_FIELD(node.reply_control),
183 STATISTICS_FIELD(client.req_call),
184 STATISTICS_FIELD(client.req_message),
185 STATISTICS_FIELD(client.req_control),
186 STATISTICS_FIELD(timeouts.call),
187 STATISTICS_FIELD(timeouts.control),
188 STATISTICS_FIELD(timeouts.traverse),
189 STATISTICS_FIELD(total_calls),
190 STATISTICS_FIELD(pending_calls),
191 STATISTICS_FIELD(lockwait_calls),
192 STATISTICS_FIELD(pending_lockwait_calls),
193 STATISTICS_FIELD(childwrite_calls),
194 STATISTICS_FIELD(pending_childwrite_calls),
195 STATISTICS_FIELD(memory_used),
196 STATISTICS_FIELD(max_hop_count),
198 printf("CTDB version %u\n", CTDB_VERSION);
199 for (i=0;i<ARRAY_SIZE(fields);i++) {
200 if (strchr(fields[i].name, '.')) {
201 preflen = strcspn(fields[i].name, ".")+1;
202 if (!prefix || strncmp(prefix, fields[i].name, preflen) != 0) {
203 prefix = fields[i].name;
204 printf(" %*.*s\n", preflen-1, preflen-1, fields[i].name);
209 printf(" %*s%-22s%*s%10u\n",
211 fields[i].name+preflen,
213 *(uint32_t *)(fields[i].offset+(uint8_t *)s));
215 printf(" %-30s %.6f sec\n", "max_reclock_ctdbd", s->reclock.ctdbd);
216 printf(" %-30s %.6f sec\n", "max_reclock_recd", s->reclock.recd);
218 printf(" %-30s %.6f sec\n", "max_call_latency", s->max_call_latency);
219 printf(" %-30s %.6f sec\n", "max_lockwait_latency", s->max_lockwait_latency);
220 printf(" %-30s %.6f sec\n", "max_childwrite_latency", s->max_childwrite_latency);
221 talloc_free(tmp_ctx);
225 display remote ctdb statistics combined from all nodes
227 static int control_statistics_all(struct ctdb_context *ctdb)
230 struct ctdb_statistics statistics;
234 nodes = ctdb_get_connected_nodes(ctdb, TIMELIMIT(), ctdb, &num_nodes);
235 CTDB_NO_MEMORY(ctdb, nodes);
237 ZERO_STRUCT(statistics);
239 for (i=0;i<num_nodes;i++) {
240 struct ctdb_statistics s1;
242 uint32_t *v1 = (uint32_t *)&s1;
243 uint32_t *v2 = (uint32_t *)&statistics;
245 offsetof(struct ctdb_statistics, __last_counter) / sizeof(uint32_t);
246 ret = ctdb_ctrl_statistics(ctdb, nodes[i], &s1);
248 DEBUG(DEBUG_ERR, ("Unable to get statistics from node %u\n", nodes[i]));
251 for (j=0;j<num_ints;j++) {
254 statistics.max_hop_count =
255 MAX(statistics.max_hop_count, s1.max_hop_count);
256 statistics.max_call_latency =
257 MAX(statistics.max_call_latency, s1.max_call_latency);
258 statistics.max_lockwait_latency =
259 MAX(statistics.max_lockwait_latency, s1.max_lockwait_latency);
262 printf("Gathered statistics for %u nodes\n", num_nodes);
263 show_statistics(&statistics);
268 display remote ctdb statistics
270 static int control_statistics(struct ctdb_context *ctdb, int argc, const char **argv)
273 struct ctdb_statistics statistics;
275 if (options.pnn == CTDB_BROADCAST_ALL) {
276 return control_statistics_all(ctdb);
279 ret = ctdb_ctrl_statistics(ctdb, options.pnn, &statistics);
281 DEBUG(DEBUG_ERR, ("Unable to get statistics from node %u\n", options.pnn));
284 show_statistics(&statistics);
290 reset remote ctdb statistics
292 static int control_statistics_reset(struct ctdb_context *ctdb, int argc, const char **argv)
296 ret = ctdb_statistics_reset(ctdb, options.pnn);
298 DEBUG(DEBUG_ERR, ("Unable to reset statistics on node %u\n", options.pnn));
306 display uptime of remote node
308 static int control_uptime(struct ctdb_context *ctdb, int argc, const char **argv)
311 struct ctdb_uptime *uptime = NULL;
312 int tmp, days, hours, minutes, seconds;
314 ret = ctdb_ctrl_uptime(ctdb, ctdb, TIMELIMIT(), options.pnn, &uptime);
316 DEBUG(DEBUG_ERR, ("Unable to get uptime from node %u\n", options.pnn));
320 if (options.machinereadable){
321 printf(":Current Node Time:Ctdb Start Time:Last Recovery/Failover Time:Last Recovery/IPFailover Duration:\n");
322 printf(":%u:%u:%u:%lf\n",
323 (unsigned int)uptime->current_time.tv_sec,
324 (unsigned int)uptime->ctdbd_start_time.tv_sec,
325 (unsigned int)uptime->last_recovery_finished.tv_sec,
326 timeval_delta(&uptime->last_recovery_finished,
327 &uptime->last_recovery_started)
332 printf("Current time of node : %s", ctime(&uptime->current_time.tv_sec));
334 tmp = uptime->current_time.tv_sec - uptime->ctdbd_start_time.tv_sec;
342 printf("Ctdbd start time : (%03d %02d:%02d:%02d) %s", days, hours, minutes, seconds, ctime(&uptime->ctdbd_start_time.tv_sec));
344 tmp = uptime->current_time.tv_sec - uptime->last_recovery_finished.tv_sec;
352 printf("Time of last recovery/failover: (%03d %02d:%02d:%02d) %s", days, hours, minutes, seconds, ctime(&uptime->last_recovery_finished.tv_sec));
354 printf("Duration of last recovery/failover: %lf seconds\n",
355 timeval_delta(&uptime->last_recovery_finished,
356 &uptime->last_recovery_started));
362 show the PNN of the current node
364 static int control_pnn(struct ctdb_context *ctdb, int argc, const char **argv)
368 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
370 DEBUG(DEBUG_ERR, ("Unable to get pnn from local node."));
374 printf("PNN:%d\n", mypnn);
380 struct pnn_node *next;
385 static struct pnn_node *read_nodes_file(TALLOC_CTX *mem_ctx)
387 const char *nodes_list;
391 struct pnn_node *pnn_nodes = NULL;
392 struct pnn_node *pnn_node;
393 struct pnn_node *tmp_node;
395 /* read the nodes file */
396 nodes_list = getenv("CTDB_NODES");
397 if (nodes_list == NULL) {
398 nodes_list = "/etc/ctdb/nodes";
400 lines = file_lines_load(nodes_list, &nlines, mem_ctx);
404 while (nlines > 0 && strcmp(lines[nlines-1], "") == 0) {
407 for (i=0, pnn=0; i<nlines; i++) {
411 /* strip leading spaces */
412 while((*node == ' ') || (*node == '\t')) {
419 if (strcmp(node, "") == 0) {
422 pnn_node = talloc(mem_ctx, struct pnn_node);
423 pnn_node->pnn = pnn++;
424 pnn_node->addr = talloc_strdup(pnn_node, node);
425 pnn_node->next = pnn_nodes;
426 pnn_nodes = pnn_node;
429 /* swap them around so we return them in incrementing order */
430 pnn_node = pnn_nodes;
434 pnn_node = pnn_node->next;
436 tmp_node->next = pnn_nodes;
437 pnn_nodes = tmp_node;
444 show the PNN of the current node
445 discover the pnn by loading the nodes file and try to bind to all
446 addresses one at a time until the ip address is found.
448 static int control_xpnn(struct ctdb_context *ctdb, int argc, const char **argv)
450 TALLOC_CTX *mem_ctx = talloc_new(NULL);
451 struct pnn_node *pnn_nodes;
452 struct pnn_node *pnn_node;
454 pnn_nodes = read_nodes_file(mem_ctx);
455 if (pnn_nodes == NULL) {
456 DEBUG(DEBUG_ERR,("Failed to read nodes file\n"));
457 talloc_free(mem_ctx);
461 for(pnn_node=pnn_nodes;pnn_node;pnn_node=pnn_node->next) {
464 if (parse_ip(pnn_node->addr, NULL, 63999, &addr) == 0) {
465 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s' in nodes file\n", pnn_node->addr));
466 talloc_free(mem_ctx);
470 if (ctdb_sys_have_ip(&addr)) {
471 printf("PNN:%d\n", pnn_node->pnn);
472 talloc_free(mem_ctx);
477 printf("Failed to detect which PNN this node is\n");
478 talloc_free(mem_ctx);
483 display remote ctdb status
485 static int control_status(struct ctdb_context *ctdb, int argc, const char **argv)
488 struct ctdb_vnn_map *vnnmap=NULL;
489 struct ctdb_node_map *nodemap=NULL;
490 uint32_t recmode, recmaster;
493 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
498 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
500 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
504 if(options.machinereadable){
505 printf(":Node:IP:Disconnected:Banned:Disabled:Unhealthy:Stopped:Inactive:\n");
506 for(i=0;i<nodemap->num;i++){
507 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
510 printf(":%d:%s:%d:%d:%d:%d:%d:%d:\n", nodemap->nodes[i].pnn,
511 ctdb_addr_to_str(&nodemap->nodes[i].addr),
512 !!(nodemap->nodes[i].flags&NODE_FLAGS_DISCONNECTED),
513 !!(nodemap->nodes[i].flags&NODE_FLAGS_BANNED),
514 !!(nodemap->nodes[i].flags&NODE_FLAGS_PERMANENTLY_DISABLED),
515 !!(nodemap->nodes[i].flags&NODE_FLAGS_UNHEALTHY),
516 !!(nodemap->nodes[i].flags&NODE_FLAGS_STOPPED),
517 !!(nodemap->nodes[i].flags&NODE_FLAGS_INACTIVE));
522 printf("Number of nodes:%d\n", nodemap->num);
523 for(i=0;i<nodemap->num;i++){
524 static const struct {
528 { NODE_FLAGS_DISCONNECTED, "DISCONNECTED" },
529 { NODE_FLAGS_PERMANENTLY_DISABLED, "DISABLED" },
530 { NODE_FLAGS_BANNED, "BANNED" },
531 { NODE_FLAGS_UNHEALTHY, "UNHEALTHY" },
532 { NODE_FLAGS_DELETED, "DELETED" },
533 { NODE_FLAGS_STOPPED, "STOPPED" },
534 { NODE_FLAGS_INACTIVE, "INACTIVE" },
536 char *flags_str = NULL;
539 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
542 for (j=0;j<ARRAY_SIZE(flag_names);j++) {
543 if (nodemap->nodes[i].flags & flag_names[j].flag) {
544 if (flags_str == NULL) {
545 flags_str = talloc_strdup(ctdb, flag_names[j].name);
547 flags_str = talloc_asprintf_append(flags_str, "|%s",
550 CTDB_NO_MEMORY_FATAL(ctdb, flags_str);
553 if (flags_str == NULL) {
554 flags_str = talloc_strdup(ctdb, "OK");
555 CTDB_NO_MEMORY_FATAL(ctdb, flags_str);
557 printf("pnn:%d %-16s %s%s\n", nodemap->nodes[i].pnn,
558 ctdb_addr_to_str(&nodemap->nodes[i].addr),
560 nodemap->nodes[i].pnn == mypnn?" (THIS NODE)":"");
561 talloc_free(flags_str);
564 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &vnnmap);
566 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n", options.pnn));
569 if (vnnmap->generation == INVALID_GENERATION) {
570 printf("Generation:INVALID\n");
572 printf("Generation:%d\n",vnnmap->generation);
574 printf("Size:%d\n",vnnmap->size);
575 for(i=0;i<vnnmap->size;i++){
576 printf("hash:%d lmaster:%d\n", i, vnnmap->map[i]);
579 ret = ctdb_ctrl_getrecmode(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmode);
581 DEBUG(DEBUG_ERR, ("Unable to get recmode from node %u\n", options.pnn));
584 printf("Recovery mode:%s (%d)\n",recmode==CTDB_RECOVERY_NORMAL?"NORMAL":"RECOVERY",recmode);
586 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
588 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
591 printf("Recovery master:%d\n",recmaster);
598 struct natgw_node *next;
603 display the list of nodes belonging to this natgw configuration
605 static int control_natgwlist(struct ctdb_context *ctdb, int argc, const char **argv)
608 const char *natgw_list;
611 struct natgw_node *natgw_nodes = NULL;
612 struct natgw_node *natgw_node;
613 struct ctdb_node_map *nodemap=NULL;
616 /* read the natgw nodes file into a linked list */
617 natgw_list = getenv("NATGW_NODES");
618 if (natgw_list == NULL) {
619 natgw_list = "/etc/ctdb/natgw_nodes";
621 lines = file_lines_load(natgw_list, &nlines, ctdb);
623 ctdb_set_error(ctdb, "Failed to load natgw node list '%s'\n", natgw_list);
626 while (nlines > 0 && strcmp(lines[nlines-1], "") == 0) {
629 for (i=0;i<nlines;i++) {
633 /* strip leading spaces */
634 while((*node == ' ') || (*node == '\t')) {
640 if (strcmp(node, "") == 0) {
643 natgw_node = talloc(ctdb, struct natgw_node);
644 natgw_node->addr = talloc_strdup(natgw_node, node);
645 CTDB_NO_MEMORY(ctdb, natgw_node->addr);
646 natgw_node->next = natgw_nodes;
647 natgw_nodes = natgw_node;
650 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
652 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node.\n"));
657 while(i<nodemap->num) {
658 for(natgw_node=natgw_nodes;natgw_node;natgw_node=natgw_node->next) {
659 if (!strcmp(natgw_node->addr, ctdb_addr_to_str(&nodemap->nodes[i].addr))) {
664 /* this node was not in the natgw so we just remove it from
667 if ((natgw_node == NULL)
668 || (nodemap->nodes[i].flags & NODE_FLAGS_DISCONNECTED) ) {
671 for (j=i+1; j<nodemap->num; j++) {
672 nodemap->nodes[j-1] = nodemap->nodes[j];
681 /* pick a node to be natgwmaster
682 * we dont allow STOPPED, DELETED, BANNED or UNHEALTHY nodes to become the natgwmaster
684 for(i=0;i<nodemap->num;i++){
685 if (!(nodemap->nodes[i].flags & (NODE_FLAGS_DISCONNECTED|NODE_FLAGS_STOPPED|NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_UNHEALTHY))) {
686 printf("%d %s\n", nodemap->nodes[i].pnn,ctdb_addr_to_str(&nodemap->nodes[i].addr));
690 /* we couldnt find any healthy node, try unhealthy ones */
691 if (i == nodemap->num) {
692 for(i=0;i<nodemap->num;i++){
693 if (!(nodemap->nodes[i].flags & (NODE_FLAGS_DISCONNECTED|NODE_FLAGS_STOPPED|NODE_FLAGS_DELETED))) {
694 printf("%d %s\n", nodemap->nodes[i].pnn,ctdb_addr_to_str(&nodemap->nodes[i].addr));
699 /* unless all nodes are STOPPED, when we pick one anyway */
700 if (i == nodemap->num) {
701 for(i=0;i<nodemap->num;i++){
702 if (!(nodemap->nodes[i].flags & (NODE_FLAGS_DISCONNECTED|NODE_FLAGS_DELETED))) {
703 printf("%d %s\n", nodemap->nodes[i].pnn, ctdb_addr_to_str(&nodemap->nodes[i].addr));
707 /* or if we still can not find any */
708 if (i == nodemap->num) {
709 printf("-1 0.0.0.0\n");
713 /* print the pruned list of nodes belonging to this natgw list */
714 for(i=0;i<nodemap->num;i++){
715 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
718 printf(":%d:%s:%d:%d:%d:%d:%d\n", nodemap->nodes[i].pnn,
719 ctdb_addr_to_str(&nodemap->nodes[i].addr),
720 !!(nodemap->nodes[i].flags&NODE_FLAGS_DISCONNECTED),
721 !!(nodemap->nodes[i].flags&NODE_FLAGS_BANNED),
722 !!(nodemap->nodes[i].flags&NODE_FLAGS_PERMANENTLY_DISABLED),
723 !!(nodemap->nodes[i].flags&NODE_FLAGS_UNHEALTHY),
724 !!(nodemap->nodes[i].flags&NODE_FLAGS_STOPPED));
731 display the status of the scripts for monitoring (or other events)
733 static int control_one_scriptstatus(struct ctdb_context *ctdb,
734 enum ctdb_eventscript_call type)
736 struct ctdb_scripts_wire *script_status;
739 ret = ctdb_ctrl_getscriptstatus(ctdb, TIMELIMIT(), options.pnn, ctdb, type, &script_status);
741 DEBUG(DEBUG_ERR, ("Unable to get script status from node %u\n", options.pnn));
745 if (script_status == NULL) {
746 if (!options.machinereadable) {
747 printf("%s cycle never run\n",
748 ctdb_eventscript_call_names[type]);
753 if (!options.machinereadable) {
754 printf("%d scripts were executed last %s cycle\n",
755 script_status->num_scripts,
756 ctdb_eventscript_call_names[type]);
758 for (i=0; i<script_status->num_scripts; i++) {
759 const char *status = NULL;
761 switch (script_status->scripts[i].status) {
772 if (script_status->scripts[i].status > 0)
776 if (options.machinereadable) {
777 printf("%s:%s:%i:%s:%lu.%06lu:%lu.%06lu:%s:\n",
778 ctdb_eventscript_call_names[type],
779 script_status->scripts[i].name,
780 script_status->scripts[i].status,
782 (long)script_status->scripts[i].start.tv_sec,
783 (long)script_status->scripts[i].start.tv_usec,
784 (long)script_status->scripts[i].finished.tv_sec,
785 (long)script_status->scripts[i].finished.tv_usec,
786 script_status->scripts[i].output);
790 printf("%-20s Status:%s ",
791 script_status->scripts[i].name, status);
793 /* Some other error, eg from stat. */
794 printf("%-20s Status:CANNOT RUN (%s)",
795 script_status->scripts[i].name,
796 strerror(-script_status->scripts[i].status));
798 if (script_status->scripts[i].status >= 0) {
799 printf("Duration:%.3lf ",
800 timeval_delta(&script_status->scripts[i].finished,
801 &script_status->scripts[i].start));
803 if (script_status->scripts[i].status != -ENOEXEC) {
805 ctime(&script_status->scripts[i].start.tv_sec));
806 if (script_status->scripts[i].status != 0) {
807 printf(" OUTPUT:%s\n",
808 script_status->scripts[i].output);
818 static int control_scriptstatus(struct ctdb_context *ctdb,
819 int argc, const char **argv)
822 enum ctdb_eventscript_call type, min, max;
826 DEBUG(DEBUG_ERR, ("Unknown arguments to scriptstatus\n"));
831 arg = ctdb_eventscript_call_names[CTDB_EVENT_MONITOR];
835 for (type = 0; type < CTDB_EVENT_MAX; type++) {
836 if (strcmp(arg, ctdb_eventscript_call_names[type]) == 0) {
842 if (type == CTDB_EVENT_MAX) {
843 if (strcmp(arg, "all") == 0) {
845 max = CTDB_EVENT_MAX;
847 DEBUG(DEBUG_ERR, ("Unknown event type %s\n", argv[0]));
852 if (options.machinereadable) {
853 printf(":Type:Name:Code:Status:Start:End:Error Output...:\n");
856 for (type = min; type < max; type++) {
857 ret = control_one_scriptstatus(ctdb, type);
867 enable an eventscript
869 static int control_enablescript(struct ctdb_context *ctdb, int argc, const char **argv)
877 ret = ctdb_ctrl_enablescript(ctdb, TIMELIMIT(), options.pnn, argv[0]);
879 DEBUG(DEBUG_ERR, ("Unable to enable script %s on node %u\n", argv[0], options.pnn));
887 disable an eventscript
889 static int control_disablescript(struct ctdb_context *ctdb, int argc, const char **argv)
897 ret = ctdb_ctrl_disablescript(ctdb, TIMELIMIT(), options.pnn, argv[0]);
899 DEBUG(DEBUG_ERR, ("Unable to disable script %s on node %u\n", argv[0], options.pnn));
907 display the pnn of the recovery master
909 static int control_recmaster(struct ctdb_context *ctdb, int argc, const char **argv)
914 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
916 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
919 printf("%d\n",recmaster);
925 get a list of all tickles for this pnn
927 static int control_get_tickles(struct ctdb_context *ctdb, int argc, const char **argv)
929 struct ctdb_control_tcp_tickle_list *list;
937 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
938 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
942 ret = ctdb_ctrl_get_tcp_tickles(ctdb, TIMELIMIT(), options.pnn, ctdb, &addr, &list);
944 DEBUG(DEBUG_ERR, ("Unable to list tickles\n"));
948 printf("Tickles for ip:%s\n", ctdb_addr_to_str(&list->addr));
949 printf("Num tickles:%u\n", list->tickles.num);
950 for (i=0;i<list->tickles.num;i++) {
951 printf("SRC: %s:%u ", ctdb_addr_to_str(&list->tickles.connections[i].src_addr), ntohs(list->tickles.connections[i].src_addr.ip.sin_port));
952 printf("DST: %s:%u\n", ctdb_addr_to_str(&list->tickles.connections[i].dst_addr), ntohs(list->tickles.connections[i].dst_addr.ip.sin_port));
962 static int move_ip(struct ctdb_context *ctdb, ctdb_sock_addr *addr, uint32_t pnn)
964 struct ctdb_all_public_ips *ips;
965 struct ctdb_public_ip ip;
968 uint32_t disable_time;
970 struct ctdb_node_map *nodemap=NULL;
971 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
974 data.dptr = (uint8_t*)&disable_time;
975 data.dsize = sizeof(disable_time);
976 ret = ctdb_send_message(ctdb, CTDB_BROADCAST_CONNECTED, CTDB_SRVID_DISABLE_IP_CHECK, data);
978 DEBUG(DEBUG_ERR,("Failed to send message to disable ipcheck\n"));
984 /* read the public ip list from the node */
985 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), pnn, ctdb, &ips);
987 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", pnn));
988 talloc_free(tmp_ctx);
992 for (i=0;i<ips->num;i++) {
993 if (ctdb_same_ip(addr, &ips->ips[i].addr)) {
998 DEBUG(DEBUG_ERR, ("Node %u can not host ip address '%s'\n",
999 pnn, ctdb_addr_to_str(addr)));
1000 talloc_free(tmp_ctx);
1007 data.dptr = (uint8_t *)&ip;
1008 data.dsize = sizeof(ip);
1010 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &nodemap);
1012 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1013 talloc_free(tmp_ctx);
1017 nodes = list_of_active_nodes_except_pnn(ctdb, nodemap, tmp_ctx, pnn);
1018 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_RELEASE_IP,
1025 DEBUG(DEBUG_ERR,("Failed to release IP on nodes\n"));
1026 talloc_free(tmp_ctx);
1030 ret = ctdb_ctrl_takeover_ip(ctdb, TIMELIMIT(), pnn, &ip);
1032 DEBUG(DEBUG_ERR,("Failed to take over IP on node %d\n", pnn));
1033 talloc_free(tmp_ctx);
1037 talloc_free(tmp_ctx);
1042 move/failover an ip address to a specific node
1044 static int control_moveip(struct ctdb_context *ctdb, int argc, const char **argv)
1047 ctdb_sock_addr addr;
1054 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1055 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1060 if (sscanf(argv[1], "%u", &pnn) != 1) {
1061 DEBUG(DEBUG_ERR, ("Badly formed pnn\n"));
1065 if (move_ip(ctdb, &addr, pnn) != 0) {
1066 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", pnn));
1073 void getips_store_callback(void *param, void *data)
1075 struct ctdb_public_ip *node_ip = (struct ctdb_public_ip *)data;
1076 struct ctdb_all_public_ips *ips = param;
1080 ips->ips[i].pnn = node_ip->pnn;
1081 ips->ips[i].addr = node_ip->addr;
1084 void getips_count_callback(void *param, void *data)
1086 uint32_t *count = param;
1092 static uint32_t *ip_key(ctdb_sock_addr *ip)
1094 static uint32_t key[IP_KEYLEN];
1096 bzero(key, sizeof(key));
1098 switch (ip->sa.sa_family) {
1100 key[0] = ip->ip.sin_addr.s_addr;
1103 key[0] = ip->ip6.sin6_addr.s6_addr32[3];
1104 key[1] = ip->ip6.sin6_addr.s6_addr32[2];
1105 key[2] = ip->ip6.sin6_addr.s6_addr32[1];
1106 key[3] = ip->ip6.sin6_addr.s6_addr32[0];
1109 DEBUG(DEBUG_ERR, (__location__ " ERROR, unknown family passed :%u\n", ip->sa.sa_family));
1116 static void *add_ip_callback(void *parm, void *data)
1122 control_get_all_public_ips(struct ctdb_context *ctdb, TALLOC_CTX *tmp_ctx, struct ctdb_all_public_ips **ips)
1124 struct ctdb_all_public_ips *tmp_ips;
1125 struct ctdb_node_map *nodemap=NULL;
1126 trbt_tree_t *ip_tree;
1130 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1132 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1136 ip_tree = trbt_create(tmp_ctx, 0);
1138 for(i=0;i<nodemap->num;i++){
1139 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
1142 if (nodemap->nodes[i].flags & NODE_FLAGS_DISCONNECTED) {
1146 /* read the public ip list from this node */
1147 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &tmp_ips);
1149 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", nodemap->nodes[i].pnn));
1153 for (j=0; j<tmp_ips->num;j++) {
1154 struct ctdb_public_ip *node_ip;
1156 node_ip = talloc(tmp_ctx, struct ctdb_public_ip);
1157 node_ip->pnn = tmp_ips->ips[j].pnn;
1158 node_ip->addr = tmp_ips->ips[j].addr;
1160 trbt_insertarray32_callback(ip_tree,
1161 IP_KEYLEN, ip_key(&tmp_ips->ips[j].addr),
1165 talloc_free(tmp_ips);
1170 trbt_traversearray32(ip_tree, IP_KEYLEN, getips_count_callback, &count);
1172 len = offsetof(struct ctdb_all_public_ips, ips) +
1173 count*sizeof(struct ctdb_public_ip);
1174 tmp_ips = talloc_zero_size(tmp_ctx, len);
1175 trbt_traversearray32(ip_tree, IP_KEYLEN, getips_store_callback, tmp_ips);
1184 * scans all other nodes and returns a pnn for another node that can host this
1188 find_other_host_for_public_ip(struct ctdb_context *ctdb, ctdb_sock_addr *addr)
1190 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1191 struct ctdb_all_public_ips *ips;
1192 struct ctdb_node_map *nodemap=NULL;
1195 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1197 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1198 talloc_free(tmp_ctx);
1202 for(i=0;i<nodemap->num;i++){
1203 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1206 if (nodemap->nodes[i].pnn == options.pnn) {
1210 /* read the public ip list from this node */
1211 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips);
1213 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", nodemap->nodes[i].pnn));
1217 for (j=0;j<ips->num;j++) {
1218 if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1219 talloc_free(tmp_ctx);
1220 return nodemap->nodes[i].pnn;
1226 talloc_free(tmp_ctx);
1231 add a public ip address to a node
1233 static int control_addip(struct ctdb_context *ctdb, int argc, const char **argv)
1239 ctdb_sock_addr addr;
1240 struct ctdb_control_ip_iface *pub;
1241 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1242 struct ctdb_all_public_ips *ips;
1246 talloc_free(tmp_ctx);
1250 if (!parse_ip_mask(argv[0], argv[1], &addr, &mask)) {
1251 DEBUG(DEBUG_ERR, ("Badly formed ip/mask : %s\n", argv[0]));
1252 talloc_free(tmp_ctx);
1256 ret = control_get_all_public_ips(ctdb, tmp_ctx, &ips);
1258 DEBUG(DEBUG_ERR, ("Unable to get public ip list from cluster\n"));
1259 talloc_free(tmp_ctx);
1264 /* check if some other node is already serving this ip, if not,
1267 for (i=0;i<ips->num;i++) {
1268 if (ctdb_same_ip(&addr, &ips->ips[i].addr)) {
1273 len = offsetof(struct ctdb_control_ip_iface, iface) + strlen(argv[1]) + 1;
1274 pub = talloc_size(tmp_ctx, len);
1275 CTDB_NO_MEMORY(ctdb, pub);
1279 pub->len = strlen(argv[1])+1;
1280 memcpy(&pub->iface[0], argv[1], strlen(argv[1])+1);
1282 ret = ctdb_ctrl_add_public_ip(ctdb, TIMELIMIT(), options.pnn, pub);
1284 DEBUG(DEBUG_ERR, ("Unable to add public ip to node %u\n", options.pnn));
1285 talloc_free(tmp_ctx);
1289 if (i == ips->num) {
1290 /* no one has this ip so we claim it */
1293 pnn = ips->ips[i].pnn;
1296 if (move_ip(ctdb, &addr, pnn) != 0) {
1297 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", pnn));
1301 talloc_free(tmp_ctx);
1305 static int control_delip(struct ctdb_context *ctdb, int argc, const char **argv);
1307 static int control_delip_all(struct ctdb_context *ctdb, int argc, const char **argv, ctdb_sock_addr *addr)
1309 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1310 struct ctdb_node_map *nodemap=NULL;
1311 struct ctdb_all_public_ips *ips;
1314 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1316 DEBUG(DEBUG_ERR, ("Unable to get nodemap from current node\n"));
1320 /* remove it from the nodes that are not hosting the ip currently */
1321 for(i=0;i<nodemap->num;i++){
1322 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1325 if (ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips) != 0) {
1326 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %d\n", nodemap->nodes[i].pnn));
1330 for (j=0;j<ips->num;j++) {
1331 if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1339 if (ips->ips[j].pnn == nodemap->nodes[i].pnn) {
1343 options.pnn = nodemap->nodes[i].pnn;
1344 control_delip(ctdb, argc, argv);
1348 /* remove it from every node (also the one hosting it) */
1349 for(i=0;i<nodemap->num;i++){
1350 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1353 if (ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips) != 0) {
1354 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %d\n", nodemap->nodes[i].pnn));
1358 for (j=0;j<ips->num;j++) {
1359 if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1367 options.pnn = nodemap->nodes[i].pnn;
1368 control_delip(ctdb, argc, argv);
1371 talloc_free(tmp_ctx);
1376 delete a public ip address from a node
1378 static int control_delip(struct ctdb_context *ctdb, int argc, const char **argv)
1381 ctdb_sock_addr addr;
1382 struct ctdb_control_ip_iface pub;
1383 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1384 struct ctdb_all_public_ips *ips;
1387 talloc_free(tmp_ctx);
1391 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1392 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1396 if (options.pnn == CTDB_BROADCAST_ALL) {
1397 return control_delip_all(ctdb, argc, argv, &addr);
1404 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &ips);
1406 DEBUG(DEBUG_ERR, ("Unable to get public ip list from cluster\n"));
1407 talloc_free(tmp_ctx);
1411 for (i=0;i<ips->num;i++) {
1412 if (ctdb_same_ip(&addr, &ips->ips[i].addr)) {
1418 DEBUG(DEBUG_ERR, ("This node does not support this public address '%s'\n",
1419 ctdb_addr_to_str(&addr)));
1420 talloc_free(tmp_ctx);
1424 if (ips->ips[i].pnn == options.pnn) {
1425 ret = find_other_host_for_public_ip(ctdb, &addr);
1427 if (move_ip(ctdb, &addr, ret) != 0) {
1428 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", ret));
1434 ret = ctdb_ctrl_del_public_ip(ctdb, TIMELIMIT(), options.pnn, &pub);
1436 DEBUG(DEBUG_ERR, ("Unable to del public ip from node %u\n", options.pnn));
1437 talloc_free(tmp_ctx);
1441 talloc_free(tmp_ctx);
1446 kill a tcp connection
1448 static int kill_tcp(struct ctdb_context *ctdb, int argc, const char **argv)
1451 struct ctdb_control_killtcp killtcp;
1457 if (!parse_ip_port(argv[0], &killtcp.src_addr)) {
1458 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[0]));
1462 if (!parse_ip_port(argv[1], &killtcp.dst_addr)) {
1463 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[1]));
1467 ret = ctdb_ctrl_killtcp(ctdb, TIMELIMIT(), options.pnn, &killtcp);
1469 DEBUG(DEBUG_ERR, ("Unable to killtcp from node %u\n", options.pnn));
1480 static int control_gratious_arp(struct ctdb_context *ctdb, int argc, const char **argv)
1483 ctdb_sock_addr addr;
1489 if (!parse_ip(argv[0], NULL, 0, &addr)) {
1490 DEBUG(DEBUG_ERR, ("Bad IP '%s'\n", argv[0]));
1494 ret = ctdb_ctrl_gratious_arp(ctdb, TIMELIMIT(), options.pnn, &addr, argv[1]);
1496 DEBUG(DEBUG_ERR, ("Unable to send gratious_arp from node %u\n", options.pnn));
1504 register a server id
1506 static int regsrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1509 struct ctdb_server_id server_id;
1515 server_id.pnn = strtoul(argv[0], NULL, 0);
1516 server_id.type = strtoul(argv[1], NULL, 0);
1517 server_id.server_id = strtoul(argv[2], NULL, 0);
1519 ret = ctdb_ctrl_register_server_id(ctdb, TIMELIMIT(), &server_id);
1521 DEBUG(DEBUG_ERR, ("Unable to register server_id from node %u\n", options.pnn));
1528 unregister a server id
1530 static int unregsrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1533 struct ctdb_server_id server_id;
1539 server_id.pnn = strtoul(argv[0], NULL, 0);
1540 server_id.type = strtoul(argv[1], NULL, 0);
1541 server_id.server_id = strtoul(argv[2], NULL, 0);
1543 ret = ctdb_ctrl_unregister_server_id(ctdb, TIMELIMIT(), &server_id);
1545 DEBUG(DEBUG_ERR, ("Unable to unregister server_id from node %u\n", options.pnn));
1552 check if a server id exists
1554 static int chksrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1558 struct ctdb_server_id server_id;
1564 server_id.pnn = strtoul(argv[0], NULL, 0);
1565 server_id.type = strtoul(argv[1], NULL, 0);
1566 server_id.server_id = strtoul(argv[2], NULL, 0);
1568 ret = ctdb_ctrl_check_server_id(ctdb, TIMELIMIT(), options.pnn, &server_id, &status);
1570 DEBUG(DEBUG_ERR, ("Unable to check server_id from node %u\n", options.pnn));
1575 printf("Server id %d:%d:%d EXISTS\n", server_id.pnn, server_id.type, server_id.server_id);
1577 printf("Server id %d:%d:%d does NOT exist\n", server_id.pnn, server_id.type, server_id.server_id);
1583 get a list of all server ids that are registered on a node
1585 static int getsrvids(struct ctdb_context *ctdb, int argc, const char **argv)
1588 struct ctdb_server_id_list *server_ids;
1590 ret = ctdb_ctrl_get_server_id_list(ctdb, ctdb, TIMELIMIT(), options.pnn, &server_ids);
1592 DEBUG(DEBUG_ERR, ("Unable to get server_id list from node %u\n", options.pnn));
1596 for (i=0; i<server_ids->num; i++) {
1597 printf("Server id %d:%d:%d\n",
1598 server_ids->server_ids[i].pnn,
1599 server_ids->server_ids[i].type,
1600 server_ids->server_ids[i].server_id);
1607 send a tcp tickle ack
1609 static int tickle_tcp(struct ctdb_context *ctdb, int argc, const char **argv)
1612 ctdb_sock_addr src, dst;
1618 if (!parse_ip_port(argv[0], &src)) {
1619 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[0]));
1623 if (!parse_ip_port(argv[1], &dst)) {
1624 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[1]));
1628 ret = ctdb_sys_send_tcp(&src, &dst, 0, 0, 0);
1632 DEBUG(DEBUG_ERR, ("Error while sending tickle ack\n"));
1639 display public ip status
1641 static int control_ip(struct ctdb_context *ctdb, int argc, const char **argv)
1644 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1645 struct ctdb_all_public_ips *ips;
1647 if (options.pnn == CTDB_BROADCAST_ALL) {
1648 /* read the list of public ips from all nodes */
1649 ret = control_get_all_public_ips(ctdb, tmp_ctx, &ips);
1651 /* read the public ip list from this node */
1652 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &ips);
1655 DEBUG(DEBUG_ERR, ("Unable to get public ips from node %u\n", options.pnn));
1656 talloc_free(tmp_ctx);
1660 if (options.machinereadable){
1661 printf(":Public IP:Node:ActiveInterface:AvailableInterfaces:ConfiguredInterfaces:\n");
1663 if (options.pnn == CTDB_BROADCAST_ALL) {
1664 printf("Public IPs on ALL nodes\n");
1666 printf("Public IPs on node %u\n", options.pnn);
1670 for (i=1;i<=ips->num;i++) {
1671 struct ctdb_control_public_ip_info *info = NULL;
1673 char *aciface = NULL;
1674 char *avifaces = NULL;
1675 char *cifaces = NULL;
1677 if (options.pnn == CTDB_BROADCAST_ALL) {
1678 pnn = ips->ips[ips->num-i].pnn;
1684 ret = ctdb_ctrl_get_public_ip_info(ctdb, TIMELIMIT(), pnn, ctdb,
1685 &ips->ips[ips->num-i].addr, &info);
1692 for (j=0; j < info->num; j++) {
1693 if (cifaces == NULL) {
1694 cifaces = talloc_strdup(info,
1695 info->ifaces[j].name);
1697 cifaces = talloc_asprintf_append(cifaces,
1699 info->ifaces[j].name);
1702 if (info->active_idx == j) {
1703 aciface = info->ifaces[j].name;
1706 if (info->ifaces[j].link_state == 0) {
1710 if (avifaces == NULL) {
1711 avifaces = talloc_strdup(info, info->ifaces[j].name);
1713 avifaces = talloc_asprintf_append(avifaces,
1715 info->ifaces[j].name);
1720 if (options.machinereadable){
1721 printf(":%s:%d:%s:%s:%s:\n",
1722 ctdb_addr_to_str(&ips->ips[ips->num-i].addr),
1723 ips->ips[ips->num-i].pnn,
1725 avifaces?avifaces:"",
1726 cifaces?cifaces:"");
1728 printf("%s node[%d] active[%s] available[%s] configured[%s]\n",
1729 ctdb_addr_to_str(&ips->ips[ips->num-i].addr),
1730 ips->ips[ips->num-i].pnn,
1732 avifaces?avifaces:"",
1733 cifaces?cifaces:"");
1738 talloc_free(tmp_ctx);
1745 static int control_ipinfo(struct ctdb_context *ctdb, int argc, const char **argv)
1748 ctdb_sock_addr addr;
1749 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1750 struct ctdb_control_public_ip_info *info;
1753 talloc_free(tmp_ctx);
1757 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1758 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1762 /* read the public ip info from this node */
1763 ret = ctdb_ctrl_get_public_ip_info(ctdb, TIMELIMIT(), options.pnn,
1764 tmp_ctx, &addr, &info);
1766 DEBUG(DEBUG_ERR, ("Unable to get public ip[%s]info from node %u\n",
1767 argv[0], options.pnn));
1768 talloc_free(tmp_ctx);
1772 printf("Public IP[%s] info on node %u\n",
1773 ctdb_addr_to_str(&info->ip.addr),
1776 printf("IP:%s\nCurrentNode:%d\nNumInterfaces:%u\n",
1777 ctdb_addr_to_str(&info->ip.addr),
1778 info->ip.pnn, info->num);
1780 for (i=0; i<info->num; i++) {
1781 info->ifaces[i].name[CTDB_IFACE_SIZE] = '\0';
1783 printf("Interface[%u]: Name:%s Link:%s References:%u%s\n",
1784 i+1, info->ifaces[i].name,
1785 info->ifaces[i].link_state?"up":"down",
1786 (unsigned int)info->ifaces[i].references,
1787 (i==info->active_idx)?" (active)":"");
1790 talloc_free(tmp_ctx);
1795 display interfaces status
1797 static int control_ifaces(struct ctdb_context *ctdb, int argc, const char **argv)
1800 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1801 struct ctdb_control_get_ifaces *ifaces;
1803 /* read the public ip list from this node */
1804 ret = ctdb_ctrl_get_ifaces(ctdb, TIMELIMIT(), options.pnn,
1807 DEBUG(DEBUG_ERR, ("Unable to get interfaces from node %u\n",
1809 talloc_free(tmp_ctx);
1813 if (options.machinereadable){
1814 printf(":Name:LinkStatus:References:\n");
1816 printf("Interfaces on node %u\n", options.pnn);
1819 for (i=0; i<ifaces->num; i++) {
1820 if (options.machinereadable){
1821 printf(":%s:%s:%u\n",
1822 ifaces->ifaces[i].name,
1823 ifaces->ifaces[i].link_state?"1":"0",
1824 (unsigned int)ifaces->ifaces[i].references);
1826 printf("name:%s link:%s references:%u\n",
1827 ifaces->ifaces[i].name,
1828 ifaces->ifaces[i].link_state?"up":"down",
1829 (unsigned int)ifaces->ifaces[i].references);
1833 talloc_free(tmp_ctx);
1839 set link status of an interface
1841 static int control_setifacelink(struct ctdb_context *ctdb, int argc, const char **argv)
1844 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1845 struct ctdb_control_iface_info info;
1853 if (strlen(argv[0]) > CTDB_IFACE_SIZE) {
1854 DEBUG(DEBUG_ERR, ("interfaces name '%s' too long\n",
1856 talloc_free(tmp_ctx);
1859 strcpy(info.name, argv[0]);
1861 if (strcmp(argv[1], "up") == 0) {
1862 info.link_state = 1;
1863 } else if (strcmp(argv[1], "down") == 0) {
1864 info.link_state = 0;
1866 DEBUG(DEBUG_ERR, ("link state invalid '%s' should be 'up' or 'down'\n",
1868 talloc_free(tmp_ctx);
1872 /* read the public ip list from this node */
1873 ret = ctdb_ctrl_set_iface_link(ctdb, TIMELIMIT(), options.pnn,
1876 DEBUG(DEBUG_ERR, ("Unable to set link state for interfaces %s node %u\n",
1877 argv[0], options.pnn));
1878 talloc_free(tmp_ctx);
1882 talloc_free(tmp_ctx);
1887 display pid of a ctdb daemon
1889 static int control_getpid(struct ctdb_context *ctdb, int argc, const char **argv)
1894 ret = ctdb_ctrl_getpid(ctdb, TIMELIMIT(), options.pnn, &pid);
1896 DEBUG(DEBUG_ERR, ("Unable to get daemon pid from node %u\n", options.pnn));
1899 printf("Pid:%d\n", pid);
1905 handler for receiving the response to ipreallocate
1907 static void ip_reallocate_handler(struct ctdb_context *ctdb, uint64_t srvid,
1908 TDB_DATA data, void *private_data)
1913 static void ctdb_every_second(struct event_context *ev, struct timed_event *te, struct timeval t, void *p)
1915 struct ctdb_context *ctdb = talloc_get_type(p, struct ctdb_context);
1917 event_add_timed(ctdb->ev, ctdb,
1918 timeval_current_ofs(1, 0),
1919 ctdb_every_second, ctdb);
1923 ask the recovery daemon on the recovery master to perform a ip reallocation
1925 static int control_ipreallocate(struct ctdb_context *ctdb, int argc, const char **argv)
1929 struct takeover_run_reply rd;
1931 struct ctdb_node_map *nodemap=NULL;
1933 struct timeval tv = timeval_current();
1935 /* we need some events to trigger so we can timeout and restart
1938 event_add_timed(ctdb->ev, ctdb,
1939 timeval_current_ofs(1, 0),
1940 ctdb_every_second, ctdb);
1942 rd.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
1944 DEBUG(DEBUG_ERR, ("Failed to get pnn of local node\n"));
1947 rd.srvid = getpid();
1949 /* register a message port for receiveing the reply so that we
1950 can receive the reply
1952 ctdb_set_message_handler(ctdb, rd.srvid, ip_reallocate_handler, NULL);
1954 data.dptr = (uint8_t *)&rd;
1955 data.dsize = sizeof(rd);
1959 DEBUG(DEBUG_ERR,("Failed waiting for cluster convergense\n"));
1963 /* check that there are valid nodes available */
1964 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap) != 0) {
1965 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
1968 for (i=0; i<nodemap->num;i++) {
1969 if ((nodemap->nodes[i].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) == 0) {
1973 if (i==nodemap->num) {
1974 DEBUG(DEBUG_ERR,("No recmaster available, no need to wait for cluster convergence\n"));
1979 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
1981 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
1985 /* verify the node exists */
1986 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), recmaster, ctdb, &nodemap) != 0) {
1987 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
1992 /* check tha there are nodes available that can act as a recmaster */
1993 for (i=0; i<nodemap->num; i++) {
1994 if (nodemap->nodes[i].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
1999 if (i == nodemap->num) {
2000 DEBUG(DEBUG_ERR,("No possible nodes to host addresses.\n"));
2004 /* verify the recovery master is not STOPPED, nor BANNED */
2005 if (nodemap->nodes[recmaster].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
2006 DEBUG(DEBUG_ERR,("No suitable recmaster found. Try again\n"));
2013 /* verify the recovery master is not STOPPED, nor BANNED */
2014 if (nodemap->nodes[recmaster].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
2015 DEBUG(DEBUG_ERR,("No suitable recmaster found. Try again\n"));
2021 ret = ctdb_send_message(ctdb, recmaster, CTDB_SRVID_TAKEOVER_RUN, data);
2023 DEBUG(DEBUG_ERR,("Failed to send ip takeover run request message to %u\n", options.pnn));
2027 tv = timeval_current();
2028 /* this loop will terminate when we have received the reply */
2029 while (timeval_elapsed(&tv) < 3.0) {
2030 event_loop_once(ctdb->ev);
2033 DEBUG(DEBUG_INFO,("Timed out waiting for recmaster ipreallocate. Trying again\n"));
2043 disable a remote node
2045 static int control_disable(struct ctdb_context *ctdb, int argc, const char **argv)
2048 struct ctdb_node_map *nodemap=NULL;
2051 ret = ctdb_ctrl_modflags(ctdb, TIMELIMIT(), options.pnn, NODE_FLAGS_PERMANENTLY_DISABLED, 0);
2053 DEBUG(DEBUG_ERR, ("Unable to disable node %u\n", options.pnn));
2059 /* read the nodemap and verify the change took effect */
2060 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2061 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2065 } while (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED));
2066 ret = control_ipreallocate(ctdb, argc, argv);
2068 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2076 enable a disabled remote node
2078 static int control_enable(struct ctdb_context *ctdb, int argc, const char **argv)
2082 struct ctdb_node_map *nodemap=NULL;
2085 ret = ctdb_ctrl_modflags(ctdb, TIMELIMIT(), options.pnn, 0, NODE_FLAGS_PERMANENTLY_DISABLED);
2087 DEBUG(DEBUG_ERR, ("Unable to enable node %u\n", options.pnn));
2093 /* read the nodemap and verify the change took effect */
2094 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2095 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2099 } while (nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED);
2100 ret = control_ipreallocate(ctdb, argc, argv);
2102 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2112 static int control_stop(struct ctdb_context *ctdb, int argc, const char **argv)
2115 struct ctdb_node_map *nodemap=NULL;
2118 ret = ctdb_ctrl_stop_node(ctdb, TIMELIMIT(), options.pnn);
2120 DEBUG(DEBUG_ERR, ("Unable to stop node %u try again\n", options.pnn));
2125 /* read the nodemap and verify the change took effect */
2126 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2127 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2131 } while (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_STOPPED));
2132 ret = control_ipreallocate(ctdb, argc, argv);
2134 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2142 restart a stopped remote node
2144 static int control_continue(struct ctdb_context *ctdb, int argc, const char **argv)
2148 struct ctdb_node_map *nodemap=NULL;
2151 ret = ctdb_ctrl_continue_node(ctdb, TIMELIMIT(), options.pnn);
2153 DEBUG(DEBUG_ERR, ("Unable to continue node %u\n", options.pnn));
2159 /* read the nodemap and verify the change took effect */
2160 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2161 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2165 } while (nodemap->nodes[options.pnn].flags & NODE_FLAGS_STOPPED);
2166 ret = control_ipreallocate(ctdb, argc, argv);
2168 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2175 static uint32_t get_generation(struct ctdb_context *ctdb)
2177 struct ctdb_vnn_map *vnnmap=NULL;
2180 /* wait until the recmaster is not in recovery mode */
2182 uint32_t recmode, recmaster;
2184 if (vnnmap != NULL) {
2185 talloc_free(vnnmap);
2189 /* get the recmaster */
2190 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, &recmaster);
2192 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
2196 /* get recovery mode */
2197 ret = ctdb_ctrl_getrecmode(ctdb, ctdb, TIMELIMIT(), recmaster, &recmode);
2199 DEBUG(DEBUG_ERR, ("Unable to get recmode from node %u\n", options.pnn));
2203 /* get the current generation number */
2204 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), recmaster, ctdb, &vnnmap);
2206 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from recmaster (%u)\n", recmaster));
2210 if ((recmode == CTDB_RECOVERY_NORMAL)
2211 && (vnnmap->generation != 1)){
2212 return vnnmap->generation;
2219 ban a node from the cluster
2221 static int control_ban(struct ctdb_context *ctdb, int argc, const char **argv)
2224 struct ctdb_node_map *nodemap=NULL;
2225 struct ctdb_ban_time bantime;
2231 /* verify the node exists */
2232 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
2234 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2238 if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_BANNED) {
2239 DEBUG(DEBUG_ERR,("Node %u is already banned.\n", options.pnn));
2243 bantime.pnn = options.pnn;
2244 bantime.time = strtoul(argv[0], NULL, 0);
2246 ret = ctdb_ctrl_set_ban(ctdb, TIMELIMIT(), options.pnn, &bantime);
2248 DEBUG(DEBUG_ERR,("Banning node %d for %d seconds failed.\n", bantime.pnn, bantime.time));
2252 ret = control_ipreallocate(ctdb, argc, argv);
2254 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2263 unban a node from the cluster
2265 static int control_unban(struct ctdb_context *ctdb, int argc, const char **argv)
2268 struct ctdb_node_map *nodemap=NULL;
2269 struct ctdb_ban_time bantime;
2271 /* verify the node exists */
2272 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
2274 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2278 if (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_BANNED)) {
2279 DEBUG(DEBUG_ERR,("Node %u is not banned.\n", options.pnn));
2283 bantime.pnn = options.pnn;
2286 ret = ctdb_ctrl_set_ban(ctdb, TIMELIMIT(), options.pnn, &bantime);
2288 DEBUG(DEBUG_ERR,("Unbanning node %d failed.\n", bantime.pnn));
2292 ret = control_ipreallocate(ctdb, argc, argv);
2294 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2303 show ban information for a node
2305 static int control_showban(struct ctdb_context *ctdb, int argc, const char **argv)
2308 struct ctdb_node_map *nodemap=NULL;
2309 struct ctdb_ban_time *bantime;
2311 /* verify the node exists */
2312 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
2314 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2318 ret = ctdb_ctrl_get_ban(ctdb, TIMELIMIT(), options.pnn, ctdb, &bantime);
2320 DEBUG(DEBUG_ERR,("Showing ban info for node %d failed.\n", options.pnn));
2324 if (bantime->time == 0) {
2325 printf("Node %u is not banned\n", bantime->pnn);
2327 printf("Node %u is banned banned for %d seconds\n", bantime->pnn, bantime->time);
2336 static int control_shutdown(struct ctdb_context *ctdb, int argc, const char **argv)
2340 ret = ctdb_ctrl_shutdown(ctdb, TIMELIMIT(), options.pnn);
2342 DEBUG(DEBUG_ERR, ("Unable to shutdown node %u\n", options.pnn));
2352 static int control_recover(struct ctdb_context *ctdb, int argc, const char **argv)
2355 uint32_t generation, next_generation;
2357 /* record the current generation number */
2358 generation = get_generation(ctdb);
2360 ret = ctdb_ctrl_freeze_priority(ctdb, TIMELIMIT(), options.pnn, 1);
2362 DEBUG(DEBUG_ERR, ("Unable to freeze node\n"));
2366 ret = ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
2368 DEBUG(DEBUG_ERR, ("Unable to set recovery mode\n"));
2372 /* wait until we are in a new generation */
2374 next_generation = get_generation(ctdb);
2375 if (next_generation != generation) {
2386 display monitoring mode of a remote node
2388 static int control_getmonmode(struct ctdb_context *ctdb, int argc, const char **argv)
2393 ret = ctdb_ctrl_getmonmode(ctdb, TIMELIMIT(), options.pnn, &monmode);
2395 DEBUG(DEBUG_ERR, ("Unable to get monmode from node %u\n", options.pnn));
2398 if (!options.machinereadable){
2399 printf("Monitoring mode:%s (%d)\n",monmode==CTDB_MONITORING_ACTIVE?"ACTIVE":"DISABLED",monmode);
2402 printf(":%d:\n",monmode);
2409 display capabilities of a remote node
2411 static int control_getcapabilities(struct ctdb_context *ctdb, int argc, const char **argv)
2413 uint32_t capabilities;
2416 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), options.pnn, &capabilities);
2418 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", options.pnn));
2422 if (!options.machinereadable){
2423 printf("RECMASTER: %s\n", (capabilities&CTDB_CAP_RECMASTER)?"YES":"NO");
2424 printf("LMASTER: %s\n", (capabilities&CTDB_CAP_LMASTER)?"YES":"NO");
2425 printf("LVS: %s\n", (capabilities&CTDB_CAP_LVS)?"YES":"NO");
2426 printf("NATGW: %s\n", (capabilities&CTDB_CAP_NATGW)?"YES":"NO");
2428 printf(":RECMASTER:LMASTER:LVS:NATGW:\n");
2429 printf(":%d:%d:%d:%d:\n",
2430 !!(capabilities&CTDB_CAP_RECMASTER),
2431 !!(capabilities&CTDB_CAP_LMASTER),
2432 !!(capabilities&CTDB_CAP_LVS),
2433 !!(capabilities&CTDB_CAP_NATGW));
2439 display lvs configuration
2441 static int control_lvs(struct ctdb_context *ctdb, int argc, const char **argv)
2443 uint32_t *capabilities;
2444 struct ctdb_node_map *nodemap=NULL;
2446 int healthy_count = 0;
2448 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
2450 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
2454 capabilities = talloc_array(ctdb, uint32_t, nodemap->num);
2455 CTDB_NO_MEMORY(ctdb, capabilities);
2457 /* collect capabilities for all connected nodes */
2458 for (i=0; i<nodemap->num; i++) {
2459 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2462 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2466 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), i, &capabilities[i]);
2468 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", i));
2472 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2476 if (!(nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY)) {
2481 /* Print all LVS nodes */
2482 for (i=0; i<nodemap->num; i++) {
2483 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2486 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2489 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2493 if (healthy_count != 0) {
2494 if (nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY) {
2499 printf("%d:%s\n", i,
2500 ctdb_addr_to_str(&nodemap->nodes[i].addr));
2507 display who is the lvs master
2509 static int control_lvsmaster(struct ctdb_context *ctdb, int argc, const char **argv)
2511 uint32_t *capabilities;
2512 struct ctdb_node_map *nodemap=NULL;
2514 int healthy_count = 0;
2516 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
2518 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
2522 capabilities = talloc_array(ctdb, uint32_t, nodemap->num);
2523 CTDB_NO_MEMORY(ctdb, capabilities);
2525 /* collect capabilities for all connected nodes */
2526 for (i=0; i<nodemap->num; i++) {
2527 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2530 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2534 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), i, &capabilities[i]);
2536 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", i));
2540 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2544 if (!(nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY)) {
2549 /* find and show the lvsmaster */
2550 for (i=0; i<nodemap->num; i++) {
2551 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2554 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2557 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2561 if (healthy_count != 0) {
2562 if (nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY) {
2567 if (options.machinereadable){
2570 printf("Node %d is LVS master\n", i);
2575 printf("There is no LVS master\n");
2580 disable monitoring on a node
2582 static int control_disable_monmode(struct ctdb_context *ctdb, int argc, const char **argv)
2587 ret = ctdb_ctrl_disable_monmode(ctdb, TIMELIMIT(), options.pnn);
2589 DEBUG(DEBUG_ERR, ("Unable to disable monmode on node %u\n", options.pnn));
2592 printf("Monitoring mode:%s\n","DISABLED");
2598 enable monitoring on a node
2600 static int control_enable_monmode(struct ctdb_context *ctdb, int argc, const char **argv)
2605 ret = ctdb_ctrl_enable_monmode(ctdb, TIMELIMIT(), options.pnn);
2607 DEBUG(DEBUG_ERR, ("Unable to enable monmode on node %u\n", options.pnn));
2610 printf("Monitoring mode:%s\n","ACTIVE");
2616 display remote list of keys/data for a db
2618 static int control_catdb(struct ctdb_context *ctdb, int argc, const char **argv)
2620 const char *db_name;
2621 struct ctdb_db_context *ctdb_db;
2631 if (db_exists(ctdb, db_name)) {
2632 DEBUG(DEBUG_ERR,("Database '%s' does not exist\n", db_name));
2636 ctdb_db = ctdb_attach(ctdb, db_name, false, 0);
2638 if (ctdb_db == NULL) {
2639 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
2643 /* traverse and dump the cluster tdb */
2644 ret = ctdb_dump_db(ctdb_db, stdout);
2646 DEBUG(DEBUG_ERR, ("Unable to dump database\n"));
2647 DEBUG(DEBUG_ERR, ("Maybe try 'ctdb getdbstatus %s'"
2648 " and 'ctdb getvar AllowUnhealthyDBRead'\n",
2652 talloc_free(ctdb_db);
2654 printf("Dumped %d records\n", ret);
2659 static void log_handler(struct ctdb_context *ctdb, uint64_t srvid,
2660 TDB_DATA data, void *private_data)
2662 DEBUG(DEBUG_ERR,("Log data received\n"));
2663 if (data.dsize > 0) {
2664 printf("%s", data.dptr);
2671 display a list of log messages from the in memory ringbuffer
2673 static int control_getlog(struct ctdb_context *ctdb, int argc, const char **argv)
2677 struct ctdb_get_log_addr log_addr;
2679 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2684 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
2685 talloc_free(tmp_ctx);
2689 log_addr.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
2690 log_addr.srvid = getpid();
2691 if (isalpha(argv[0][0]) || argv[0][0] == '-') {
2692 log_addr.level = get_debug_by_desc(argv[0]);
2694 log_addr.level = strtol(argv[0], NULL, 0);
2698 data.dptr = (unsigned char *)&log_addr;
2699 data.dsize = sizeof(log_addr);
2701 DEBUG(DEBUG_ERR, ("Pulling logs from node %u\n", options.pnn));
2703 ctdb_set_message_handler(ctdb, log_addr.srvid, log_handler, NULL);
2706 DEBUG(DEBUG_ERR,("Listen for response on %d\n", (int)log_addr.srvid));
2708 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_GET_LOG,
2709 0, data, tmp_ctx, NULL, &res, NULL, &errmsg);
2710 if (ret != 0 || res != 0) {
2711 DEBUG(DEBUG_ERR,("Failed to get logs - %s\n", errmsg));
2712 talloc_free(tmp_ctx);
2717 tv = timeval_current();
2718 /* this loop will terminate when we have received the reply */
2719 while (timeval_elapsed(&tv) < 3.0) {
2720 event_loop_once(ctdb->ev);
2723 DEBUG(DEBUG_INFO,("Timed out waiting for log data.\n"));
2725 talloc_free(tmp_ctx);
2730 clear the in memory log area
2732 static int control_clearlog(struct ctdb_context *ctdb, int argc, const char **argv)
2737 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2739 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_CLEAR_LOG,
2740 0, tdb_null, tmp_ctx, NULL, &res, NULL, &errmsg);
2741 if (ret != 0 || res != 0) {
2742 DEBUG(DEBUG_ERR,("Failed to clear logs\n"));
2743 talloc_free(tmp_ctx);
2747 talloc_free(tmp_ctx);
2754 display a list of the databases on a remote ctdb
2756 static int control_getdbmap(struct ctdb_context *ctdb, int argc, const char **argv)
2759 struct ctdb_dbid_map *dbmap=NULL;
2761 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
2763 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
2767 if(options.machinereadable){
2768 printf(":ID:Name:Path:Persistent:Unhealthy:\n");
2769 for(i=0;i<dbmap->num;i++){
2775 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn,
2776 dbmap->dbs[i].dbid, ctdb, &path);
2777 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn,
2778 dbmap->dbs[i].dbid, ctdb, &name);
2779 ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn,
2780 dbmap->dbs[i].dbid, ctdb, &health);
2781 persistent = dbmap->dbs[i].persistent;
2782 printf(":0x%08X:%s:%s:%d:%d:\n",
2783 dbmap->dbs[i].dbid, name, path,
2784 !!(persistent), !!(health));
2789 printf("Number of databases:%d\n", dbmap->num);
2790 for(i=0;i<dbmap->num;i++){
2796 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &path);
2797 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
2798 ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &health);
2799 persistent = dbmap->dbs[i].persistent;
2800 printf("dbid:0x%08x name:%s path:%s%s%s\n",
2801 dbmap->dbs[i].dbid, name, path,
2802 persistent?" PERSISTENT":"",
2803 health?" UNHEALTHY":"");
2810 display the status of a database on a remote ctdb
2812 static int control_getdbstatus(struct ctdb_context *ctdb, int argc, const char **argv)
2815 struct ctdb_dbid_map *dbmap=NULL;
2816 const char *db_name;
2824 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
2826 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
2830 for(i=0;i<dbmap->num;i++){
2836 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
2837 if (strcmp(name, db_name) != 0) {
2841 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &path);
2842 ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &health);
2843 persistent = dbmap->dbs[i].persistent;
2844 printf("dbid: 0x%08x\nname: %s\npath: %s\nPERSISTENT: %s\nHEALTH: %s\n",
2845 dbmap->dbs[i].dbid, name, path,
2846 persistent?"yes":"no",
2847 health?health:"OK");
2851 DEBUG(DEBUG_ERR, ("db %s doesn't exist on node %u\n", db_name, options.pnn));
2856 check if the local node is recmaster or not
2857 it will return 1 if this node is the recmaster and 0 if it is not
2858 or if the local ctdb daemon could not be contacted
2860 static int control_isnotrecmaster(struct ctdb_context *ctdb, int argc, const char **argv)
2862 uint32_t mypnn, recmaster;
2865 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
2867 printf("Failed to get pnn of node\n");
2871 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
2873 printf("Failed to get the recmaster\n");
2877 if (recmaster != mypnn) {
2878 printf("this node is not the recmaster\n");
2882 printf("this node is the recmaster\n");
2889 static int control_ping(struct ctdb_context *ctdb, int argc, const char **argv)
2892 struct timeval tv = timeval_current();
2893 ret = ctdb_ctrl_ping(ctdb, options.pnn);
2895 printf("Unable to get ping response from node %u\n", options.pnn);
2898 printf("response from %u time=%.6f sec (%d clients)\n",
2899 options.pnn, timeval_elapsed(&tv), ret);
2908 static int control_getvar(struct ctdb_context *ctdb, int argc, const char **argv)
2919 ret = ctdb_ctrl_get_tunable(ctdb, TIMELIMIT(), options.pnn, name, &value);
2921 DEBUG(DEBUG_ERR, ("Unable to get tunable variable '%s'\n", name));
2925 printf("%-19s = %u\n", name, value);
2932 static int control_setvar(struct ctdb_context *ctdb, int argc, const char **argv)
2943 value = strtoul(argv[1], NULL, 0);
2945 ret = ctdb_ctrl_set_tunable(ctdb, TIMELIMIT(), options.pnn, name, value);
2947 DEBUG(DEBUG_ERR, ("Unable to set tunable variable '%s'\n", name));
2956 static int control_listvars(struct ctdb_context *ctdb, int argc, const char **argv)
2962 ret = ctdb_ctrl_list_tunables(ctdb, TIMELIMIT(), options.pnn, ctdb, &list, &count);
2964 DEBUG(DEBUG_ERR, ("Unable to list tunable variables\n"));
2968 for (i=0;i<count;i++) {
2969 control_getvar(ctdb, 1, &list[i]);
2978 display debug level on a node
2980 static int control_getdebug(struct ctdb_context *ctdb, int argc, const char **argv)
2985 ret = ctdb_ctrl_get_debuglevel(ctdb, options.pnn, &level);
2987 DEBUG(DEBUG_ERR, ("Unable to get debuglevel response from node %u\n", options.pnn));
2990 if (options.machinereadable){
2991 printf(":Name:Level:\n");
2992 printf(":%s:%d:\n",get_debug_by_level(level),level);
2994 printf("Node %u is at debug level %s (%d)\n", options.pnn, get_debug_by_level(level), level);
3001 display reclock file of a node
3003 static int control_getreclock(struct ctdb_context *ctdb, int argc, const char **argv)
3006 const char *reclock;
3008 ret = ctdb_ctrl_getreclock(ctdb, TIMELIMIT(), options.pnn, ctdb, &reclock);
3010 DEBUG(DEBUG_ERR, ("Unable to get reclock file from node %u\n", options.pnn));
3013 if (options.machinereadable){
3014 if (reclock != NULL) {
3015 printf("%s", reclock);
3018 if (reclock == NULL) {
3019 printf("No reclock file used.\n");
3021 printf("Reclock file:%s\n", reclock);
3029 set the reclock file of a node
3031 static int control_setreclock(struct ctdb_context *ctdb, int argc, const char **argv)
3034 const char *reclock;
3038 } else if (argc == 1) {
3044 ret = ctdb_ctrl_setreclock(ctdb, TIMELIMIT(), options.pnn, reclock);
3046 DEBUG(DEBUG_ERR, ("Unable to get reclock file from node %u\n", options.pnn));
3053 set the natgw state on/off
3055 static int control_setnatgwstate(struct ctdb_context *ctdb, int argc, const char **argv)
3058 uint32_t natgwstate;
3064 if (!strcmp(argv[0], "on")) {
3066 } else if (!strcmp(argv[0], "off")) {
3072 ret = ctdb_ctrl_setnatgwstate(ctdb, TIMELIMIT(), options.pnn, natgwstate);
3074 DEBUG(DEBUG_ERR, ("Unable to set the natgw state for node %u\n", options.pnn));
3082 set the lmaster role on/off
3084 static int control_setlmasterrole(struct ctdb_context *ctdb, int argc, const char **argv)
3087 uint32_t lmasterrole;
3093 if (!strcmp(argv[0], "on")) {
3095 } else if (!strcmp(argv[0], "off")) {
3101 ret = ctdb_ctrl_setlmasterrole(ctdb, TIMELIMIT(), options.pnn, lmasterrole);
3103 DEBUG(DEBUG_ERR, ("Unable to set the lmaster role for node %u\n", options.pnn));
3111 set the recmaster role on/off
3113 static int control_setrecmasterrole(struct ctdb_context *ctdb, int argc, const char **argv)
3116 uint32_t recmasterrole;
3122 if (!strcmp(argv[0], "on")) {
3124 } else if (!strcmp(argv[0], "off")) {
3130 ret = ctdb_ctrl_setrecmasterrole(ctdb, TIMELIMIT(), options.pnn, recmasterrole);
3132 DEBUG(DEBUG_ERR, ("Unable to set the recmaster role for node %u\n", options.pnn));
3140 set debug level on a node or all nodes
3142 static int control_setdebug(struct ctdb_context *ctdb, int argc, const char **argv)
3148 printf("You must specify the debug level. Valid levels are:\n");
3149 for (i=0; debug_levels[i].description != NULL; i++) {
3150 printf("%s (%d)\n", debug_levels[i].description, debug_levels[i].level);
3156 if (isalpha(argv[0][0]) || argv[0][0] == '-') {
3157 level = get_debug_by_desc(argv[0]);
3159 level = strtol(argv[0], NULL, 0);
3162 for (i=0; debug_levels[i].description != NULL; i++) {
3163 if (level == debug_levels[i].level) {
3167 if (debug_levels[i].description == NULL) {
3168 printf("Invalid debug level, must be one of\n");
3169 for (i=0; debug_levels[i].description != NULL; i++) {
3170 printf("%s (%d)\n", debug_levels[i].description, debug_levels[i].level);
3175 ret = ctdb_ctrl_set_debuglevel(ctdb, options.pnn, level);
3177 DEBUG(DEBUG_ERR, ("Unable to set debug level on node %u\n", options.pnn));
3186 static int control_freeze(struct ctdb_context *ctdb, int argc, const char **argv)
3192 priority = strtol(argv[0], NULL, 0);
3196 DEBUG(DEBUG_ERR,("Freeze by priority %u\n", priority));
3198 ret = ctdb_ctrl_freeze_priority(ctdb, TIMELIMIT(), options.pnn, priority);
3200 DEBUG(DEBUG_ERR, ("Unable to freeze node %u\n", options.pnn));
3208 static int control_thaw(struct ctdb_context *ctdb, int argc, const char **argv)
3214 priority = strtol(argv[0], NULL, 0);
3218 DEBUG(DEBUG_ERR,("Thaw by priority %u\n", priority));
3220 ret = ctdb_ctrl_thaw_priority(ctdb, TIMELIMIT(), options.pnn, priority);
3222 DEBUG(DEBUG_ERR, ("Unable to thaw node %u\n", options.pnn));
3229 attach to a database
3231 static int control_attach(struct ctdb_context *ctdb, int argc, const char **argv)
3233 const char *db_name;
3234 struct ctdb_db_context *ctdb_db;
3241 ctdb_db = ctdb_attach(ctdb, db_name, false, 0);
3242 if (ctdb_db == NULL) {
3243 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
3253 static int control_setdbprio(struct ctdb_context *ctdb, int argc, const char **argv)
3255 struct ctdb_db_priority db_prio;
3262 db_prio.db_id = strtoul(argv[0], NULL, 0);
3263 db_prio.priority = strtoul(argv[1], NULL, 0);
3265 ret = ctdb_ctrl_set_db_priority(ctdb, TIMELIMIT(), options.pnn, &db_prio);
3267 DEBUG(DEBUG_ERR,("Unable to set db prio\n"));
3277 static int control_getdbprio(struct ctdb_context *ctdb, int argc, const char **argv)
3279 uint32_t db_id, priority;
3286 db_id = strtoul(argv[0], NULL, 0);
3288 ret = ctdb_ctrl_get_db_priority(ctdb, TIMELIMIT(), options.pnn, db_id, &priority);
3290 DEBUG(DEBUG_ERR,("Unable to get db prio\n"));
3294 DEBUG(DEBUG_ERR,("Priority:%u\n", priority));
3300 run an eventscript on a node
3302 static int control_eventscript(struct ctdb_context *ctdb, int argc, const char **argv)
3308 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3311 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3315 data.dptr = (unsigned char *)discard_const(argv[0]);
3316 data.dsize = strlen((char *)data.dptr) + 1;
3318 DEBUG(DEBUG_ERR, ("Running eventscripts with arguments \"%s\" on node %u\n", data.dptr, options.pnn));
3320 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_RUN_EVENTSCRIPTS,
3321 0, data, tmp_ctx, NULL, &res, NULL, &errmsg);
3322 if (ret != 0 || res != 0) {
3323 DEBUG(DEBUG_ERR,("Failed to run eventscripts - %s\n", errmsg));
3324 talloc_free(tmp_ctx);
3327 talloc_free(tmp_ctx);
3331 #define DB_VERSION 1
3332 #define MAX_DB_NAME 64
3333 struct db_file_header {
3334 unsigned long version;
3336 unsigned long persistent;
3338 const char name[MAX_DB_NAME];
3341 struct backup_data {
3342 struct ctdb_marshall_buffer *records;
3345 bool traverse_error;
3348 static int backup_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *private)
3350 struct backup_data *bd = talloc_get_type(private, struct backup_data);
3351 struct ctdb_rec_data *rec;
3353 /* add the record */
3354 rec = ctdb_marshall_record(bd->records, 0, key, NULL, data);
3356 bd->traverse_error = true;
3357 DEBUG(DEBUG_ERR,("Failed to marshall record\n"));
3360 bd->records = talloc_realloc_size(NULL, bd->records, rec->length + bd->len);
3361 if (bd->records == NULL) {
3362 DEBUG(DEBUG_ERR,("Failed to expand marshalling buffer\n"));
3363 bd->traverse_error = true;
3366 bd->records->count++;
3367 memcpy(bd->len+(uint8_t *)bd->records, rec, rec->length);
3368 bd->len += rec->length;
3376 * backup a database to a file
3378 static int control_backupdb(struct ctdb_context *ctdb, int argc, const char **argv)
3381 struct ctdb_dbid_map *dbmap=NULL;
3382 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3383 struct db_file_header dbhdr;
3384 struct ctdb_db_context *ctdb_db;
3385 struct backup_data *bd;
3388 const char *reason = NULL;
3391 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3395 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &dbmap);
3397 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
3401 for(i=0;i<dbmap->num;i++){
3404 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, tmp_ctx, &name);
3405 if(!strcmp(argv[0], name)){
3406 talloc_free(discard_const(name));
3409 talloc_free(discard_const(name));
3411 if (i == dbmap->num) {
3412 DEBUG(DEBUG_ERR,("No database with name '%s' found\n", argv[0]));
3413 talloc_free(tmp_ctx);
3417 ret = ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn,
3418 dbmap->dbs[i].dbid, tmp_ctx, &reason);
3420 DEBUG(DEBUG_ERR,("Unable to get dbhealth for database '%s'\n",
3422 talloc_free(tmp_ctx);
3426 uint32_t allow_unhealthy = 0;
3428 ctdb_ctrl_get_tunable(ctdb, TIMELIMIT(), options.pnn,
3429 "AllowUnhealthyDBRead",
3432 if (allow_unhealthy != 1) {
3433 DEBUG(DEBUG_ERR,("database '%s' is unhealthy: %s\n",
3436 DEBUG(DEBUG_ERR,("disallow backup : tunnable AllowUnhealthyDBRead = %u\n",
3438 talloc_free(tmp_ctx);
3442 DEBUG(DEBUG_WARNING,("WARNING database '%s' is unhealthy - see 'ctdb getdbstatus %s'\n",
3444 DEBUG(DEBUG_WARNING,("WARNING! allow backup of unhealthy database: "
3445 "tunnable AllowUnhealthyDBRead = %u\n",
3449 ctdb_db = ctdb_attach(ctdb, argv[0], dbmap->dbs[i].persistent, 0);
3450 if (ctdb_db == NULL) {
3451 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", argv[0]));
3452 talloc_free(tmp_ctx);
3457 ret = tdb_transaction_start(ctdb_db->ltdb->tdb);
3459 DEBUG(DEBUG_ERR,("Failed to start transaction\n"));
3460 talloc_free(tmp_ctx);
3465 bd = talloc_zero(tmp_ctx, struct backup_data);
3467 DEBUG(DEBUG_ERR,("Failed to allocate backup_data\n"));
3468 talloc_free(tmp_ctx);
3472 bd->records = talloc_zero(bd, struct ctdb_marshall_buffer);
3473 if (bd->records == NULL) {
3474 DEBUG(DEBUG_ERR,("Failed to allocate ctdb_marshall_buffer\n"));
3475 talloc_free(tmp_ctx);
3479 bd->len = offsetof(struct ctdb_marshall_buffer, data);
3480 bd->records->db_id = ctdb_db->db_id;
3481 /* traverse the database collecting all records */
3482 if (tdb_traverse_read(ctdb_db->ltdb->tdb, backup_traverse, bd) == -1 ||
3483 bd->traverse_error) {
3484 DEBUG(DEBUG_ERR,("Traverse error\n"));
3485 talloc_free(tmp_ctx);
3489 tdb_transaction_cancel(ctdb_db->ltdb->tdb);
3492 fh = open(argv[1], O_RDWR|O_CREAT, 0600);
3494 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[1]));
3495 talloc_free(tmp_ctx);
3499 dbhdr.version = DB_VERSION;
3500 dbhdr.timestamp = time(NULL);
3501 dbhdr.persistent = dbmap->dbs[i].persistent;
3502 dbhdr.size = bd->len;
3503 if (strlen(argv[0]) >= MAX_DB_NAME) {
3504 DEBUG(DEBUG_ERR,("Too long dbname\n"));
3507 strncpy(discard_const(dbhdr.name), argv[0], MAX_DB_NAME);
3508 ret = write(fh, &dbhdr, sizeof(dbhdr));
3510 DEBUG(DEBUG_ERR,("write failed: %s\n", strerror(errno)));
3513 ret = write(fh, bd->records, bd->len);
3515 DEBUG(DEBUG_ERR,("write failed: %s\n", strerror(errno)));
3524 DEBUG(DEBUG_ERR,("close failed: %s\n", strerror(errno)));
3527 talloc_free(tmp_ctx);
3532 * restore a database from a file
3534 static int control_restoredb(struct ctdb_context *ctdb, int argc, const char **argv)
3537 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3540 struct db_file_header dbhdr;
3541 struct ctdb_db_context *ctdb_db;
3542 struct ctdb_node_map *nodemap=NULL;
3543 struct ctdb_vnn_map *vnnmap=NULL;
3545 struct ctdb_control_wipe_database w;
3547 uint32_t generation;
3552 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3556 fh = open(argv[0], O_RDONLY);
3558 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[0]));
3559 talloc_free(tmp_ctx);
3563 read(fh, &dbhdr, sizeof(dbhdr));
3564 if (dbhdr.version != DB_VERSION) {
3565 DEBUG(DEBUG_ERR,("Invalid version of database dump. File is version %lu but expected version was %u\n", dbhdr.version, DB_VERSION));
3566 talloc_free(tmp_ctx);
3570 outdata.dsize = dbhdr.size;
3571 outdata.dptr = talloc_size(tmp_ctx, outdata.dsize);
3572 if (outdata.dptr == NULL) {
3573 DEBUG(DEBUG_ERR,("Failed to allocate data of size '%lu'\n", dbhdr.size));
3575 talloc_free(tmp_ctx);
3578 read(fh, outdata.dptr, outdata.dsize);
3581 tm = localtime(&dbhdr.timestamp);
3582 strftime(tbuf,sizeof(tbuf)-1,"%Y/%m/%d %H:%M:%S", tm);
3583 printf("Restoring database '%s' from backup @ %s\n",
3587 ctdb_db = ctdb_attach(ctdb, dbhdr.name, dbhdr.persistent, 0);
3588 if (ctdb_db == NULL) {
3589 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", dbhdr.name));
3590 talloc_free(tmp_ctx);
3594 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
3596 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
3597 talloc_free(tmp_ctx);
3602 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &vnnmap);
3604 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n", options.pnn));
3605 talloc_free(tmp_ctx);
3609 /* freeze all nodes */
3610 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3611 for (i=1; i<=NUM_DB_PRIORITIES; i++) {
3612 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_FREEZE,
3618 DEBUG(DEBUG_ERR, ("Unable to freeze nodes.\n"));
3619 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3620 talloc_free(tmp_ctx);
3625 generation = vnnmap->generation;
3626 data.dptr = (void *)&generation;
3627 data.dsize = sizeof(generation);
3629 /* start a cluster wide transaction */
3630 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3631 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_START,
3633 TIMELIMIT(), false, data,
3636 DEBUG(DEBUG_ERR, ("Unable to start cluster wide transactions.\n"));
3641 w.db_id = ctdb_db->db_id;
3642 w.transaction_id = generation;
3644 data.dptr = (void *)&w;
3645 data.dsize = sizeof(w);
3647 /* wipe all the remote databases. */
3648 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3649 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_WIPE_DATABASE,
3651 TIMELIMIT(), false, data,
3654 DEBUG(DEBUG_ERR, ("Unable to wipe database.\n"));
3655 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3656 talloc_free(tmp_ctx);
3660 /* push the database */
3661 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3662 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_PUSH_DB,
3664 TIMELIMIT(), false, outdata,
3667 DEBUG(DEBUG_ERR, ("Failed to push database.\n"));
3668 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3669 talloc_free(tmp_ctx);
3673 data.dptr = (void *)&ctdb_db->db_id;
3674 data.dsize = sizeof(ctdb_db->db_id);
3676 /* mark the database as healthy */
3677 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3678 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_DB_SET_HEALTHY,
3680 TIMELIMIT(), false, data,
3683 DEBUG(DEBUG_ERR, ("Failed to mark database as healthy.\n"));
3684 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3685 talloc_free(tmp_ctx);
3689 data.dptr = (void *)&generation;
3690 data.dsize = sizeof(generation);
3692 /* commit all the changes */
3693 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_COMMIT,
3695 TIMELIMIT(), false, data,
3698 DEBUG(DEBUG_ERR, ("Unable to commit databases.\n"));
3699 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3700 talloc_free(tmp_ctx);
3705 /* thaw all nodes */
3706 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3707 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_THAW,
3713 DEBUG(DEBUG_ERR, ("Unable to thaw nodes.\n"));
3714 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3715 talloc_free(tmp_ctx);
3720 talloc_free(tmp_ctx);
3725 * dump a database backup from a file
3727 static int control_dumpdbbackup(struct ctdb_context *ctdb, int argc, const char **argv)
3729 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3731 struct db_file_header dbhdr;
3735 struct ctdb_rec_data *rec = NULL;
3736 struct ctdb_marshall_buffer *m;
3739 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3743 fh = open(argv[0], O_RDONLY);
3745 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[0]));
3746 talloc_free(tmp_ctx);
3750 read(fh, &dbhdr, sizeof(dbhdr));
3751 if (dbhdr.version != DB_VERSION) {
3752 DEBUG(DEBUG_ERR,("Invalid version of database dump. File is version %lu but expected version was %u\n", dbhdr.version, DB_VERSION));
3753 talloc_free(tmp_ctx);
3757 outdata.dsize = dbhdr.size;
3758 outdata.dptr = talloc_size(tmp_ctx, outdata.dsize);
3759 if (outdata.dptr == NULL) {
3760 DEBUG(DEBUG_ERR,("Failed to allocate data of size '%lu'\n", dbhdr.size));
3762 talloc_free(tmp_ctx);
3765 read(fh, outdata.dptr, outdata.dsize);
3767 m = (struct ctdb_marshall_buffer *)outdata.dptr;
3769 tm = localtime(&dbhdr.timestamp);
3770 strftime(tbuf,sizeof(tbuf)-1,"%Y/%m/%d %H:%M:%S", tm);
3771 printf("Backup of database name:'%s' dbid:0x%x08x from @ %s\n",
3772 dbhdr.name, m->db_id, tbuf);
3774 for (i=0; i < m->count; i++) {
3778 /* we do not want the header splitted, so we pass NULL*/
3779 rec = ctdb_marshall_loop_next(m, rec, &reqid,
3782 ctdb_dumpdb_record(ctdb, key, data, stdout);
3785 printf("Dumped %d records\n", i);
3786 talloc_free(tmp_ctx);
3791 * wipe a database from a file
3793 static int control_wipedb(struct ctdb_context *ctdb, int argc,
3797 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3799 struct ctdb_db_context *ctdb_db;
3800 struct ctdb_node_map *nodemap = NULL;
3801 struct ctdb_vnn_map *vnnmap = NULL;
3803 struct ctdb_control_wipe_database w;
3805 uint32_t generation;
3806 struct ctdb_dbid_map *dbmap = NULL;
3809 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3813 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx,
3816 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n",
3821 for(i=0;i<dbmap->num;i++){
3824 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn,
3825 dbmap->dbs[i].dbid, tmp_ctx, &name);
3826 if(!strcmp(argv[0], name)){
3827 talloc_free(discard_const(name));
3830 talloc_free(discard_const(name));
3832 if (i == dbmap->num) {
3833 DEBUG(DEBUG_ERR, ("No database with name '%s' found\n",
3835 talloc_free(tmp_ctx);
3839 ctdb_db = ctdb_attach(ctdb, argv[0], dbmap->dbs[i].persistent, 0);
3840 if (ctdb_db == NULL) {
3841 DEBUG(DEBUG_ERR, ("Unable to attach to database '%s'\n",
3843 talloc_free(tmp_ctx);
3847 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb,
3850 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n",
3852 talloc_free(tmp_ctx);
3856 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx,
3859 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n",
3861 talloc_free(tmp_ctx);
3865 /* freeze all nodes */
3866 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3867 for (i=1; i<=NUM_DB_PRIORITIES; i++) {
3868 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_FREEZE,
3875 DEBUG(DEBUG_ERR, ("Unable to freeze nodes.\n"));
3876 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn,
3877 CTDB_RECOVERY_ACTIVE);
3878 talloc_free(tmp_ctx);
3883 generation = vnnmap->generation;
3884 data.dptr = (void *)&generation;
3885 data.dsize = sizeof(generation);
3887 /* start a cluster wide transaction */
3888 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3889 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_START,
3891 TIMELIMIT(), false, data,
3895 DEBUG(DEBUG_ERR, ("Unable to start cluster wide "
3896 "transactions.\n"));
3900 w.db_id = ctdb_db->db_id;
3901 w.transaction_id = generation;
3903 data.dptr = (void *)&w;
3904 data.dsize = sizeof(w);
3906 /* wipe all the remote databases. */
3907 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3908 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_WIPE_DATABASE,
3910 TIMELIMIT(), false, data,
3913 DEBUG(DEBUG_ERR, ("Unable to wipe database.\n"));
3914 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3915 talloc_free(tmp_ctx);
3919 data.dptr = (void *)&ctdb_db->db_id;
3920 data.dsize = sizeof(ctdb_db->db_id);
3922 /* mark the database as healthy */
3923 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3924 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_DB_SET_HEALTHY,
3926 TIMELIMIT(), false, data,
3929 DEBUG(DEBUG_ERR, ("Failed to mark database as healthy.\n"));
3930 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3931 talloc_free(tmp_ctx);
3935 data.dptr = (void *)&generation;
3936 data.dsize = sizeof(generation);
3938 /* commit all the changes */
3939 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_COMMIT,
3941 TIMELIMIT(), false, data,
3944 DEBUG(DEBUG_ERR, ("Unable to commit databases.\n"));
3945 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3946 talloc_free(tmp_ctx);
3950 /* thaw all nodes */
3951 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3952 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_THAW,
3958 DEBUG(DEBUG_ERR, ("Unable to thaw nodes.\n"));
3959 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3960 talloc_free(tmp_ctx);
3964 talloc_free(tmp_ctx);
3969 * set flags of a node in the nodemap
3971 static int control_setflags(struct ctdb_context *ctdb, int argc, const char **argv)
3978 struct ctdb_node_flag_change c;
3985 if (sscanf(argv[0], "%d", &node) != 1) {
3986 DEBUG(DEBUG_ERR, ("Badly formed node\n"));
3990 if (sscanf(argv[1], "0x%x", &flags) != 1) {
3991 DEBUG(DEBUG_ERR, ("Badly formed flags\n"));
3998 c.new_flags = flags;
4000 data.dsize = sizeof(c);
4001 data.dptr = (unsigned char *)&c;
4003 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_MODIFY_FLAGS, 0,
4004 data, NULL, NULL, &status, NULL, NULL);
4005 if (ret != 0 || status != 0) {
4006 DEBUG(DEBUG_ERR,("Failed to modify flags\n"));
4015 static int control_dumpmemory(struct ctdb_context *ctdb, int argc, const char **argv)
4021 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
4022 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_DUMP_MEMORY,
4023 0, tdb_null, tmp_ctx, &data, &res, NULL, &errmsg);
4024 if (ret != 0 || res != 0) {
4025 DEBUG(DEBUG_ERR,("Failed to dump memory - %s\n", errmsg));
4026 talloc_free(tmp_ctx);
4029 write(1, data.dptr, data.dsize);
4030 talloc_free(tmp_ctx);
4035 handler for memory dumps
4037 static void mem_dump_handler(struct ctdb_context *ctdb, uint64_t srvid,
4038 TDB_DATA data, void *private_data)
4040 write(1, data.dptr, data.dsize);
4045 dump memory usage on the recovery daemon
4047 static int control_rddumpmemory(struct ctdb_context *ctdb, int argc, const char **argv)
4051 struct rd_memdump_reply rd;
4053 rd.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
4055 DEBUG(DEBUG_ERR, ("Failed to get pnn of local node\n"));
4058 rd.srvid = getpid();
4060 /* register a message port for receiveing the reply so that we
4061 can receive the reply
4063 ctdb_set_message_handler(ctdb, rd.srvid, mem_dump_handler, NULL);
4066 data.dptr = (uint8_t *)&rd;
4067 data.dsize = sizeof(rd);
4069 ret = ctdb_send_message(ctdb, options.pnn, CTDB_SRVID_MEM_DUMP, data);
4071 DEBUG(DEBUG_ERR,("Failed to send memdump request message to %u\n", options.pnn));
4075 /* this loop will terminate when we have received the reply */
4077 event_loop_once(ctdb->ev);
4084 list all nodes in the cluster
4085 if the daemon is running, we read the data from the daemon.
4086 if the daemon is not running we parse the nodes file directly
4088 static int control_listnodes(struct ctdb_context *ctdb, int argc, const char **argv)
4091 struct ctdb_node_map *nodemap=NULL;
4094 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
4096 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
4100 for(i=0;i<nodemap->num;i++){
4101 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
4104 if (options.machinereadable){
4105 printf(":%d:%s:\n", nodemap->nodes[i].pnn, ctdb_addr_to_str(&nodemap->nodes[i].addr));
4107 printf("%s\n", ctdb_addr_to_str(&nodemap->nodes[i].addr));
4111 TALLOC_CTX *mem_ctx = talloc_new(NULL);
4112 struct pnn_node *pnn_nodes;
4113 struct pnn_node *pnn_node;
4115 pnn_nodes = read_nodes_file(mem_ctx);
4116 if (pnn_nodes == NULL) {
4117 DEBUG(DEBUG_ERR,("Failed to read nodes file\n"));
4118 talloc_free(mem_ctx);
4122 for(pnn_node=pnn_nodes;pnn_node;pnn_node=pnn_node->next) {
4123 ctdb_sock_addr addr;
4125 if (parse_ip(pnn_node->addr, NULL, 63999, &addr) == 0) {
4126 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s' in nodes file\n", pnn_node->addr));
4127 talloc_free(mem_ctx);
4131 if (options.machinereadable){
4132 printf(":%d:%s:\n", pnn_node->pnn, pnn_node->addr);
4134 printf("%s\n", pnn_node->addr);
4137 talloc_free(mem_ctx);
4144 reload the nodes file on the local node
4146 static int control_reload_nodes_file(struct ctdb_context *ctdb, int argc, const char **argv)
4150 struct ctdb_node_map *nodemap=NULL;
4152 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
4154 DEBUG(DEBUG_ERR, ("Failed to read pnn of local node\n"));
4158 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
4160 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
4164 /* reload the nodes file on all remote nodes */
4165 for (i=0;i<nodemap->num;i++) {
4166 if (nodemap->nodes[i].pnn == mypnn) {
4169 DEBUG(DEBUG_NOTICE, ("Reloading nodes file on node %u\n", nodemap->nodes[i].pnn));
4170 ret = ctdb_ctrl_reload_nodes_file(ctdb, TIMELIMIT(),
4171 nodemap->nodes[i].pnn);
4173 DEBUG(DEBUG_ERR, ("ERROR: Failed to reload nodes file on node %u. You MUST fix that node manually!\n", nodemap->nodes[i].pnn));
4177 /* reload the nodes file on the local node */
4178 DEBUG(DEBUG_NOTICE, ("Reloading nodes file on node %u\n", mypnn));
4179 ret = ctdb_ctrl_reload_nodes_file(ctdb, TIMELIMIT(), mypnn);
4181 DEBUG(DEBUG_ERR, ("ERROR: Failed to reload nodes file on node %u. You MUST fix that node manually!\n", mypnn));
4184 /* initiate a recovery */
4185 control_recover(ctdb, argc, argv);
4191 static const struct {
4193 int (*fn)(struct ctdb_context *, int, const char **);
4195 bool without_daemon; /* can be run without daemon running ? */
4198 } ctdb_commands[] = {
4200 { "version", control_version, true, false, "show version of ctdb" },
4202 { "status", control_status, true, false, "show node status" },
4203 { "uptime", control_uptime, true, false, "show node uptime" },
4204 { "ping", control_ping, true, false, "ping all nodes" },
4205 { "getvar", control_getvar, true, false, "get a tunable variable", "<name>"},
4206 { "setvar", control_setvar, true, false, "set a tunable variable", "<name> <value>"},
4207 { "listvars", control_listvars, true, false, "list tunable variables"},
4208 { "statistics", control_statistics, false, false, "show statistics" },
4209 { "statisticsreset", control_statistics_reset, true, false, "reset statistics"},
4210 { "ip", control_ip, false, false, "show which public ip's that ctdb manages" },
4211 { "ipinfo", control_ipinfo, true, false, "show details about a public ip that ctdb manages", "<ip>" },
4212 { "ifaces", control_ifaces, true, false, "show which interfaces that ctdb manages" },
4213 { "setifacelink", control_setifacelink, true, false, "set interface link status", "<iface> <status>" },
4214 { "process-exists", control_process_exists, true, false, "check if a process exists on a node", "<pid>"},
4215 { "getdbmap", control_getdbmap, true, false, "show the database map" },
4216 { "getdbstatus", control_getdbstatus, true, false, "show the status of a database", "<dbname>" },
4217 { "catdb", control_catdb, true, false, "dump a database" , "<dbname>"},
4218 { "getmonmode", control_getmonmode, true, false, "show monitoring mode" },
4219 { "getcapabilities", control_getcapabilities, true, false, "show node capabilities" },
4220 { "pnn", control_pnn, true, false, "show the pnn of the currnet node" },
4221 { "lvs", control_lvs, true, false, "show lvs configuration" },
4222 { "lvsmaster", control_lvsmaster, true, false, "show which node is the lvs master" },
4223 { "disablemonitor", control_disable_monmode,true, false, "set monitoring mode to DISABLE" },
4224 { "enablemonitor", control_enable_monmode, true, false, "set monitoring mode to ACTIVE" },
4225 { "setdebug", control_setdebug, true, false, "set debug level", "<EMERG|ALERT|CRIT|ERR|WARNING|NOTICE|INFO|DEBUG>" },
4226 { "getdebug", control_getdebug, true, false, "get debug level" },
4227 { "getlog", control_getlog, true, false, "get the log data from the in memory ringbuffer", "<level>" },
4228 { "clearlog", control_clearlog, true, false, "clear the log data from the in memory ringbuffer" },
4229 { "attach", control_attach, true, false, "attach to a database", "<dbname>" },
4230 { "dumpmemory", control_dumpmemory, true, false, "dump memory map to stdout" },
4231 { "rddumpmemory", control_rddumpmemory, true, false, "dump memory map from the recovery daemon to stdout" },
4232 { "getpid", control_getpid, true, false, "get ctdbd process ID" },
4233 { "disable", control_disable, true, false, "disable a nodes public IP" },
4234 { "enable", control_enable, true, false, "enable a nodes public IP" },
4235 { "stop", control_stop, true, false, "stop a node" },
4236 { "continue", control_continue, true, false, "re-start a stopped node" },
4237 { "ban", control_ban, true, false, "ban a node from the cluster", "<bantime|0>"},
4238 { "unban", control_unban, true, false, "unban a node" },
4239 { "showban", control_showban, true, false, "show ban information"},
4240 { "shutdown", control_shutdown, true, false, "shutdown ctdbd" },
4241 { "recover", control_recover, true, false, "force recovery" },
4242 { "ipreallocate", control_ipreallocate, true, false, "force the recovery daemon to perform a ip reallocation procedure" },
4243 { "freeze", control_freeze, true, false, "freeze databases", "[priority:1-3]" },
4244 { "thaw", control_thaw, true, false, "thaw databases", "[priority:1-3]" },
4245 { "isnotrecmaster", control_isnotrecmaster, false, false, "check if the local node is recmaster or not" },
4246 { "killtcp", kill_tcp, false, false, "kill a tcp connection.", "<srcip:port> <dstip:port>" },
4247 { "gratiousarp", control_gratious_arp, false, false, "send a gratious arp", "<ip> <interface>" },
4248 { "tickle", tickle_tcp, false, false, "send a tcp tickle ack", "<srcip:port> <dstip:port>" },
4249 { "gettickles", control_get_tickles, false, false, "get the list of tickles registered for this ip", "<ip>" },
4251 { "regsrvid", regsrvid, false, false, "register a server id", "<pnn> <type> <id>" },
4252 { "unregsrvid", unregsrvid, false, false, "unregister a server id", "<pnn> <type> <id>" },
4253 { "chksrvid", chksrvid, false, false, "check if a server id exists", "<pnn> <type> <id>" },
4254 { "getsrvids", getsrvids, false, false, "get a list of all server ids"},
4255 { "vacuum", ctdb_vacuum, false, false, "vacuum the databases of empty records", "[max_records]"},
4256 { "repack", ctdb_repack, false, false, "repack all databases", "[max_freelist]"},
4257 { "listnodes", control_listnodes, false, true, "list all nodes in the cluster"},
4258 { "reloadnodes", control_reload_nodes_file, false, false, "reload the nodes file and restart the transport on all nodes"},
4259 { "moveip", control_moveip, false, false, "move/failover an ip address to another node", "<ip> <node>"},
4260 { "addip", control_addip, true, false, "add a ip address to a node", "<ip/mask> <iface>"},
4261 { "delip", control_delip, false, false, "delete an ip address from a node", "<ip>"},
4262 { "eventscript", control_eventscript, true, false, "run the eventscript with the given parameters on a node", "<arguments>"},
4263 { "backupdb", control_backupdb, false, false, "backup the database into a file.", "<database> <file>"},
4264 { "restoredb", control_restoredb, false, false, "restore the database from a file.", "<file>"},
4265 { "dumpdbbackup", control_dumpdbbackup, false, true, "dump database backup from a file.", "<file>"},
4266 { "wipedb", control_wipedb, false, false, "wipe the contents of a database.", "<dbname>"},
4267 { "recmaster", control_recmaster, false, false, "show the pnn for the recovery master."},
4268 { "setflags", control_setflags, false, false, "set flags for a node in the nodemap.", "<node> <flags>"},
4269 { "scriptstatus", control_scriptstatus, false, false, "show the status of the monitoring scripts (or all scripts)", "[all]"},
4270 { "enablescript", control_enablescript, false, false, "enable an eventscript", "<script>"},
4271 { "disablescript", control_disablescript, false, false, "disable an eventscript", "<script>"},
4272 { "natgwlist", control_natgwlist, false, false, "show the nodes belonging to this natgw configuration"},
4273 { "xpnn", control_xpnn, true, true, "find the pnn of the local node without talking to the daemon (unreliable)" },
4274 { "getreclock", control_getreclock, false, false, "Show the reclock file of a node"},
4275 { "setreclock", control_setreclock, false, false, "Set/clear the reclock file of a node", "[filename]"},
4276 { "setnatgwstate", control_setnatgwstate, false, false, "Set NATGW state to on/off", "{on|off}"},
4277 { "setlmasterrole", control_setlmasterrole, false, false, "Set LMASTER role to on/off", "{on|off}"},
4278 { "setrecmasterrole", control_setrecmasterrole, false, false, "Set RECMASTER role to on/off", "{on|off}"},
4279 { "setdbprio", control_setdbprio, false, false, "Set DB priority", "<dbid> <prio:1-3>"},
4280 { "getdbprio", control_getdbprio, false, false, "Get DB priority", "<dbid>"},
4286 static void usage(void)
4290 "Usage: ctdb [options] <control>\n" \
4292 " -n <node> choose node number, or 'all' (defaults to local node)\n"
4293 " -Y generate machinereadable output\n"
4294 " -t <timelimit> set timelimit for control in seconds (default %u)\n", options.timelimit);
4295 printf("Controls:\n");
4296 for (i=0;i<ARRAY_SIZE(ctdb_commands);i++) {
4297 printf(" %-15s %-27s %s\n",
4298 ctdb_commands[i].name,
4299 ctdb_commands[i].args?ctdb_commands[i].args:"",
4300 ctdb_commands[i].msg);
4306 static void ctdb_alarm(int sig)
4308 printf("Maximum runtime exceeded - exiting\n");
4315 int main(int argc, const char *argv[])
4317 struct ctdb_context *ctdb;
4318 char *nodestring = NULL;
4319 struct poptOption popt_options[] = {
4322 { "timelimit", 't', POPT_ARG_INT, &options.timelimit, 0, "timelimit", "integer" },
4323 { "node", 'n', POPT_ARG_STRING, &nodestring, 0, "node", "integer|all" },
4324 { "machinereadable", 'Y', POPT_ARG_NONE, &options.machinereadable, 0, "enable machinereadable output", NULL },
4325 { "maxruntime", 'T', POPT_ARG_INT, &options.maxruntime, 0, "die if runtime exceeds this limit (in seconds)", "integer" },
4329 const char **extra_argv;
4333 struct event_context *ev;
4334 const char *control;
4338 /* set some defaults */
4339 options.maxruntime = 0;
4340 options.timelimit = 3;
4341 options.pnn = CTDB_CURRENT_NODE;
4343 pc = poptGetContext(argv[0], argc, argv, popt_options, POPT_CONTEXT_KEEP_FIRST);
4345 while ((opt = poptGetNextOpt(pc)) != -1) {
4348 DEBUG(DEBUG_ERR, ("Invalid option %s: %s\n",
4349 poptBadOption(pc, 0), poptStrerror(opt)));
4354 /* setup the remaining options for the main program to use */
4355 extra_argv = poptGetArgs(pc);
4358 while (extra_argv[extra_argc]) extra_argc++;
4361 if (extra_argc < 1) {
4365 if (options.maxruntime == 0) {
4366 const char *ctdb_timeout;
4367 ctdb_timeout = getenv("CTDB_TIMEOUT");
4368 if (ctdb_timeout != NULL) {
4369 options.maxruntime = strtoul(ctdb_timeout, NULL, 0);
4371 /* default timeout is 120 seconds */
4372 options.maxruntime = 120;
4376 signal(SIGALRM, ctdb_alarm);
4377 alarm(options.maxruntime);
4379 /* setup the node number to contact */
4380 if (nodestring != NULL) {
4381 if (strcmp(nodestring, "all") == 0) {
4382 options.pnn = CTDB_BROADCAST_ALL;
4384 options.pnn = strtoul(nodestring, NULL, 0);
4388 control = extra_argv[0];
4390 ev = event_context_init(NULL);
4392 for (i=0;i<ARRAY_SIZE(ctdb_commands);i++) {
4393 if (strcmp(control, ctdb_commands[i].name) == 0) {
4396 if (ctdb_commands[i].without_daemon == true) {
4400 /* initialise ctdb */
4401 ctdb = ctdb_cmdline_client(ev);
4403 if (ctdb_commands[i].without_daemon == false) {
4405 DEBUG(DEBUG_ERR, ("Failed to init ctdb\n"));
4409 /* verify the node exists */
4412 if (options.pnn == CTDB_CURRENT_NODE) {
4414 pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
4422 if (ctdb_commands[i].auto_all &&
4423 options.pnn == CTDB_BROADCAST_ALL) {
4428 nodes = ctdb_get_connected_nodes(ctdb, TIMELIMIT(), ctdb, &num_nodes);
4429 CTDB_NO_MEMORY(ctdb, nodes);
4431 for (j=0;j<num_nodes;j++) {
4432 options.pnn = nodes[j];
4433 ret |= ctdb_commands[i].fn(ctdb, extra_argc-1, extra_argv+1);
4437 ret = ctdb_commands[i].fn(ctdb, extra_argc-1, extra_argv+1);
4443 if (i == ARRAY_SIZE(ctdb_commands)) {
4444 DEBUG(DEBUG_ERR, ("Unknown control '%s'\n", control));