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/tevent/tevent.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_client.h"
31 #include "../include/ctdb_private.h"
32 #include "../common/rb_tree.h"
35 #define ERR_TIMEOUT 20 /* timed out trying to reach node */
36 #define ERR_NONODE 21 /* node does not exist */
37 #define ERR_DISNODE 22 /* node is disconnected */
39 struct ctdb_connection *ctdb_connection;
41 static void usage(void);
51 #define TIMELIMIT() timeval_current_ofs(options.timelimit, 0)
52 #define LONGTIMELIMIT() timeval_current_ofs(options.timelimit*10, 0)
55 static int control_version(struct ctdb_context *ctdb, int argc, const char **argv)
58 #define XSTR(x) STR(x)
59 printf("CTDB version: %s\n", XSTR(CTDB_VERS));
66 verify that a node exists and is reachable
68 static void verify_node(struct ctdb_context *ctdb)
71 struct ctdb_node_map *nodemap=NULL;
73 if (options.pnn == CTDB_CURRENT_NODE) {
76 if (options.pnn == CTDB_BROADCAST_ALL) {
80 /* verify the node exists */
81 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
82 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
85 if (options.pnn >= nodemap->num) {
86 DEBUG(DEBUG_ERR, ("Node %u does not exist\n", options.pnn));
89 if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_DELETED) {
90 DEBUG(DEBUG_ERR, ("Node %u is DELETED\n", options.pnn));
93 if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_DISCONNECTED) {
94 DEBUG(DEBUG_ERR, ("Node %u is DISCONNECTED\n", options.pnn));
98 /* verify we can access the node */
99 ret = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
101 DEBUG(DEBUG_ERR,("Can not access node. Node is not operational.\n"));
107 check if a database exists
109 static int db_exists(struct ctdb_context *ctdb, const char *db_name)
112 struct ctdb_dbid_map *dbmap=NULL;
114 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
116 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
120 for(i=0;i<dbmap->num;i++){
123 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
124 if (!strcmp(name, db_name)) {
133 see if a process exists
135 static int control_process_exists(struct ctdb_context *ctdb, int argc, const char **argv)
143 if (sscanf(argv[0], "%u:%u", &pnn, &pid) != 2) {
144 DEBUG(DEBUG_ERR, ("Badly formed pnn:pid\n"));
148 ret = ctdb_ctrl_process_exists(ctdb, pnn, pid);
150 printf("%u:%u exists\n", pnn, pid);
152 printf("%u:%u does not exist\n", pnn, pid);
158 display statistics structure
160 static void show_statistics(struct ctdb_statistics *s)
162 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
164 const char *prefix=NULL;
166 int tmp, days, hours, minutes, seconds;
171 #define STATISTICS_FIELD(n) { #n, offsetof(struct ctdb_statistics, n) }
172 STATISTICS_FIELD(num_clients),
173 STATISTICS_FIELD(frozen),
174 STATISTICS_FIELD(recovering),
175 STATISTICS_FIELD(num_recoveries),
176 STATISTICS_FIELD(client_packets_sent),
177 STATISTICS_FIELD(client_packets_recv),
178 STATISTICS_FIELD(node_packets_sent),
179 STATISTICS_FIELD(node_packets_recv),
180 STATISTICS_FIELD(keepalive_packets_sent),
181 STATISTICS_FIELD(keepalive_packets_recv),
182 STATISTICS_FIELD(node.req_call),
183 STATISTICS_FIELD(node.reply_call),
184 STATISTICS_FIELD(node.req_dmaster),
185 STATISTICS_FIELD(node.reply_dmaster),
186 STATISTICS_FIELD(node.reply_error),
187 STATISTICS_FIELD(node.req_message),
188 STATISTICS_FIELD(node.req_control),
189 STATISTICS_FIELD(node.reply_control),
190 STATISTICS_FIELD(client.req_call),
191 STATISTICS_FIELD(client.req_message),
192 STATISTICS_FIELD(client.req_control),
193 STATISTICS_FIELD(timeouts.call),
194 STATISTICS_FIELD(timeouts.control),
195 STATISTICS_FIELD(timeouts.traverse),
196 STATISTICS_FIELD(total_calls),
197 STATISTICS_FIELD(pending_calls),
198 STATISTICS_FIELD(lockwait_calls),
199 STATISTICS_FIELD(pending_lockwait_calls),
200 STATISTICS_FIELD(childwrite_calls),
201 STATISTICS_FIELD(pending_childwrite_calls),
202 STATISTICS_FIELD(memory_used),
203 STATISTICS_FIELD(max_hop_count),
205 tmp = s->statistics_current_time.tv_sec - s->statistics_start_time.tv_sec;
214 printf("CTDB version %u\n", CTDB_VERSION);
215 printf("Current time of statistics : %s", ctime(&s->statistics_current_time.tv_sec));
216 printf("Statistics collected since : (%03d %02d:%02d:%02d) %s", days, hours, minutes, seconds, ctime(&s->statistics_start_time.tv_sec));
218 for (i=0;i<ARRAY_SIZE(fields);i++) {
219 if (strchr(fields[i].name, '.')) {
220 preflen = strcspn(fields[i].name, ".")+1;
221 if (!prefix || strncmp(prefix, fields[i].name, preflen) != 0) {
222 prefix = fields[i].name;
223 printf(" %*.*s\n", preflen-1, preflen-1, fields[i].name);
228 printf(" %*s%-22s%*s%10u\n",
230 fields[i].name+preflen,
232 *(uint32_t *)(fields[i].offset+(uint8_t *)s));
234 printf(" %-30s %.6f sec\n", "max_reclock_ctdbd", s->reclock.ctdbd);
235 printf(" %-30s %.6f sec\n", "max_reclock_recd", s->reclock.recd);
237 printf(" %-30s %.6f sec\n", "max_call_latency", s->max_call_latency);
238 printf(" %-30s %.6f sec\n", "max_lockwait_latency", s->max_lockwait_latency);
239 printf(" %-30s %.6f sec\n", "max_childwrite_latency", s->max_childwrite_latency);
240 printf(" %-30s %.6f sec\n", "max_childwrite_latency", s->max_childwrite_latency);
242 talloc_free(tmp_ctx);
246 display remote ctdb statistics combined from all nodes
248 static int control_statistics_all(struct ctdb_context *ctdb)
251 struct ctdb_statistics statistics;
255 nodes = ctdb_get_connected_nodes(ctdb, TIMELIMIT(), ctdb, &num_nodes);
256 CTDB_NO_MEMORY(ctdb, nodes);
258 ZERO_STRUCT(statistics);
260 for (i=0;i<num_nodes;i++) {
261 struct ctdb_statistics s1;
263 uint32_t *v1 = (uint32_t *)&s1;
264 uint32_t *v2 = (uint32_t *)&statistics;
266 offsetof(struct ctdb_statistics, __last_counter) / sizeof(uint32_t);
267 ret = ctdb_ctrl_statistics(ctdb, nodes[i], &s1);
269 DEBUG(DEBUG_ERR, ("Unable to get statistics from node %u\n", nodes[i]));
272 for (j=0;j<num_ints;j++) {
275 statistics.max_hop_count =
276 MAX(statistics.max_hop_count, s1.max_hop_count);
277 statistics.max_call_latency =
278 MAX(statistics.max_call_latency, s1.max_call_latency);
279 statistics.max_lockwait_latency =
280 MAX(statistics.max_lockwait_latency, s1.max_lockwait_latency);
283 printf("Gathered statistics for %u nodes\n", num_nodes);
284 show_statistics(&statistics);
289 display remote ctdb statistics
291 static int control_statistics(struct ctdb_context *ctdb, int argc, const char **argv)
294 struct ctdb_statistics statistics;
296 if (options.pnn == CTDB_BROADCAST_ALL) {
297 return control_statistics_all(ctdb);
300 ret = ctdb_ctrl_statistics(ctdb, options.pnn, &statistics);
302 DEBUG(DEBUG_ERR, ("Unable to get statistics from node %u\n", options.pnn));
305 show_statistics(&statistics);
311 reset remote ctdb statistics
313 static int control_statistics_reset(struct ctdb_context *ctdb, int argc, const char **argv)
317 ret = ctdb_statistics_reset(ctdb, options.pnn);
319 DEBUG(DEBUG_ERR, ("Unable to reset statistics on node %u\n", options.pnn));
327 display uptime of remote node
329 static int control_uptime(struct ctdb_context *ctdb, int argc, const char **argv)
332 struct ctdb_uptime *uptime = NULL;
333 int tmp, days, hours, minutes, seconds;
335 ret = ctdb_ctrl_uptime(ctdb, ctdb, TIMELIMIT(), options.pnn, &uptime);
337 DEBUG(DEBUG_ERR, ("Unable to get uptime from node %u\n", options.pnn));
341 if (options.machinereadable){
342 printf(":Current Node Time:Ctdb Start Time:Last Recovery/Failover Time:Last Recovery/IPFailover Duration:\n");
343 printf(":%u:%u:%u:%lf\n",
344 (unsigned int)uptime->current_time.tv_sec,
345 (unsigned int)uptime->ctdbd_start_time.tv_sec,
346 (unsigned int)uptime->last_recovery_finished.tv_sec,
347 timeval_delta(&uptime->last_recovery_finished,
348 &uptime->last_recovery_started)
353 printf("Current time of node : %s", ctime(&uptime->current_time.tv_sec));
355 tmp = uptime->current_time.tv_sec - uptime->ctdbd_start_time.tv_sec;
363 printf("Ctdbd start time : (%03d %02d:%02d:%02d) %s", days, hours, minutes, seconds, ctime(&uptime->ctdbd_start_time.tv_sec));
365 tmp = uptime->current_time.tv_sec - uptime->last_recovery_finished.tv_sec;
373 printf("Time of last recovery/failover: (%03d %02d:%02d:%02d) %s", days, hours, minutes, seconds, ctime(&uptime->last_recovery_finished.tv_sec));
375 printf("Duration of last recovery/failover: %lf seconds\n",
376 timeval_delta(&uptime->last_recovery_finished,
377 &uptime->last_recovery_started));
383 show the PNN of the current node
385 static int control_pnn(struct ctdb_context *ctdb, int argc, const char **argv)
390 ret = ctdb_getpnn(ctdb_connection, options.pnn, &mypnn);
392 DEBUG(DEBUG_ERR, ("Unable to get pnn from node."));
396 printf("PNN:%d\n", mypnn);
402 struct pnn_node *next;
407 static struct pnn_node *read_nodes_file(TALLOC_CTX *mem_ctx)
409 const char *nodes_list;
413 struct pnn_node *pnn_nodes = NULL;
414 struct pnn_node *pnn_node;
415 struct pnn_node *tmp_node;
417 /* read the nodes file */
418 nodes_list = getenv("CTDB_NODES");
419 if (nodes_list == NULL) {
420 nodes_list = "/etc/ctdb/nodes";
422 lines = file_lines_load(nodes_list, &nlines, mem_ctx);
426 while (nlines > 0 && strcmp(lines[nlines-1], "") == 0) {
429 for (i=0, pnn=0; i<nlines; i++) {
433 /* strip leading spaces */
434 while((*node == ' ') || (*node == '\t')) {
441 if (strcmp(node, "") == 0) {
444 pnn_node = talloc(mem_ctx, struct pnn_node);
445 pnn_node->pnn = pnn++;
446 pnn_node->addr = talloc_strdup(pnn_node, node);
447 pnn_node->next = pnn_nodes;
448 pnn_nodes = pnn_node;
451 /* swap them around so we return them in incrementing order */
452 pnn_node = pnn_nodes;
456 pnn_node = pnn_node->next;
458 tmp_node->next = pnn_nodes;
459 pnn_nodes = tmp_node;
466 show the PNN of the current node
467 discover the pnn by loading the nodes file and try to bind to all
468 addresses one at a time until the ip address is found.
470 static int control_xpnn(struct ctdb_context *ctdb, int argc, const char **argv)
472 TALLOC_CTX *mem_ctx = talloc_new(NULL);
473 struct pnn_node *pnn_nodes;
474 struct pnn_node *pnn_node;
476 pnn_nodes = read_nodes_file(mem_ctx);
477 if (pnn_nodes == NULL) {
478 DEBUG(DEBUG_ERR,("Failed to read nodes file\n"));
479 talloc_free(mem_ctx);
483 for(pnn_node=pnn_nodes;pnn_node;pnn_node=pnn_node->next) {
486 if (parse_ip(pnn_node->addr, NULL, 63999, &addr) == 0) {
487 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s' in nodes file\n", pnn_node->addr));
488 talloc_free(mem_ctx);
492 if (ctdb_sys_have_ip(&addr)) {
493 printf("PNN:%d\n", pnn_node->pnn);
494 talloc_free(mem_ctx);
499 printf("Failed to detect which PNN this node is\n");
500 talloc_free(mem_ctx);
505 display remote ctdb status
507 static int control_status(struct ctdb_context *ctdb, int argc, const char **argv)
510 struct ctdb_vnn_map *vnnmap=NULL;
511 struct ctdb_node_map *nodemap=NULL;
512 uint32_t recmode, recmaster;
515 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
520 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
522 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
526 if(options.machinereadable){
527 printf(":Node:IP:Disconnected:Banned:Disabled:Unhealthy:Stopped:Inactive:\n");
528 for(i=0;i<nodemap->num;i++){
529 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
532 printf(":%d:%s:%d:%d:%d:%d:%d:%d:\n", nodemap->nodes[i].pnn,
533 ctdb_addr_to_str(&nodemap->nodes[i].addr),
534 !!(nodemap->nodes[i].flags&NODE_FLAGS_DISCONNECTED),
535 !!(nodemap->nodes[i].flags&NODE_FLAGS_BANNED),
536 !!(nodemap->nodes[i].flags&NODE_FLAGS_PERMANENTLY_DISABLED),
537 !!(nodemap->nodes[i].flags&NODE_FLAGS_UNHEALTHY),
538 !!(nodemap->nodes[i].flags&NODE_FLAGS_STOPPED),
539 !!(nodemap->nodes[i].flags&NODE_FLAGS_INACTIVE));
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 for (j=0;j<ARRAY_SIZE(flag_names);j++) {
565 if (nodemap->nodes[i].flags & flag_names[j].flag) {
566 if (flags_str == NULL) {
567 flags_str = talloc_strdup(ctdb, flag_names[j].name);
569 flags_str = talloc_asprintf_append(flags_str, "|%s",
572 CTDB_NO_MEMORY_FATAL(ctdb, flags_str);
575 if (flags_str == NULL) {
576 flags_str = talloc_strdup(ctdb, "OK");
577 CTDB_NO_MEMORY_FATAL(ctdb, flags_str);
579 printf("pnn:%d %-16s %s%s\n", nodemap->nodes[i].pnn,
580 ctdb_addr_to_str(&nodemap->nodes[i].addr),
582 nodemap->nodes[i].pnn == mypnn?" (THIS NODE)":"");
583 talloc_free(flags_str);
586 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &vnnmap);
588 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n", options.pnn));
591 if (vnnmap->generation == INVALID_GENERATION) {
592 printf("Generation:INVALID\n");
594 printf("Generation:%d\n",vnnmap->generation);
596 printf("Size:%d\n",vnnmap->size);
597 for(i=0;i<vnnmap->size;i++){
598 printf("hash:%d lmaster:%d\n", i, vnnmap->map[i]);
601 ret = ctdb_ctrl_getrecmode(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmode);
603 DEBUG(DEBUG_ERR, ("Unable to get recmode from node %u\n", options.pnn));
606 printf("Recovery mode:%s (%d)\n",recmode==CTDB_RECOVERY_NORMAL?"NORMAL":"RECOVERY",recmode);
608 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
610 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
613 printf("Recovery master:%d\n",recmaster);
620 struct natgw_node *next;
625 display the list of nodes belonging to this natgw configuration
627 static int control_natgwlist(struct ctdb_context *ctdb, int argc, const char **argv)
630 const char *natgw_list;
633 struct natgw_node *natgw_nodes = NULL;
634 struct natgw_node *natgw_node;
635 struct ctdb_node_map *nodemap=NULL;
638 /* read the natgw nodes file into a linked list */
639 natgw_list = getenv("NATGW_NODES");
640 if (natgw_list == NULL) {
641 natgw_list = "/etc/ctdb/natgw_nodes";
643 lines = file_lines_load(natgw_list, &nlines, ctdb);
645 ctdb_set_error(ctdb, "Failed to load natgw node list '%s'\n", natgw_list);
648 while (nlines > 0 && strcmp(lines[nlines-1], "") == 0) {
651 for (i=0;i<nlines;i++) {
655 /* strip leading spaces */
656 while((*node == ' ') || (*node == '\t')) {
662 if (strcmp(node, "") == 0) {
665 natgw_node = talloc(ctdb, struct natgw_node);
666 natgw_node->addr = talloc_strdup(natgw_node, node);
667 CTDB_NO_MEMORY(ctdb, natgw_node->addr);
668 natgw_node->next = natgw_nodes;
669 natgw_nodes = natgw_node;
672 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
674 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node.\n"));
679 while(i<nodemap->num) {
680 for(natgw_node=natgw_nodes;natgw_node;natgw_node=natgw_node->next) {
681 if (!strcmp(natgw_node->addr, ctdb_addr_to_str(&nodemap->nodes[i].addr))) {
686 /* this node was not in the natgw so we just remove it from
689 if ((natgw_node == NULL)
690 || (nodemap->nodes[i].flags & NODE_FLAGS_DISCONNECTED) ) {
693 for (j=i+1; j<nodemap->num; j++) {
694 nodemap->nodes[j-1] = nodemap->nodes[j];
703 /* pick a node to be natgwmaster
704 * we dont allow STOPPED, DELETED, BANNED or UNHEALTHY nodes to become the natgwmaster
706 for(i=0;i<nodemap->num;i++){
707 if (!(nodemap->nodes[i].flags & (NODE_FLAGS_DISCONNECTED|NODE_FLAGS_STOPPED|NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_UNHEALTHY))) {
708 printf("%d %s\n", nodemap->nodes[i].pnn,ctdb_addr_to_str(&nodemap->nodes[i].addr));
712 /* we couldnt find any healthy node, try unhealthy ones */
713 if (i == nodemap->num) {
714 for(i=0;i<nodemap->num;i++){
715 if (!(nodemap->nodes[i].flags & (NODE_FLAGS_DISCONNECTED|NODE_FLAGS_STOPPED|NODE_FLAGS_DELETED))) {
716 printf("%d %s\n", nodemap->nodes[i].pnn,ctdb_addr_to_str(&nodemap->nodes[i].addr));
721 /* unless all nodes are STOPPED, when we pick one anyway */
722 if (i == nodemap->num) {
723 for(i=0;i<nodemap->num;i++){
724 if (!(nodemap->nodes[i].flags & (NODE_FLAGS_DISCONNECTED|NODE_FLAGS_DELETED))) {
725 printf("%d %s\n", nodemap->nodes[i].pnn, ctdb_addr_to_str(&nodemap->nodes[i].addr));
729 /* or if we still can not find any */
730 if (i == nodemap->num) {
731 printf("-1 0.0.0.0\n");
735 /* print the pruned list of nodes belonging to this natgw list */
736 for(i=0;i<nodemap->num;i++){
737 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
740 printf(":%d:%s:%d:%d:%d:%d:%d\n", nodemap->nodes[i].pnn,
741 ctdb_addr_to_str(&nodemap->nodes[i].addr),
742 !!(nodemap->nodes[i].flags&NODE_FLAGS_DISCONNECTED),
743 !!(nodemap->nodes[i].flags&NODE_FLAGS_BANNED),
744 !!(nodemap->nodes[i].flags&NODE_FLAGS_PERMANENTLY_DISABLED),
745 !!(nodemap->nodes[i].flags&NODE_FLAGS_UNHEALTHY),
746 !!(nodemap->nodes[i].flags&NODE_FLAGS_STOPPED));
753 display the status of the scripts for monitoring (or other events)
755 static int control_one_scriptstatus(struct ctdb_context *ctdb,
756 enum ctdb_eventscript_call type)
758 struct ctdb_scripts_wire *script_status;
761 ret = ctdb_ctrl_getscriptstatus(ctdb, TIMELIMIT(), options.pnn, ctdb, type, &script_status);
763 DEBUG(DEBUG_ERR, ("Unable to get script status from node %u\n", options.pnn));
767 if (script_status == NULL) {
768 if (!options.machinereadable) {
769 printf("%s cycle never run\n",
770 ctdb_eventscript_call_names[type]);
775 if (!options.machinereadable) {
776 printf("%d scripts were executed last %s cycle\n",
777 script_status->num_scripts,
778 ctdb_eventscript_call_names[type]);
780 for (i=0; i<script_status->num_scripts; i++) {
781 const char *status = NULL;
783 switch (script_status->scripts[i].status) {
794 if (script_status->scripts[i].status > 0)
798 if (options.machinereadable) {
799 printf("%s:%s:%i:%s:%lu.%06lu:%lu.%06lu:%s:\n",
800 ctdb_eventscript_call_names[type],
801 script_status->scripts[i].name,
802 script_status->scripts[i].status,
804 (long)script_status->scripts[i].start.tv_sec,
805 (long)script_status->scripts[i].start.tv_usec,
806 (long)script_status->scripts[i].finished.tv_sec,
807 (long)script_status->scripts[i].finished.tv_usec,
808 script_status->scripts[i].output);
812 printf("%-20s Status:%s ",
813 script_status->scripts[i].name, status);
815 /* Some other error, eg from stat. */
816 printf("%-20s Status:CANNOT RUN (%s)",
817 script_status->scripts[i].name,
818 strerror(-script_status->scripts[i].status));
820 if (script_status->scripts[i].status >= 0) {
821 printf("Duration:%.3lf ",
822 timeval_delta(&script_status->scripts[i].finished,
823 &script_status->scripts[i].start));
825 if (script_status->scripts[i].status != -ENOEXEC) {
827 ctime(&script_status->scripts[i].start.tv_sec));
828 if (script_status->scripts[i].status != 0) {
829 printf(" OUTPUT:%s\n",
830 script_status->scripts[i].output);
840 static int control_scriptstatus(struct ctdb_context *ctdb,
841 int argc, const char **argv)
844 enum ctdb_eventscript_call type, min, max;
848 DEBUG(DEBUG_ERR, ("Unknown arguments to scriptstatus\n"));
853 arg = ctdb_eventscript_call_names[CTDB_EVENT_MONITOR];
857 for (type = 0; type < CTDB_EVENT_MAX; type++) {
858 if (strcmp(arg, ctdb_eventscript_call_names[type]) == 0) {
864 if (type == CTDB_EVENT_MAX) {
865 if (strcmp(arg, "all") == 0) {
867 max = CTDB_EVENT_MAX;
869 DEBUG(DEBUG_ERR, ("Unknown event type %s\n", argv[0]));
874 if (options.machinereadable) {
875 printf(":Type:Name:Code:Status:Start:End:Error Output...:\n");
878 for (type = min; type < max; type++) {
879 ret = control_one_scriptstatus(ctdb, type);
889 enable an eventscript
891 static int control_enablescript(struct ctdb_context *ctdb, int argc, const char **argv)
899 ret = ctdb_ctrl_enablescript(ctdb, TIMELIMIT(), options.pnn, argv[0]);
901 DEBUG(DEBUG_ERR, ("Unable to enable script %s on node %u\n", argv[0], options.pnn));
909 disable an eventscript
911 static int control_disablescript(struct ctdb_context *ctdb, int argc, const char **argv)
919 ret = ctdb_ctrl_disablescript(ctdb, TIMELIMIT(), options.pnn, argv[0]);
921 DEBUG(DEBUG_ERR, ("Unable to disable script %s on node %u\n", argv[0], options.pnn));
929 display the pnn of the recovery master
931 static int control_recmaster(struct ctdb_context *ctdb, int argc, const char **argv)
936 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
938 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
941 printf("%d\n",recmaster);
947 add a tickle to a public address
949 static int control_add_tickle(struct ctdb_context *ctdb, int argc, const char **argv)
951 struct ctdb_tcp_connection t;
959 if (parse_ip_port(argv[0], &t.src_addr) == 0) {
960 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
963 if (parse_ip_port(argv[1], &t.dst_addr) == 0) {
964 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[1]));
968 data.dptr = (uint8_t *)&t;
969 data.dsize = sizeof(t);
971 /* tell all nodes about this tcp connection */
972 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_TCP_ADD_DELAYED_UPDATE,
973 0, data, ctdb, NULL, NULL, NULL, NULL);
975 DEBUG(DEBUG_ERR,("Failed to add tickle\n"));
984 delete a tickle from a node
986 static int control_del_tickle(struct ctdb_context *ctdb, int argc, const char **argv)
988 struct ctdb_tcp_connection t;
996 if (parse_ip_port(argv[0], &t.src_addr) == 0) {
997 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1000 if (parse_ip_port(argv[1], &t.dst_addr) == 0) {
1001 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[1]));
1005 data.dptr = (uint8_t *)&t;
1006 data.dsize = sizeof(t);
1008 /* tell all nodes about this tcp connection */
1009 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_TCP_REMOVE,
1010 0, data, ctdb, NULL, NULL, NULL, NULL);
1012 DEBUG(DEBUG_ERR,("Failed to remove tickle\n"));
1021 get a list of all tickles for this pnn
1023 static int control_get_tickles(struct ctdb_context *ctdb, int argc, const char **argv)
1025 struct ctdb_control_tcp_tickle_list *list;
1026 ctdb_sock_addr addr;
1035 port = atoi(argv[1]);
1038 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1039 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1043 ret = ctdb_ctrl_get_tcp_tickles(ctdb, TIMELIMIT(), options.pnn, ctdb, &addr, &list);
1045 DEBUG(DEBUG_ERR, ("Unable to list tickles\n"));
1049 if (options.machinereadable){
1050 printf(":source ip:port:destination ip:port:\n");
1051 for (i=0;i<list->tickles.num;i++) {
1052 if (port && port != ntohs(list->tickles.connections[i].dst_addr.ip.sin_port)) {
1055 printf(":%s:%u", ctdb_addr_to_str(&list->tickles.connections[i].src_addr), ntohs(list->tickles.connections[i].src_addr.ip.sin_port));
1056 printf(":%s:%u:\n", ctdb_addr_to_str(&list->tickles.connections[i].dst_addr), ntohs(list->tickles.connections[i].dst_addr.ip.sin_port));
1059 printf("Tickles for ip:%s\n", ctdb_addr_to_str(&list->addr));
1060 printf("Num tickles:%u\n", list->tickles.num);
1061 for (i=0;i<list->tickles.num;i++) {
1062 if (port && port != ntohs(list->tickles.connections[i].dst_addr.ip.sin_port)) {
1065 printf("SRC: %s:%u ", ctdb_addr_to_str(&list->tickles.connections[i].src_addr), ntohs(list->tickles.connections[i].src_addr.ip.sin_port));
1066 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));
1076 static int move_ip(struct ctdb_context *ctdb, ctdb_sock_addr *addr, uint32_t pnn)
1078 struct ctdb_all_public_ips *ips;
1079 struct ctdb_public_ip ip;
1082 uint32_t disable_time;
1084 struct ctdb_node_map *nodemap=NULL;
1085 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1088 data.dptr = (uint8_t*)&disable_time;
1089 data.dsize = sizeof(disable_time);
1090 ret = ctdb_client_send_message(ctdb, CTDB_BROADCAST_CONNECTED, CTDB_SRVID_DISABLE_IP_CHECK, data);
1092 DEBUG(DEBUG_ERR,("Failed to send message to disable ipcheck\n"));
1098 /* read the public ip list from the node */
1099 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), pnn, ctdb, &ips);
1101 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", pnn));
1102 talloc_free(tmp_ctx);
1106 for (i=0;i<ips->num;i++) {
1107 if (ctdb_same_ip(addr, &ips->ips[i].addr)) {
1112 DEBUG(DEBUG_ERR, ("Node %u can not host ip address '%s'\n",
1113 pnn, ctdb_addr_to_str(addr)));
1114 talloc_free(tmp_ctx);
1121 data.dptr = (uint8_t *)&ip;
1122 data.dsize = sizeof(ip);
1124 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &nodemap);
1126 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1127 talloc_free(tmp_ctx);
1131 nodes = list_of_active_nodes_except_pnn(ctdb, nodemap, tmp_ctx, pnn);
1132 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_RELEASE_IP,
1139 DEBUG(DEBUG_ERR,("Failed to release IP on nodes\n"));
1140 talloc_free(tmp_ctx);
1144 ret = ctdb_ctrl_takeover_ip(ctdb, LONGTIMELIMIT(), pnn, &ip);
1146 DEBUG(DEBUG_ERR,("Failed to take over IP on node %d\n", pnn));
1147 talloc_free(tmp_ctx);
1151 /* update the recovery daemon so it now knows to expect the new
1152 node assignment for this ip.
1154 ret = ctdb_client_send_message(ctdb, CTDB_BROADCAST_CONNECTED, CTDB_SRVID_RECD_UPDATE_IP, data);
1156 DEBUG(DEBUG_ERR,("Failed to send message to update the ip on the recovery master.\n"));
1160 talloc_free(tmp_ctx);
1165 move/failover an ip address to a specific node
1167 static int control_moveip(struct ctdb_context *ctdb, int argc, const char **argv)
1170 ctdb_sock_addr addr;
1177 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1178 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1183 if (sscanf(argv[1], "%u", &pnn) != 1) {
1184 DEBUG(DEBUG_ERR, ("Badly formed pnn\n"));
1188 if (move_ip(ctdb, &addr, pnn) != 0) {
1189 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", pnn));
1196 void getips_store_callback(void *param, void *data)
1198 struct ctdb_public_ip *node_ip = (struct ctdb_public_ip *)data;
1199 struct ctdb_all_public_ips *ips = param;
1203 ips->ips[i].pnn = node_ip->pnn;
1204 ips->ips[i].addr = node_ip->addr;
1207 void getips_count_callback(void *param, void *data)
1209 uint32_t *count = param;
1215 static uint32_t *ip_key(ctdb_sock_addr *ip)
1217 static uint32_t key[IP_KEYLEN];
1219 bzero(key, sizeof(key));
1221 switch (ip->sa.sa_family) {
1223 key[0] = ip->ip.sin_addr.s_addr;
1226 key[0] = ip->ip6.sin6_addr.s6_addr32[3];
1227 key[1] = ip->ip6.sin6_addr.s6_addr32[2];
1228 key[2] = ip->ip6.sin6_addr.s6_addr32[1];
1229 key[3] = ip->ip6.sin6_addr.s6_addr32[0];
1232 DEBUG(DEBUG_ERR, (__location__ " ERROR, unknown family passed :%u\n", ip->sa.sa_family));
1239 static void *add_ip_callback(void *parm, void *data)
1245 control_get_all_public_ips(struct ctdb_context *ctdb, TALLOC_CTX *tmp_ctx, struct ctdb_all_public_ips **ips)
1247 struct ctdb_all_public_ips *tmp_ips;
1248 struct ctdb_node_map *nodemap=NULL;
1249 trbt_tree_t *ip_tree;
1253 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1255 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1259 ip_tree = trbt_create(tmp_ctx, 0);
1261 for(i=0;i<nodemap->num;i++){
1262 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
1265 if (nodemap->nodes[i].flags & NODE_FLAGS_DISCONNECTED) {
1269 /* read the public ip list from this node */
1270 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &tmp_ips);
1272 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", nodemap->nodes[i].pnn));
1276 for (j=0; j<tmp_ips->num;j++) {
1277 struct ctdb_public_ip *node_ip;
1279 node_ip = talloc(tmp_ctx, struct ctdb_public_ip);
1280 node_ip->pnn = tmp_ips->ips[j].pnn;
1281 node_ip->addr = tmp_ips->ips[j].addr;
1283 trbt_insertarray32_callback(ip_tree,
1284 IP_KEYLEN, ip_key(&tmp_ips->ips[j].addr),
1288 talloc_free(tmp_ips);
1293 trbt_traversearray32(ip_tree, IP_KEYLEN, getips_count_callback, &count);
1295 len = offsetof(struct ctdb_all_public_ips, ips) +
1296 count*sizeof(struct ctdb_public_ip);
1297 tmp_ips = talloc_zero_size(tmp_ctx, len);
1298 trbt_traversearray32(ip_tree, IP_KEYLEN, getips_store_callback, tmp_ips);
1307 * scans all other nodes and returns a pnn for another node that can host this
1311 find_other_host_for_public_ip(struct ctdb_context *ctdb, ctdb_sock_addr *addr)
1313 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1314 struct ctdb_all_public_ips *ips;
1315 struct ctdb_node_map *nodemap=NULL;
1318 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1320 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1321 talloc_free(tmp_ctx);
1325 for(i=0;i<nodemap->num;i++){
1326 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1329 if (nodemap->nodes[i].pnn == options.pnn) {
1333 /* read the public ip list from this node */
1334 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips);
1336 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", nodemap->nodes[i].pnn));
1340 for (j=0;j<ips->num;j++) {
1341 if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1342 talloc_free(tmp_ctx);
1343 return nodemap->nodes[i].pnn;
1349 talloc_free(tmp_ctx);
1354 add a public ip address to a node
1356 static int control_addip(struct ctdb_context *ctdb, int argc, const char **argv)
1362 ctdb_sock_addr addr;
1363 struct ctdb_control_ip_iface *pub;
1364 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1365 struct ctdb_all_public_ips *ips;
1369 talloc_free(tmp_ctx);
1373 if (!parse_ip_mask(argv[0], argv[1], &addr, &mask)) {
1374 DEBUG(DEBUG_ERR, ("Badly formed ip/mask : %s\n", argv[0]));
1375 talloc_free(tmp_ctx);
1379 ret = control_get_all_public_ips(ctdb, tmp_ctx, &ips);
1381 DEBUG(DEBUG_ERR, ("Unable to get public ip list from cluster\n"));
1382 talloc_free(tmp_ctx);
1387 /* check if some other node is already serving this ip, if not,
1390 for (i=0;i<ips->num;i++) {
1391 if (ctdb_same_ip(&addr, &ips->ips[i].addr)) {
1396 len = offsetof(struct ctdb_control_ip_iface, iface) + strlen(argv[1]) + 1;
1397 pub = talloc_size(tmp_ctx, len);
1398 CTDB_NO_MEMORY(ctdb, pub);
1402 pub->len = strlen(argv[1])+1;
1403 memcpy(&pub->iface[0], argv[1], strlen(argv[1])+1);
1405 ret = ctdb_ctrl_add_public_ip(ctdb, TIMELIMIT(), options.pnn, pub);
1407 DEBUG(DEBUG_ERR, ("Unable to add public ip to node %u\n", options.pnn));
1408 talloc_free(tmp_ctx);
1412 if (i == ips->num) {
1413 /* no one has this ip so we claim it */
1416 pnn = ips->ips[i].pnn;
1419 if (move_ip(ctdb, &addr, pnn) != 0) {
1420 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", pnn));
1424 talloc_free(tmp_ctx);
1428 static int control_delip(struct ctdb_context *ctdb, int argc, const char **argv);
1430 static int control_delip_all(struct ctdb_context *ctdb, int argc, const char **argv, ctdb_sock_addr *addr)
1432 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1433 struct ctdb_node_map *nodemap=NULL;
1434 struct ctdb_all_public_ips *ips;
1437 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1439 DEBUG(DEBUG_ERR, ("Unable to get nodemap from current node\n"));
1443 /* remove it from the nodes that are not hosting the ip currently */
1444 for(i=0;i<nodemap->num;i++){
1445 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1448 if (ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips) != 0) {
1449 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %d\n", nodemap->nodes[i].pnn));
1453 for (j=0;j<ips->num;j++) {
1454 if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1462 if (ips->ips[j].pnn == nodemap->nodes[i].pnn) {
1466 options.pnn = nodemap->nodes[i].pnn;
1467 control_delip(ctdb, argc, argv);
1471 /* remove it from every node (also the one hosting it) */
1472 for(i=0;i<nodemap->num;i++){
1473 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1476 if (ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips) != 0) {
1477 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %d\n", nodemap->nodes[i].pnn));
1481 for (j=0;j<ips->num;j++) {
1482 if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1490 options.pnn = nodemap->nodes[i].pnn;
1491 control_delip(ctdb, argc, argv);
1494 talloc_free(tmp_ctx);
1499 delete a public ip address from a node
1501 static int control_delip(struct ctdb_context *ctdb, int argc, const char **argv)
1504 ctdb_sock_addr addr;
1505 struct ctdb_control_ip_iface pub;
1506 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1507 struct ctdb_all_public_ips *ips;
1510 talloc_free(tmp_ctx);
1514 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1515 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1519 if (options.pnn == CTDB_BROADCAST_ALL) {
1520 return control_delip_all(ctdb, argc, argv, &addr);
1527 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &ips);
1529 DEBUG(DEBUG_ERR, ("Unable to get public ip list from cluster\n"));
1530 talloc_free(tmp_ctx);
1534 for (i=0;i<ips->num;i++) {
1535 if (ctdb_same_ip(&addr, &ips->ips[i].addr)) {
1541 DEBUG(DEBUG_ERR, ("This node does not support this public address '%s'\n",
1542 ctdb_addr_to_str(&addr)));
1543 talloc_free(tmp_ctx);
1547 if (ips->ips[i].pnn == options.pnn) {
1548 ret = find_other_host_for_public_ip(ctdb, &addr);
1550 if (move_ip(ctdb, &addr, ret) != 0) {
1551 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", ret));
1557 ret = ctdb_ctrl_del_public_ip(ctdb, TIMELIMIT(), options.pnn, &pub);
1559 DEBUG(DEBUG_ERR, ("Unable to del public ip from node %u\n", options.pnn));
1560 talloc_free(tmp_ctx);
1564 talloc_free(tmp_ctx);
1569 kill a tcp connection
1571 static int kill_tcp(struct ctdb_context *ctdb, int argc, const char **argv)
1574 struct ctdb_control_killtcp killtcp;
1580 if (!parse_ip_port(argv[0], &killtcp.src_addr)) {
1581 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[0]));
1585 if (!parse_ip_port(argv[1], &killtcp.dst_addr)) {
1586 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[1]));
1590 ret = ctdb_ctrl_killtcp(ctdb, TIMELIMIT(), options.pnn, &killtcp);
1592 DEBUG(DEBUG_ERR, ("Unable to killtcp from node %u\n", options.pnn));
1603 static int control_gratious_arp(struct ctdb_context *ctdb, int argc, const char **argv)
1606 ctdb_sock_addr addr;
1612 if (!parse_ip(argv[0], NULL, 0, &addr)) {
1613 DEBUG(DEBUG_ERR, ("Bad IP '%s'\n", argv[0]));
1617 ret = ctdb_ctrl_gratious_arp(ctdb, TIMELIMIT(), options.pnn, &addr, argv[1]);
1619 DEBUG(DEBUG_ERR, ("Unable to send gratious_arp from node %u\n", options.pnn));
1627 register a server id
1629 static int regsrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1632 struct ctdb_server_id server_id;
1638 server_id.pnn = strtoul(argv[0], NULL, 0);
1639 server_id.type = strtoul(argv[1], NULL, 0);
1640 server_id.server_id = strtoul(argv[2], NULL, 0);
1642 ret = ctdb_ctrl_register_server_id(ctdb, TIMELIMIT(), &server_id);
1644 DEBUG(DEBUG_ERR, ("Unable to register server_id from node %u\n", options.pnn));
1647 DEBUG(DEBUG_ERR,("Srvid registered. Sleeping for 999 seconds\n"));
1653 unregister a server id
1655 static int unregsrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1658 struct ctdb_server_id server_id;
1664 server_id.pnn = strtoul(argv[0], NULL, 0);
1665 server_id.type = strtoul(argv[1], NULL, 0);
1666 server_id.server_id = strtoul(argv[2], NULL, 0);
1668 ret = ctdb_ctrl_unregister_server_id(ctdb, TIMELIMIT(), &server_id);
1670 DEBUG(DEBUG_ERR, ("Unable to unregister server_id from node %u\n", options.pnn));
1677 check if a server id exists
1679 static int chksrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1683 struct ctdb_server_id server_id;
1689 server_id.pnn = strtoul(argv[0], NULL, 0);
1690 server_id.type = strtoul(argv[1], NULL, 0);
1691 server_id.server_id = strtoul(argv[2], NULL, 0);
1693 ret = ctdb_ctrl_check_server_id(ctdb, TIMELIMIT(), options.pnn, &server_id, &status);
1695 DEBUG(DEBUG_ERR, ("Unable to check server_id from node %u\n", options.pnn));
1700 printf("Server id %d:%d:%d EXISTS\n", server_id.pnn, server_id.type, server_id.server_id);
1702 printf("Server id %d:%d:%d does NOT exist\n", server_id.pnn, server_id.type, server_id.server_id);
1708 get a list of all server ids that are registered on a node
1710 static int getsrvids(struct ctdb_context *ctdb, int argc, const char **argv)
1713 struct ctdb_server_id_list *server_ids;
1715 ret = ctdb_ctrl_get_server_id_list(ctdb, ctdb, TIMELIMIT(), options.pnn, &server_ids);
1717 DEBUG(DEBUG_ERR, ("Unable to get server_id list from node %u\n", options.pnn));
1721 for (i=0; i<server_ids->num; i++) {
1722 printf("Server id %d:%d:%d\n",
1723 server_ids->server_ids[i].pnn,
1724 server_ids->server_ids[i].type,
1725 server_ids->server_ids[i].server_id);
1732 send a tcp tickle ack
1734 static int tickle_tcp(struct ctdb_context *ctdb, int argc, const char **argv)
1737 ctdb_sock_addr src, dst;
1743 if (!parse_ip_port(argv[0], &src)) {
1744 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[0]));
1748 if (!parse_ip_port(argv[1], &dst)) {
1749 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[1]));
1753 ret = ctdb_sys_send_tcp(&src, &dst, 0, 0, 0);
1757 DEBUG(DEBUG_ERR, ("Error while sending tickle ack\n"));
1764 display public ip status
1766 static int control_ip(struct ctdb_context *ctdb, int argc, const char **argv)
1769 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1770 struct ctdb_all_public_ips *ips;
1772 if (options.pnn == CTDB_BROADCAST_ALL) {
1773 /* read the list of public ips from all nodes */
1774 ret = control_get_all_public_ips(ctdb, tmp_ctx, &ips);
1776 /* read the public ip list from this node */
1777 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &ips);
1780 DEBUG(DEBUG_ERR, ("Unable to get public ips from node %u\n", options.pnn));
1781 talloc_free(tmp_ctx);
1785 if (options.machinereadable){
1786 printf(":Public IP:Node:");
1787 if (options.verbose){
1788 printf("ActiveInterface:AvailableInterfaces:ConfiguredInterfaces:");
1792 if (options.pnn == CTDB_BROADCAST_ALL) {
1793 printf("Public IPs on ALL nodes\n");
1795 printf("Public IPs on node %u\n", options.pnn);
1799 for (i=1;i<=ips->num;i++) {
1800 struct ctdb_control_public_ip_info *info = NULL;
1802 char *aciface = NULL;
1803 char *avifaces = NULL;
1804 char *cifaces = NULL;
1806 if (options.pnn == CTDB_BROADCAST_ALL) {
1807 pnn = ips->ips[ips->num-i].pnn;
1813 ret = ctdb_ctrl_get_public_ip_info(ctdb, TIMELIMIT(), pnn, ctdb,
1814 &ips->ips[ips->num-i].addr, &info);
1821 for (j=0; j < info->num; j++) {
1822 if (cifaces == NULL) {
1823 cifaces = talloc_strdup(info,
1824 info->ifaces[j].name);
1826 cifaces = talloc_asprintf_append(cifaces,
1828 info->ifaces[j].name);
1831 if (info->active_idx == j) {
1832 aciface = info->ifaces[j].name;
1835 if (info->ifaces[j].link_state == 0) {
1839 if (avifaces == NULL) {
1840 avifaces = talloc_strdup(info, info->ifaces[j].name);
1842 avifaces = talloc_asprintf_append(avifaces,
1844 info->ifaces[j].name);
1849 if (options.machinereadable){
1851 ctdb_addr_to_str(&ips->ips[ips->num-i].addr),
1852 ips->ips[ips->num-i].pnn);
1853 if (options.verbose){
1856 avifaces?avifaces:"",
1857 cifaces?cifaces:"");
1861 if (options.verbose) {
1862 printf("%s node[%d] active[%s] available[%s] configured[%s]\n",
1863 ctdb_addr_to_str(&ips->ips[ips->num-i].addr),
1864 ips->ips[ips->num-i].pnn,
1866 avifaces?avifaces:"",
1867 cifaces?cifaces:"");
1870 ctdb_addr_to_str(&ips->ips[ips->num-i].addr),
1871 ips->ips[ips->num-i].pnn);
1877 talloc_free(tmp_ctx);
1884 static int control_ipinfo(struct ctdb_context *ctdb, int argc, const char **argv)
1887 ctdb_sock_addr addr;
1888 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1889 struct ctdb_control_public_ip_info *info;
1892 talloc_free(tmp_ctx);
1896 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1897 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1901 /* read the public ip info from this node */
1902 ret = ctdb_ctrl_get_public_ip_info(ctdb, TIMELIMIT(), options.pnn,
1903 tmp_ctx, &addr, &info);
1905 DEBUG(DEBUG_ERR, ("Unable to get public ip[%s]info from node %u\n",
1906 argv[0], options.pnn));
1907 talloc_free(tmp_ctx);
1911 printf("Public IP[%s] info on node %u\n",
1912 ctdb_addr_to_str(&info->ip.addr),
1915 printf("IP:%s\nCurrentNode:%d\nNumInterfaces:%u\n",
1916 ctdb_addr_to_str(&info->ip.addr),
1917 info->ip.pnn, info->num);
1919 for (i=0; i<info->num; i++) {
1920 info->ifaces[i].name[CTDB_IFACE_SIZE] = '\0';
1922 printf("Interface[%u]: Name:%s Link:%s References:%u%s\n",
1923 i+1, info->ifaces[i].name,
1924 info->ifaces[i].link_state?"up":"down",
1925 (unsigned int)info->ifaces[i].references,
1926 (i==info->active_idx)?" (active)":"");
1929 talloc_free(tmp_ctx);
1934 display interfaces status
1936 static int control_ifaces(struct ctdb_context *ctdb, int argc, const char **argv)
1939 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1940 struct ctdb_control_get_ifaces *ifaces;
1942 /* read the public ip list from this node */
1943 ret = ctdb_ctrl_get_ifaces(ctdb, TIMELIMIT(), options.pnn,
1946 DEBUG(DEBUG_ERR, ("Unable to get interfaces from node %u\n",
1948 talloc_free(tmp_ctx);
1952 if (options.machinereadable){
1953 printf(":Name:LinkStatus:References:\n");
1955 printf("Interfaces on node %u\n", options.pnn);
1958 for (i=0; i<ifaces->num; i++) {
1959 if (options.machinereadable){
1960 printf(":%s:%s:%u\n",
1961 ifaces->ifaces[i].name,
1962 ifaces->ifaces[i].link_state?"1":"0",
1963 (unsigned int)ifaces->ifaces[i].references);
1965 printf("name:%s link:%s references:%u\n",
1966 ifaces->ifaces[i].name,
1967 ifaces->ifaces[i].link_state?"up":"down",
1968 (unsigned int)ifaces->ifaces[i].references);
1972 talloc_free(tmp_ctx);
1978 set link status of an interface
1980 static int control_setifacelink(struct ctdb_context *ctdb, int argc, const char **argv)
1983 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1984 struct ctdb_control_iface_info info;
1992 if (strlen(argv[0]) > CTDB_IFACE_SIZE) {
1993 DEBUG(DEBUG_ERR, ("interfaces name '%s' too long\n",
1995 talloc_free(tmp_ctx);
1998 strcpy(info.name, argv[0]);
2000 if (strcmp(argv[1], "up") == 0) {
2001 info.link_state = 1;
2002 } else if (strcmp(argv[1], "down") == 0) {
2003 info.link_state = 0;
2005 DEBUG(DEBUG_ERR, ("link state invalid '%s' should be 'up' or 'down'\n",
2007 talloc_free(tmp_ctx);
2011 /* read the public ip list from this node */
2012 ret = ctdb_ctrl_set_iface_link(ctdb, TIMELIMIT(), options.pnn,
2015 DEBUG(DEBUG_ERR, ("Unable to set link state for interfaces %s node %u\n",
2016 argv[0], options.pnn));
2017 talloc_free(tmp_ctx);
2021 talloc_free(tmp_ctx);
2026 display pid of a ctdb daemon
2028 static int control_getpid(struct ctdb_context *ctdb, int argc, const char **argv)
2033 ret = ctdb_ctrl_getpid(ctdb, TIMELIMIT(), options.pnn, &pid);
2035 DEBUG(DEBUG_ERR, ("Unable to get daemon pid from node %u\n", options.pnn));
2038 printf("Pid:%d\n", pid);
2043 static uint32_t ipreallocate_finished;
2046 handler for receiving the response to ipreallocate
2048 static void ip_reallocate_handler(struct ctdb_context *ctdb, uint64_t srvid,
2049 TDB_DATA data, void *private_data)
2051 ipreallocate_finished = 1;
2054 static void ctdb_every_second(struct event_context *ev, struct timed_event *te, struct timeval t, void *p)
2056 struct ctdb_context *ctdb = talloc_get_type(p, struct ctdb_context);
2058 event_add_timed(ctdb->ev, ctdb,
2059 timeval_current_ofs(1, 0),
2060 ctdb_every_second, ctdb);
2064 ask the recovery daemon on the recovery master to perform a ip reallocation
2066 static int control_ipreallocate(struct ctdb_context *ctdb, int argc, const char **argv)
2070 struct takeover_run_reply rd;
2072 struct ctdb_node_map *nodemap=NULL;
2074 struct timeval tv = timeval_current();
2076 /* we need some events to trigger so we can timeout and restart
2079 event_add_timed(ctdb->ev, ctdb,
2080 timeval_current_ofs(1, 0),
2081 ctdb_every_second, ctdb);
2083 rd.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
2085 DEBUG(DEBUG_ERR, ("Failed to get pnn of local node\n"));
2088 rd.srvid = getpid();
2090 /* register a message port for receiveing the reply so that we
2091 can receive the reply
2093 ctdb_client_set_message_handler(ctdb, rd.srvid, ip_reallocate_handler, NULL);
2095 data.dptr = (uint8_t *)&rd;
2096 data.dsize = sizeof(rd);
2099 /* check that there are valid nodes available */
2100 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap) != 0) {
2101 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2104 for (i=0; i<nodemap->num;i++) {
2105 if ((nodemap->nodes[i].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) == 0) {
2109 if (i==nodemap->num) {
2110 DEBUG(DEBUG_ERR,("No recmaster available, no need to wait for cluster convergence\n"));
2115 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
2117 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
2121 /* verify the node exists */
2122 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), recmaster, ctdb, &nodemap) != 0) {
2123 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2128 /* check tha there are nodes available that can act as a recmaster */
2129 for (i=0; i<nodemap->num; i++) {
2130 if (nodemap->nodes[i].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
2135 if (i == nodemap->num) {
2136 DEBUG(DEBUG_ERR,("No possible nodes to host addresses.\n"));
2140 /* verify the recovery master is not STOPPED, nor BANNED */
2141 if (nodemap->nodes[recmaster].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
2142 DEBUG(DEBUG_ERR,("No suitable recmaster found. Try again\n"));
2149 /* verify the recovery master is not STOPPED, nor BANNED */
2150 if (nodemap->nodes[recmaster].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
2151 DEBUG(DEBUG_ERR,("No suitable recmaster found. Try again\n"));
2157 ipreallocate_finished = 0;
2158 ret = ctdb_client_send_message(ctdb, recmaster, CTDB_SRVID_TAKEOVER_RUN, data);
2160 DEBUG(DEBUG_ERR,("Failed to send ip takeover run request message to %u\n", options.pnn));
2164 tv = timeval_current();
2165 /* this loop will terminate when we have received the reply */
2166 while (timeval_elapsed(&tv) < 3.0) {
2167 event_loop_once(ctdb->ev);
2169 if (ipreallocate_finished == 1) {
2173 DEBUG(DEBUG_ERR,("Timed out waiting for recmaster ipreallocate. Trying again\n"));
2183 disable a remote node
2185 static int control_disable(struct ctdb_context *ctdb, int argc, const char **argv)
2188 struct ctdb_node_map *nodemap=NULL;
2190 /* check if the node is already disabled */
2191 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2192 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2195 if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2196 DEBUG(DEBUG_ERR,("Node %d is already disabled.\n", options.pnn));
2201 ret = ctdb_ctrl_modflags(ctdb, TIMELIMIT(), options.pnn, NODE_FLAGS_PERMANENTLY_DISABLED, 0);
2203 DEBUG(DEBUG_ERR, ("Unable to disable node %u\n", options.pnn));
2209 /* read the nodemap and verify the change took effect */
2210 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2211 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2215 } while (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED));
2216 ret = control_ipreallocate(ctdb, argc, argv);
2218 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2226 enable a disabled remote node
2228 static int control_enable(struct ctdb_context *ctdb, int argc, const char **argv)
2232 struct ctdb_node_map *nodemap=NULL;
2235 /* check if the node is already enabled */
2236 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2237 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2240 if (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED)) {
2241 DEBUG(DEBUG_ERR,("Node %d is already enabled.\n", options.pnn));
2246 ret = ctdb_ctrl_modflags(ctdb, TIMELIMIT(), options.pnn, 0, NODE_FLAGS_PERMANENTLY_DISABLED);
2248 DEBUG(DEBUG_ERR, ("Unable to enable node %u\n", options.pnn));
2254 /* read the nodemap and verify the change took effect */
2255 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2256 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2260 } while (nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED);
2262 ret = control_ipreallocate(ctdb, argc, argv);
2264 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2274 static int control_stop(struct ctdb_context *ctdb, int argc, const char **argv)
2277 struct ctdb_node_map *nodemap=NULL;
2280 ret = ctdb_ctrl_stop_node(ctdb, TIMELIMIT(), options.pnn);
2282 DEBUG(DEBUG_ERR, ("Unable to stop node %u try again\n", options.pnn));
2287 /* read the nodemap and verify the change took effect */
2288 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2289 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2293 } while (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_STOPPED));
2294 ret = control_ipreallocate(ctdb, argc, argv);
2296 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2304 restart a stopped remote node
2306 static int control_continue(struct ctdb_context *ctdb, int argc, const char **argv)
2310 struct ctdb_node_map *nodemap=NULL;
2313 ret = ctdb_ctrl_continue_node(ctdb, TIMELIMIT(), options.pnn);
2315 DEBUG(DEBUG_ERR, ("Unable to continue node %u\n", options.pnn));
2321 /* read the nodemap and verify the change took effect */
2322 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2323 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2327 } while (nodemap->nodes[options.pnn].flags & NODE_FLAGS_STOPPED);
2328 ret = control_ipreallocate(ctdb, argc, argv);
2330 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2337 static uint32_t get_generation(struct ctdb_context *ctdb)
2339 struct ctdb_vnn_map *vnnmap=NULL;
2342 /* wait until the recmaster is not in recovery mode */
2344 uint32_t recmode, recmaster;
2346 if (vnnmap != NULL) {
2347 talloc_free(vnnmap);
2351 /* get the recmaster */
2352 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, &recmaster);
2354 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
2358 /* get recovery mode */
2359 ret = ctdb_ctrl_getrecmode(ctdb, ctdb, TIMELIMIT(), recmaster, &recmode);
2361 DEBUG(DEBUG_ERR, ("Unable to get recmode from node %u\n", options.pnn));
2365 /* get the current generation number */
2366 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), recmaster, ctdb, &vnnmap);
2368 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from recmaster (%u)\n", recmaster));
2372 if ((recmode == CTDB_RECOVERY_NORMAL)
2373 && (vnnmap->generation != 1)){
2374 return vnnmap->generation;
2381 ban a node from the cluster
2383 static int control_ban(struct ctdb_context *ctdb, int argc, const char **argv)
2386 struct ctdb_node_map *nodemap=NULL;
2387 struct ctdb_ban_time bantime;
2393 /* verify the node exists */
2394 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
2396 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2400 if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_BANNED) {
2401 DEBUG(DEBUG_ERR,("Node %u is already banned.\n", options.pnn));
2405 bantime.pnn = options.pnn;
2406 bantime.time = strtoul(argv[0], NULL, 0);
2408 ret = ctdb_ctrl_set_ban(ctdb, TIMELIMIT(), options.pnn, &bantime);
2410 DEBUG(DEBUG_ERR,("Banning node %d for %d seconds failed.\n", bantime.pnn, bantime.time));
2414 ret = control_ipreallocate(ctdb, argc, argv);
2416 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2425 unban a node from the cluster
2427 static int control_unban(struct ctdb_context *ctdb, int argc, const char **argv)
2430 struct ctdb_node_map *nodemap=NULL;
2431 struct ctdb_ban_time bantime;
2433 /* verify the node exists */
2434 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
2436 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2440 if (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_BANNED)) {
2441 DEBUG(DEBUG_ERR,("Node %u is not banned.\n", options.pnn));
2445 bantime.pnn = options.pnn;
2448 ret = ctdb_ctrl_set_ban(ctdb, TIMELIMIT(), options.pnn, &bantime);
2450 DEBUG(DEBUG_ERR,("Unbanning node %d failed.\n", bantime.pnn));
2454 ret = control_ipreallocate(ctdb, argc, argv);
2456 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2465 show ban information for a node
2467 static int control_showban(struct ctdb_context *ctdb, int argc, const char **argv)
2470 struct ctdb_node_map *nodemap=NULL;
2471 struct ctdb_ban_time *bantime;
2473 /* verify the node exists */
2474 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
2476 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2480 ret = ctdb_ctrl_get_ban(ctdb, TIMELIMIT(), options.pnn, ctdb, &bantime);
2482 DEBUG(DEBUG_ERR,("Showing ban info for node %d failed.\n", options.pnn));
2486 if (bantime->time == 0) {
2487 printf("Node %u is not banned\n", bantime->pnn);
2489 printf("Node %u is banned banned for %d seconds\n", bantime->pnn, bantime->time);
2498 static int control_shutdown(struct ctdb_context *ctdb, int argc, const char **argv)
2502 ret = ctdb_ctrl_shutdown(ctdb, TIMELIMIT(), options.pnn);
2504 DEBUG(DEBUG_ERR, ("Unable to shutdown node %u\n", options.pnn));
2514 static int control_recover(struct ctdb_context *ctdb, int argc, const char **argv)
2517 uint32_t generation, next_generation;
2519 /* record the current generation number */
2520 generation = get_generation(ctdb);
2522 ret = ctdb_ctrl_freeze_priority(ctdb, TIMELIMIT(), options.pnn, 1);
2524 DEBUG(DEBUG_ERR, ("Unable to freeze node\n"));
2528 ret = ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
2530 DEBUG(DEBUG_ERR, ("Unable to set recovery mode\n"));
2534 /* wait until we are in a new generation */
2536 next_generation = get_generation(ctdb);
2537 if (next_generation != generation) {
2548 display monitoring mode of a remote node
2550 static int control_getmonmode(struct ctdb_context *ctdb, int argc, const char **argv)
2555 ret = ctdb_ctrl_getmonmode(ctdb, TIMELIMIT(), options.pnn, &monmode);
2557 DEBUG(DEBUG_ERR, ("Unable to get monmode from node %u\n", options.pnn));
2560 if (!options.machinereadable){
2561 printf("Monitoring mode:%s (%d)\n",monmode==CTDB_MONITORING_ACTIVE?"ACTIVE":"DISABLED",monmode);
2564 printf(":%d:\n",monmode);
2571 display capabilities of a remote node
2573 static int control_getcapabilities(struct ctdb_context *ctdb, int argc, const char **argv)
2575 uint32_t capabilities;
2578 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), options.pnn, &capabilities);
2580 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", options.pnn));
2584 if (!options.machinereadable){
2585 printf("RECMASTER: %s\n", (capabilities&CTDB_CAP_RECMASTER)?"YES":"NO");
2586 printf("LMASTER: %s\n", (capabilities&CTDB_CAP_LMASTER)?"YES":"NO");
2587 printf("LVS: %s\n", (capabilities&CTDB_CAP_LVS)?"YES":"NO");
2588 printf("NATGW: %s\n", (capabilities&CTDB_CAP_NATGW)?"YES":"NO");
2590 printf(":RECMASTER:LMASTER:LVS:NATGW:\n");
2591 printf(":%d:%d:%d:%d:\n",
2592 !!(capabilities&CTDB_CAP_RECMASTER),
2593 !!(capabilities&CTDB_CAP_LMASTER),
2594 !!(capabilities&CTDB_CAP_LVS),
2595 !!(capabilities&CTDB_CAP_NATGW));
2601 display lvs configuration
2603 static int control_lvs(struct ctdb_context *ctdb, int argc, const char **argv)
2605 uint32_t *capabilities;
2606 struct ctdb_node_map *nodemap=NULL;
2608 int healthy_count = 0;
2610 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
2612 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
2616 capabilities = talloc_array(ctdb, uint32_t, nodemap->num);
2617 CTDB_NO_MEMORY(ctdb, capabilities);
2619 /* collect capabilities for all connected nodes */
2620 for (i=0; i<nodemap->num; i++) {
2621 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2624 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2628 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), i, &capabilities[i]);
2630 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", i));
2634 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2638 if (!(nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY)) {
2643 /* Print all LVS nodes */
2644 for (i=0; i<nodemap->num; i++) {
2645 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2648 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2651 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2655 if (healthy_count != 0) {
2656 if (nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY) {
2661 printf("%d:%s\n", i,
2662 ctdb_addr_to_str(&nodemap->nodes[i].addr));
2669 display who is the lvs master
2671 static int control_lvsmaster(struct ctdb_context *ctdb, int argc, const char **argv)
2673 uint32_t *capabilities;
2674 struct ctdb_node_map *nodemap=NULL;
2676 int healthy_count = 0;
2678 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
2680 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
2684 capabilities = talloc_array(ctdb, uint32_t, nodemap->num);
2685 CTDB_NO_MEMORY(ctdb, capabilities);
2687 /* collect capabilities for all connected nodes */
2688 for (i=0; i<nodemap->num; i++) {
2689 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2692 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2696 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), i, &capabilities[i]);
2698 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", i));
2702 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2706 if (!(nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY)) {
2711 /* find and show the lvsmaster */
2712 for (i=0; i<nodemap->num; i++) {
2713 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2716 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2719 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2723 if (healthy_count != 0) {
2724 if (nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY) {
2729 if (options.machinereadable){
2732 printf("Node %d is LVS master\n", i);
2737 printf("There is no LVS master\n");
2742 disable monitoring on a node
2744 static int control_disable_monmode(struct ctdb_context *ctdb, int argc, const char **argv)
2749 ret = ctdb_ctrl_disable_monmode(ctdb, TIMELIMIT(), options.pnn);
2751 DEBUG(DEBUG_ERR, ("Unable to disable monmode on node %u\n", options.pnn));
2754 printf("Monitoring mode:%s\n","DISABLED");
2760 enable monitoring on a node
2762 static int control_enable_monmode(struct ctdb_context *ctdb, int argc, const char **argv)
2767 ret = ctdb_ctrl_enable_monmode(ctdb, TIMELIMIT(), options.pnn);
2769 DEBUG(DEBUG_ERR, ("Unable to enable monmode on node %u\n", options.pnn));
2772 printf("Monitoring mode:%s\n","ACTIVE");
2778 display remote list of keys/data for a db
2780 static int control_catdb(struct ctdb_context *ctdb, int argc, const char **argv)
2782 const char *db_name;
2783 struct ctdb_db_context *ctdb_db;
2793 if (db_exists(ctdb, db_name)) {
2794 DEBUG(DEBUG_ERR,("Database '%s' does not exist\n", db_name));
2798 ctdb_db = ctdb_attach(ctdb, db_name, false, 0);
2800 if (ctdb_db == NULL) {
2801 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
2805 /* traverse and dump the cluster tdb */
2806 ret = ctdb_dump_db(ctdb_db, stdout);
2808 DEBUG(DEBUG_ERR, ("Unable to dump database\n"));
2809 DEBUG(DEBUG_ERR, ("Maybe try 'ctdb getdbstatus %s'"
2810 " and 'ctdb getvar AllowUnhealthyDBRead'\n",
2814 talloc_free(ctdb_db);
2816 printf("Dumped %d records\n", ret);
2822 fetch a record from a persistent database
2824 static int control_pfetch(struct ctdb_context *ctdb, int argc, const char **argv)
2826 const char *db_name;
2827 struct ctdb_db_context *ctdb_db;
2828 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2829 struct ctdb_transaction_handle *h;
2834 talloc_free(tmp_ctx);
2841 if (db_exists(ctdb, db_name)) {
2842 DEBUG(DEBUG_ERR,("Database '%s' does not exist\n", db_name));
2843 talloc_free(tmp_ctx);
2847 ctdb_db = ctdb_attach(ctdb, db_name, true, 0);
2849 if (ctdb_db == NULL) {
2850 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
2851 talloc_free(tmp_ctx);
2855 h = ctdb_transaction_start(ctdb_db, tmp_ctx);
2857 DEBUG(DEBUG_ERR,("Failed to start transaction on database %s\n", db_name));
2858 talloc_free(tmp_ctx);
2862 key.dptr = discard_const(argv[1]);
2863 key.dsize = strlen(argv[1]);
2864 ret = ctdb_transaction_fetch(h, tmp_ctx, key, &data);
2866 DEBUG(DEBUG_ERR,("Failed to fetch record\n"));
2867 talloc_free(tmp_ctx);
2871 if (data.dsize == 0 || data.dptr == NULL) {
2872 DEBUG(DEBUG_ERR,("Record is empty\n"));
2873 talloc_free(tmp_ctx);
2877 fwrite(data.dptr, data.dsize, 1, stdout);
2879 /* abort the transaction */
2883 talloc_free(tmp_ctx);
2888 write a record to a persistent database
2890 static int control_pstore(struct ctdb_context *ctdb, int argc, const char **argv)
2892 const char *db_name;
2893 struct ctdb_db_context *ctdb_db;
2894 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2895 struct ctdb_transaction_handle *h;
2901 talloc_free(tmp_ctx);
2905 fd = open(argv[2], O_RDONLY);
2907 DEBUG(DEBUG_ERR,("Failed to open file containing record data : %s %s\n", argv[2], strerror(errno)));
2908 talloc_free(tmp_ctx);
2912 ret = fstat(fd, &st);
2914 DEBUG(DEBUG_ERR,("fstat of file %s failed: %s\n", argv[2], strerror(errno)));
2916 talloc_free(tmp_ctx);
2920 if (!S_ISREG(st.st_mode)) {
2921 DEBUG(DEBUG_ERR,("Not a regular file %s\n", argv[2]));
2923 talloc_free(tmp_ctx);
2927 data.dsize = st.st_size;
2928 if (data.dsize == 0) {
2931 data.dptr = talloc_size(tmp_ctx, data.dsize);
2932 if (data.dptr == NULL) {
2933 DEBUG(DEBUG_ERR,("Failed to talloc %d of memory to store record data\n", (int)data.dsize));
2935 talloc_free(tmp_ctx);
2938 ret = read(fd, data.dptr, data.dsize);
2939 if (ret != data.dsize) {
2940 DEBUG(DEBUG_ERR,("Failed to read %d bytes of record data\n", (int)data.dsize));
2942 talloc_free(tmp_ctx);
2951 ctdb_db = ctdb_attach(ctdb, db_name, true, 0);
2953 if (ctdb_db == NULL) {
2954 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
2955 talloc_free(tmp_ctx);
2959 h = ctdb_transaction_start(ctdb_db, tmp_ctx);
2961 DEBUG(DEBUG_ERR,("Failed to start transaction on database %s\n", db_name));
2962 talloc_free(tmp_ctx);
2966 key.dptr = discard_const(argv[1]);
2967 key.dsize = strlen(argv[1]);
2968 ret = ctdb_transaction_store(h, key, data);
2970 DEBUG(DEBUG_ERR,("Failed to store record\n"));
2971 talloc_free(tmp_ctx);
2975 ret = ctdb_transaction_commit(h);
2977 DEBUG(DEBUG_ERR,("Failed to commit transaction\n"));
2978 talloc_free(tmp_ctx);
2983 talloc_free(tmp_ctx);
2987 static void log_handler(struct ctdb_context *ctdb, uint64_t srvid,
2988 TDB_DATA data, void *private_data)
2990 DEBUG(DEBUG_ERR,("Log data received\n"));
2991 if (data.dsize > 0) {
2992 printf("%s", data.dptr);
2999 display a list of log messages from the in memory ringbuffer
3001 static int control_getlog(struct ctdb_context *ctdb, int argc, const char **argv)
3005 struct ctdb_get_log_addr log_addr;
3007 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3012 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3013 talloc_free(tmp_ctx);
3017 log_addr.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
3018 log_addr.srvid = getpid();
3019 if (isalpha(argv[0][0]) || argv[0][0] == '-') {
3020 log_addr.level = get_debug_by_desc(argv[0]);
3022 log_addr.level = strtol(argv[0], NULL, 0);
3026 data.dptr = (unsigned char *)&log_addr;
3027 data.dsize = sizeof(log_addr);
3029 DEBUG(DEBUG_ERR, ("Pulling logs from node %u\n", options.pnn));
3031 ctdb_client_set_message_handler(ctdb, log_addr.srvid, log_handler, NULL);
3034 DEBUG(DEBUG_ERR,("Listen for response on %d\n", (int)log_addr.srvid));
3036 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_GET_LOG,
3037 0, data, tmp_ctx, NULL, &res, NULL, &errmsg);
3038 if (ret != 0 || res != 0) {
3039 DEBUG(DEBUG_ERR,("Failed to get logs - %s\n", errmsg));
3040 talloc_free(tmp_ctx);
3045 tv = timeval_current();
3046 /* this loop will terminate when we have received the reply */
3047 while (timeval_elapsed(&tv) < 3.0) {
3048 event_loop_once(ctdb->ev);
3051 DEBUG(DEBUG_INFO,("Timed out waiting for log data.\n"));
3053 talloc_free(tmp_ctx);
3058 clear the in memory log area
3060 static int control_clearlog(struct ctdb_context *ctdb, int argc, const char **argv)
3065 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3067 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_CLEAR_LOG,
3068 0, tdb_null, tmp_ctx, NULL, &res, NULL, &errmsg);
3069 if (ret != 0 || res != 0) {
3070 DEBUG(DEBUG_ERR,("Failed to clear logs\n"));
3071 talloc_free(tmp_ctx);
3075 talloc_free(tmp_ctx);
3082 display a list of the databases on a remote ctdb
3084 static int control_getdbmap(struct ctdb_context *ctdb, int argc, const char **argv)
3087 struct ctdb_dbid_map *dbmap=NULL;
3089 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
3091 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
3095 if(options.machinereadable){
3096 printf(":ID:Name:Path:Persistent:Unhealthy:\n");
3097 for(i=0;i<dbmap->num;i++){
3103 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn,
3104 dbmap->dbs[i].dbid, ctdb, &path);
3105 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn,
3106 dbmap->dbs[i].dbid, ctdb, &name);
3107 ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn,
3108 dbmap->dbs[i].dbid, ctdb, &health);
3109 persistent = dbmap->dbs[i].persistent;
3110 printf(":0x%08X:%s:%s:%d:%d:\n",
3111 dbmap->dbs[i].dbid, name, path,
3112 !!(persistent), !!(health));
3117 printf("Number of databases:%d\n", dbmap->num);
3118 for(i=0;i<dbmap->num;i++){
3124 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &path);
3125 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
3126 ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &health);
3127 persistent = dbmap->dbs[i].persistent;
3128 printf("dbid:0x%08x name:%s path:%s%s%s\n",
3129 dbmap->dbs[i].dbid, name, path,
3130 persistent?" PERSISTENT":"",
3131 health?" UNHEALTHY":"");
3138 display the status of a database on a remote ctdb
3140 static int control_getdbstatus(struct ctdb_context *ctdb, int argc, const char **argv)
3143 struct ctdb_dbid_map *dbmap=NULL;
3144 const char *db_name;
3152 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
3154 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
3158 for(i=0;i<dbmap->num;i++){
3164 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
3165 if (strcmp(name, db_name) != 0) {
3169 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &path);
3170 ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &health);
3171 persistent = dbmap->dbs[i].persistent;
3172 printf("dbid: 0x%08x\nname: %s\npath: %s\nPERSISTENT: %s\nHEALTH: %s\n",
3173 dbmap->dbs[i].dbid, name, path,
3174 persistent?"yes":"no",
3175 health?health:"OK");
3179 DEBUG(DEBUG_ERR, ("db %s doesn't exist on node %u\n", db_name, options.pnn));
3184 check if the local node is recmaster or not
3185 it will return 1 if this node is the recmaster and 0 if it is not
3186 or if the local ctdb daemon could not be contacted
3188 static int control_isnotrecmaster(struct ctdb_context *ctdb, int argc, const char **argv)
3190 uint32_t mypnn, recmaster;
3193 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
3195 printf("Failed to get pnn of node\n");
3199 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
3201 printf("Failed to get the recmaster\n");
3205 if (recmaster != mypnn) {
3206 printf("this node is not the recmaster\n");
3210 printf("this node is the recmaster\n");
3217 static int control_ping(struct ctdb_context *ctdb, int argc, const char **argv)
3220 struct timeval tv = timeval_current();
3221 ret = ctdb_ctrl_ping(ctdb, options.pnn);
3223 printf("Unable to get ping response from node %u\n", options.pnn);
3226 printf("response from %u time=%.6f sec (%d clients)\n",
3227 options.pnn, timeval_elapsed(&tv), ret);
3236 static int control_getvar(struct ctdb_context *ctdb, int argc, const char **argv)
3247 ret = ctdb_ctrl_get_tunable(ctdb, TIMELIMIT(), options.pnn, name, &value);
3249 DEBUG(DEBUG_ERR, ("Unable to get tunable variable '%s'\n", name));
3253 printf("%-19s = %u\n", name, value);
3260 static int control_setvar(struct ctdb_context *ctdb, int argc, const char **argv)
3271 value = strtoul(argv[1], NULL, 0);
3273 ret = ctdb_ctrl_set_tunable(ctdb, TIMELIMIT(), options.pnn, name, value);
3275 DEBUG(DEBUG_ERR, ("Unable to set tunable variable '%s'\n", name));
3284 static int control_listvars(struct ctdb_context *ctdb, int argc, const char **argv)
3290 ret = ctdb_ctrl_list_tunables(ctdb, TIMELIMIT(), options.pnn, ctdb, &list, &count);
3292 DEBUG(DEBUG_ERR, ("Unable to list tunable variables\n"));
3296 for (i=0;i<count;i++) {
3297 control_getvar(ctdb, 1, &list[i]);
3306 display debug level on a node
3308 static int control_getdebug(struct ctdb_context *ctdb, int argc, const char **argv)
3313 ret = ctdb_ctrl_get_debuglevel(ctdb, options.pnn, &level);
3315 DEBUG(DEBUG_ERR, ("Unable to get debuglevel response from node %u\n", options.pnn));
3318 if (options.machinereadable){
3319 printf(":Name:Level:\n");
3320 printf(":%s:%d:\n",get_debug_by_level(level),level);
3322 printf("Node %u is at debug level %s (%d)\n", options.pnn, get_debug_by_level(level), level);
3329 display reclock file of a node
3331 static int control_getreclock(struct ctdb_context *ctdb, int argc, const char **argv)
3334 const char *reclock;
3336 ret = ctdb_ctrl_getreclock(ctdb, TIMELIMIT(), options.pnn, ctdb, &reclock);
3338 DEBUG(DEBUG_ERR, ("Unable to get reclock file from node %u\n", options.pnn));
3341 if (options.machinereadable){
3342 if (reclock != NULL) {
3343 printf("%s", reclock);
3346 if (reclock == NULL) {
3347 printf("No reclock file used.\n");
3349 printf("Reclock file:%s\n", reclock);
3357 set the reclock file of a node
3359 static int control_setreclock(struct ctdb_context *ctdb, int argc, const char **argv)
3362 const char *reclock;
3366 } else if (argc == 1) {
3372 ret = ctdb_ctrl_setreclock(ctdb, TIMELIMIT(), options.pnn, reclock);
3374 DEBUG(DEBUG_ERR, ("Unable to get reclock file from node %u\n", options.pnn));
3381 set the natgw state on/off
3383 static int control_setnatgwstate(struct ctdb_context *ctdb, int argc, const char **argv)
3386 uint32_t natgwstate;
3392 if (!strcmp(argv[0], "on")) {
3394 } else if (!strcmp(argv[0], "off")) {
3400 ret = ctdb_ctrl_setnatgwstate(ctdb, TIMELIMIT(), options.pnn, natgwstate);
3402 DEBUG(DEBUG_ERR, ("Unable to set the natgw state for node %u\n", options.pnn));
3410 set the lmaster role on/off
3412 static int control_setlmasterrole(struct ctdb_context *ctdb, int argc, const char **argv)
3415 uint32_t lmasterrole;
3421 if (!strcmp(argv[0], "on")) {
3423 } else if (!strcmp(argv[0], "off")) {
3429 ret = ctdb_ctrl_setlmasterrole(ctdb, TIMELIMIT(), options.pnn, lmasterrole);
3431 DEBUG(DEBUG_ERR, ("Unable to set the lmaster role for node %u\n", options.pnn));
3439 set the recmaster role on/off
3441 static int control_setrecmasterrole(struct ctdb_context *ctdb, int argc, const char **argv)
3444 uint32_t recmasterrole;
3450 if (!strcmp(argv[0], "on")) {
3452 } else if (!strcmp(argv[0], "off")) {
3458 ret = ctdb_ctrl_setrecmasterrole(ctdb, TIMELIMIT(), options.pnn, recmasterrole);
3460 DEBUG(DEBUG_ERR, ("Unable to set the recmaster role for node %u\n", options.pnn));
3468 set debug level on a node or all nodes
3470 static int control_setdebug(struct ctdb_context *ctdb, int argc, const char **argv)
3476 printf("You must specify the debug level. Valid levels are:\n");
3477 for (i=0; debug_levels[i].description != NULL; i++) {
3478 printf("%s (%d)\n", debug_levels[i].description, debug_levels[i].level);
3484 if (isalpha(argv[0][0]) || argv[0][0] == '-') {
3485 level = get_debug_by_desc(argv[0]);
3487 level = strtol(argv[0], NULL, 0);
3490 for (i=0; debug_levels[i].description != NULL; i++) {
3491 if (level == debug_levels[i].level) {
3495 if (debug_levels[i].description == NULL) {
3496 printf("Invalid debug level, must be one of\n");
3497 for (i=0; debug_levels[i].description != NULL; i++) {
3498 printf("%s (%d)\n", debug_levels[i].description, debug_levels[i].level);
3503 ret = ctdb_ctrl_set_debuglevel(ctdb, options.pnn, level);
3505 DEBUG(DEBUG_ERR, ("Unable to set debug level on node %u\n", options.pnn));
3514 static int control_thaw(struct ctdb_context *ctdb, int argc, const char **argv)
3520 priority = strtol(argv[0], NULL, 0);
3524 DEBUG(DEBUG_ERR,("Thaw by priority %u\n", priority));
3526 ret = ctdb_ctrl_thaw_priority(ctdb, TIMELIMIT(), options.pnn, priority);
3528 DEBUG(DEBUG_ERR, ("Unable to thaw node %u\n", options.pnn));
3535 attach to a database
3537 static int control_attach(struct ctdb_context *ctdb, int argc, const char **argv)
3539 const char *db_name;
3540 struct ctdb_db_context *ctdb_db;
3547 ctdb_db = ctdb_attach(ctdb, db_name, false, 0);
3548 if (ctdb_db == NULL) {
3549 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
3559 static int control_setdbprio(struct ctdb_context *ctdb, int argc, const char **argv)
3561 struct ctdb_db_priority db_prio;
3568 db_prio.db_id = strtoul(argv[0], NULL, 0);
3569 db_prio.priority = strtoul(argv[1], NULL, 0);
3571 ret = ctdb_ctrl_set_db_priority(ctdb, TIMELIMIT(), options.pnn, &db_prio);
3573 DEBUG(DEBUG_ERR,("Unable to set db prio\n"));
3583 static int control_getdbprio(struct ctdb_context *ctdb, int argc, const char **argv)
3585 uint32_t db_id, priority;
3592 db_id = strtoul(argv[0], NULL, 0);
3594 ret = ctdb_ctrl_get_db_priority(ctdb, TIMELIMIT(), options.pnn, db_id, &priority);
3596 DEBUG(DEBUG_ERR,("Unable to get db prio\n"));
3600 DEBUG(DEBUG_ERR,("Priority:%u\n", priority));
3606 run an eventscript on a node
3608 static int control_eventscript(struct ctdb_context *ctdb, int argc, const char **argv)
3614 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3617 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3621 data.dptr = (unsigned char *)discard_const(argv[0]);
3622 data.dsize = strlen((char *)data.dptr) + 1;
3624 DEBUG(DEBUG_ERR, ("Running eventscripts with arguments \"%s\" on node %u\n", data.dptr, options.pnn));
3626 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_RUN_EVENTSCRIPTS,
3627 0, data, tmp_ctx, NULL, &res, NULL, &errmsg);
3628 if (ret != 0 || res != 0) {
3629 DEBUG(DEBUG_ERR,("Failed to run eventscripts - %s\n", errmsg));
3630 talloc_free(tmp_ctx);
3633 talloc_free(tmp_ctx);
3637 #define DB_VERSION 1
3638 #define MAX_DB_NAME 64
3639 struct db_file_header {
3640 unsigned long version;
3642 unsigned long persistent;
3644 const char name[MAX_DB_NAME];
3647 struct backup_data {
3648 struct ctdb_marshall_buffer *records;
3651 bool traverse_error;
3654 static int backup_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *private)
3656 struct backup_data *bd = talloc_get_type(private, struct backup_data);
3657 struct ctdb_rec_data *rec;
3659 /* add the record */
3660 rec = ctdb_marshall_record(bd->records, 0, key, NULL, data);
3662 bd->traverse_error = true;
3663 DEBUG(DEBUG_ERR,("Failed to marshall record\n"));
3666 bd->records = talloc_realloc_size(NULL, bd->records, rec->length + bd->len);
3667 if (bd->records == NULL) {
3668 DEBUG(DEBUG_ERR,("Failed to expand marshalling buffer\n"));
3669 bd->traverse_error = true;
3672 bd->records->count++;
3673 memcpy(bd->len+(uint8_t *)bd->records, rec, rec->length);
3674 bd->len += rec->length;
3682 * backup a database to a file
3684 static int control_backupdb(struct ctdb_context *ctdb, int argc, const char **argv)
3687 struct ctdb_dbid_map *dbmap=NULL;
3688 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3689 struct db_file_header dbhdr;
3690 struct ctdb_db_context *ctdb_db;
3691 struct backup_data *bd;
3694 const char *reason = NULL;
3697 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3701 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &dbmap);
3703 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
3707 for(i=0;i<dbmap->num;i++){
3710 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, tmp_ctx, &name);
3711 if(!strcmp(argv[0], name)){
3712 talloc_free(discard_const(name));
3715 talloc_free(discard_const(name));
3717 if (i == dbmap->num) {
3718 DEBUG(DEBUG_ERR,("No database with name '%s' found\n", argv[0]));
3719 talloc_free(tmp_ctx);
3723 ret = ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn,
3724 dbmap->dbs[i].dbid, tmp_ctx, &reason);
3726 DEBUG(DEBUG_ERR,("Unable to get dbhealth for database '%s'\n",
3728 talloc_free(tmp_ctx);
3732 uint32_t allow_unhealthy = 0;
3734 ctdb_ctrl_get_tunable(ctdb, TIMELIMIT(), options.pnn,
3735 "AllowUnhealthyDBRead",
3738 if (allow_unhealthy != 1) {
3739 DEBUG(DEBUG_ERR,("database '%s' is unhealthy: %s\n",
3742 DEBUG(DEBUG_ERR,("disallow backup : tunnable AllowUnhealthyDBRead = %u\n",
3744 talloc_free(tmp_ctx);
3748 DEBUG(DEBUG_WARNING,("WARNING database '%s' is unhealthy - see 'ctdb getdbstatus %s'\n",
3750 DEBUG(DEBUG_WARNING,("WARNING! allow backup of unhealthy database: "
3751 "tunnable AllowUnhealthyDBRead = %u\n",
3755 ctdb_db = ctdb_attach(ctdb, argv[0], dbmap->dbs[i].persistent, 0);
3756 if (ctdb_db == NULL) {
3757 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", argv[0]));
3758 talloc_free(tmp_ctx);
3763 ret = tdb_transaction_start(ctdb_db->ltdb->tdb);
3765 DEBUG(DEBUG_ERR,("Failed to start transaction\n"));
3766 talloc_free(tmp_ctx);
3771 bd = talloc_zero(tmp_ctx, struct backup_data);
3773 DEBUG(DEBUG_ERR,("Failed to allocate backup_data\n"));
3774 talloc_free(tmp_ctx);
3778 bd->records = talloc_zero(bd, struct ctdb_marshall_buffer);
3779 if (bd->records == NULL) {
3780 DEBUG(DEBUG_ERR,("Failed to allocate ctdb_marshall_buffer\n"));
3781 talloc_free(tmp_ctx);
3785 bd->len = offsetof(struct ctdb_marshall_buffer, data);
3786 bd->records->db_id = ctdb_db->db_id;
3787 /* traverse the database collecting all records */
3788 if (tdb_traverse_read(ctdb_db->ltdb->tdb, backup_traverse, bd) == -1 ||
3789 bd->traverse_error) {
3790 DEBUG(DEBUG_ERR,("Traverse error\n"));
3791 talloc_free(tmp_ctx);
3795 tdb_transaction_cancel(ctdb_db->ltdb->tdb);
3798 fh = open(argv[1], O_RDWR|O_CREAT, 0600);
3800 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[1]));
3801 talloc_free(tmp_ctx);
3805 dbhdr.version = DB_VERSION;
3806 dbhdr.timestamp = time(NULL);
3807 dbhdr.persistent = dbmap->dbs[i].persistent;
3808 dbhdr.size = bd->len;
3809 if (strlen(argv[0]) >= MAX_DB_NAME) {
3810 DEBUG(DEBUG_ERR,("Too long dbname\n"));
3813 strncpy(discard_const(dbhdr.name), argv[0], MAX_DB_NAME);
3814 ret = write(fh, &dbhdr, sizeof(dbhdr));
3816 DEBUG(DEBUG_ERR,("write failed: %s\n", strerror(errno)));
3819 ret = write(fh, bd->records, bd->len);
3821 DEBUG(DEBUG_ERR,("write failed: %s\n", strerror(errno)));
3830 DEBUG(DEBUG_ERR,("close failed: %s\n", strerror(errno)));
3833 talloc_free(tmp_ctx);
3838 * restore a database from a file
3840 static int control_restoredb(struct ctdb_context *ctdb, int argc, const char **argv)
3843 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3846 struct db_file_header dbhdr;
3847 struct ctdb_db_context *ctdb_db;
3848 struct ctdb_node_map *nodemap=NULL;
3849 struct ctdb_vnn_map *vnnmap=NULL;
3851 struct ctdb_control_wipe_database w;
3853 uint32_t generation;
3858 if (argc < 1 || argc > 2) {
3859 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3863 fh = open(argv[0], O_RDONLY);
3865 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[0]));
3866 talloc_free(tmp_ctx);
3870 read(fh, &dbhdr, sizeof(dbhdr));
3871 if (dbhdr.version != DB_VERSION) {
3872 DEBUG(DEBUG_ERR,("Invalid version of database dump. File is version %lu but expected version was %u\n", dbhdr.version, DB_VERSION));
3873 talloc_free(tmp_ctx);
3877 dbname = discard_const(dbhdr.name);
3879 dbname = discard_const(argv[1]);
3882 outdata.dsize = dbhdr.size;
3883 outdata.dptr = talloc_size(tmp_ctx, outdata.dsize);
3884 if (outdata.dptr == NULL) {
3885 DEBUG(DEBUG_ERR,("Failed to allocate data of size '%lu'\n", dbhdr.size));
3887 talloc_free(tmp_ctx);
3890 read(fh, outdata.dptr, outdata.dsize);
3893 tm = localtime(&dbhdr.timestamp);
3894 strftime(tbuf,sizeof(tbuf)-1,"%Y/%m/%d %H:%M:%S", tm);
3895 printf("Restoring database '%s' from backup @ %s\n",
3899 ctdb_db = ctdb_attach(ctdb, dbname, dbhdr.persistent, 0);
3900 if (ctdb_db == NULL) {
3901 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", dbname));
3902 talloc_free(tmp_ctx);
3906 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
3908 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
3909 talloc_free(tmp_ctx);
3914 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &vnnmap);
3916 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n", options.pnn));
3917 talloc_free(tmp_ctx);
3921 /* freeze all nodes */
3922 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3923 for (i=1; i<=NUM_DB_PRIORITIES; i++) {
3924 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_FREEZE,
3930 DEBUG(DEBUG_ERR, ("Unable to freeze nodes.\n"));
3931 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3932 talloc_free(tmp_ctx);
3937 generation = vnnmap->generation;
3938 data.dptr = (void *)&generation;
3939 data.dsize = sizeof(generation);
3941 /* start a cluster wide transaction */
3942 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3943 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_START,
3945 TIMELIMIT(), false, data,
3948 DEBUG(DEBUG_ERR, ("Unable to start cluster wide transactions.\n"));
3953 w.db_id = ctdb_db->db_id;
3954 w.transaction_id = generation;
3956 data.dptr = (void *)&w;
3957 data.dsize = sizeof(w);
3959 /* wipe all the remote databases. */
3960 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3961 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_WIPE_DATABASE,
3963 TIMELIMIT(), false, data,
3966 DEBUG(DEBUG_ERR, ("Unable to wipe database.\n"));
3967 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3968 talloc_free(tmp_ctx);
3972 /* push the database */
3973 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3974 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_PUSH_DB,
3976 TIMELIMIT(), false, outdata,
3979 DEBUG(DEBUG_ERR, ("Failed to push database.\n"));
3980 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3981 talloc_free(tmp_ctx);
3985 data.dptr = (void *)&ctdb_db->db_id;
3986 data.dsize = sizeof(ctdb_db->db_id);
3988 /* mark the database as healthy */
3989 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3990 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_DB_SET_HEALTHY,
3992 TIMELIMIT(), false, data,
3995 DEBUG(DEBUG_ERR, ("Failed to mark database as healthy.\n"));
3996 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3997 talloc_free(tmp_ctx);
4001 data.dptr = (void *)&generation;
4002 data.dsize = sizeof(generation);
4004 /* commit all the changes */
4005 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_COMMIT,
4007 TIMELIMIT(), false, data,
4010 DEBUG(DEBUG_ERR, ("Unable to commit databases.\n"));
4011 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4012 talloc_free(tmp_ctx);
4017 /* thaw all nodes */
4018 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4019 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_THAW,
4025 DEBUG(DEBUG_ERR, ("Unable to thaw nodes.\n"));
4026 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4027 talloc_free(tmp_ctx);
4032 talloc_free(tmp_ctx);
4037 * dump a database backup from a file
4039 static int control_dumpdbbackup(struct ctdb_context *ctdb, int argc, const char **argv)
4041 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
4043 struct db_file_header dbhdr;
4047 struct ctdb_rec_data *rec = NULL;
4048 struct ctdb_marshall_buffer *m;
4051 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
4055 fh = open(argv[0], O_RDONLY);
4057 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[0]));
4058 talloc_free(tmp_ctx);
4062 read(fh, &dbhdr, sizeof(dbhdr));
4063 if (dbhdr.version != DB_VERSION) {
4064 DEBUG(DEBUG_ERR,("Invalid version of database dump. File is version %lu but expected version was %u\n", dbhdr.version, DB_VERSION));
4065 talloc_free(tmp_ctx);
4069 outdata.dsize = dbhdr.size;
4070 outdata.dptr = talloc_size(tmp_ctx, outdata.dsize);
4071 if (outdata.dptr == NULL) {
4072 DEBUG(DEBUG_ERR,("Failed to allocate data of size '%lu'\n", dbhdr.size));
4074 talloc_free(tmp_ctx);
4077 read(fh, outdata.dptr, outdata.dsize);
4079 m = (struct ctdb_marshall_buffer *)outdata.dptr;
4081 tm = localtime(&dbhdr.timestamp);
4082 strftime(tbuf,sizeof(tbuf)-1,"%Y/%m/%d %H:%M:%S", tm);
4083 printf("Backup of database name:'%s' dbid:0x%x08x from @ %s\n",
4084 dbhdr.name, m->db_id, tbuf);
4086 for (i=0; i < m->count; i++) {
4090 /* we do not want the header splitted, so we pass NULL*/
4091 rec = ctdb_marshall_loop_next(m, rec, &reqid,
4094 ctdb_dumpdb_record(ctdb, key, data, stdout);
4097 printf("Dumped %d records\n", i);
4098 talloc_free(tmp_ctx);
4103 * wipe a database from a file
4105 static int control_wipedb(struct ctdb_context *ctdb, int argc,
4109 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
4111 struct ctdb_db_context *ctdb_db;
4112 struct ctdb_node_map *nodemap = NULL;
4113 struct ctdb_vnn_map *vnnmap = NULL;
4115 struct ctdb_control_wipe_database w;
4117 uint32_t generation;
4118 struct ctdb_dbid_map *dbmap = NULL;
4121 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
4125 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx,
4128 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n",
4133 for(i=0;i<dbmap->num;i++){
4136 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn,
4137 dbmap->dbs[i].dbid, tmp_ctx, &name);
4138 if(!strcmp(argv[0], name)){
4139 talloc_free(discard_const(name));
4142 talloc_free(discard_const(name));
4144 if (i == dbmap->num) {
4145 DEBUG(DEBUG_ERR, ("No database with name '%s' found\n",
4147 talloc_free(tmp_ctx);
4151 ctdb_db = ctdb_attach(ctdb, argv[0], dbmap->dbs[i].persistent, 0);
4152 if (ctdb_db == NULL) {
4153 DEBUG(DEBUG_ERR, ("Unable to attach to database '%s'\n",
4155 talloc_free(tmp_ctx);
4159 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb,
4162 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n",
4164 talloc_free(tmp_ctx);
4168 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx,
4171 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n",
4173 talloc_free(tmp_ctx);
4177 /* freeze all nodes */
4178 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4179 for (i=1; i<=NUM_DB_PRIORITIES; i++) {
4180 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_FREEZE,
4187 DEBUG(DEBUG_ERR, ("Unable to freeze nodes.\n"));
4188 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn,
4189 CTDB_RECOVERY_ACTIVE);
4190 talloc_free(tmp_ctx);
4195 generation = vnnmap->generation;
4196 data.dptr = (void *)&generation;
4197 data.dsize = sizeof(generation);
4199 /* start a cluster wide transaction */
4200 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4201 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_START,
4203 TIMELIMIT(), false, data,
4207 DEBUG(DEBUG_ERR, ("Unable to start cluster wide "
4208 "transactions.\n"));
4212 w.db_id = ctdb_db->db_id;
4213 w.transaction_id = generation;
4215 data.dptr = (void *)&w;
4216 data.dsize = sizeof(w);
4218 /* wipe all the remote databases. */
4219 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4220 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_WIPE_DATABASE,
4222 TIMELIMIT(), false, data,
4225 DEBUG(DEBUG_ERR, ("Unable to wipe database.\n"));
4226 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4227 talloc_free(tmp_ctx);
4231 data.dptr = (void *)&ctdb_db->db_id;
4232 data.dsize = sizeof(ctdb_db->db_id);
4234 /* mark the database as healthy */
4235 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4236 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_DB_SET_HEALTHY,
4238 TIMELIMIT(), false, data,
4241 DEBUG(DEBUG_ERR, ("Failed to mark database as healthy.\n"));
4242 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4243 talloc_free(tmp_ctx);
4247 data.dptr = (void *)&generation;
4248 data.dsize = sizeof(generation);
4250 /* commit all the changes */
4251 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_COMMIT,
4253 TIMELIMIT(), false, data,
4256 DEBUG(DEBUG_ERR, ("Unable to commit databases.\n"));
4257 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4258 talloc_free(tmp_ctx);
4262 /* thaw all nodes */
4263 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4264 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_THAW,
4270 DEBUG(DEBUG_ERR, ("Unable to thaw nodes.\n"));
4271 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4272 talloc_free(tmp_ctx);
4276 talloc_free(tmp_ctx);
4281 * set flags of a node in the nodemap
4283 static int control_setflags(struct ctdb_context *ctdb, int argc, const char **argv)
4290 struct ctdb_node_flag_change c;
4297 if (sscanf(argv[0], "%d", &node) != 1) {
4298 DEBUG(DEBUG_ERR, ("Badly formed node\n"));
4302 if (sscanf(argv[1], "0x%x", &flags) != 1) {
4303 DEBUG(DEBUG_ERR, ("Badly formed flags\n"));
4310 c.new_flags = flags;
4312 data.dsize = sizeof(c);
4313 data.dptr = (unsigned char *)&c;
4315 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_MODIFY_FLAGS, 0,
4316 data, NULL, NULL, &status, NULL, NULL);
4317 if (ret != 0 || status != 0) {
4318 DEBUG(DEBUG_ERR,("Failed to modify flags\n"));
4327 static int control_dumpmemory(struct ctdb_context *ctdb, int argc, const char **argv)
4333 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
4334 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_DUMP_MEMORY,
4335 0, tdb_null, tmp_ctx, &data, &res, NULL, &errmsg);
4336 if (ret != 0 || res != 0) {
4337 DEBUG(DEBUG_ERR,("Failed to dump memory - %s\n", errmsg));
4338 talloc_free(tmp_ctx);
4341 write(1, data.dptr, data.dsize);
4342 talloc_free(tmp_ctx);
4347 handler for memory dumps
4349 static void mem_dump_handler(struct ctdb_context *ctdb, uint64_t srvid,
4350 TDB_DATA data, void *private_data)
4352 write(1, data.dptr, data.dsize);
4357 dump memory usage on the recovery daemon
4359 static int control_rddumpmemory(struct ctdb_context *ctdb, int argc, const char **argv)
4363 struct rd_memdump_reply rd;
4365 rd.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
4367 DEBUG(DEBUG_ERR, ("Failed to get pnn of local node\n"));
4370 rd.srvid = getpid();
4372 /* register a message port for receiveing the reply so that we
4373 can receive the reply
4375 ctdb_client_set_message_handler(ctdb, rd.srvid, mem_dump_handler, NULL);
4378 data.dptr = (uint8_t *)&rd;
4379 data.dsize = sizeof(rd);
4381 ret = ctdb_client_send_message(ctdb, options.pnn, CTDB_SRVID_MEM_DUMP, data);
4383 DEBUG(DEBUG_ERR,("Failed to send memdump request message to %u\n", options.pnn));
4387 /* this loop will terminate when we have received the reply */
4389 event_loop_once(ctdb->ev);
4396 send a message to a srvid
4398 static int control_msgsend(struct ctdb_context *ctdb, int argc, const char **argv)
4400 unsigned long srvid;
4408 srvid = strtoul(argv[0], NULL, 0);
4410 data.dptr = (uint8_t *)discard_const(argv[1]);
4411 data.dsize= strlen(argv[1]);
4413 ret = ctdb_client_send_message(ctdb, CTDB_BROADCAST_CONNECTED, srvid, data);
4415 DEBUG(DEBUG_ERR,("Failed to send memdump request message to %u\n", options.pnn));
4423 handler for msglisten
4425 static void msglisten_handler(struct ctdb_context *ctdb, uint64_t srvid,
4426 TDB_DATA data, void *private_data)
4430 printf("Message received: ");
4431 for (i=0;i<data.dsize;i++) {
4432 printf("%c", data.dptr[i]);
4438 listen for messages on a messageport
4440 static int control_msglisten(struct ctdb_context *ctdb, int argc, const char **argv)
4446 /* register a message port and listen for messages
4448 ctdb_client_set_message_handler(ctdb, srvid, msglisten_handler, NULL);
4449 printf("Listening for messages on srvid:%d\n", (int)srvid);
4452 event_loop_once(ctdb->ev);
4459 list all nodes in the cluster
4460 if the daemon is running, we read the data from the daemon.
4461 if the daemon is not running we parse the nodes file directly
4463 static int control_listnodes(struct ctdb_context *ctdb, int argc, const char **argv)
4466 struct ctdb_node_map *nodemap=NULL;
4469 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
4471 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
4475 for(i=0;i<nodemap->num;i++){
4476 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
4479 if (options.machinereadable){
4480 printf(":%d:%s:\n", nodemap->nodes[i].pnn, ctdb_addr_to_str(&nodemap->nodes[i].addr));
4482 printf("%s\n", ctdb_addr_to_str(&nodemap->nodes[i].addr));
4486 TALLOC_CTX *mem_ctx = talloc_new(NULL);
4487 struct pnn_node *pnn_nodes;
4488 struct pnn_node *pnn_node;
4490 pnn_nodes = read_nodes_file(mem_ctx);
4491 if (pnn_nodes == NULL) {
4492 DEBUG(DEBUG_ERR,("Failed to read nodes file\n"));
4493 talloc_free(mem_ctx);
4497 for(pnn_node=pnn_nodes;pnn_node;pnn_node=pnn_node->next) {
4498 ctdb_sock_addr addr;
4500 if (parse_ip(pnn_node->addr, NULL, 63999, &addr) == 0) {
4501 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s' in nodes file\n", pnn_node->addr));
4502 talloc_free(mem_ctx);
4506 if (options.machinereadable){
4507 printf(":%d:%s:\n", pnn_node->pnn, pnn_node->addr);
4509 printf("%s\n", pnn_node->addr);
4512 talloc_free(mem_ctx);
4519 reload the nodes file on the local node
4521 static int control_reload_nodes_file(struct ctdb_context *ctdb, int argc, const char **argv)
4525 struct ctdb_node_map *nodemap=NULL;
4527 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
4529 DEBUG(DEBUG_ERR, ("Failed to read pnn of local node\n"));
4533 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
4535 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
4539 /* reload the nodes file on all remote nodes */
4540 for (i=0;i<nodemap->num;i++) {
4541 if (nodemap->nodes[i].pnn == mypnn) {
4544 DEBUG(DEBUG_NOTICE, ("Reloading nodes file on node %u\n", nodemap->nodes[i].pnn));
4545 ret = ctdb_ctrl_reload_nodes_file(ctdb, TIMELIMIT(),
4546 nodemap->nodes[i].pnn);
4548 DEBUG(DEBUG_ERR, ("ERROR: Failed to reload nodes file on node %u. You MUST fix that node manually!\n", nodemap->nodes[i].pnn));
4552 /* reload the nodes file on the local node */
4553 DEBUG(DEBUG_NOTICE, ("Reloading nodes file on node %u\n", mypnn));
4554 ret = ctdb_ctrl_reload_nodes_file(ctdb, TIMELIMIT(), mypnn);
4556 DEBUG(DEBUG_ERR, ("ERROR: Failed to reload nodes file on node %u. You MUST fix that node manually!\n", mypnn));
4559 /* initiate a recovery */
4560 control_recover(ctdb, argc, argv);
4566 static const struct {
4568 int (*fn)(struct ctdb_context *, int, const char **);
4570 bool without_daemon; /* can be run without daemon running ? */
4573 } ctdb_commands[] = {
4575 { "version", control_version, true, false, "show version of ctdb" },
4577 { "status", control_status, true, false, "show node status" },
4578 { "uptime", control_uptime, true, false, "show node uptime" },
4579 { "ping", control_ping, true, false, "ping all nodes" },
4580 { "getvar", control_getvar, true, false, "get a tunable variable", "<name>"},
4581 { "setvar", control_setvar, true, false, "set a tunable variable", "<name> <value>"},
4582 { "listvars", control_listvars, true, false, "list tunable variables"},
4583 { "statistics", control_statistics, false, false, "show statistics" },
4584 { "statisticsreset", control_statistics_reset, true, false, "reset statistics"},
4585 { "ip", control_ip, false, false, "show which public ip's that ctdb manages" },
4586 { "ipinfo", control_ipinfo, true, false, "show details about a public ip that ctdb manages", "<ip>" },
4587 { "ifaces", control_ifaces, true, false, "show which interfaces that ctdb manages" },
4588 { "setifacelink", control_setifacelink, true, false, "set interface link status", "<iface> <status>" },
4589 { "process-exists", control_process_exists, true, false, "check if a process exists on a node", "<pid>"},
4590 { "getdbmap", control_getdbmap, true, false, "show the database map" },
4591 { "getdbstatus", control_getdbstatus, true, false, "show the status of a database", "<dbname>" },
4592 { "catdb", control_catdb, true, false, "dump a database" , "<dbname>"},
4593 { "getmonmode", control_getmonmode, true, false, "show monitoring mode" },
4594 { "getcapabilities", control_getcapabilities, true, false, "show node capabilities" },
4595 { "pnn", control_pnn, true, false, "show the pnn of the currnet node" },
4596 { "lvs", control_lvs, true, false, "show lvs configuration" },
4597 { "lvsmaster", control_lvsmaster, true, false, "show which node is the lvs master" },
4598 { "disablemonitor", control_disable_monmode,true, false, "set monitoring mode to DISABLE" },
4599 { "enablemonitor", control_enable_monmode, true, false, "set monitoring mode to ACTIVE" },
4600 { "setdebug", control_setdebug, true, false, "set debug level", "<EMERG|ALERT|CRIT|ERR|WARNING|NOTICE|INFO|DEBUG>" },
4601 { "getdebug", control_getdebug, true, false, "get debug level" },
4602 { "getlog", control_getlog, true, false, "get the log data from the in memory ringbuffer", "<level>" },
4603 { "clearlog", control_clearlog, true, false, "clear the log data from the in memory ringbuffer" },
4604 { "attach", control_attach, true, false, "attach to a database", "<dbname>" },
4605 { "dumpmemory", control_dumpmemory, true, false, "dump memory map to stdout" },
4606 { "rddumpmemory", control_rddumpmemory, true, false, "dump memory map from the recovery daemon to stdout" },
4607 { "getpid", control_getpid, true, false, "get ctdbd process ID" },
4608 { "disable", control_disable, true, false, "disable a nodes public IP" },
4609 { "enable", control_enable, true, false, "enable a nodes public IP" },
4610 { "stop", control_stop, true, false, "stop a node" },
4611 { "continue", control_continue, true, false, "re-start a stopped node" },
4612 { "ban", control_ban, true, false, "ban a node from the cluster", "<bantime|0>"},
4613 { "unban", control_unban, true, false, "unban a node" },
4614 { "showban", control_showban, true, false, "show ban information"},
4615 { "shutdown", control_shutdown, true, false, "shutdown ctdbd" },
4616 { "recover", control_recover, true, false, "force recovery" },
4617 { "sync", control_ipreallocate, true, false, "wait until ctdbd has synced all state changes" },
4618 { "ipreallocate", control_ipreallocate, true, false, "force the recovery daemon to perform a ip reallocation procedure" },
4619 { "thaw", control_thaw, true, false, "thaw databases", "[priority:1-3]" },
4620 { "isnotrecmaster", control_isnotrecmaster, false, false, "check if the local node is recmaster or not" },
4621 { "killtcp", kill_tcp, false, false, "kill a tcp connection.", "<srcip:port> <dstip:port>" },
4622 { "gratiousarp", control_gratious_arp, false, false, "send a gratious arp", "<ip> <interface>" },
4623 { "tickle", tickle_tcp, false, false, "send a tcp tickle ack", "<srcip:port> <dstip:port>" },
4624 { "gettickles", control_get_tickles, false, false, "get the list of tickles registered for this ip", "<ip> [<port>]" },
4625 { "addtickle", control_add_tickle, false, false, "add a tickle for this ip", "<ip>:<port> <ip>:<port>" },
4627 { "deltickle", control_del_tickle, false, false, "delete a tickle from this ip", "<ip>:<port> <ip>:<port>" },
4629 { "regsrvid", regsrvid, false, false, "register a server id", "<pnn> <type> <id>" },
4630 { "unregsrvid", unregsrvid, false, false, "unregister a server id", "<pnn> <type> <id>" },
4631 { "chksrvid", chksrvid, false, false, "check if a server id exists", "<pnn> <type> <id>" },
4632 { "getsrvids", getsrvids, false, false, "get a list of all server ids"},
4633 { "vacuum", ctdb_vacuum, false, false, "vacuum the databases of empty records", "[max_records]"},
4634 { "repack", ctdb_repack, false, false, "repack all databases", "[max_freelist]"},
4635 { "listnodes", control_listnodes, false, true, "list all nodes in the cluster"},
4636 { "reloadnodes", control_reload_nodes_file, false, false, "reload the nodes file and restart the transport on all nodes"},
4637 { "moveip", control_moveip, false, false, "move/failover an ip address to another node", "<ip> <node>"},
4638 { "addip", control_addip, true, false, "add a ip address to a node", "<ip/mask> <iface>"},
4639 { "delip", control_delip, false, false, "delete an ip address from a node", "<ip>"},
4640 { "eventscript", control_eventscript, true, false, "run the eventscript with the given parameters on a node", "<arguments>"},
4641 { "backupdb", control_backupdb, false, false, "backup the database into a file.", "<database> <file>"},
4642 { "restoredb", control_restoredb, false, false, "restore the database from a file.", "<file> [dbname]"},
4643 { "dumpdbbackup", control_dumpdbbackup, false, true, "dump database backup from a file.", "<file>"},
4644 { "wipedb", control_wipedb, false, false, "wipe the contents of a database.", "<dbname>"},
4645 { "recmaster", control_recmaster, false, false, "show the pnn for the recovery master."},
4646 { "setflags", control_setflags, false, false, "set flags for a node in the nodemap.", "<node> <flags>"},
4647 { "scriptstatus", control_scriptstatus, false, false, "show the status of the monitoring scripts (or all scripts)", "[all]"},
4648 { "enablescript", control_enablescript, false, false, "enable an eventscript", "<script>"},
4649 { "disablescript", control_disablescript, false, false, "disable an eventscript", "<script>"},
4650 { "natgwlist", control_natgwlist, false, false, "show the nodes belonging to this natgw configuration"},
4651 { "xpnn", control_xpnn, true, true, "find the pnn of the local node without talking to the daemon (unreliable)" },
4652 { "getreclock", control_getreclock, false, false, "Show the reclock file of a node"},
4653 { "setreclock", control_setreclock, false, false, "Set/clear the reclock file of a node", "[filename]"},
4654 { "setnatgwstate", control_setnatgwstate, false, false, "Set NATGW state to on/off", "{on|off}"},
4655 { "setlmasterrole", control_setlmasterrole, false, false, "Set LMASTER role to on/off", "{on|off}"},
4656 { "setrecmasterrole", control_setrecmasterrole, false, false, "Set RECMASTER role to on/off", "{on|off}"},
4657 { "setdbprio", control_setdbprio, false, false, "Set DB priority", "<dbid> <prio:1-3>"},
4658 { "getdbprio", control_getdbprio, false, false, "Get DB priority", "<dbid>"},
4659 { "msglisten", control_msglisten, false, false, "Listen on a srvid port for messages", "<msg srvid>"},
4660 { "msgsend", control_msgsend, false, false, "Send a message to srvid", "<srvid> <message>"},
4661 { "sync", control_ipreallocate, true, false, "wait until ctdbd has synced all state changes" },
4662 { "pfetch", control_pfetch, true, false, "fetch a record from a persistent database", "<db> <key>" },
4663 { "pstore", control_pstore, true, false, "write a record to a persistent database", "<db> <key> <file containing record>" },
4669 static void usage(void)
4673 "Usage: ctdb [options] <control>\n" \
4675 " -n <node> choose node number, or 'all' (defaults to local node)\n"
4676 " -Y generate machinereadable output\n"
4677 " -v generate verbose output\n"
4678 " -t <timelimit> set timelimit for control in seconds (default %u)\n", options.timelimit);
4679 printf("Controls:\n");
4680 for (i=0;i<ARRAY_SIZE(ctdb_commands);i++) {
4681 printf(" %-15s %-27s %s\n",
4682 ctdb_commands[i].name,
4683 ctdb_commands[i].args?ctdb_commands[i].args:"",
4684 ctdb_commands[i].msg);
4690 static void ctdb_alarm(int sig)
4692 printf("Maximum runtime exceeded - exiting\n");
4699 int main(int argc, const char *argv[])
4701 struct ctdb_context *ctdb;
4702 char *nodestring = NULL;
4703 struct poptOption popt_options[] = {
4706 { "timelimit", 't', POPT_ARG_INT, &options.timelimit, 0, "timelimit", "integer" },
4707 { "node", 'n', POPT_ARG_STRING, &nodestring, 0, "node", "integer|all" },
4708 { "machinereadable", 'Y', POPT_ARG_NONE, &options.machinereadable, 0, "enable machinereadable output", NULL },
4709 { "verbose", 'v', POPT_ARG_NONE, &options.verbose, 0, "enable verbose output", NULL },
4710 { "maxruntime", 'T', POPT_ARG_INT, &options.maxruntime, 0, "die if runtime exceeds this limit (in seconds)", "integer" },
4714 const char **extra_argv;
4718 struct event_context *ev;
4719 const char *control;
4723 /* set some defaults */
4724 options.maxruntime = 0;
4725 options.timelimit = 3;
4726 options.pnn = CTDB_CURRENT_NODE;
4728 pc = poptGetContext(argv[0], argc, argv, popt_options, POPT_CONTEXT_KEEP_FIRST);
4730 while ((opt = poptGetNextOpt(pc)) != -1) {
4733 DEBUG(DEBUG_ERR, ("Invalid option %s: %s\n",
4734 poptBadOption(pc, 0), poptStrerror(opt)));
4739 /* setup the remaining options for the main program to use */
4740 extra_argv = poptGetArgs(pc);
4743 while (extra_argv[extra_argc]) extra_argc++;
4746 if (extra_argc < 1) {
4750 if (options.maxruntime == 0) {
4751 const char *ctdb_timeout;
4752 ctdb_timeout = getenv("CTDB_TIMEOUT");
4753 if (ctdb_timeout != NULL) {
4754 options.maxruntime = strtoul(ctdb_timeout, NULL, 0);
4756 /* default timeout is 120 seconds */
4757 options.maxruntime = 120;
4761 signal(SIGALRM, ctdb_alarm);
4762 alarm(options.maxruntime);
4764 /* setup the node number to contact */
4765 if (nodestring != NULL) {
4766 if (strcmp(nodestring, "all") == 0) {
4767 options.pnn = CTDB_BROADCAST_ALL;
4769 options.pnn = strtoul(nodestring, NULL, 0);
4773 control = extra_argv[0];
4775 ev = event_context_init(NULL);
4777 DEBUG(DEBUG_ERR, ("Failed to initialize event system\n"));
4780 tevent_loop_allow_nesting(ev);
4782 for (i=0;i<ARRAY_SIZE(ctdb_commands);i++) {
4783 if (strcmp(control, ctdb_commands[i].name) == 0) {
4786 if (ctdb_commands[i].without_daemon == true) {
4790 /* initialise ctdb */
4791 ctdb = ctdb_cmdline_client(ev);
4793 if (ctdb_commands[i].without_daemon == false) {
4794 const char *socket_name;
4797 DEBUG(DEBUG_ERR, ("Failed to init ctdb\n"));
4801 /* initialize a libctdb connection as well */
4802 socket_name = ctdb_get_socketname(ctdb);
4803 ctdb_connection = ctdb_connect(socket_name,
4804 ctdb_log_file, stderr);
4805 if (ctdb_connection == NULL) {
4806 fprintf(stderr, "Failed to connect to daemon from libctdb\n");
4810 /* verify the node exists */
4813 if (options.pnn == CTDB_CURRENT_NODE) {
4815 pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
4823 if (ctdb_commands[i].auto_all &&
4824 options.pnn == CTDB_BROADCAST_ALL) {
4829 nodes = ctdb_get_connected_nodes(ctdb, TIMELIMIT(), ctdb, &num_nodes);
4830 CTDB_NO_MEMORY(ctdb, nodes);
4832 for (j=0;j<num_nodes;j++) {
4833 options.pnn = nodes[j];
4834 ret |= ctdb_commands[i].fn(ctdb, extra_argc-1, extra_argv+1);
4838 ret = ctdb_commands[i].fn(ctdb, extra_argc-1, extra_argv+1);
4844 if (i == ARRAY_SIZE(ctdb_commands)) {
4845 DEBUG(DEBUG_ERR, ("Unknown control '%s'\n", control));