4 Copyright (C) Andrew Tridgell 2007
5 Copyright (C) Ronnie Sahlberg 2007
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, see <http://www.gnu.org/licenses/>.
22 #include "lib/events/events.h"
23 #include "system/time.h"
24 #include "system/filesys.h"
25 #include "system/network.h"
26 #include "system/locale.h"
29 #include "../include/ctdb.h"
30 #include "../include/ctdb_private.h"
31 #include "../common/rb_tree.h"
34 #define ERR_TIMEOUT 20 /* timed out trying to reach node */
35 #define ERR_NONODE 21 /* node does not exist */
36 #define ERR_DISNODE 22 /* node is disconnected */
38 static void usage(void);
47 #define TIMELIMIT() timeval_current_ofs(options.timelimit, 0)
48 #define LONGTIMELIMIT() timeval_current_ofs(options.timelimit*10, 0)
51 static int control_version(struct ctdb_context *ctdb, int argc, const char **argv)
54 #define XSTR(x) STR(x)
55 printf("CTDB version: %s\n", XSTR(CTDB_VERS));
62 verify that a node exists and is reachable
64 static void verify_node(struct ctdb_context *ctdb)
67 struct ctdb_node_map *nodemap=NULL;
69 if (options.pnn == CTDB_CURRENT_NODE) {
72 if (options.pnn == CTDB_BROADCAST_ALL) {
76 /* verify the node exists */
77 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
78 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
81 if (options.pnn >= nodemap->num) {
82 DEBUG(DEBUG_ERR, ("Node %u does not exist\n", options.pnn));
85 if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_DELETED) {
86 DEBUG(DEBUG_ERR, ("Node %u is DELETED\n", options.pnn));
89 if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_DISCONNECTED) {
90 DEBUG(DEBUG_ERR, ("Node %u is DISCONNECTED\n", options.pnn));
94 /* verify we can access the node */
95 ret = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
97 DEBUG(DEBUG_ERR,("Can not ban node. Node is not operational.\n"));
103 check if a database exists
105 static int db_exists(struct ctdb_context *ctdb, const char *db_name)
108 struct ctdb_dbid_map *dbmap=NULL;
110 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
112 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
116 for(i=0;i<dbmap->num;i++){
119 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
120 if (!strcmp(name, db_name)) {
129 see if a process exists
131 static int control_process_exists(struct ctdb_context *ctdb, int argc, const char **argv)
139 if (sscanf(argv[0], "%u:%u", &pnn, &pid) != 2) {
140 DEBUG(DEBUG_ERR, ("Badly formed pnn:pid\n"));
144 ret = ctdb_ctrl_process_exists(ctdb, pnn, pid);
146 printf("%u:%u exists\n", pnn, pid);
148 printf("%u:%u does not exist\n", pnn, pid);
154 display statistics structure
156 static void show_statistics(struct ctdb_statistics *s)
158 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
160 const char *prefix=NULL;
166 #define STATISTICS_FIELD(n) { #n, offsetof(struct ctdb_statistics, n) }
167 STATISTICS_FIELD(num_clients),
168 STATISTICS_FIELD(frozen),
169 STATISTICS_FIELD(recovering),
170 STATISTICS_FIELD(client_packets_sent),
171 STATISTICS_FIELD(client_packets_recv),
172 STATISTICS_FIELD(node_packets_sent),
173 STATISTICS_FIELD(node_packets_recv),
174 STATISTICS_FIELD(keepalive_packets_sent),
175 STATISTICS_FIELD(keepalive_packets_recv),
176 STATISTICS_FIELD(node.req_call),
177 STATISTICS_FIELD(node.reply_call),
178 STATISTICS_FIELD(node.req_dmaster),
179 STATISTICS_FIELD(node.reply_dmaster),
180 STATISTICS_FIELD(node.reply_error),
181 STATISTICS_FIELD(node.req_message),
182 STATISTICS_FIELD(node.req_control),
183 STATISTICS_FIELD(node.reply_control),
184 STATISTICS_FIELD(client.req_call),
185 STATISTICS_FIELD(client.req_message),
186 STATISTICS_FIELD(client.req_control),
187 STATISTICS_FIELD(timeouts.call),
188 STATISTICS_FIELD(timeouts.control),
189 STATISTICS_FIELD(timeouts.traverse),
190 STATISTICS_FIELD(total_calls),
191 STATISTICS_FIELD(pending_calls),
192 STATISTICS_FIELD(lockwait_calls),
193 STATISTICS_FIELD(pending_lockwait_calls),
194 STATISTICS_FIELD(childwrite_calls),
195 STATISTICS_FIELD(pending_childwrite_calls),
196 STATISTICS_FIELD(memory_used),
197 STATISTICS_FIELD(max_hop_count),
199 printf("CTDB version %u\n", CTDB_VERSION);
200 for (i=0;i<ARRAY_SIZE(fields);i++) {
201 if (strchr(fields[i].name, '.')) {
202 preflen = strcspn(fields[i].name, ".")+1;
203 if (!prefix || strncmp(prefix, fields[i].name, preflen) != 0) {
204 prefix = fields[i].name;
205 printf(" %*.*s\n", preflen-1, preflen-1, fields[i].name);
210 printf(" %*s%-22s%*s%10u\n",
212 fields[i].name+preflen,
214 *(uint32_t *)(fields[i].offset+(uint8_t *)s));
216 printf(" %-30s %.6f sec\n", "max_reclock_ctdbd", s->reclock.ctdbd);
217 printf(" %-30s %.6f sec\n", "max_reclock_recd", s->reclock.recd);
219 printf(" %-30s %.6f sec\n", "max_call_latency", s->max_call_latency);
220 printf(" %-30s %.6f sec\n", "max_lockwait_latency", s->max_lockwait_latency);
221 printf(" %-30s %.6f sec\n", "max_childwrite_latency", s->max_childwrite_latency);
222 talloc_free(tmp_ctx);
226 display remote ctdb statistics combined from all nodes
228 static int control_statistics_all(struct ctdb_context *ctdb)
231 struct ctdb_statistics statistics;
235 nodes = ctdb_get_connected_nodes(ctdb, TIMELIMIT(), ctdb, &num_nodes);
236 CTDB_NO_MEMORY(ctdb, nodes);
238 ZERO_STRUCT(statistics);
240 for (i=0;i<num_nodes;i++) {
241 struct ctdb_statistics s1;
243 uint32_t *v1 = (uint32_t *)&s1;
244 uint32_t *v2 = (uint32_t *)&statistics;
246 offsetof(struct ctdb_statistics, __last_counter) / sizeof(uint32_t);
247 ret = ctdb_ctrl_statistics(ctdb, nodes[i], &s1);
249 DEBUG(DEBUG_ERR, ("Unable to get statistics from node %u\n", nodes[i]));
252 for (j=0;j<num_ints;j++) {
255 statistics.max_hop_count =
256 MAX(statistics.max_hop_count, s1.max_hop_count);
257 statistics.max_call_latency =
258 MAX(statistics.max_call_latency, s1.max_call_latency);
259 statistics.max_lockwait_latency =
260 MAX(statistics.max_lockwait_latency, s1.max_lockwait_latency);
263 printf("Gathered statistics for %u nodes\n", num_nodes);
264 show_statistics(&statistics);
269 display remote ctdb statistics
271 static int control_statistics(struct ctdb_context *ctdb, int argc, const char **argv)
274 struct ctdb_statistics statistics;
276 if (options.pnn == CTDB_BROADCAST_ALL) {
277 return control_statistics_all(ctdb);
280 ret = ctdb_ctrl_statistics(ctdb, options.pnn, &statistics);
282 DEBUG(DEBUG_ERR, ("Unable to get statistics from node %u\n", options.pnn));
285 show_statistics(&statistics);
291 reset remote ctdb statistics
293 static int control_statistics_reset(struct ctdb_context *ctdb, int argc, const char **argv)
297 ret = ctdb_statistics_reset(ctdb, options.pnn);
299 DEBUG(DEBUG_ERR, ("Unable to reset statistics on node %u\n", options.pnn));
307 display uptime of remote node
309 static int control_uptime(struct ctdb_context *ctdb, int argc, const char **argv)
312 struct ctdb_uptime *uptime = NULL;
313 int tmp, days, hours, minutes, seconds;
315 ret = ctdb_ctrl_uptime(ctdb, ctdb, TIMELIMIT(), options.pnn, &uptime);
317 DEBUG(DEBUG_ERR, ("Unable to get uptime from node %u\n", options.pnn));
321 if (options.machinereadable){
322 printf(":Current Node Time:Ctdb Start Time:Last Recovery/Failover Time:Last Recovery/IPFailover Duration:\n");
323 printf(":%u:%u:%u:%lf\n",
324 (unsigned int)uptime->current_time.tv_sec,
325 (unsigned int)uptime->ctdbd_start_time.tv_sec,
326 (unsigned int)uptime->last_recovery_finished.tv_sec,
327 timeval_delta(&uptime->last_recovery_finished,
328 &uptime->last_recovery_started)
333 printf("Current time of node : %s", ctime(&uptime->current_time.tv_sec));
335 tmp = uptime->current_time.tv_sec - uptime->ctdbd_start_time.tv_sec;
343 printf("Ctdbd start time : (%03d %02d:%02d:%02d) %s", days, hours, minutes, seconds, ctime(&uptime->ctdbd_start_time.tv_sec));
345 tmp = uptime->current_time.tv_sec - uptime->last_recovery_finished.tv_sec;
353 printf("Time of last recovery/failover: (%03d %02d:%02d:%02d) %s", days, hours, minutes, seconds, ctime(&uptime->last_recovery_finished.tv_sec));
355 printf("Duration of last recovery/failover: %lf seconds\n",
356 timeval_delta(&uptime->last_recovery_finished,
357 &uptime->last_recovery_started));
363 show the PNN of the current node
365 static int control_pnn(struct ctdb_context *ctdb, int argc, const char **argv)
369 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
371 DEBUG(DEBUG_ERR, ("Unable to get pnn from local node."));
375 printf("PNN:%d\n", mypnn);
381 struct pnn_node *next;
386 static struct pnn_node *read_nodes_file(TALLOC_CTX *mem_ctx)
388 const char *nodes_list;
392 struct pnn_node *pnn_nodes = NULL;
393 struct pnn_node *pnn_node;
394 struct pnn_node *tmp_node;
396 /* read the nodes file */
397 nodes_list = getenv("CTDB_NODES");
398 if (nodes_list == NULL) {
399 nodes_list = "/etc/ctdb/nodes";
401 lines = file_lines_load(nodes_list, &nlines, mem_ctx);
405 while (nlines > 0 && strcmp(lines[nlines-1], "") == 0) {
408 for (i=0, pnn=0; i<nlines; i++) {
412 /* strip leading spaces */
413 while((*node == ' ') || (*node == '\t')) {
420 if (strcmp(node, "") == 0) {
423 pnn_node = talloc(mem_ctx, struct pnn_node);
424 pnn_node->pnn = pnn++;
425 pnn_node->addr = talloc_strdup(pnn_node, node);
426 pnn_node->next = pnn_nodes;
427 pnn_nodes = pnn_node;
430 /* swap them around so we return them in incrementing order */
431 pnn_node = pnn_nodes;
435 pnn_node = pnn_node->next;
437 tmp_node->next = pnn_nodes;
438 pnn_nodes = tmp_node;
445 show the PNN of the current node
446 discover the pnn by loading the nodes file and try to bind to all
447 addresses one at a time until the ip address is found.
449 static int control_xpnn(struct ctdb_context *ctdb, int argc, const char **argv)
451 TALLOC_CTX *mem_ctx = talloc_new(NULL);
452 struct pnn_node *pnn_nodes;
453 struct pnn_node *pnn_node;
455 pnn_nodes = read_nodes_file(mem_ctx);
456 if (pnn_nodes == NULL) {
457 DEBUG(DEBUG_ERR,("Failed to read nodes file\n"));
458 talloc_free(mem_ctx);
462 for(pnn_node=pnn_nodes;pnn_node;pnn_node=pnn_node->next) {
465 if (parse_ip(pnn_node->addr, NULL, 63999, &addr) == 0) {
466 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s' in nodes file\n", pnn_node->addr));
467 talloc_free(mem_ctx);
471 if (ctdb_sys_have_ip(&addr)) {
472 printf("PNN:%d\n", pnn_node->pnn);
473 talloc_free(mem_ctx);
478 printf("Failed to detect which PNN this node is\n");
479 talloc_free(mem_ctx);
484 display remote ctdb status
486 static int control_status(struct ctdb_context *ctdb, int argc, const char **argv)
489 struct ctdb_vnn_map *vnnmap=NULL;
490 struct ctdb_node_map *nodemap=NULL;
491 uint32_t recmode, recmaster;
494 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
499 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
501 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
505 if(options.machinereadable){
506 printf(":Node:IP:Disconnected:Banned:Disabled:Unhealthy:Stopped:Inactive:PartiallyOnline:\n");
507 for(i=0;i<nodemap->num;i++){
508 int partially_online = 0;
511 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
514 if (nodemap->nodes[i].flags == 0) {
515 struct ctdb_control_get_ifaces *ifaces;
517 ret = ctdb_ctrl_get_ifaces(ctdb, TIMELIMIT(),
518 nodemap->nodes[i].pnn,
521 for (j=0; j < ifaces->num; j++) {
522 if (ifaces->ifaces[j].link_state != 0) {
525 partially_online = 1;
531 printf(":%d:%s:%d:%d:%d:%d:%d:%d:%d:\n", nodemap->nodes[i].pnn,
532 ctdb_addr_to_str(&nodemap->nodes[i].addr),
533 !!(nodemap->nodes[i].flags&NODE_FLAGS_DISCONNECTED),
534 !!(nodemap->nodes[i].flags&NODE_FLAGS_BANNED),
535 !!(nodemap->nodes[i].flags&NODE_FLAGS_PERMANENTLY_DISABLED),
536 !!(nodemap->nodes[i].flags&NODE_FLAGS_UNHEALTHY),
537 !!(nodemap->nodes[i].flags&NODE_FLAGS_STOPPED),
538 !!(nodemap->nodes[i].flags&NODE_FLAGS_INACTIVE),
544 printf("Number of nodes:%d\n", nodemap->num);
545 for(i=0;i<nodemap->num;i++){
546 static const struct {
550 { NODE_FLAGS_DISCONNECTED, "DISCONNECTED" },
551 { NODE_FLAGS_PERMANENTLY_DISABLED, "DISABLED" },
552 { NODE_FLAGS_BANNED, "BANNED" },
553 { NODE_FLAGS_UNHEALTHY, "UNHEALTHY" },
554 { NODE_FLAGS_DELETED, "DELETED" },
555 { NODE_FLAGS_STOPPED, "STOPPED" },
556 { NODE_FLAGS_INACTIVE, "INACTIVE" },
558 char *flags_str = NULL;
561 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
564 if (nodemap->nodes[i].flags == 0) {
565 struct ctdb_control_get_ifaces *ifaces;
567 ret = ctdb_ctrl_get_ifaces(ctdb, TIMELIMIT(),
568 nodemap->nodes[i].pnn,
571 for (j=0; j < ifaces->num; j++) {
572 if (ifaces->ifaces[j].link_state != 0) {
575 flags_str = talloc_strdup(ctdb, "PARTIALLYONLINE");
581 for (j=0;j<ARRAY_SIZE(flag_names);j++) {
582 if (nodemap->nodes[i].flags & flag_names[j].flag) {
583 if (flags_str == NULL) {
584 flags_str = talloc_strdup(ctdb, flag_names[j].name);
586 flags_str = talloc_asprintf_append(flags_str, "|%s",
589 CTDB_NO_MEMORY_FATAL(ctdb, flags_str);
592 if (flags_str == NULL) {
593 flags_str = talloc_strdup(ctdb, "OK");
594 CTDB_NO_MEMORY_FATAL(ctdb, flags_str);
596 printf("pnn:%d %-16s %s%s\n", nodemap->nodes[i].pnn,
597 ctdb_addr_to_str(&nodemap->nodes[i].addr),
599 nodemap->nodes[i].pnn == mypnn?" (THIS NODE)":"");
600 talloc_free(flags_str);
603 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &vnnmap);
605 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n", options.pnn));
608 if (vnnmap->generation == INVALID_GENERATION) {
609 printf("Generation:INVALID\n");
611 printf("Generation:%d\n",vnnmap->generation);
613 printf("Size:%d\n",vnnmap->size);
614 for(i=0;i<vnnmap->size;i++){
615 printf("hash:%d lmaster:%d\n", i, vnnmap->map[i]);
618 ret = ctdb_ctrl_getrecmode(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmode);
620 DEBUG(DEBUG_ERR, ("Unable to get recmode from node %u\n", options.pnn));
623 printf("Recovery mode:%s (%d)\n",recmode==CTDB_RECOVERY_NORMAL?"NORMAL":"RECOVERY",recmode);
625 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
627 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
630 printf("Recovery master:%d\n",recmaster);
637 struct natgw_node *next;
642 display the list of nodes belonging to this natgw configuration
644 static int control_natgwlist(struct ctdb_context *ctdb, int argc, const char **argv)
647 const char *natgw_list;
650 struct natgw_node *natgw_nodes = NULL;
651 struct natgw_node *natgw_node;
652 struct ctdb_node_map *nodemap=NULL;
655 /* read the natgw nodes file into a linked list */
656 natgw_list = getenv("NATGW_NODES");
657 if (natgw_list == NULL) {
658 natgw_list = "/etc/ctdb/natgw_nodes";
660 lines = file_lines_load(natgw_list, &nlines, ctdb);
662 ctdb_set_error(ctdb, "Failed to load natgw node list '%s'\n", natgw_list);
665 while (nlines > 0 && strcmp(lines[nlines-1], "") == 0) {
668 for (i=0;i<nlines;i++) {
672 /* strip leading spaces */
673 while((*node == ' ') || (*node == '\t')) {
679 if (strcmp(node, "") == 0) {
682 natgw_node = talloc(ctdb, struct natgw_node);
683 natgw_node->addr = talloc_strdup(natgw_node, node);
684 CTDB_NO_MEMORY(ctdb, natgw_node->addr);
685 natgw_node->next = natgw_nodes;
686 natgw_nodes = natgw_node;
689 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
691 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node.\n"));
696 while(i<nodemap->num) {
697 for(natgw_node=natgw_nodes;natgw_node;natgw_node=natgw_node->next) {
698 if (!strcmp(natgw_node->addr, ctdb_addr_to_str(&nodemap->nodes[i].addr))) {
703 /* this node was not in the natgw so we just remove it from
706 if ((natgw_node == NULL)
707 || (nodemap->nodes[i].flags & NODE_FLAGS_DISCONNECTED) ) {
710 for (j=i+1; j<nodemap->num; j++) {
711 nodemap->nodes[j-1] = nodemap->nodes[j];
720 /* pick a node to be natgwmaster
721 * we dont allow STOPPED, DELETED, BANNED or UNHEALTHY nodes to become the natgwmaster
723 for(i=0;i<nodemap->num;i++){
724 if (!(nodemap->nodes[i].flags & (NODE_FLAGS_DISCONNECTED|NODE_FLAGS_STOPPED|NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_UNHEALTHY))) {
725 printf("%d %s\n", nodemap->nodes[i].pnn,ctdb_addr_to_str(&nodemap->nodes[i].addr));
729 /* we couldnt find any healthy node, try unhealthy ones */
730 if (i == nodemap->num) {
731 for(i=0;i<nodemap->num;i++){
732 if (!(nodemap->nodes[i].flags & (NODE_FLAGS_DISCONNECTED|NODE_FLAGS_STOPPED|NODE_FLAGS_DELETED))) {
733 printf("%d %s\n", nodemap->nodes[i].pnn,ctdb_addr_to_str(&nodemap->nodes[i].addr));
738 /* unless all nodes are STOPPED, when we pick one anyway */
739 if (i == nodemap->num) {
740 for(i=0;i<nodemap->num;i++){
741 if (!(nodemap->nodes[i].flags & (NODE_FLAGS_DISCONNECTED|NODE_FLAGS_DELETED))) {
742 printf("%d %s\n", nodemap->nodes[i].pnn, ctdb_addr_to_str(&nodemap->nodes[i].addr));
746 /* or if we still can not find any */
747 if (i == nodemap->num) {
748 printf("-1 0.0.0.0\n");
752 /* print the pruned list of nodes belonging to this natgw list */
753 for(i=0;i<nodemap->num;i++){
754 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
757 printf(":%d:%s:%d:%d:%d:%d:%d\n", nodemap->nodes[i].pnn,
758 ctdb_addr_to_str(&nodemap->nodes[i].addr),
759 !!(nodemap->nodes[i].flags&NODE_FLAGS_DISCONNECTED),
760 !!(nodemap->nodes[i].flags&NODE_FLAGS_BANNED),
761 !!(nodemap->nodes[i].flags&NODE_FLAGS_PERMANENTLY_DISABLED),
762 !!(nodemap->nodes[i].flags&NODE_FLAGS_UNHEALTHY),
763 !!(nodemap->nodes[i].flags&NODE_FLAGS_STOPPED));
770 display the status of the scripts for monitoring (or other events)
772 static int control_one_scriptstatus(struct ctdb_context *ctdb,
773 enum ctdb_eventscript_call type)
775 struct ctdb_scripts_wire *script_status;
778 ret = ctdb_ctrl_getscriptstatus(ctdb, TIMELIMIT(), options.pnn, ctdb, type, &script_status);
780 DEBUG(DEBUG_ERR, ("Unable to get script status from node %u\n", options.pnn));
784 if (script_status == NULL) {
785 if (!options.machinereadable) {
786 printf("%s cycle never run\n",
787 ctdb_eventscript_call_names[type]);
792 if (!options.machinereadable) {
793 printf("%d scripts were executed last %s cycle\n",
794 script_status->num_scripts,
795 ctdb_eventscript_call_names[type]);
797 for (i=0; i<script_status->num_scripts; i++) {
798 const char *status = NULL;
800 switch (script_status->scripts[i].status) {
811 if (script_status->scripts[i].status > 0)
815 if (options.machinereadable) {
816 printf("%s:%s:%i:%s:%lu.%06lu:%lu.%06lu:%s:\n",
817 ctdb_eventscript_call_names[type],
818 script_status->scripts[i].name,
819 script_status->scripts[i].status,
821 (long)script_status->scripts[i].start.tv_sec,
822 (long)script_status->scripts[i].start.tv_usec,
823 (long)script_status->scripts[i].finished.tv_sec,
824 (long)script_status->scripts[i].finished.tv_usec,
825 script_status->scripts[i].output);
829 printf("%-20s Status:%s ",
830 script_status->scripts[i].name, status);
832 /* Some other error, eg from stat. */
833 printf("%-20s Status:CANNOT RUN (%s)",
834 script_status->scripts[i].name,
835 strerror(-script_status->scripts[i].status));
837 if (script_status->scripts[i].status >= 0) {
838 printf("Duration:%.3lf ",
839 timeval_delta(&script_status->scripts[i].finished,
840 &script_status->scripts[i].start));
842 if (script_status->scripts[i].status != -ENOEXEC) {
844 ctime(&script_status->scripts[i].start.tv_sec));
845 if (script_status->scripts[i].status != 0) {
846 printf(" OUTPUT:%s\n",
847 script_status->scripts[i].output);
857 static int control_scriptstatus(struct ctdb_context *ctdb,
858 int argc, const char **argv)
861 enum ctdb_eventscript_call type, min, max;
865 DEBUG(DEBUG_ERR, ("Unknown arguments to scriptstatus\n"));
870 arg = ctdb_eventscript_call_names[CTDB_EVENT_MONITOR];
874 for (type = 0; type < CTDB_EVENT_MAX; type++) {
875 if (strcmp(arg, ctdb_eventscript_call_names[type]) == 0) {
881 if (type == CTDB_EVENT_MAX) {
882 if (strcmp(arg, "all") == 0) {
884 max = CTDB_EVENT_MAX;
886 DEBUG(DEBUG_ERR, ("Unknown event type %s\n", argv[0]));
891 if (options.machinereadable) {
892 printf(":Type:Name:Code:Status:Start:End:Error Output...:\n");
895 for (type = min; type < max; type++) {
896 ret = control_one_scriptstatus(ctdb, type);
906 enable an eventscript
908 static int control_enablescript(struct ctdb_context *ctdb, int argc, const char **argv)
916 ret = ctdb_ctrl_enablescript(ctdb, TIMELIMIT(), options.pnn, argv[0]);
918 DEBUG(DEBUG_ERR, ("Unable to enable script %s on node %u\n", argv[0], options.pnn));
926 disable an eventscript
928 static int control_disablescript(struct ctdb_context *ctdb, int argc, const char **argv)
936 ret = ctdb_ctrl_disablescript(ctdb, TIMELIMIT(), options.pnn, argv[0]);
938 DEBUG(DEBUG_ERR, ("Unable to disable script %s on node %u\n", argv[0], options.pnn));
946 display the pnn of the recovery master
948 static int control_recmaster(struct ctdb_context *ctdb, int argc, const char **argv)
953 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
955 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
958 printf("%d\n",recmaster);
964 get a list of all tickles for this pnn
966 static int control_get_tickles(struct ctdb_context *ctdb, int argc, const char **argv)
968 struct ctdb_control_tcp_tickle_list *list;
976 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
977 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
981 ret = ctdb_ctrl_get_tcp_tickles(ctdb, TIMELIMIT(), options.pnn, ctdb, &addr, &list);
983 DEBUG(DEBUG_ERR, ("Unable to list tickles\n"));
987 printf("Tickles for ip:%s\n", ctdb_addr_to_str(&list->addr));
988 printf("Num tickles:%u\n", list->tickles.num);
989 for (i=0;i<list->tickles.num;i++) {
990 printf("SRC: %s:%u ", ctdb_addr_to_str(&list->tickles.connections[i].src_addr), ntohs(list->tickles.connections[i].src_addr.ip.sin_port));
991 printf("DST: %s:%u\n", ctdb_addr_to_str(&list->tickles.connections[i].dst_addr), ntohs(list->tickles.connections[i].dst_addr.ip.sin_port));
1000 static int move_ip(struct ctdb_context *ctdb, ctdb_sock_addr *addr, uint32_t pnn)
1002 struct ctdb_all_public_ips *ips;
1003 struct ctdb_public_ip ip;
1006 uint32_t disable_time;
1008 struct ctdb_node_map *nodemap=NULL;
1009 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1012 data.dptr = (uint8_t*)&disable_time;
1013 data.dsize = sizeof(disable_time);
1014 ret = ctdb_send_message(ctdb, CTDB_BROADCAST_CONNECTED, CTDB_SRVID_DISABLE_IP_CHECK, data);
1016 DEBUG(DEBUG_ERR,("Failed to send message to disable ipcheck\n"));
1022 /* read the public ip list from the node */
1023 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), pnn, ctdb, &ips);
1025 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", pnn));
1026 talloc_free(tmp_ctx);
1030 for (i=0;i<ips->num;i++) {
1031 if (ctdb_same_ip(addr, &ips->ips[i].addr)) {
1036 DEBUG(DEBUG_ERR, ("Node %u can not host ip address '%s'\n",
1037 pnn, ctdb_addr_to_str(addr)));
1038 talloc_free(tmp_ctx);
1045 data.dptr = (uint8_t *)&ip;
1046 data.dsize = sizeof(ip);
1048 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &nodemap);
1050 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1051 talloc_free(tmp_ctx);
1055 nodes = list_of_active_nodes_except_pnn(ctdb, nodemap, tmp_ctx, pnn);
1056 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_RELEASE_IP,
1063 DEBUG(DEBUG_ERR,("Failed to release IP on nodes\n"));
1064 talloc_free(tmp_ctx);
1068 ret = ctdb_ctrl_takeover_ip(ctdb, LONGTIMELIMIT(), pnn, &ip);
1070 DEBUG(DEBUG_ERR,("Failed to take over IP on node %d\n", pnn));
1071 talloc_free(tmp_ctx);
1075 talloc_free(tmp_ctx);
1080 move/failover an ip address to a specific node
1082 static int control_moveip(struct ctdb_context *ctdb, int argc, const char **argv)
1085 ctdb_sock_addr addr;
1092 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1093 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1098 if (sscanf(argv[1], "%u", &pnn) != 1) {
1099 DEBUG(DEBUG_ERR, ("Badly formed pnn\n"));
1103 if (move_ip(ctdb, &addr, pnn) != 0) {
1104 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", pnn));
1111 void getips_store_callback(void *param, void *data)
1113 struct ctdb_public_ip *node_ip = (struct ctdb_public_ip *)data;
1114 struct ctdb_all_public_ips *ips = param;
1118 ips->ips[i].pnn = node_ip->pnn;
1119 ips->ips[i].addr = node_ip->addr;
1122 void getips_count_callback(void *param, void *data)
1124 uint32_t *count = param;
1130 static uint32_t *ip_key(ctdb_sock_addr *ip)
1132 static uint32_t key[IP_KEYLEN];
1134 bzero(key, sizeof(key));
1136 switch (ip->sa.sa_family) {
1138 key[0] = ip->ip.sin_addr.s_addr;
1141 key[0] = ip->ip6.sin6_addr.s6_addr32[3];
1142 key[1] = ip->ip6.sin6_addr.s6_addr32[2];
1143 key[2] = ip->ip6.sin6_addr.s6_addr32[1];
1144 key[3] = ip->ip6.sin6_addr.s6_addr32[0];
1147 DEBUG(DEBUG_ERR, (__location__ " ERROR, unknown family passed :%u\n", ip->sa.sa_family));
1154 static void *add_ip_callback(void *parm, void *data)
1160 control_get_all_public_ips(struct ctdb_context *ctdb, TALLOC_CTX *tmp_ctx, struct ctdb_all_public_ips **ips)
1162 struct ctdb_all_public_ips *tmp_ips;
1163 struct ctdb_node_map *nodemap=NULL;
1164 trbt_tree_t *ip_tree;
1168 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1170 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1174 ip_tree = trbt_create(tmp_ctx, 0);
1176 for(i=0;i<nodemap->num;i++){
1177 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
1180 if (nodemap->nodes[i].flags & NODE_FLAGS_DISCONNECTED) {
1184 /* read the public ip list from this node */
1185 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &tmp_ips);
1187 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", nodemap->nodes[i].pnn));
1191 for (j=0; j<tmp_ips->num;j++) {
1192 struct ctdb_public_ip *node_ip;
1194 node_ip = talloc(tmp_ctx, struct ctdb_public_ip);
1195 node_ip->pnn = tmp_ips->ips[j].pnn;
1196 node_ip->addr = tmp_ips->ips[j].addr;
1198 trbt_insertarray32_callback(ip_tree,
1199 IP_KEYLEN, ip_key(&tmp_ips->ips[j].addr),
1203 talloc_free(tmp_ips);
1208 trbt_traversearray32(ip_tree, IP_KEYLEN, getips_count_callback, &count);
1210 len = offsetof(struct ctdb_all_public_ips, ips) +
1211 count*sizeof(struct ctdb_public_ip);
1212 tmp_ips = talloc_zero_size(tmp_ctx, len);
1213 trbt_traversearray32(ip_tree, IP_KEYLEN, getips_store_callback, tmp_ips);
1222 * scans all other nodes and returns a pnn for another node that can host this
1226 find_other_host_for_public_ip(struct ctdb_context *ctdb, ctdb_sock_addr *addr)
1228 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1229 struct ctdb_all_public_ips *ips;
1230 struct ctdb_node_map *nodemap=NULL;
1233 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1235 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1236 talloc_free(tmp_ctx);
1240 for(i=0;i<nodemap->num;i++){
1241 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1244 if (nodemap->nodes[i].pnn == options.pnn) {
1248 /* read the public ip list from this node */
1249 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips);
1251 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", nodemap->nodes[i].pnn));
1255 for (j=0;j<ips->num;j++) {
1256 if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1257 talloc_free(tmp_ctx);
1258 return nodemap->nodes[i].pnn;
1264 talloc_free(tmp_ctx);
1269 add a public ip address to a node
1271 static int control_addip(struct ctdb_context *ctdb, int argc, const char **argv)
1277 ctdb_sock_addr addr;
1278 struct ctdb_control_ip_iface *pub;
1279 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1280 struct ctdb_all_public_ips *ips;
1284 talloc_free(tmp_ctx);
1288 if (!parse_ip_mask(argv[0], argv[1], &addr, &mask)) {
1289 DEBUG(DEBUG_ERR, ("Badly formed ip/mask : %s\n", argv[0]));
1290 talloc_free(tmp_ctx);
1294 ret = control_get_all_public_ips(ctdb, tmp_ctx, &ips);
1296 DEBUG(DEBUG_ERR, ("Unable to get public ip list from cluster\n"));
1297 talloc_free(tmp_ctx);
1302 /* check if some other node is already serving this ip, if not,
1305 for (i=0;i<ips->num;i++) {
1306 if (ctdb_same_ip(&addr, &ips->ips[i].addr)) {
1311 len = offsetof(struct ctdb_control_ip_iface, iface) + strlen(argv[1]) + 1;
1312 pub = talloc_size(tmp_ctx, len);
1313 CTDB_NO_MEMORY(ctdb, pub);
1317 pub->len = strlen(argv[1])+1;
1318 memcpy(&pub->iface[0], argv[1], strlen(argv[1])+1);
1320 ret = ctdb_ctrl_add_public_ip(ctdb, TIMELIMIT(), options.pnn, pub);
1322 DEBUG(DEBUG_ERR, ("Unable to add public ip to node %u\n", options.pnn));
1323 talloc_free(tmp_ctx);
1327 if (i == ips->num) {
1328 /* no one has this ip so we claim it */
1331 pnn = ips->ips[i].pnn;
1334 if (move_ip(ctdb, &addr, pnn) != 0) {
1335 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", pnn));
1339 talloc_free(tmp_ctx);
1343 static int control_delip(struct ctdb_context *ctdb, int argc, const char **argv);
1345 static int control_delip_all(struct ctdb_context *ctdb, int argc, const char **argv, ctdb_sock_addr *addr)
1347 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1348 struct ctdb_node_map *nodemap=NULL;
1349 struct ctdb_all_public_ips *ips;
1352 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1354 DEBUG(DEBUG_ERR, ("Unable to get nodemap from current node\n"));
1358 /* remove it from the nodes that are not hosting the ip currently */
1359 for(i=0;i<nodemap->num;i++){
1360 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1363 if (ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips) != 0) {
1364 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %d\n", nodemap->nodes[i].pnn));
1368 for (j=0;j<ips->num;j++) {
1369 if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1377 if (ips->ips[j].pnn == nodemap->nodes[i].pnn) {
1381 options.pnn = nodemap->nodes[i].pnn;
1382 control_delip(ctdb, argc, argv);
1386 /* remove it from every node (also the one hosting it) */
1387 for(i=0;i<nodemap->num;i++){
1388 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1391 if (ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips) != 0) {
1392 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %d\n", nodemap->nodes[i].pnn));
1396 for (j=0;j<ips->num;j++) {
1397 if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1405 options.pnn = nodemap->nodes[i].pnn;
1406 control_delip(ctdb, argc, argv);
1409 talloc_free(tmp_ctx);
1414 delete a public ip address from a node
1416 static int control_delip(struct ctdb_context *ctdb, int argc, const char **argv)
1419 ctdb_sock_addr addr;
1420 struct ctdb_control_ip_iface pub;
1421 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1422 struct ctdb_all_public_ips *ips;
1425 talloc_free(tmp_ctx);
1429 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1430 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1434 if (options.pnn == CTDB_BROADCAST_ALL) {
1435 return control_delip_all(ctdb, argc, argv, &addr);
1442 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &ips);
1444 DEBUG(DEBUG_ERR, ("Unable to get public ip list from cluster\n"));
1445 talloc_free(tmp_ctx);
1449 for (i=0;i<ips->num;i++) {
1450 if (ctdb_same_ip(&addr, &ips->ips[i].addr)) {
1456 DEBUG(DEBUG_ERR, ("This node does not support this public address '%s'\n",
1457 ctdb_addr_to_str(&addr)));
1458 talloc_free(tmp_ctx);
1462 if (ips->ips[i].pnn == options.pnn) {
1463 ret = find_other_host_for_public_ip(ctdb, &addr);
1465 if (move_ip(ctdb, &addr, ret) != 0) {
1466 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", ret));
1472 ret = ctdb_ctrl_del_public_ip(ctdb, TIMELIMIT(), options.pnn, &pub);
1474 DEBUG(DEBUG_ERR, ("Unable to del public ip from node %u\n", options.pnn));
1475 talloc_free(tmp_ctx);
1479 talloc_free(tmp_ctx);
1484 kill a tcp connection
1486 static int kill_tcp(struct ctdb_context *ctdb, int argc, const char **argv)
1489 struct ctdb_control_killtcp killtcp;
1495 if (!parse_ip_port(argv[0], &killtcp.src_addr)) {
1496 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[0]));
1500 if (!parse_ip_port(argv[1], &killtcp.dst_addr)) {
1501 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[1]));
1505 ret = ctdb_ctrl_killtcp(ctdb, TIMELIMIT(), options.pnn, &killtcp);
1507 DEBUG(DEBUG_ERR, ("Unable to killtcp from node %u\n", options.pnn));
1518 static int control_gratious_arp(struct ctdb_context *ctdb, int argc, const char **argv)
1521 ctdb_sock_addr addr;
1527 if (!parse_ip(argv[0], NULL, 0, &addr)) {
1528 DEBUG(DEBUG_ERR, ("Bad IP '%s'\n", argv[0]));
1532 ret = ctdb_ctrl_gratious_arp(ctdb, TIMELIMIT(), options.pnn, &addr, argv[1]);
1534 DEBUG(DEBUG_ERR, ("Unable to send gratious_arp from node %u\n", options.pnn));
1542 register a server id
1544 static int regsrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1547 struct ctdb_server_id server_id;
1553 server_id.pnn = strtoul(argv[0], NULL, 0);
1554 server_id.type = strtoul(argv[1], NULL, 0);
1555 server_id.server_id = strtoul(argv[2], NULL, 0);
1557 ret = ctdb_ctrl_register_server_id(ctdb, TIMELIMIT(), &server_id);
1559 DEBUG(DEBUG_ERR, ("Unable to register server_id from node %u\n", options.pnn));
1562 DEBUG(DEBUG_ERR,("Srvid registered. Sleeping for 999 seconds\n"));
1568 unregister a server id
1570 static int unregsrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1573 struct ctdb_server_id server_id;
1579 server_id.pnn = strtoul(argv[0], NULL, 0);
1580 server_id.type = strtoul(argv[1], NULL, 0);
1581 server_id.server_id = strtoul(argv[2], NULL, 0);
1583 ret = ctdb_ctrl_unregister_server_id(ctdb, TIMELIMIT(), &server_id);
1585 DEBUG(DEBUG_ERR, ("Unable to unregister server_id from node %u\n", options.pnn));
1592 check if a server id exists
1594 static int chksrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1598 struct ctdb_server_id server_id;
1604 server_id.pnn = strtoul(argv[0], NULL, 0);
1605 server_id.type = strtoul(argv[1], NULL, 0);
1606 server_id.server_id = strtoul(argv[2], NULL, 0);
1608 ret = ctdb_ctrl_check_server_id(ctdb, TIMELIMIT(), options.pnn, &server_id, &status);
1610 DEBUG(DEBUG_ERR, ("Unable to check server_id from node %u\n", options.pnn));
1615 printf("Server id %d:%d:%d EXISTS\n", server_id.pnn, server_id.type, server_id.server_id);
1617 printf("Server id %d:%d:%d does NOT exist\n", server_id.pnn, server_id.type, server_id.server_id);
1623 get a list of all server ids that are registered on a node
1625 static int getsrvids(struct ctdb_context *ctdb, int argc, const char **argv)
1628 struct ctdb_server_id_list *server_ids;
1630 ret = ctdb_ctrl_get_server_id_list(ctdb, ctdb, TIMELIMIT(), options.pnn, &server_ids);
1632 DEBUG(DEBUG_ERR, ("Unable to get server_id list from node %u\n", options.pnn));
1636 for (i=0; i<server_ids->num; i++) {
1637 printf("Server id %d:%d:%d\n",
1638 server_ids->server_ids[i].pnn,
1639 server_ids->server_ids[i].type,
1640 server_ids->server_ids[i].server_id);
1647 send a tcp tickle ack
1649 static int tickle_tcp(struct ctdb_context *ctdb, int argc, const char **argv)
1652 ctdb_sock_addr src, dst;
1658 if (!parse_ip_port(argv[0], &src)) {
1659 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[0]));
1663 if (!parse_ip_port(argv[1], &dst)) {
1664 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[1]));
1668 ret = ctdb_sys_send_tcp(&src, &dst, 0, 0, 0);
1672 DEBUG(DEBUG_ERR, ("Error while sending tickle ack\n"));
1679 display public ip status
1681 static int control_ip(struct ctdb_context *ctdb, int argc, const char **argv)
1684 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1685 struct ctdb_all_public_ips *ips;
1687 if (options.pnn == CTDB_BROADCAST_ALL) {
1688 /* read the list of public ips from all nodes */
1689 ret = control_get_all_public_ips(ctdb, tmp_ctx, &ips);
1691 /* read the public ip list from this node */
1692 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &ips);
1695 DEBUG(DEBUG_ERR, ("Unable to get public ips from node %u\n", options.pnn));
1696 talloc_free(tmp_ctx);
1700 if (options.machinereadable){
1701 printf(":Public IP:Node:ActiveInterface:AvailableInterfaces:ConfiguredInterfaces:\n");
1703 if (options.pnn == CTDB_BROADCAST_ALL) {
1704 printf("Public IPs on ALL nodes\n");
1706 printf("Public IPs on node %u\n", options.pnn);
1710 for (i=1;i<=ips->num;i++) {
1711 struct ctdb_control_public_ip_info *info = NULL;
1713 char *aciface = NULL;
1714 char *avifaces = NULL;
1715 char *cifaces = NULL;
1717 if (options.pnn == CTDB_BROADCAST_ALL) {
1718 pnn = ips->ips[ips->num-i].pnn;
1724 ret = ctdb_ctrl_get_public_ip_info(ctdb, TIMELIMIT(), pnn, ctdb,
1725 &ips->ips[ips->num-i].addr, &info);
1732 for (j=0; j < info->num; j++) {
1733 if (cifaces == NULL) {
1734 cifaces = talloc_strdup(info,
1735 info->ifaces[j].name);
1737 cifaces = talloc_asprintf_append(cifaces,
1739 info->ifaces[j].name);
1742 if (info->active_idx == j) {
1743 aciface = info->ifaces[j].name;
1746 if (info->ifaces[j].link_state == 0) {
1750 if (avifaces == NULL) {
1751 avifaces = talloc_strdup(info, info->ifaces[j].name);
1753 avifaces = talloc_asprintf_append(avifaces,
1755 info->ifaces[j].name);
1760 if (options.machinereadable){
1761 printf(":%s:%d:%s:%s:%s:\n",
1762 ctdb_addr_to_str(&ips->ips[ips->num-i].addr),
1763 ips->ips[ips->num-i].pnn,
1765 avifaces?avifaces:"",
1766 cifaces?cifaces:"");
1768 printf("%s node[%d] active[%s] available[%s] configured[%s]\n",
1769 ctdb_addr_to_str(&ips->ips[ips->num-i].addr),
1770 ips->ips[ips->num-i].pnn,
1772 avifaces?avifaces:"",
1773 cifaces?cifaces:"");
1778 talloc_free(tmp_ctx);
1785 static int control_ipinfo(struct ctdb_context *ctdb, int argc, const char **argv)
1788 ctdb_sock_addr addr;
1789 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1790 struct ctdb_control_public_ip_info *info;
1793 talloc_free(tmp_ctx);
1797 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1798 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1802 /* read the public ip info from this node */
1803 ret = ctdb_ctrl_get_public_ip_info(ctdb, TIMELIMIT(), options.pnn,
1804 tmp_ctx, &addr, &info);
1806 DEBUG(DEBUG_ERR, ("Unable to get public ip[%s]info from node %u\n",
1807 argv[0], options.pnn));
1808 talloc_free(tmp_ctx);
1812 printf("Public IP[%s] info on node %u\n",
1813 ctdb_addr_to_str(&info->ip.addr),
1816 printf("IP:%s\nCurrentNode:%d\nNumInterfaces:%u\n",
1817 ctdb_addr_to_str(&info->ip.addr),
1818 info->ip.pnn, info->num);
1820 for (i=0; i<info->num; i++) {
1821 info->ifaces[i].name[CTDB_IFACE_SIZE] = '\0';
1823 printf("Interface[%u]: Name:%s Link:%s References:%u%s\n",
1824 i+1, info->ifaces[i].name,
1825 info->ifaces[i].link_state?"up":"down",
1826 (unsigned int)info->ifaces[i].references,
1827 (i==info->active_idx)?" (active)":"");
1830 talloc_free(tmp_ctx);
1835 display interfaces status
1837 static int control_ifaces(struct ctdb_context *ctdb, int argc, const char **argv)
1840 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1841 struct ctdb_control_get_ifaces *ifaces;
1843 /* read the public ip list from this node */
1844 ret = ctdb_ctrl_get_ifaces(ctdb, TIMELIMIT(), options.pnn,
1847 DEBUG(DEBUG_ERR, ("Unable to get interfaces from node %u\n",
1849 talloc_free(tmp_ctx);
1853 if (options.machinereadable){
1854 printf(":Name:LinkStatus:References:\n");
1856 printf("Interfaces on node %u\n", options.pnn);
1859 for (i=0; i<ifaces->num; i++) {
1860 if (options.machinereadable){
1861 printf(":%s:%s:%u\n",
1862 ifaces->ifaces[i].name,
1863 ifaces->ifaces[i].link_state?"1":"0",
1864 (unsigned int)ifaces->ifaces[i].references);
1866 printf("name:%s link:%s references:%u\n",
1867 ifaces->ifaces[i].name,
1868 ifaces->ifaces[i].link_state?"up":"down",
1869 (unsigned int)ifaces->ifaces[i].references);
1873 talloc_free(tmp_ctx);
1879 set link status of an interface
1881 static int control_setifacelink(struct ctdb_context *ctdb, int argc, const char **argv)
1884 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1885 struct ctdb_control_iface_info info;
1893 if (strlen(argv[0]) > CTDB_IFACE_SIZE) {
1894 DEBUG(DEBUG_ERR, ("interfaces name '%s' too long\n",
1896 talloc_free(tmp_ctx);
1899 strcpy(info.name, argv[0]);
1901 if (strcmp(argv[1], "up") == 0) {
1902 info.link_state = 1;
1903 } else if (strcmp(argv[1], "down") == 0) {
1904 info.link_state = 0;
1906 DEBUG(DEBUG_ERR, ("link state invalid '%s' should be 'up' or 'down'\n",
1908 talloc_free(tmp_ctx);
1912 /* read the public ip list from this node */
1913 ret = ctdb_ctrl_set_iface_link(ctdb, TIMELIMIT(), options.pnn,
1916 DEBUG(DEBUG_ERR, ("Unable to set link state for interfaces %s node %u\n",
1917 argv[0], options.pnn));
1918 talloc_free(tmp_ctx);
1922 talloc_free(tmp_ctx);
1927 display pid of a ctdb daemon
1929 static int control_getpid(struct ctdb_context *ctdb, int argc, const char **argv)
1934 ret = ctdb_ctrl_getpid(ctdb, TIMELIMIT(), options.pnn, &pid);
1936 DEBUG(DEBUG_ERR, ("Unable to get daemon pid from node %u\n", options.pnn));
1939 printf("Pid:%d\n", pid);
1944 static uint32_t ipreallocate_finished;
1947 handler for receiving the response to ipreallocate
1949 static void ip_reallocate_handler(struct ctdb_context *ctdb, uint64_t srvid,
1950 TDB_DATA data, void *private_data)
1952 ipreallocate_finished = 1;
1955 static void ctdb_every_second(struct event_context *ev, struct timed_event *te, struct timeval t, void *p)
1957 struct ctdb_context *ctdb = talloc_get_type(p, struct ctdb_context);
1959 event_add_timed(ctdb->ev, ctdb,
1960 timeval_current_ofs(1, 0),
1961 ctdb_every_second, ctdb);
1965 ask the recovery daemon on the recovery master to perform a ip reallocation
1967 static int control_ipreallocate(struct ctdb_context *ctdb, int argc, const char **argv)
1971 struct takeover_run_reply rd;
1973 struct ctdb_node_map *nodemap=NULL;
1975 struct timeval tv = timeval_current();
1977 /* we need some events to trigger so we can timeout and restart
1980 event_add_timed(ctdb->ev, ctdb,
1981 timeval_current_ofs(1, 0),
1982 ctdb_every_second, ctdb);
1984 rd.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
1986 DEBUG(DEBUG_ERR, ("Failed to get pnn of local node\n"));
1989 rd.srvid = getpid();
1991 /* register a message port for receiveing the reply so that we
1992 can receive the reply
1994 ctdb_set_message_handler(ctdb, rd.srvid, ip_reallocate_handler, NULL);
1996 data.dptr = (uint8_t *)&rd;
1997 data.dsize = sizeof(rd);
2001 DEBUG(DEBUG_ERR,("Failed waiting for cluster convergense\n"));
2005 /* check that there are valid nodes available */
2006 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap) != 0) {
2007 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2010 for (i=0; i<nodemap->num;i++) {
2011 if ((nodemap->nodes[i].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) == 0) {
2015 if (i==nodemap->num) {
2016 DEBUG(DEBUG_ERR,("No recmaster available, no need to wait for cluster convergence\n"));
2021 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
2023 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
2027 /* verify the node exists */
2028 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), recmaster, ctdb, &nodemap) != 0) {
2029 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2034 /* check tha there are nodes available that can act as a recmaster */
2035 for (i=0; i<nodemap->num; i++) {
2036 if (nodemap->nodes[i].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
2041 if (i == nodemap->num) {
2042 DEBUG(DEBUG_ERR,("No possible nodes to host addresses.\n"));
2046 /* verify the recovery master is not STOPPED, nor BANNED */
2047 if (nodemap->nodes[recmaster].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
2048 DEBUG(DEBUG_ERR,("No suitable recmaster found. Try again\n"));
2055 /* verify the recovery master is not STOPPED, nor BANNED */
2056 if (nodemap->nodes[recmaster].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
2057 DEBUG(DEBUG_ERR,("No suitable recmaster found. Try again\n"));
2063 ipreallocate_finished = 0;
2064 ret = ctdb_send_message(ctdb, recmaster, CTDB_SRVID_TAKEOVER_RUN, data);
2066 DEBUG(DEBUG_ERR,("Failed to send ip takeover run request message to %u\n", options.pnn));
2070 tv = timeval_current();
2071 /* this loop will terminate when we have received the reply */
2072 while (timeval_elapsed(&tv) < 3.0) {
2073 event_loop_once(ctdb->ev);
2075 if (ipreallocate_finished == 1) {
2079 DEBUG(DEBUG_INFO,("Timed out waiting for recmaster ipreallocate. Trying again\n"));
2089 disable a remote node
2091 static int control_disable(struct ctdb_context *ctdb, int argc, const char **argv)
2094 struct ctdb_node_map *nodemap=NULL;
2096 /* check if the node is already disabled */
2097 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2098 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2101 if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2102 DEBUG(DEBUG_ERR,("Node %d is already disabled.\n", options.pnn));
2107 ret = ctdb_ctrl_modflags(ctdb, TIMELIMIT(), options.pnn, NODE_FLAGS_PERMANENTLY_DISABLED, 0);
2109 DEBUG(DEBUG_ERR, ("Unable to disable node %u\n", options.pnn));
2115 /* read the nodemap and verify the change took effect */
2116 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2117 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2121 } while (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED));
2122 ret = control_ipreallocate(ctdb, argc, argv);
2124 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2132 enable a disabled remote node
2134 static int control_enable(struct ctdb_context *ctdb, int argc, const char **argv)
2138 struct ctdb_node_map *nodemap=NULL;
2141 /* check if the node is already enabled */
2142 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2143 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2146 if (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED)) {
2147 DEBUG(DEBUG_ERR,("Node %d is already enabled.\n", options.pnn));
2152 ret = ctdb_ctrl_modflags(ctdb, TIMELIMIT(), options.pnn, 0, NODE_FLAGS_PERMANENTLY_DISABLED);
2154 DEBUG(DEBUG_ERR, ("Unable to enable node %u\n", options.pnn));
2160 /* read the nodemap and verify the change took effect */
2161 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2162 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2166 } while (nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED);
2168 ret = control_ipreallocate(ctdb, argc, argv);
2170 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2180 static int control_stop(struct ctdb_context *ctdb, int argc, const char **argv)
2183 struct ctdb_node_map *nodemap=NULL;
2186 ret = ctdb_ctrl_stop_node(ctdb, TIMELIMIT(), options.pnn);
2188 DEBUG(DEBUG_ERR, ("Unable to stop node %u try again\n", options.pnn));
2193 /* read the nodemap and verify the change took effect */
2194 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2195 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2199 } while (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_STOPPED));
2200 ret = control_ipreallocate(ctdb, argc, argv);
2202 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2210 restart a stopped remote node
2212 static int control_continue(struct ctdb_context *ctdb, int argc, const char **argv)
2216 struct ctdb_node_map *nodemap=NULL;
2219 ret = ctdb_ctrl_continue_node(ctdb, TIMELIMIT(), options.pnn);
2221 DEBUG(DEBUG_ERR, ("Unable to continue node %u\n", options.pnn));
2227 /* read the nodemap and verify the change took effect */
2228 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2229 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2233 } while (nodemap->nodes[options.pnn].flags & NODE_FLAGS_STOPPED);
2234 ret = control_ipreallocate(ctdb, argc, argv);
2236 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2243 static uint32_t get_generation(struct ctdb_context *ctdb)
2245 struct ctdb_vnn_map *vnnmap=NULL;
2248 /* wait until the recmaster is not in recovery mode */
2250 uint32_t recmode, recmaster;
2252 if (vnnmap != NULL) {
2253 talloc_free(vnnmap);
2257 /* get the recmaster */
2258 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, &recmaster);
2260 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
2264 /* get recovery mode */
2265 ret = ctdb_ctrl_getrecmode(ctdb, ctdb, TIMELIMIT(), recmaster, &recmode);
2267 DEBUG(DEBUG_ERR, ("Unable to get recmode from node %u\n", options.pnn));
2271 /* get the current generation number */
2272 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), recmaster, ctdb, &vnnmap);
2274 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from recmaster (%u)\n", recmaster));
2278 if ((recmode == CTDB_RECOVERY_NORMAL)
2279 && (vnnmap->generation != 1)){
2280 return vnnmap->generation;
2287 ban a node from the cluster
2289 static int control_ban(struct ctdb_context *ctdb, int argc, const char **argv)
2292 struct ctdb_node_map *nodemap=NULL;
2293 struct ctdb_ban_time bantime;
2299 /* verify the node exists */
2300 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
2302 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2306 if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_BANNED) {
2307 DEBUG(DEBUG_ERR,("Node %u is already banned.\n", options.pnn));
2311 bantime.pnn = options.pnn;
2312 bantime.time = strtoul(argv[0], NULL, 0);
2314 ret = ctdb_ctrl_set_ban(ctdb, TIMELIMIT(), options.pnn, &bantime);
2316 DEBUG(DEBUG_ERR,("Banning node %d for %d seconds failed.\n", bantime.pnn, bantime.time));
2320 ret = control_ipreallocate(ctdb, argc, argv);
2322 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2331 unban a node from the cluster
2333 static int control_unban(struct ctdb_context *ctdb, int argc, const char **argv)
2336 struct ctdb_node_map *nodemap=NULL;
2337 struct ctdb_ban_time bantime;
2339 /* verify the node exists */
2340 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
2342 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2346 if (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_BANNED)) {
2347 DEBUG(DEBUG_ERR,("Node %u is not banned.\n", options.pnn));
2351 bantime.pnn = options.pnn;
2354 ret = ctdb_ctrl_set_ban(ctdb, TIMELIMIT(), options.pnn, &bantime);
2356 DEBUG(DEBUG_ERR,("Unbanning node %d failed.\n", bantime.pnn));
2360 ret = control_ipreallocate(ctdb, argc, argv);
2362 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2371 show ban information for a node
2373 static int control_showban(struct ctdb_context *ctdb, int argc, const char **argv)
2376 struct ctdb_node_map *nodemap=NULL;
2377 struct ctdb_ban_time *bantime;
2379 /* verify the node exists */
2380 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
2382 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2386 ret = ctdb_ctrl_get_ban(ctdb, TIMELIMIT(), options.pnn, ctdb, &bantime);
2388 DEBUG(DEBUG_ERR,("Showing ban info for node %d failed.\n", options.pnn));
2392 if (bantime->time == 0) {
2393 printf("Node %u is not banned\n", bantime->pnn);
2395 printf("Node %u is banned banned for %d seconds\n", bantime->pnn, bantime->time);
2404 static int control_shutdown(struct ctdb_context *ctdb, int argc, const char **argv)
2408 ret = ctdb_ctrl_shutdown(ctdb, TIMELIMIT(), options.pnn);
2410 DEBUG(DEBUG_ERR, ("Unable to shutdown node %u\n", options.pnn));
2420 static int control_recover(struct ctdb_context *ctdb, int argc, const char **argv)
2423 uint32_t generation, next_generation;
2425 /* record the current generation number */
2426 generation = get_generation(ctdb);
2428 ret = ctdb_ctrl_freeze_priority(ctdb, TIMELIMIT(), options.pnn, 1);
2430 DEBUG(DEBUG_ERR, ("Unable to freeze node\n"));
2434 ret = ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
2436 DEBUG(DEBUG_ERR, ("Unable to set recovery mode\n"));
2440 /* wait until we are in a new generation */
2442 next_generation = get_generation(ctdb);
2443 if (next_generation != generation) {
2454 display monitoring mode of a remote node
2456 static int control_getmonmode(struct ctdb_context *ctdb, int argc, const char **argv)
2461 ret = ctdb_ctrl_getmonmode(ctdb, TIMELIMIT(), options.pnn, &monmode);
2463 DEBUG(DEBUG_ERR, ("Unable to get monmode from node %u\n", options.pnn));
2466 if (!options.machinereadable){
2467 printf("Monitoring mode:%s (%d)\n",monmode==CTDB_MONITORING_ACTIVE?"ACTIVE":"DISABLED",monmode);
2470 printf(":%d:\n",monmode);
2477 display capabilities of a remote node
2479 static int control_getcapabilities(struct ctdb_context *ctdb, int argc, const char **argv)
2481 uint32_t capabilities;
2484 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), options.pnn, &capabilities);
2486 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", options.pnn));
2490 if (!options.machinereadable){
2491 printf("RECMASTER: %s\n", (capabilities&CTDB_CAP_RECMASTER)?"YES":"NO");
2492 printf("LMASTER: %s\n", (capabilities&CTDB_CAP_LMASTER)?"YES":"NO");
2493 printf("LVS: %s\n", (capabilities&CTDB_CAP_LVS)?"YES":"NO");
2494 printf("NATGW: %s\n", (capabilities&CTDB_CAP_NATGW)?"YES":"NO");
2496 printf(":RECMASTER:LMASTER:LVS:NATGW:\n");
2497 printf(":%d:%d:%d:%d:\n",
2498 !!(capabilities&CTDB_CAP_RECMASTER),
2499 !!(capabilities&CTDB_CAP_LMASTER),
2500 !!(capabilities&CTDB_CAP_LVS),
2501 !!(capabilities&CTDB_CAP_NATGW));
2507 display lvs configuration
2509 static int control_lvs(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 /* Print all LVS nodes */
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 printf("%d:%s\n", i,
2568 ctdb_addr_to_str(&nodemap->nodes[i].addr));
2575 display who is the lvs master
2577 static int control_lvsmaster(struct ctdb_context *ctdb, int argc, const char **argv)
2579 uint32_t *capabilities;
2580 struct ctdb_node_map *nodemap=NULL;
2582 int healthy_count = 0;
2584 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
2586 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
2590 capabilities = talloc_array(ctdb, uint32_t, nodemap->num);
2591 CTDB_NO_MEMORY(ctdb, capabilities);
2593 /* collect capabilities for all connected nodes */
2594 for (i=0; i<nodemap->num; i++) {
2595 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2598 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2602 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), i, &capabilities[i]);
2604 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", i));
2608 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2612 if (!(nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY)) {
2617 /* find and show the lvsmaster */
2618 for (i=0; i<nodemap->num; i++) {
2619 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2622 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2625 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2629 if (healthy_count != 0) {
2630 if (nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY) {
2635 if (options.machinereadable){
2638 printf("Node %d is LVS master\n", i);
2643 printf("There is no LVS master\n");
2648 disable monitoring on a node
2650 static int control_disable_monmode(struct ctdb_context *ctdb, int argc, const char **argv)
2655 ret = ctdb_ctrl_disable_monmode(ctdb, TIMELIMIT(), options.pnn);
2657 DEBUG(DEBUG_ERR, ("Unable to disable monmode on node %u\n", options.pnn));
2660 printf("Monitoring mode:%s\n","DISABLED");
2666 enable monitoring on a node
2668 static int control_enable_monmode(struct ctdb_context *ctdb, int argc, const char **argv)
2673 ret = ctdb_ctrl_enable_monmode(ctdb, TIMELIMIT(), options.pnn);
2675 DEBUG(DEBUG_ERR, ("Unable to enable monmode on node %u\n", options.pnn));
2678 printf("Monitoring mode:%s\n","ACTIVE");
2684 display remote list of keys/data for a db
2686 static int control_catdb(struct ctdb_context *ctdb, int argc, const char **argv)
2688 const char *db_name;
2689 struct ctdb_db_context *ctdb_db;
2699 if (db_exists(ctdb, db_name)) {
2700 DEBUG(DEBUG_ERR,("Database '%s' does not exist\n", db_name));
2704 ctdb_db = ctdb_attach(ctdb, db_name, false, 0);
2706 if (ctdb_db == NULL) {
2707 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
2711 /* traverse and dump the cluster tdb */
2712 ret = ctdb_dump_db(ctdb_db, stdout);
2714 DEBUG(DEBUG_ERR, ("Unable to dump database\n"));
2715 DEBUG(DEBUG_ERR, ("Maybe try 'ctdb getdbstatus %s'"
2716 " and 'ctdb getvar AllowUnhealthyDBRead'\n",
2720 talloc_free(ctdb_db);
2722 printf("Dumped %d records\n", ret);
2727 static void log_handler(struct ctdb_context *ctdb, uint64_t srvid,
2728 TDB_DATA data, void *private_data)
2730 DEBUG(DEBUG_ERR,("Log data received\n"));
2731 if (data.dsize > 0) {
2732 printf("%s", data.dptr);
2739 display a list of log messages from the in memory ringbuffer
2741 static int control_getlog(struct ctdb_context *ctdb, int argc, const char **argv)
2745 struct ctdb_get_log_addr log_addr;
2747 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2752 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
2753 talloc_free(tmp_ctx);
2757 log_addr.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
2758 log_addr.srvid = getpid();
2759 if (isalpha(argv[0][0]) || argv[0][0] == '-') {
2760 log_addr.level = get_debug_by_desc(argv[0]);
2762 log_addr.level = strtol(argv[0], NULL, 0);
2766 data.dptr = (unsigned char *)&log_addr;
2767 data.dsize = sizeof(log_addr);
2769 DEBUG(DEBUG_ERR, ("Pulling logs from node %u\n", options.pnn));
2771 ctdb_set_message_handler(ctdb, log_addr.srvid, log_handler, NULL);
2774 DEBUG(DEBUG_ERR,("Listen for response on %d\n", (int)log_addr.srvid));
2776 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_GET_LOG,
2777 0, data, tmp_ctx, NULL, &res, NULL, &errmsg);
2778 if (ret != 0 || res != 0) {
2779 DEBUG(DEBUG_ERR,("Failed to get logs - %s\n", errmsg));
2780 talloc_free(tmp_ctx);
2785 tv = timeval_current();
2786 /* this loop will terminate when we have received the reply */
2787 while (timeval_elapsed(&tv) < 3.0) {
2788 event_loop_once(ctdb->ev);
2791 DEBUG(DEBUG_INFO,("Timed out waiting for log data.\n"));
2793 talloc_free(tmp_ctx);
2798 clear the in memory log area
2800 static int control_clearlog(struct ctdb_context *ctdb, int argc, const char **argv)
2805 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2807 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_CLEAR_LOG,
2808 0, tdb_null, tmp_ctx, NULL, &res, NULL, &errmsg);
2809 if (ret != 0 || res != 0) {
2810 DEBUG(DEBUG_ERR,("Failed to clear logs\n"));
2811 talloc_free(tmp_ctx);
2815 talloc_free(tmp_ctx);
2822 display a list of the databases on a remote ctdb
2824 static int control_getdbmap(struct ctdb_context *ctdb, int argc, const char **argv)
2827 struct ctdb_dbid_map *dbmap=NULL;
2829 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
2831 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
2835 if(options.machinereadable){
2836 printf(":ID:Name:Path:Persistent:Unhealthy:\n");
2837 for(i=0;i<dbmap->num;i++){
2843 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn,
2844 dbmap->dbs[i].dbid, ctdb, &path);
2845 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn,
2846 dbmap->dbs[i].dbid, ctdb, &name);
2847 ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn,
2848 dbmap->dbs[i].dbid, ctdb, &health);
2849 persistent = dbmap->dbs[i].persistent;
2850 printf(":0x%08X:%s:%s:%d:%d:\n",
2851 dbmap->dbs[i].dbid, name, path,
2852 !!(persistent), !!(health));
2857 printf("Number of databases:%d\n", dbmap->num);
2858 for(i=0;i<dbmap->num;i++){
2864 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &path);
2865 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
2866 ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &health);
2867 persistent = dbmap->dbs[i].persistent;
2868 printf("dbid:0x%08x name:%s path:%s%s%s\n",
2869 dbmap->dbs[i].dbid, name, path,
2870 persistent?" PERSISTENT":"",
2871 health?" UNHEALTHY":"");
2878 display the status of a database on a remote ctdb
2880 static int control_getdbstatus(struct ctdb_context *ctdb, int argc, const char **argv)
2883 struct ctdb_dbid_map *dbmap=NULL;
2884 const char *db_name;
2892 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
2894 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
2898 for(i=0;i<dbmap->num;i++){
2904 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
2905 if (strcmp(name, db_name) != 0) {
2909 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &path);
2910 ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &health);
2911 persistent = dbmap->dbs[i].persistent;
2912 printf("dbid: 0x%08x\nname: %s\npath: %s\nPERSISTENT: %s\nHEALTH: %s\n",
2913 dbmap->dbs[i].dbid, name, path,
2914 persistent?"yes":"no",
2915 health?health:"OK");
2919 DEBUG(DEBUG_ERR, ("db %s doesn't exist on node %u\n", db_name, options.pnn));
2924 check if the local node is recmaster or not
2925 it will return 1 if this node is the recmaster and 0 if it is not
2926 or if the local ctdb daemon could not be contacted
2928 static int control_isnotrecmaster(struct ctdb_context *ctdb, int argc, const char **argv)
2930 uint32_t mypnn, recmaster;
2933 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
2935 printf("Failed to get pnn of node\n");
2939 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
2941 printf("Failed to get the recmaster\n");
2945 if (recmaster != mypnn) {
2946 printf("this node is not the recmaster\n");
2950 printf("this node is the recmaster\n");
2957 static int control_ping(struct ctdb_context *ctdb, int argc, const char **argv)
2960 struct timeval tv = timeval_current();
2961 ret = ctdb_ctrl_ping(ctdb, options.pnn);
2963 printf("Unable to get ping response from node %u\n", options.pnn);
2966 printf("response from %u time=%.6f sec (%d clients)\n",
2967 options.pnn, timeval_elapsed(&tv), ret);
2976 static int control_getvar(struct ctdb_context *ctdb, int argc, const char **argv)
2987 ret = ctdb_ctrl_get_tunable(ctdb, TIMELIMIT(), options.pnn, name, &value);
2989 DEBUG(DEBUG_ERR, ("Unable to get tunable variable '%s'\n", name));
2993 printf("%-19s = %u\n", name, value);
3000 static int control_setvar(struct ctdb_context *ctdb, int argc, const char **argv)
3011 value = strtoul(argv[1], NULL, 0);
3013 ret = ctdb_ctrl_set_tunable(ctdb, TIMELIMIT(), options.pnn, name, value);
3015 DEBUG(DEBUG_ERR, ("Unable to set tunable variable '%s'\n", name));
3024 static int control_listvars(struct ctdb_context *ctdb, int argc, const char **argv)
3030 ret = ctdb_ctrl_list_tunables(ctdb, TIMELIMIT(), options.pnn, ctdb, &list, &count);
3032 DEBUG(DEBUG_ERR, ("Unable to list tunable variables\n"));
3036 for (i=0;i<count;i++) {
3037 control_getvar(ctdb, 1, &list[i]);
3046 display debug level on a node
3048 static int control_getdebug(struct ctdb_context *ctdb, int argc, const char **argv)
3053 ret = ctdb_ctrl_get_debuglevel(ctdb, options.pnn, &level);
3055 DEBUG(DEBUG_ERR, ("Unable to get debuglevel response from node %u\n", options.pnn));
3058 if (options.machinereadable){
3059 printf(":Name:Level:\n");
3060 printf(":%s:%d:\n",get_debug_by_level(level),level);
3062 printf("Node %u is at debug level %s (%d)\n", options.pnn, get_debug_by_level(level), level);
3069 display reclock file of a node
3071 static int control_getreclock(struct ctdb_context *ctdb, int argc, const char **argv)
3074 const char *reclock;
3076 ret = ctdb_ctrl_getreclock(ctdb, TIMELIMIT(), options.pnn, ctdb, &reclock);
3078 DEBUG(DEBUG_ERR, ("Unable to get reclock file from node %u\n", options.pnn));
3081 if (options.machinereadable){
3082 if (reclock != NULL) {
3083 printf("%s", reclock);
3086 if (reclock == NULL) {
3087 printf("No reclock file used.\n");
3089 printf("Reclock file:%s\n", reclock);
3097 set the reclock file of a node
3099 static int control_setreclock(struct ctdb_context *ctdb, int argc, const char **argv)
3102 const char *reclock;
3106 } else if (argc == 1) {
3112 ret = ctdb_ctrl_setreclock(ctdb, TIMELIMIT(), options.pnn, reclock);
3114 DEBUG(DEBUG_ERR, ("Unable to get reclock file from node %u\n", options.pnn));
3121 set the natgw state on/off
3123 static int control_setnatgwstate(struct ctdb_context *ctdb, int argc, const char **argv)
3126 uint32_t natgwstate;
3132 if (!strcmp(argv[0], "on")) {
3134 } else if (!strcmp(argv[0], "off")) {
3140 ret = ctdb_ctrl_setnatgwstate(ctdb, TIMELIMIT(), options.pnn, natgwstate);
3142 DEBUG(DEBUG_ERR, ("Unable to set the natgw state for node %u\n", options.pnn));
3150 set the lmaster role on/off
3152 static int control_setlmasterrole(struct ctdb_context *ctdb, int argc, const char **argv)
3155 uint32_t lmasterrole;
3161 if (!strcmp(argv[0], "on")) {
3163 } else if (!strcmp(argv[0], "off")) {
3169 ret = ctdb_ctrl_setlmasterrole(ctdb, TIMELIMIT(), options.pnn, lmasterrole);
3171 DEBUG(DEBUG_ERR, ("Unable to set the lmaster role for node %u\n", options.pnn));
3179 set the recmaster role on/off
3181 static int control_setrecmasterrole(struct ctdb_context *ctdb, int argc, const char **argv)
3184 uint32_t recmasterrole;
3190 if (!strcmp(argv[0], "on")) {
3192 } else if (!strcmp(argv[0], "off")) {
3198 ret = ctdb_ctrl_setrecmasterrole(ctdb, TIMELIMIT(), options.pnn, recmasterrole);
3200 DEBUG(DEBUG_ERR, ("Unable to set the recmaster role for node %u\n", options.pnn));
3208 set debug level on a node or all nodes
3210 static int control_setdebug(struct ctdb_context *ctdb, int argc, const char **argv)
3216 printf("You must specify the debug level. Valid levels are:\n");
3217 for (i=0; debug_levels[i].description != NULL; i++) {
3218 printf("%s (%d)\n", debug_levels[i].description, debug_levels[i].level);
3224 if (isalpha(argv[0][0]) || argv[0][0] == '-') {
3225 level = get_debug_by_desc(argv[0]);
3227 level = strtol(argv[0], NULL, 0);
3230 for (i=0; debug_levels[i].description != NULL; i++) {
3231 if (level == debug_levels[i].level) {
3235 if (debug_levels[i].description == NULL) {
3236 printf("Invalid debug level, must be one of\n");
3237 for (i=0; debug_levels[i].description != NULL; i++) {
3238 printf("%s (%d)\n", debug_levels[i].description, debug_levels[i].level);
3243 ret = ctdb_ctrl_set_debuglevel(ctdb, options.pnn, level);
3245 DEBUG(DEBUG_ERR, ("Unable to set debug level on node %u\n", options.pnn));
3254 static int control_freeze(struct ctdb_context *ctdb, int argc, const char **argv)
3260 priority = strtol(argv[0], NULL, 0);
3264 DEBUG(DEBUG_ERR,("Freeze by priority %u\n", priority));
3266 ret = ctdb_ctrl_freeze_priority(ctdb, TIMELIMIT(), options.pnn, priority);
3268 DEBUG(DEBUG_ERR, ("Unable to freeze node %u\n", options.pnn));
3276 static int control_thaw(struct ctdb_context *ctdb, int argc, const char **argv)
3282 priority = strtol(argv[0], NULL, 0);
3286 DEBUG(DEBUG_ERR,("Thaw by priority %u\n", priority));
3288 ret = ctdb_ctrl_thaw_priority(ctdb, TIMELIMIT(), options.pnn, priority);
3290 DEBUG(DEBUG_ERR, ("Unable to thaw node %u\n", options.pnn));
3297 attach to a database
3299 static int control_attach(struct ctdb_context *ctdb, int argc, const char **argv)
3301 const char *db_name;
3302 struct ctdb_db_context *ctdb_db;
3309 ctdb_db = ctdb_attach(ctdb, db_name, false, 0);
3310 if (ctdb_db == NULL) {
3311 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
3321 static int control_setdbprio(struct ctdb_context *ctdb, int argc, const char **argv)
3323 struct ctdb_db_priority db_prio;
3330 db_prio.db_id = strtoul(argv[0], NULL, 0);
3331 db_prio.priority = strtoul(argv[1], NULL, 0);
3333 ret = ctdb_ctrl_set_db_priority(ctdb, TIMELIMIT(), options.pnn, &db_prio);
3335 DEBUG(DEBUG_ERR,("Unable to set db prio\n"));
3345 static int control_getdbprio(struct ctdb_context *ctdb, int argc, const char **argv)
3347 uint32_t db_id, priority;
3354 db_id = strtoul(argv[0], NULL, 0);
3356 ret = ctdb_ctrl_get_db_priority(ctdb, TIMELIMIT(), options.pnn, db_id, &priority);
3358 DEBUG(DEBUG_ERR,("Unable to get db prio\n"));
3362 DEBUG(DEBUG_ERR,("Priority:%u\n", priority));
3368 run an eventscript on a node
3370 static int control_eventscript(struct ctdb_context *ctdb, int argc, const char **argv)
3376 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3379 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3383 data.dptr = (unsigned char *)discard_const(argv[0]);
3384 data.dsize = strlen((char *)data.dptr) + 1;
3386 DEBUG(DEBUG_ERR, ("Running eventscripts with arguments \"%s\" on node %u\n", data.dptr, options.pnn));
3388 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_RUN_EVENTSCRIPTS,
3389 0, data, tmp_ctx, NULL, &res, NULL, &errmsg);
3390 if (ret != 0 || res != 0) {
3391 DEBUG(DEBUG_ERR,("Failed to run eventscripts - %s\n", errmsg));
3392 talloc_free(tmp_ctx);
3395 talloc_free(tmp_ctx);
3399 #define DB_VERSION 1
3400 #define MAX_DB_NAME 64
3401 struct db_file_header {
3402 unsigned long version;
3404 unsigned long persistent;
3406 const char name[MAX_DB_NAME];
3409 struct backup_data {
3410 struct ctdb_marshall_buffer *records;
3413 bool traverse_error;
3416 static int backup_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *private)
3418 struct backup_data *bd = talloc_get_type(private, struct backup_data);
3419 struct ctdb_rec_data *rec;
3421 /* add the record */
3422 rec = ctdb_marshall_record(bd->records, 0, key, NULL, data);
3424 bd->traverse_error = true;
3425 DEBUG(DEBUG_ERR,("Failed to marshall record\n"));
3428 bd->records = talloc_realloc_size(NULL, bd->records, rec->length + bd->len);
3429 if (bd->records == NULL) {
3430 DEBUG(DEBUG_ERR,("Failed to expand marshalling buffer\n"));
3431 bd->traverse_error = true;
3434 bd->records->count++;
3435 memcpy(bd->len+(uint8_t *)bd->records, rec, rec->length);
3436 bd->len += rec->length;
3444 * backup a database to a file
3446 static int control_backupdb(struct ctdb_context *ctdb, int argc, const char **argv)
3449 struct ctdb_dbid_map *dbmap=NULL;
3450 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3451 struct db_file_header dbhdr;
3452 struct ctdb_db_context *ctdb_db;
3453 struct backup_data *bd;
3456 const char *reason = NULL;
3459 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3463 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &dbmap);
3465 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
3469 for(i=0;i<dbmap->num;i++){
3472 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, tmp_ctx, &name);
3473 if(!strcmp(argv[0], name)){
3474 talloc_free(discard_const(name));
3477 talloc_free(discard_const(name));
3479 if (i == dbmap->num) {
3480 DEBUG(DEBUG_ERR,("No database with name '%s' found\n", argv[0]));
3481 talloc_free(tmp_ctx);
3485 ret = ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn,
3486 dbmap->dbs[i].dbid, tmp_ctx, &reason);
3488 DEBUG(DEBUG_ERR,("Unable to get dbhealth for database '%s'\n",
3490 talloc_free(tmp_ctx);
3494 uint32_t allow_unhealthy = 0;
3496 ctdb_ctrl_get_tunable(ctdb, TIMELIMIT(), options.pnn,
3497 "AllowUnhealthyDBRead",
3500 if (allow_unhealthy != 1) {
3501 DEBUG(DEBUG_ERR,("database '%s' is unhealthy: %s\n",
3504 DEBUG(DEBUG_ERR,("disallow backup : tunnable AllowUnhealthyDBRead = %u\n",
3506 talloc_free(tmp_ctx);
3510 DEBUG(DEBUG_WARNING,("WARNING database '%s' is unhealthy - see 'ctdb getdbstatus %s'\n",
3512 DEBUG(DEBUG_WARNING,("WARNING! allow backup of unhealthy database: "
3513 "tunnable AllowUnhealthyDBRead = %u\n",
3517 ctdb_db = ctdb_attach(ctdb, argv[0], dbmap->dbs[i].persistent, 0);
3518 if (ctdb_db == NULL) {
3519 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", argv[0]));
3520 talloc_free(tmp_ctx);
3525 ret = tdb_transaction_start(ctdb_db->ltdb->tdb);
3527 DEBUG(DEBUG_ERR,("Failed to start transaction\n"));
3528 talloc_free(tmp_ctx);
3533 bd = talloc_zero(tmp_ctx, struct backup_data);
3535 DEBUG(DEBUG_ERR,("Failed to allocate backup_data\n"));
3536 talloc_free(tmp_ctx);
3540 bd->records = talloc_zero(bd, struct ctdb_marshall_buffer);
3541 if (bd->records == NULL) {
3542 DEBUG(DEBUG_ERR,("Failed to allocate ctdb_marshall_buffer\n"));
3543 talloc_free(tmp_ctx);
3547 bd->len = offsetof(struct ctdb_marshall_buffer, data);
3548 bd->records->db_id = ctdb_db->db_id;
3549 /* traverse the database collecting all records */
3550 if (tdb_traverse_read(ctdb_db->ltdb->tdb, backup_traverse, bd) == -1 ||
3551 bd->traverse_error) {
3552 DEBUG(DEBUG_ERR,("Traverse error\n"));
3553 talloc_free(tmp_ctx);
3557 tdb_transaction_cancel(ctdb_db->ltdb->tdb);
3560 fh = open(argv[1], O_RDWR|O_CREAT, 0600);
3562 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[1]));
3563 talloc_free(tmp_ctx);
3567 dbhdr.version = DB_VERSION;
3568 dbhdr.timestamp = time(NULL);
3569 dbhdr.persistent = dbmap->dbs[i].persistent;
3570 dbhdr.size = bd->len;
3571 if (strlen(argv[0]) >= MAX_DB_NAME) {
3572 DEBUG(DEBUG_ERR,("Too long dbname\n"));
3575 strncpy(discard_const(dbhdr.name), argv[0], MAX_DB_NAME);
3576 ret = write(fh, &dbhdr, sizeof(dbhdr));
3578 DEBUG(DEBUG_ERR,("write failed: %s\n", strerror(errno)));
3581 ret = write(fh, bd->records, bd->len);
3583 DEBUG(DEBUG_ERR,("write failed: %s\n", strerror(errno)));
3592 DEBUG(DEBUG_ERR,("close failed: %s\n", strerror(errno)));
3595 talloc_free(tmp_ctx);
3600 * restore a database from a file
3602 static int control_restoredb(struct ctdb_context *ctdb, int argc, const char **argv)
3605 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3608 struct db_file_header dbhdr;
3609 struct ctdb_db_context *ctdb_db;
3610 struct ctdb_node_map *nodemap=NULL;
3611 struct ctdb_vnn_map *vnnmap=NULL;
3613 struct ctdb_control_wipe_database w;
3615 uint32_t generation;
3620 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3624 fh = open(argv[0], O_RDONLY);
3626 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[0]));
3627 talloc_free(tmp_ctx);
3631 read(fh, &dbhdr, sizeof(dbhdr));
3632 if (dbhdr.version != DB_VERSION) {
3633 DEBUG(DEBUG_ERR,("Invalid version of database dump. File is version %lu but expected version was %u\n", dbhdr.version, DB_VERSION));
3634 talloc_free(tmp_ctx);
3638 outdata.dsize = dbhdr.size;
3639 outdata.dptr = talloc_size(tmp_ctx, outdata.dsize);
3640 if (outdata.dptr == NULL) {
3641 DEBUG(DEBUG_ERR,("Failed to allocate data of size '%lu'\n", dbhdr.size));
3643 talloc_free(tmp_ctx);
3646 read(fh, outdata.dptr, outdata.dsize);
3649 tm = localtime(&dbhdr.timestamp);
3650 strftime(tbuf,sizeof(tbuf)-1,"%Y/%m/%d %H:%M:%S", tm);
3651 printf("Restoring database '%s' from backup @ %s\n",
3655 ctdb_db = ctdb_attach(ctdb, dbhdr.name, dbhdr.persistent, 0);
3656 if (ctdb_db == NULL) {
3657 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", dbhdr.name));
3658 talloc_free(tmp_ctx);
3662 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
3664 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
3665 talloc_free(tmp_ctx);
3670 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &vnnmap);
3672 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n", options.pnn));
3673 talloc_free(tmp_ctx);
3677 /* freeze all nodes */
3678 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3679 for (i=1; i<=NUM_DB_PRIORITIES; i++) {
3680 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_FREEZE,
3686 DEBUG(DEBUG_ERR, ("Unable to freeze nodes.\n"));
3687 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3688 talloc_free(tmp_ctx);
3693 generation = vnnmap->generation;
3694 data.dptr = (void *)&generation;
3695 data.dsize = sizeof(generation);
3697 /* start a cluster wide transaction */
3698 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3699 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_START,
3701 TIMELIMIT(), false, data,
3704 DEBUG(DEBUG_ERR, ("Unable to start cluster wide transactions.\n"));
3709 w.db_id = ctdb_db->db_id;
3710 w.transaction_id = generation;
3712 data.dptr = (void *)&w;
3713 data.dsize = sizeof(w);
3715 /* wipe all the remote databases. */
3716 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3717 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_WIPE_DATABASE,
3719 TIMELIMIT(), false, data,
3722 DEBUG(DEBUG_ERR, ("Unable to wipe database.\n"));
3723 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3724 talloc_free(tmp_ctx);
3728 /* push the database */
3729 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3730 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_PUSH_DB,
3732 TIMELIMIT(), false, outdata,
3735 DEBUG(DEBUG_ERR, ("Failed to push database.\n"));
3736 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3737 talloc_free(tmp_ctx);
3741 data.dptr = (void *)&ctdb_db->db_id;
3742 data.dsize = sizeof(ctdb_db->db_id);
3744 /* mark the database as healthy */
3745 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3746 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_DB_SET_HEALTHY,
3748 TIMELIMIT(), false, data,
3751 DEBUG(DEBUG_ERR, ("Failed to mark database as healthy.\n"));
3752 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3753 talloc_free(tmp_ctx);
3757 data.dptr = (void *)&generation;
3758 data.dsize = sizeof(generation);
3760 /* commit all the changes */
3761 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_COMMIT,
3763 TIMELIMIT(), false, data,
3766 DEBUG(DEBUG_ERR, ("Unable to commit databases.\n"));
3767 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3768 talloc_free(tmp_ctx);
3773 /* thaw all nodes */
3774 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3775 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_THAW,
3781 DEBUG(DEBUG_ERR, ("Unable to thaw nodes.\n"));
3782 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3783 talloc_free(tmp_ctx);
3788 talloc_free(tmp_ctx);
3793 * dump a database backup from a file
3795 static int control_dumpdbbackup(struct ctdb_context *ctdb, int argc, const char **argv)
3797 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3799 struct db_file_header dbhdr;
3803 struct ctdb_rec_data *rec = NULL;
3804 struct ctdb_marshall_buffer *m;
3807 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3811 fh = open(argv[0], O_RDONLY);
3813 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[0]));
3814 talloc_free(tmp_ctx);
3818 read(fh, &dbhdr, sizeof(dbhdr));
3819 if (dbhdr.version != DB_VERSION) {
3820 DEBUG(DEBUG_ERR,("Invalid version of database dump. File is version %lu but expected version was %u\n", dbhdr.version, DB_VERSION));
3821 talloc_free(tmp_ctx);
3825 outdata.dsize = dbhdr.size;
3826 outdata.dptr = talloc_size(tmp_ctx, outdata.dsize);
3827 if (outdata.dptr == NULL) {
3828 DEBUG(DEBUG_ERR,("Failed to allocate data of size '%lu'\n", dbhdr.size));
3830 talloc_free(tmp_ctx);
3833 read(fh, outdata.dptr, outdata.dsize);
3835 m = (struct ctdb_marshall_buffer *)outdata.dptr;
3837 tm = localtime(&dbhdr.timestamp);
3838 strftime(tbuf,sizeof(tbuf)-1,"%Y/%m/%d %H:%M:%S", tm);
3839 printf("Backup of database name:'%s' dbid:0x%x08x from @ %s\n",
3840 dbhdr.name, m->db_id, tbuf);
3842 for (i=0; i < m->count; i++) {
3846 /* we do not want the header splitted, so we pass NULL*/
3847 rec = ctdb_marshall_loop_next(m, rec, &reqid,
3850 ctdb_dumpdb_record(ctdb, key, data, stdout);
3853 printf("Dumped %d records\n", i);
3854 talloc_free(tmp_ctx);
3859 * wipe a database from a file
3861 static int control_wipedb(struct ctdb_context *ctdb, int argc,
3865 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3867 struct ctdb_db_context *ctdb_db;
3868 struct ctdb_node_map *nodemap = NULL;
3869 struct ctdb_vnn_map *vnnmap = NULL;
3871 struct ctdb_control_wipe_database w;
3873 uint32_t generation;
3874 struct ctdb_dbid_map *dbmap = NULL;
3877 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3881 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx,
3884 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n",
3889 for(i=0;i<dbmap->num;i++){
3892 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn,
3893 dbmap->dbs[i].dbid, tmp_ctx, &name);
3894 if(!strcmp(argv[0], name)){
3895 talloc_free(discard_const(name));
3898 talloc_free(discard_const(name));
3900 if (i == dbmap->num) {
3901 DEBUG(DEBUG_ERR, ("No database with name '%s' found\n",
3903 talloc_free(tmp_ctx);
3907 ctdb_db = ctdb_attach(ctdb, argv[0], dbmap->dbs[i].persistent, 0);
3908 if (ctdb_db == NULL) {
3909 DEBUG(DEBUG_ERR, ("Unable to attach to database '%s'\n",
3911 talloc_free(tmp_ctx);
3915 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb,
3918 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n",
3920 talloc_free(tmp_ctx);
3924 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx,
3927 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n",
3929 talloc_free(tmp_ctx);
3933 /* freeze all nodes */
3934 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3935 for (i=1; i<=NUM_DB_PRIORITIES; i++) {
3936 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_FREEZE,
3943 DEBUG(DEBUG_ERR, ("Unable to freeze nodes.\n"));
3944 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn,
3945 CTDB_RECOVERY_ACTIVE);
3946 talloc_free(tmp_ctx);
3951 generation = vnnmap->generation;
3952 data.dptr = (void *)&generation;
3953 data.dsize = sizeof(generation);
3955 /* start a cluster wide transaction */
3956 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3957 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_START,
3959 TIMELIMIT(), false, data,
3963 DEBUG(DEBUG_ERR, ("Unable to start cluster wide "
3964 "transactions.\n"));
3968 w.db_id = ctdb_db->db_id;
3969 w.transaction_id = generation;
3971 data.dptr = (void *)&w;
3972 data.dsize = sizeof(w);
3974 /* wipe all the remote databases. */
3975 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3976 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_WIPE_DATABASE,
3978 TIMELIMIT(), false, data,
3981 DEBUG(DEBUG_ERR, ("Unable to wipe database.\n"));
3982 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3983 talloc_free(tmp_ctx);
3987 data.dptr = (void *)&ctdb_db->db_id;
3988 data.dsize = sizeof(ctdb_db->db_id);
3990 /* mark the database as healthy */
3991 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3992 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_DB_SET_HEALTHY,
3994 TIMELIMIT(), false, data,
3997 DEBUG(DEBUG_ERR, ("Failed to mark database as healthy.\n"));
3998 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3999 talloc_free(tmp_ctx);
4003 data.dptr = (void *)&generation;
4004 data.dsize = sizeof(generation);
4006 /* commit all the changes */
4007 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_COMMIT,
4009 TIMELIMIT(), false, data,
4012 DEBUG(DEBUG_ERR, ("Unable to commit databases.\n"));
4013 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4014 talloc_free(tmp_ctx);
4018 /* thaw all nodes */
4019 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4020 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_THAW,
4026 DEBUG(DEBUG_ERR, ("Unable to thaw nodes.\n"));
4027 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4028 talloc_free(tmp_ctx);
4032 talloc_free(tmp_ctx);
4037 * set flags of a node in the nodemap
4039 static int control_setflags(struct ctdb_context *ctdb, int argc, const char **argv)
4046 struct ctdb_node_flag_change c;
4053 if (sscanf(argv[0], "%d", &node) != 1) {
4054 DEBUG(DEBUG_ERR, ("Badly formed node\n"));
4058 if (sscanf(argv[1], "0x%x", &flags) != 1) {
4059 DEBUG(DEBUG_ERR, ("Badly formed flags\n"));
4066 c.new_flags = flags;
4068 data.dsize = sizeof(c);
4069 data.dptr = (unsigned char *)&c;
4071 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_MODIFY_FLAGS, 0,
4072 data, NULL, NULL, &status, NULL, NULL);
4073 if (ret != 0 || status != 0) {
4074 DEBUG(DEBUG_ERR,("Failed to modify flags\n"));
4083 static int control_dumpmemory(struct ctdb_context *ctdb, int argc, const char **argv)
4089 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
4090 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_DUMP_MEMORY,
4091 0, tdb_null, tmp_ctx, &data, &res, NULL, &errmsg);
4092 if (ret != 0 || res != 0) {
4093 DEBUG(DEBUG_ERR,("Failed to dump memory - %s\n", errmsg));
4094 talloc_free(tmp_ctx);
4097 write(1, data.dptr, data.dsize);
4098 talloc_free(tmp_ctx);
4103 handler for memory dumps
4105 static void mem_dump_handler(struct ctdb_context *ctdb, uint64_t srvid,
4106 TDB_DATA data, void *private_data)
4108 write(1, data.dptr, data.dsize);
4113 dump memory usage on the recovery daemon
4115 static int control_rddumpmemory(struct ctdb_context *ctdb, int argc, const char **argv)
4119 struct rd_memdump_reply rd;
4121 rd.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
4123 DEBUG(DEBUG_ERR, ("Failed to get pnn of local node\n"));
4126 rd.srvid = getpid();
4128 /* register a message port for receiveing the reply so that we
4129 can receive the reply
4131 ctdb_set_message_handler(ctdb, rd.srvid, mem_dump_handler, NULL);
4134 data.dptr = (uint8_t *)&rd;
4135 data.dsize = sizeof(rd);
4137 ret = ctdb_send_message(ctdb, options.pnn, CTDB_SRVID_MEM_DUMP, data);
4139 DEBUG(DEBUG_ERR,("Failed to send memdump request message to %u\n", options.pnn));
4143 /* this loop will terminate when we have received the reply */
4145 event_loop_once(ctdb->ev);
4152 send a message to a srvid
4154 static int control_msgsend(struct ctdb_context *ctdb, int argc, const char **argv)
4156 unsigned long srvid;
4164 srvid = strtoul(argv[0], NULL, 0);
4166 data.dptr = (uint8_t *)discard_const(argv[1]);
4167 data.dsize= strlen(argv[1]);
4169 ret = ctdb_send_message(ctdb, CTDB_BROADCAST_CONNECTED, srvid, data);
4171 DEBUG(DEBUG_ERR,("Failed to send memdump request message to %u\n", options.pnn));
4179 handler for msglisten
4181 static void msglisten_handler(struct ctdb_context *ctdb, uint64_t srvid,
4182 TDB_DATA data, void *private_data)
4186 printf("Message received: ");
4187 for (i=0;i<data.dsize;i++) {
4188 printf("%c", data.dptr[i]);
4194 listen for messages on a messageport
4196 static int control_msglisten(struct ctdb_context *ctdb, int argc, const char **argv)
4202 /* register a message port and listen for messages
4204 ctdb_set_message_handler(ctdb, srvid, msglisten_handler, NULL);
4205 printf("Listening for messages on srvid:%d\n", (int)srvid);
4208 event_loop_once(ctdb->ev);
4215 list all nodes in the cluster
4216 if the daemon is running, we read the data from the daemon.
4217 if the daemon is not running we parse the nodes file directly
4219 static int control_listnodes(struct ctdb_context *ctdb, int argc, const char **argv)
4222 struct ctdb_node_map *nodemap=NULL;
4225 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
4227 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
4231 for(i=0;i<nodemap->num;i++){
4232 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
4235 if (options.machinereadable){
4236 printf(":%d:%s:\n", nodemap->nodes[i].pnn, ctdb_addr_to_str(&nodemap->nodes[i].addr));
4238 printf("%s\n", ctdb_addr_to_str(&nodemap->nodes[i].addr));
4242 TALLOC_CTX *mem_ctx = talloc_new(NULL);
4243 struct pnn_node *pnn_nodes;
4244 struct pnn_node *pnn_node;
4246 pnn_nodes = read_nodes_file(mem_ctx);
4247 if (pnn_nodes == NULL) {
4248 DEBUG(DEBUG_ERR,("Failed to read nodes file\n"));
4249 talloc_free(mem_ctx);
4253 for(pnn_node=pnn_nodes;pnn_node;pnn_node=pnn_node->next) {
4254 ctdb_sock_addr addr;
4256 if (parse_ip(pnn_node->addr, NULL, 63999, &addr) == 0) {
4257 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s' in nodes file\n", pnn_node->addr));
4258 talloc_free(mem_ctx);
4262 if (options.machinereadable){
4263 printf(":%d:%s:\n", pnn_node->pnn, pnn_node->addr);
4265 printf("%s\n", pnn_node->addr);
4268 talloc_free(mem_ctx);
4275 reload the nodes file on the local node
4277 static int control_reload_nodes_file(struct ctdb_context *ctdb, int argc, const char **argv)
4281 struct ctdb_node_map *nodemap=NULL;
4283 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
4285 DEBUG(DEBUG_ERR, ("Failed to read pnn of local node\n"));
4289 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
4291 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
4295 /* reload the nodes file on all remote nodes */
4296 for (i=0;i<nodemap->num;i++) {
4297 if (nodemap->nodes[i].pnn == mypnn) {
4300 DEBUG(DEBUG_NOTICE, ("Reloading nodes file on node %u\n", nodemap->nodes[i].pnn));
4301 ret = ctdb_ctrl_reload_nodes_file(ctdb, TIMELIMIT(),
4302 nodemap->nodes[i].pnn);
4304 DEBUG(DEBUG_ERR, ("ERROR: Failed to reload nodes file on node %u. You MUST fix that node manually!\n", nodemap->nodes[i].pnn));
4308 /* reload the nodes file on the local node */
4309 DEBUG(DEBUG_NOTICE, ("Reloading nodes file on node %u\n", mypnn));
4310 ret = ctdb_ctrl_reload_nodes_file(ctdb, TIMELIMIT(), mypnn);
4312 DEBUG(DEBUG_ERR, ("ERROR: Failed to reload nodes file on node %u. You MUST fix that node manually!\n", mypnn));
4315 /* initiate a recovery */
4316 control_recover(ctdb, argc, argv);
4322 static const struct {
4324 int (*fn)(struct ctdb_context *, int, const char **);
4326 bool without_daemon; /* can be run without daemon running ? */
4329 } ctdb_commands[] = {
4331 { "version", control_version, true, false, "show version of ctdb" },
4333 { "status", control_status, true, false, "show node status" },
4334 { "uptime", control_uptime, true, false, "show node uptime" },
4335 { "ping", control_ping, true, false, "ping all nodes" },
4336 { "getvar", control_getvar, true, false, "get a tunable variable", "<name>"},
4337 { "setvar", control_setvar, true, false, "set a tunable variable", "<name> <value>"},
4338 { "listvars", control_listvars, true, false, "list tunable variables"},
4339 { "statistics", control_statistics, false, false, "show statistics" },
4340 { "statisticsreset", control_statistics_reset, true, false, "reset statistics"},
4341 { "ip", control_ip, false, false, "show which public ip's that ctdb manages" },
4342 { "ipinfo", control_ipinfo, true, false, "show details about a public ip that ctdb manages", "<ip>" },
4343 { "ifaces", control_ifaces, true, false, "show which interfaces that ctdb manages" },
4344 { "setifacelink", control_setifacelink, true, false, "set interface link status", "<iface> <status>" },
4345 { "process-exists", control_process_exists, true, false, "check if a process exists on a node", "<pid>"},
4346 { "getdbmap", control_getdbmap, true, false, "show the database map" },
4347 { "getdbstatus", control_getdbstatus, true, false, "show the status of a database", "<dbname>" },
4348 { "catdb", control_catdb, true, false, "dump a database" , "<dbname>"},
4349 { "getmonmode", control_getmonmode, true, false, "show monitoring mode" },
4350 { "getcapabilities", control_getcapabilities, true, false, "show node capabilities" },
4351 { "pnn", control_pnn, true, false, "show the pnn of the currnet node" },
4352 { "lvs", control_lvs, true, false, "show lvs configuration" },
4353 { "lvsmaster", control_lvsmaster, true, false, "show which node is the lvs master" },
4354 { "disablemonitor", control_disable_monmode,true, false, "set monitoring mode to DISABLE" },
4355 { "enablemonitor", control_enable_monmode, true, false, "set monitoring mode to ACTIVE" },
4356 { "setdebug", control_setdebug, true, false, "set debug level", "<EMERG|ALERT|CRIT|ERR|WARNING|NOTICE|INFO|DEBUG>" },
4357 { "getdebug", control_getdebug, true, false, "get debug level" },
4358 { "getlog", control_getlog, true, false, "get the log data from the in memory ringbuffer", "<level>" },
4359 { "clearlog", control_clearlog, true, false, "clear the log data from the in memory ringbuffer" },
4360 { "attach", control_attach, true, false, "attach to a database", "<dbname>" },
4361 { "dumpmemory", control_dumpmemory, true, false, "dump memory map to stdout" },
4362 { "rddumpmemory", control_rddumpmemory, true, false, "dump memory map from the recovery daemon to stdout" },
4363 { "getpid", control_getpid, true, false, "get ctdbd process ID" },
4364 { "disable", control_disable, true, false, "disable a nodes public IP" },
4365 { "enable", control_enable, true, false, "enable a nodes public IP" },
4366 { "stop", control_stop, true, false, "stop a node" },
4367 { "continue", control_continue, true, false, "re-start a stopped node" },
4368 { "ban", control_ban, true, false, "ban a node from the cluster", "<bantime|0>"},
4369 { "unban", control_unban, true, false, "unban a node" },
4370 { "showban", control_showban, true, false, "show ban information"},
4371 { "shutdown", control_shutdown, true, false, "shutdown ctdbd" },
4372 { "recover", control_recover, true, false, "force recovery" },
4373 { "ipreallocate", control_ipreallocate, true, false, "force the recovery daemon to perform a ip reallocation procedure" },
4374 { "freeze", control_freeze, true, false, "freeze databases", "[priority:1-3]" },
4375 { "thaw", control_thaw, true, false, "thaw databases", "[priority:1-3]" },
4376 { "isnotrecmaster", control_isnotrecmaster, false, false, "check if the local node is recmaster or not" },
4377 { "killtcp", kill_tcp, false, false, "kill a tcp connection.", "<srcip:port> <dstip:port>" },
4378 { "gratiousarp", control_gratious_arp, false, false, "send a gratious arp", "<ip> <interface>" },
4379 { "tickle", tickle_tcp, false, false, "send a tcp tickle ack", "<srcip:port> <dstip:port>" },
4380 { "gettickles", control_get_tickles, false, false, "get the list of tickles registered for this ip", "<ip>" },
4382 { "regsrvid", regsrvid, false, false, "register a server id", "<pnn> <type> <id>" },
4383 { "unregsrvid", unregsrvid, false, false, "unregister a server id", "<pnn> <type> <id>" },
4384 { "chksrvid", chksrvid, false, false, "check if a server id exists", "<pnn> <type> <id>" },
4385 { "getsrvids", getsrvids, false, false, "get a list of all server ids"},
4386 { "vacuum", ctdb_vacuum, false, false, "vacuum the databases of empty records", "[max_records]"},
4387 { "repack", ctdb_repack, false, false, "repack all databases", "[max_freelist]"},
4388 { "listnodes", control_listnodes, false, true, "list all nodes in the cluster"},
4389 { "reloadnodes", control_reload_nodes_file, false, false, "reload the nodes file and restart the transport on all nodes"},
4390 { "moveip", control_moveip, false, false, "move/failover an ip address to another node", "<ip> <node>"},
4391 { "addip", control_addip, true, false, "add a ip address to a node", "<ip/mask> <iface>"},
4392 { "delip", control_delip, false, false, "delete an ip address from a node", "<ip>"},
4393 { "eventscript", control_eventscript, true, false, "run the eventscript with the given parameters on a node", "<arguments>"},
4394 { "backupdb", control_backupdb, false, false, "backup the database into a file.", "<database> <file>"},
4395 { "restoredb", control_restoredb, false, false, "restore the database from a file.", "<file>"},
4396 { "dumpdbbackup", control_dumpdbbackup, false, true, "dump database backup from a file.", "<file>"},
4397 { "wipedb", control_wipedb, false, false, "wipe the contents of a database.", "<dbname>"},
4398 { "recmaster", control_recmaster, false, false, "show the pnn for the recovery master."},
4399 { "setflags", control_setflags, false, false, "set flags for a node in the nodemap.", "<node> <flags>"},
4400 { "scriptstatus", control_scriptstatus, false, false, "show the status of the monitoring scripts (or all scripts)", "[all]"},
4401 { "enablescript", control_enablescript, false, false, "enable an eventscript", "<script>"},
4402 { "disablescript", control_disablescript, false, false, "disable an eventscript", "<script>"},
4403 { "natgwlist", control_natgwlist, false, false, "show the nodes belonging to this natgw configuration"},
4404 { "xpnn", control_xpnn, true, true, "find the pnn of the local node without talking to the daemon (unreliable)" },
4405 { "getreclock", control_getreclock, false, false, "Show the reclock file of a node"},
4406 { "setreclock", control_setreclock, false, false, "Set/clear the reclock file of a node", "[filename]"},
4407 { "setnatgwstate", control_setnatgwstate, false, false, "Set NATGW state to on/off", "{on|off}"},
4408 { "setlmasterrole", control_setlmasterrole, false, false, "Set LMASTER role to on/off", "{on|off}"},
4409 { "setrecmasterrole", control_setrecmasterrole, false, false, "Set RECMASTER role to on/off", "{on|off}"},
4410 { "setdbprio", control_setdbprio, false, false, "Set DB priority", "<dbid> <prio:1-3>"},
4411 { "getdbprio", control_getdbprio, false, false, "Get DB priority", "<dbid>"},
4412 { "msglisten", control_msglisten, false, false, "Listen on a srvid port for messages", "<msg srvid>"},
4413 { "msgsend", control_msgsend, false, false, "Send a message to srvid", "<srvid> <message>"},
4419 static void usage(void)
4423 "Usage: ctdb [options] <control>\n" \
4425 " -n <node> choose node number, or 'all' (defaults to local node)\n"
4426 " -Y generate machinereadable output\n"
4427 " -t <timelimit> set timelimit for control in seconds (default %u)\n", options.timelimit);
4428 printf("Controls:\n");
4429 for (i=0;i<ARRAY_SIZE(ctdb_commands);i++) {
4430 printf(" %-15s %-27s %s\n",
4431 ctdb_commands[i].name,
4432 ctdb_commands[i].args?ctdb_commands[i].args:"",
4433 ctdb_commands[i].msg);
4439 static void ctdb_alarm(int sig)
4441 printf("Maximum runtime exceeded - exiting\n");
4448 int main(int argc, const char *argv[])
4450 struct ctdb_context *ctdb;
4451 char *nodestring = NULL;
4452 struct poptOption popt_options[] = {
4455 { "timelimit", 't', POPT_ARG_INT, &options.timelimit, 0, "timelimit", "integer" },
4456 { "node", 'n', POPT_ARG_STRING, &nodestring, 0, "node", "integer|all" },
4457 { "machinereadable", 'Y', POPT_ARG_NONE, &options.machinereadable, 0, "enable machinereadable output", NULL },
4458 { "maxruntime", 'T', POPT_ARG_INT, &options.maxruntime, 0, "die if runtime exceeds this limit (in seconds)", "integer" },
4462 const char **extra_argv;
4466 struct event_context *ev;
4467 const char *control;
4471 /* set some defaults */
4472 options.maxruntime = 0;
4473 options.timelimit = 3;
4474 options.pnn = CTDB_CURRENT_NODE;
4476 pc = poptGetContext(argv[0], argc, argv, popt_options, POPT_CONTEXT_KEEP_FIRST);
4478 while ((opt = poptGetNextOpt(pc)) != -1) {
4481 DEBUG(DEBUG_ERR, ("Invalid option %s: %s\n",
4482 poptBadOption(pc, 0), poptStrerror(opt)));
4487 /* setup the remaining options for the main program to use */
4488 extra_argv = poptGetArgs(pc);
4491 while (extra_argv[extra_argc]) extra_argc++;
4494 if (extra_argc < 1) {
4498 if (options.maxruntime == 0) {
4499 const char *ctdb_timeout;
4500 ctdb_timeout = getenv("CTDB_TIMEOUT");
4501 if (ctdb_timeout != NULL) {
4502 options.maxruntime = strtoul(ctdb_timeout, NULL, 0);
4504 /* default timeout is 120 seconds */
4505 options.maxruntime = 120;
4509 signal(SIGALRM, ctdb_alarm);
4510 alarm(options.maxruntime);
4512 /* setup the node number to contact */
4513 if (nodestring != NULL) {
4514 if (strcmp(nodestring, "all") == 0) {
4515 options.pnn = CTDB_BROADCAST_ALL;
4517 options.pnn = strtoul(nodestring, NULL, 0);
4521 control = extra_argv[0];
4523 ev = event_context_init(NULL);
4525 for (i=0;i<ARRAY_SIZE(ctdb_commands);i++) {
4526 if (strcmp(control, ctdb_commands[i].name) == 0) {
4529 if (ctdb_commands[i].without_daemon == true) {
4533 /* initialise ctdb */
4534 ctdb = ctdb_cmdline_client(ev);
4536 if (ctdb_commands[i].without_daemon == false) {
4538 DEBUG(DEBUG_ERR, ("Failed to init ctdb\n"));
4542 /* verify the node exists */
4545 if (options.pnn == CTDB_CURRENT_NODE) {
4547 pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
4555 if (ctdb_commands[i].auto_all &&
4556 options.pnn == CTDB_BROADCAST_ALL) {
4561 nodes = ctdb_get_connected_nodes(ctdb, TIMELIMIT(), ctdb, &num_nodes);
4562 CTDB_NO_MEMORY(ctdb, nodes);
4564 for (j=0;j<num_nodes;j++) {
4565 options.pnn = nodes[j];
4566 ret |= ctdb_commands[i].fn(ctdb, extra_argc-1, extra_argv+1);
4570 ret = ctdb_commands[i].fn(ctdb, extra_argc-1, extra_argv+1);
4576 if (i == ARRAY_SIZE(ctdb_commands)) {
4577 DEBUG(DEBUG_ERR, ("Unknown control '%s'\n", control));