4 Copyright (C) Andrew Tridgell 2007
5 Copyright (C) Ronnie Sahlberg 2007
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, see <http://www.gnu.org/licenses/>.
22 #include "lib/events/events.h"
23 #include "system/time.h"
24 #include "system/filesys.h"
25 #include "system/network.h"
26 #include "system/locale.h"
29 #include "../include/ctdb.h"
30 #include "../include/ctdb_private.h"
31 #include "../common/rb_tree.h"
34 #define ERR_TIMEOUT 20 /* timed out trying to reach node */
35 #define ERR_NONODE 21 /* node does not exist */
36 #define ERR_DISNODE 22 /* node is disconnected */
38 static void usage(void);
47 #define TIMELIMIT() timeval_current_ofs(options.timelimit, 0)
50 static int control_version(struct ctdb_context *ctdb, int argc, const char **argv)
53 #define XSTR(x) STR(x)
54 printf("CTDB version: %s\n", XSTR(CTDB_VERS));
61 verify that a node exists and is reachable
63 static void verify_node(struct ctdb_context *ctdb)
66 struct ctdb_node_map *nodemap=NULL;
68 if (options.pnn == CTDB_CURRENT_NODE) {
71 if (options.pnn == CTDB_BROADCAST_ALL) {
75 /* verify the node exists */
76 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
77 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
80 if (options.pnn >= nodemap->num) {
81 DEBUG(DEBUG_ERR, ("Node %u does not exist\n", options.pnn));
84 if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_DELETED) {
85 DEBUG(DEBUG_ERR, ("Node %u is DELETED\n", options.pnn));
88 if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_DISCONNECTED) {
89 DEBUG(DEBUG_ERR, ("Node %u is DISCONNECTED\n", options.pnn));
93 /* verify we can access the node */
94 ret = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
96 DEBUG(DEBUG_ERR,("Can not ban node. Node is not operational.\n"));
102 check if a database exists
104 static int db_exists(struct ctdb_context *ctdb, const char *db_name)
107 struct ctdb_dbid_map *dbmap=NULL;
109 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
111 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
115 for(i=0;i<dbmap->num;i++){
118 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
119 if (!strcmp(name, db_name)) {
128 see if a process exists
130 static int control_process_exists(struct ctdb_context *ctdb, int argc, const char **argv)
138 if (sscanf(argv[0], "%u:%u", &pnn, &pid) != 2) {
139 DEBUG(DEBUG_ERR, ("Badly formed pnn:pid\n"));
143 ret = ctdb_ctrl_process_exists(ctdb, pnn, pid);
145 printf("%u:%u exists\n", pnn, pid);
147 printf("%u:%u does not exist\n", pnn, pid);
153 display statistics structure
155 static void show_statistics(struct ctdb_statistics *s)
157 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
159 const char *prefix=NULL;
165 #define STATISTICS_FIELD(n) { #n, offsetof(struct ctdb_statistics, n) }
166 STATISTICS_FIELD(num_clients),
167 STATISTICS_FIELD(frozen),
168 STATISTICS_FIELD(recovering),
169 STATISTICS_FIELD(client_packets_sent),
170 STATISTICS_FIELD(client_packets_recv),
171 STATISTICS_FIELD(node_packets_sent),
172 STATISTICS_FIELD(node_packets_recv),
173 STATISTICS_FIELD(keepalive_packets_sent),
174 STATISTICS_FIELD(keepalive_packets_recv),
175 STATISTICS_FIELD(node.req_call),
176 STATISTICS_FIELD(node.reply_call),
177 STATISTICS_FIELD(node.req_dmaster),
178 STATISTICS_FIELD(node.reply_dmaster),
179 STATISTICS_FIELD(node.reply_error),
180 STATISTICS_FIELD(node.req_message),
181 STATISTICS_FIELD(node.req_control),
182 STATISTICS_FIELD(node.reply_control),
183 STATISTICS_FIELD(client.req_call),
184 STATISTICS_FIELD(client.req_message),
185 STATISTICS_FIELD(client.req_control),
186 STATISTICS_FIELD(timeouts.call),
187 STATISTICS_FIELD(timeouts.control),
188 STATISTICS_FIELD(timeouts.traverse),
189 STATISTICS_FIELD(total_calls),
190 STATISTICS_FIELD(pending_calls),
191 STATISTICS_FIELD(lockwait_calls),
192 STATISTICS_FIELD(pending_lockwait_calls),
193 STATISTICS_FIELD(childwrite_calls),
194 STATISTICS_FIELD(pending_childwrite_calls),
195 STATISTICS_FIELD(memory_used),
196 STATISTICS_FIELD(max_hop_count),
198 printf("CTDB version %u\n", CTDB_VERSION);
199 for (i=0;i<ARRAY_SIZE(fields);i++) {
200 if (strchr(fields[i].name, '.')) {
201 preflen = strcspn(fields[i].name, ".")+1;
202 if (!prefix || strncmp(prefix, fields[i].name, preflen) != 0) {
203 prefix = fields[i].name;
204 printf(" %*.*s\n", preflen-1, preflen-1, fields[i].name);
209 printf(" %*s%-22s%*s%10u\n",
211 fields[i].name+preflen,
213 *(uint32_t *)(fields[i].offset+(uint8_t *)s));
215 printf(" %-30s %.6f sec\n", "max_reclock_ctdbd", s->reclock.ctdbd);
216 printf(" %-30s %.6f sec\n", "max_reclock_recd", s->reclock.recd);
218 printf(" %-30s %.6f sec\n", "max_call_latency", s->max_call_latency);
219 printf(" %-30s %.6f sec\n", "max_lockwait_latency", s->max_lockwait_latency);
220 printf(" %-30s %.6f sec\n", "max_childwrite_latency", s->max_childwrite_latency);
221 talloc_free(tmp_ctx);
225 display remote ctdb statistics combined from all nodes
227 static int control_statistics_all(struct ctdb_context *ctdb)
230 struct ctdb_statistics statistics;
234 nodes = ctdb_get_connected_nodes(ctdb, TIMELIMIT(), ctdb, &num_nodes);
235 CTDB_NO_MEMORY(ctdb, nodes);
237 ZERO_STRUCT(statistics);
239 for (i=0;i<num_nodes;i++) {
240 struct ctdb_statistics s1;
242 uint32_t *v1 = (uint32_t *)&s1;
243 uint32_t *v2 = (uint32_t *)&statistics;
245 offsetof(struct ctdb_statistics, __last_counter) / sizeof(uint32_t);
246 ret = ctdb_ctrl_statistics(ctdb, nodes[i], &s1);
248 DEBUG(DEBUG_ERR, ("Unable to get statistics from node %u\n", nodes[i]));
251 for (j=0;j<num_ints;j++) {
254 statistics.max_hop_count =
255 MAX(statistics.max_hop_count, s1.max_hop_count);
256 statistics.max_call_latency =
257 MAX(statistics.max_call_latency, s1.max_call_latency);
258 statistics.max_lockwait_latency =
259 MAX(statistics.max_lockwait_latency, s1.max_lockwait_latency);
262 printf("Gathered statistics for %u nodes\n", num_nodes);
263 show_statistics(&statistics);
268 display remote ctdb statistics
270 static int control_statistics(struct ctdb_context *ctdb, int argc, const char **argv)
273 struct ctdb_statistics statistics;
275 if (options.pnn == CTDB_BROADCAST_ALL) {
276 return control_statistics_all(ctdb);
279 ret = ctdb_ctrl_statistics(ctdb, options.pnn, &statistics);
281 DEBUG(DEBUG_ERR, ("Unable to get statistics from node %u\n", options.pnn));
284 show_statistics(&statistics);
290 reset remote ctdb statistics
292 static int control_statistics_reset(struct ctdb_context *ctdb, int argc, const char **argv)
296 ret = ctdb_statistics_reset(ctdb, options.pnn);
298 DEBUG(DEBUG_ERR, ("Unable to reset statistics on node %u\n", options.pnn));
306 display uptime of remote node
308 static int control_uptime(struct ctdb_context *ctdb, int argc, const char **argv)
311 struct ctdb_uptime *uptime = NULL;
312 int tmp, days, hours, minutes, seconds;
314 ret = ctdb_ctrl_uptime(ctdb, ctdb, TIMELIMIT(), options.pnn, &uptime);
316 DEBUG(DEBUG_ERR, ("Unable to get uptime from node %u\n", options.pnn));
320 if (options.machinereadable){
321 printf(":Current Node Time:Ctdb Start Time:Last Recovery/Failover Time:Last Recovery/IPFailover Duration:\n");
322 printf(":%u:%u:%u:%lf\n",
323 (unsigned int)uptime->current_time.tv_sec,
324 (unsigned int)uptime->ctdbd_start_time.tv_sec,
325 (unsigned int)uptime->last_recovery_finished.tv_sec,
326 timeval_delta(&uptime->last_recovery_finished,
327 &uptime->last_recovery_started)
332 printf("Current time of node : %s", ctime(&uptime->current_time.tv_sec));
334 tmp = uptime->current_time.tv_sec - uptime->ctdbd_start_time.tv_sec;
342 printf("Ctdbd start time : (%03d %02d:%02d:%02d) %s", days, hours, minutes, seconds, ctime(&uptime->ctdbd_start_time.tv_sec));
344 tmp = uptime->current_time.tv_sec - uptime->last_recovery_finished.tv_sec;
352 printf("Time of last recovery/failover: (%03d %02d:%02d:%02d) %s", days, hours, minutes, seconds, ctime(&uptime->last_recovery_finished.tv_sec));
354 printf("Duration of last recovery/failover: %lf seconds\n",
355 timeval_delta(&uptime->last_recovery_finished,
356 &uptime->last_recovery_started));
362 show the PNN of the current node
364 static int control_pnn(struct ctdb_context *ctdb, int argc, const char **argv)
368 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
370 DEBUG(DEBUG_ERR, ("Unable to get pnn from local node."));
374 printf("PNN:%d\n", mypnn);
380 struct pnn_node *next;
385 static struct pnn_node *read_nodes_file(TALLOC_CTX *mem_ctx)
387 const char *nodes_list;
391 struct pnn_node *pnn_nodes = NULL;
392 struct pnn_node *pnn_node;
393 struct pnn_node *tmp_node;
395 /* read the nodes file */
396 nodes_list = getenv("CTDB_NODES");
397 if (nodes_list == NULL) {
398 nodes_list = "/etc/ctdb/nodes";
400 lines = file_lines_load(nodes_list, &nlines, mem_ctx);
404 while (nlines > 0 && strcmp(lines[nlines-1], "") == 0) {
407 for (i=0, pnn=0; i<nlines; i++) {
411 /* strip leading spaces */
412 while((*node == ' ') || (*node == '\t')) {
419 if (strcmp(node, "") == 0) {
422 pnn_node = talloc(mem_ctx, struct pnn_node);
423 pnn_node->pnn = pnn++;
424 pnn_node->addr = talloc_strdup(pnn_node, node);
425 pnn_node->next = pnn_nodes;
426 pnn_nodes = pnn_node;
429 /* swap them around so we return them in incrementing order */
430 pnn_node = pnn_nodes;
434 pnn_node = pnn_node->next;
436 tmp_node->next = pnn_nodes;
437 pnn_nodes = tmp_node;
444 show the PNN of the current node
445 discover the pnn by loading the nodes file and try to bind to all
446 addresses one at a time until the ip address is found.
448 static int control_xpnn(struct ctdb_context *ctdb, int argc, const char **argv)
450 TALLOC_CTX *mem_ctx = talloc_new(NULL);
451 struct pnn_node *pnn_nodes;
452 struct pnn_node *pnn_node;
454 pnn_nodes = read_nodes_file(mem_ctx);
455 if (pnn_nodes == NULL) {
456 DEBUG(DEBUG_ERR,("Failed to read nodes file\n"));
457 talloc_free(mem_ctx);
461 for(pnn_node=pnn_nodes;pnn_node;pnn_node=pnn_node->next) {
464 if (parse_ip(pnn_node->addr, NULL, 63999, &addr) == 0) {
465 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s' in nodes file\n", pnn_node->addr));
466 talloc_free(mem_ctx);
470 if (ctdb_sys_have_ip(&addr)) {
471 printf("PNN:%d\n", pnn_node->pnn);
472 talloc_free(mem_ctx);
477 printf("Failed to detect which PNN this node is\n");
478 talloc_free(mem_ctx);
483 display remote ctdb status
485 static int control_status(struct ctdb_context *ctdb, int argc, const char **argv)
488 struct ctdb_vnn_map *vnnmap=NULL;
489 struct ctdb_node_map *nodemap=NULL;
490 uint32_t recmode, recmaster;
493 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
498 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
500 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
504 if(options.machinereadable){
505 printf(":Node:IP:Disconnected:Banned:Disabled:Unhealthy:Stopped:\n");
506 for(i=0;i<nodemap->num;i++){
507 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
510 printf(":%d:%s:%d:%d:%d:%d:%d:\n", nodemap->nodes[i].pnn,
511 ctdb_addr_to_str(&nodemap->nodes[i].addr),
512 !!(nodemap->nodes[i].flags&NODE_FLAGS_DISCONNECTED),
513 !!(nodemap->nodes[i].flags&NODE_FLAGS_BANNED),
514 !!(nodemap->nodes[i].flags&NODE_FLAGS_PERMANENTLY_DISABLED),
515 !!(nodemap->nodes[i].flags&NODE_FLAGS_UNHEALTHY),
516 !!(nodemap->nodes[i].flags&NODE_FLAGS_STOPPED));
521 printf("Number of nodes:%d\n", nodemap->num);
522 for(i=0;i<nodemap->num;i++){
523 static const struct {
527 { NODE_FLAGS_DISCONNECTED, "DISCONNECTED" },
528 { NODE_FLAGS_PERMANENTLY_DISABLED, "DISABLED" },
529 { NODE_FLAGS_BANNED, "BANNED" },
530 { NODE_FLAGS_UNHEALTHY, "UNHEALTHY" },
531 { NODE_FLAGS_DELETED, "DELETED" },
532 { NODE_FLAGS_STOPPED, "STOPPED" },
534 char *flags_str = NULL;
537 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
540 for (j=0;j<ARRAY_SIZE(flag_names);j++) {
541 if (nodemap->nodes[i].flags & flag_names[j].flag) {
542 if (flags_str == NULL) {
543 flags_str = talloc_strdup(ctdb, flag_names[j].name);
545 flags_str = talloc_asprintf_append(flags_str, "|%s",
548 CTDB_NO_MEMORY_FATAL(ctdb, flags_str);
551 if (flags_str == NULL) {
552 flags_str = talloc_strdup(ctdb, "OK");
553 CTDB_NO_MEMORY_FATAL(ctdb, flags_str);
555 printf("pnn:%d %-16s %s%s\n", nodemap->nodes[i].pnn,
556 ctdb_addr_to_str(&nodemap->nodes[i].addr),
558 nodemap->nodes[i].pnn == mypnn?" (THIS NODE)":"");
559 talloc_free(flags_str);
562 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &vnnmap);
564 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n", options.pnn));
567 if (vnnmap->generation == INVALID_GENERATION) {
568 printf("Generation:INVALID\n");
570 printf("Generation:%d\n",vnnmap->generation);
572 printf("Size:%d\n",vnnmap->size);
573 for(i=0;i<vnnmap->size;i++){
574 printf("hash:%d lmaster:%d\n", i, vnnmap->map[i]);
577 ret = ctdb_ctrl_getrecmode(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmode);
579 DEBUG(DEBUG_ERR, ("Unable to get recmode from node %u\n", options.pnn));
582 printf("Recovery mode:%s (%d)\n",recmode==CTDB_RECOVERY_NORMAL?"NORMAL":"RECOVERY",recmode);
584 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
586 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
589 printf("Recovery master:%d\n",recmaster);
596 struct natgw_node *next;
601 display the list of nodes belonging to this natgw configuration
603 static int control_natgwlist(struct ctdb_context *ctdb, int argc, const char **argv)
606 const char *natgw_list;
609 struct natgw_node *natgw_nodes = NULL;
610 struct natgw_node *natgw_node;
611 struct ctdb_node_map *nodemap=NULL;
614 /* read the natgw nodes file into a linked list */
615 natgw_list = getenv("NATGW_NODES");
616 if (natgw_list == NULL) {
617 natgw_list = "/etc/ctdb/natgw_nodes";
619 lines = file_lines_load(natgw_list, &nlines, ctdb);
621 ctdb_set_error(ctdb, "Failed to load natgw node list '%s'\n", natgw_list);
624 while (nlines > 0 && strcmp(lines[nlines-1], "") == 0) {
627 for (i=0;i<nlines;i++) {
631 /* strip leading spaces */
632 while((*node == ' ') || (*node == '\t')) {
638 if (strcmp(node, "") == 0) {
641 natgw_node = talloc(ctdb, struct natgw_node);
642 natgw_node->addr = talloc_strdup(natgw_node, node);
643 CTDB_NO_MEMORY(ctdb, natgw_node->addr);
644 natgw_node->next = natgw_nodes;
645 natgw_nodes = natgw_node;
648 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
650 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node.\n"));
655 while(i<nodemap->num) {
656 for(natgw_node=natgw_nodes;natgw_node;natgw_node=natgw_node->next) {
657 if (!strcmp(natgw_node->addr, ctdb_addr_to_str(&nodemap->nodes[i].addr))) {
662 /* this node was not in the natgw so we just remove it from
665 if ((natgw_node == NULL)
666 || (nodemap->nodes[i].flags & NODE_FLAGS_DISCONNECTED) ) {
669 for (j=i+1; j<nodemap->num; j++) {
670 nodemap->nodes[j-1] = nodemap->nodes[j];
679 /* pick a node to be natgwmaster
680 * we dont allow STOPPED, DELETED, BANNED or UNHEALTHY nodes to become the natgwmaster
682 for(i=0;i<nodemap->num;i++){
683 if (!(nodemap->nodes[i].flags & (NODE_FLAGS_DISCONNECTED|NODE_FLAGS_STOPPED|NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_UNHEALTHY))) {
684 printf("%d %s\n", nodemap->nodes[i].pnn,ctdb_addr_to_str(&nodemap->nodes[i].addr));
688 /* we couldnt find any healthy node, try unhealthy ones */
689 if (i == nodemap->num) {
690 for(i=0;i<nodemap->num;i++){
691 if (!(nodemap->nodes[i].flags & (NODE_FLAGS_DISCONNECTED|NODE_FLAGS_STOPPED|NODE_FLAGS_DELETED))) {
692 printf("%d %s\n", nodemap->nodes[i].pnn,ctdb_addr_to_str(&nodemap->nodes[i].addr));
697 /* unless all nodes are STOPPED, when we pick one anyway */
698 if (i == nodemap->num) {
699 for(i=0;i<nodemap->num;i++){
700 if (!(nodemap->nodes[i].flags & (NODE_FLAGS_DISCONNECTED|NODE_FLAGS_DELETED))) {
701 printf("%d %s\n", nodemap->nodes[i].pnn, ctdb_addr_to_str(&nodemap->nodes[i].addr));
705 /* or if we still can not find any */
706 if (i == nodemap->num) {
707 printf("-1 0.0.0.0\n");
711 /* print the pruned list of nodes belonging to this natgw list */
712 for(i=0;i<nodemap->num;i++){
713 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
716 printf(":%d:%s:%d:%d:%d:%d:%d\n", nodemap->nodes[i].pnn,
717 ctdb_addr_to_str(&nodemap->nodes[i].addr),
718 !!(nodemap->nodes[i].flags&NODE_FLAGS_DISCONNECTED),
719 !!(nodemap->nodes[i].flags&NODE_FLAGS_BANNED),
720 !!(nodemap->nodes[i].flags&NODE_FLAGS_PERMANENTLY_DISABLED),
721 !!(nodemap->nodes[i].flags&NODE_FLAGS_UNHEALTHY),
722 !!(nodemap->nodes[i].flags&NODE_FLAGS_STOPPED));
729 display the status of the scripts for monitoring (or other events)
731 static int control_one_scriptstatus(struct ctdb_context *ctdb,
732 enum ctdb_eventscript_call type)
734 struct ctdb_scripts_wire *script_status;
737 ret = ctdb_ctrl_getscriptstatus(ctdb, TIMELIMIT(), options.pnn, ctdb, type, &script_status);
739 DEBUG(DEBUG_ERR, ("Unable to get script status from node %u\n", options.pnn));
743 if (script_status == NULL) {
744 if (!options.machinereadable) {
745 printf("%s cycle never run\n",
746 ctdb_eventscript_call_names[type]);
751 if (!options.machinereadable) {
752 printf("%d scripts were executed last %s cycle\n",
753 script_status->num_scripts,
754 ctdb_eventscript_call_names[type]);
756 for (i=0; i<script_status->num_scripts; i++) {
757 const char *status = NULL;
759 switch (script_status->scripts[i].status) {
770 if (script_status->scripts[i].status > 0)
774 if (options.machinereadable) {
775 printf("%s:%s:%i:%s:%lu.%06lu:%lu.%06lu:%s:\n",
776 ctdb_eventscript_call_names[type],
777 script_status->scripts[i].name,
778 script_status->scripts[i].status,
780 (long)script_status->scripts[i].start.tv_sec,
781 (long)script_status->scripts[i].start.tv_usec,
782 (long)script_status->scripts[i].finished.tv_sec,
783 (long)script_status->scripts[i].finished.tv_usec,
784 script_status->scripts[i].output);
788 printf("%-20s Status:%s ",
789 script_status->scripts[i].name, status);
791 /* Some other error, eg from stat. */
792 printf("%-20s Status:CANNOT RUN (%s)",
793 script_status->scripts[i].name,
794 strerror(-script_status->scripts[i].status));
796 if (script_status->scripts[i].status >= 0) {
797 printf("Duration:%.3lf ",
798 timeval_delta(&script_status->scripts[i].finished,
799 &script_status->scripts[i].start));
801 if (script_status->scripts[i].status != -ENOEXEC) {
803 ctime(&script_status->scripts[i].start.tv_sec));
804 if (script_status->scripts[i].status != 0) {
805 printf(" OUTPUT:%s\n",
806 script_status->scripts[i].output);
816 static int control_scriptstatus(struct ctdb_context *ctdb,
817 int argc, const char **argv)
820 enum ctdb_eventscript_call type, min, max;
824 DEBUG(DEBUG_ERR, ("Unknown arguments to scriptstatus\n"));
829 arg = ctdb_eventscript_call_names[CTDB_EVENT_MONITOR];
833 for (type = 0; type < CTDB_EVENT_MAX; type++) {
834 if (strcmp(arg, ctdb_eventscript_call_names[type]) == 0) {
840 if (type == CTDB_EVENT_MAX) {
841 if (strcmp(arg, "all") == 0) {
843 max = CTDB_EVENT_MAX;
845 DEBUG(DEBUG_ERR, ("Unknown event type %s\n", argv[0]));
850 if (options.machinereadable) {
851 printf(":Type:Name:Code:Status:Start:End:Error Output...:\n");
854 for (type = min; type < max; type++) {
855 ret = control_one_scriptstatus(ctdb, type);
865 enable an eventscript
867 static int control_enablescript(struct ctdb_context *ctdb, int argc, const char **argv)
875 ret = ctdb_ctrl_enablescript(ctdb, TIMELIMIT(), options.pnn, argv[0]);
877 DEBUG(DEBUG_ERR, ("Unable to enable script %s on node %u\n", argv[0], options.pnn));
885 disable an eventscript
887 static int control_disablescript(struct ctdb_context *ctdb, int argc, const char **argv)
895 ret = ctdb_ctrl_disablescript(ctdb, TIMELIMIT(), options.pnn, argv[0]);
897 DEBUG(DEBUG_ERR, ("Unable to disable script %s on node %u\n", argv[0], options.pnn));
905 display the pnn of the recovery master
907 static int control_recmaster(struct ctdb_context *ctdb, int argc, const char **argv)
912 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
914 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
917 printf("%d\n",recmaster);
923 get a list of all tickles for this pnn
925 static int control_get_tickles(struct ctdb_context *ctdb, int argc, const char **argv)
927 struct ctdb_control_tcp_tickle_list *list;
935 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
936 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
940 ret = ctdb_ctrl_get_tcp_tickles(ctdb, TIMELIMIT(), options.pnn, ctdb, &addr, &list);
942 DEBUG(DEBUG_ERR, ("Unable to list tickles\n"));
946 printf("Tickles for ip:%s\n", ctdb_addr_to_str(&list->addr));
947 printf("Num tickles:%u\n", list->tickles.num);
948 for (i=0;i<list->tickles.num;i++) {
949 printf("SRC: %s:%u ", ctdb_addr_to_str(&list->tickles.connections[i].src_addr), ntohs(list->tickles.connections[i].src_addr.ip.sin_port));
950 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));
960 static int move_ip(struct ctdb_context *ctdb, ctdb_sock_addr *addr, uint32_t pnn)
962 struct ctdb_all_public_ips *ips;
963 struct ctdb_public_ip ip;
966 uint32_t disable_time;
968 struct ctdb_node_map *nodemap=NULL;
969 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
972 data.dptr = (uint8_t*)&disable_time;
973 data.dsize = sizeof(disable_time);
974 ret = ctdb_send_message(ctdb, CTDB_BROADCAST_CONNECTED, CTDB_SRVID_DISABLE_IP_CHECK, data);
976 DEBUG(DEBUG_ERR,("Failed to send message to disable ipcheck\n"));
982 /* read the public ip list from the node */
983 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), pnn, ctdb, &ips);
985 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", pnn));
986 talloc_free(tmp_ctx);
990 for (i=0;i<ips->num;i++) {
991 if (ctdb_same_ip(addr, &ips->ips[i].addr)) {
996 DEBUG(DEBUG_ERR, ("Node %u can not host ip address '%s'\n",
997 pnn, ctdb_addr_to_str(addr)));
998 talloc_free(tmp_ctx);
1005 data.dptr = (uint8_t *)&ip;
1006 data.dsize = sizeof(ip);
1008 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &nodemap);
1010 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1011 talloc_free(tmp_ctx);
1015 nodes = list_of_active_nodes_except_pnn(ctdb, nodemap, tmp_ctx, pnn);
1016 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_RELEASE_IP,
1023 DEBUG(DEBUG_ERR,("Failed to release IP on nodes\n"));
1024 talloc_free(tmp_ctx);
1028 ret = ctdb_ctrl_takeover_ip(ctdb, TIMELIMIT(), pnn, &ip);
1030 DEBUG(DEBUG_ERR,("Failed to take over IP on node %d\n", pnn));
1031 talloc_free(tmp_ctx);
1035 talloc_free(tmp_ctx);
1040 move/failover an ip address to a specific node
1042 static int control_moveip(struct ctdb_context *ctdb, int argc, const char **argv)
1045 ctdb_sock_addr addr;
1052 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1053 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1058 if (sscanf(argv[1], "%u", &pnn) != 1) {
1059 DEBUG(DEBUG_ERR, ("Badly formed pnn\n"));
1063 if (move_ip(ctdb, &addr, pnn) != 0) {
1064 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", pnn));
1071 void getips_store_callback(void *param, void *data)
1073 struct ctdb_public_ip *node_ip = (struct ctdb_public_ip *)data;
1074 struct ctdb_all_public_ips *ips = param;
1078 ips->ips[i].pnn = node_ip->pnn;
1079 ips->ips[i].addr = node_ip->addr;
1082 void getips_count_callback(void *param, void *data)
1084 uint32_t *count = param;
1090 static uint32_t *ip_key(ctdb_sock_addr *ip)
1092 static uint32_t key[IP_KEYLEN];
1094 bzero(key, sizeof(key));
1096 switch (ip->sa.sa_family) {
1098 key[0] = ip->ip.sin_addr.s_addr;
1101 key[0] = ip->ip6.sin6_addr.s6_addr32[3];
1102 key[1] = ip->ip6.sin6_addr.s6_addr32[2];
1103 key[2] = ip->ip6.sin6_addr.s6_addr32[1];
1104 key[3] = ip->ip6.sin6_addr.s6_addr32[0];
1107 DEBUG(DEBUG_ERR, (__location__ " ERROR, unknown family passed :%u\n", ip->sa.sa_family));
1114 static void *add_ip_callback(void *parm, void *data)
1120 control_get_all_public_ips(struct ctdb_context *ctdb, TALLOC_CTX *tmp_ctx, struct ctdb_all_public_ips **ips)
1122 struct ctdb_all_public_ips *tmp_ips;
1123 struct ctdb_node_map *nodemap=NULL;
1124 trbt_tree_t *ip_tree;
1128 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1130 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1134 ip_tree = trbt_create(tmp_ctx, 0);
1136 for(i=0;i<nodemap->num;i++){
1137 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
1140 if (nodemap->nodes[i].flags & NODE_FLAGS_DISCONNECTED) {
1144 /* read the public ip list from this node */
1145 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &tmp_ips);
1147 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", nodemap->nodes[i].pnn));
1151 for (j=0; j<tmp_ips->num;j++) {
1152 struct ctdb_public_ip *node_ip;
1154 node_ip = talloc(tmp_ctx, struct ctdb_public_ip);
1155 node_ip->pnn = tmp_ips->ips[j].pnn;
1156 node_ip->addr = tmp_ips->ips[j].addr;
1158 trbt_insertarray32_callback(ip_tree,
1159 IP_KEYLEN, ip_key(&tmp_ips->ips[j].addr),
1163 talloc_free(tmp_ips);
1168 trbt_traversearray32(ip_tree, IP_KEYLEN, getips_count_callback, &count);
1170 len = offsetof(struct ctdb_all_public_ips, ips) +
1171 count*sizeof(struct ctdb_public_ip);
1172 tmp_ips = talloc_zero_size(tmp_ctx, len);
1173 trbt_traversearray32(ip_tree, IP_KEYLEN, getips_store_callback, tmp_ips);
1182 * scans all other nodes and returns a pnn for another node that can host this
1186 find_other_host_for_public_ip(struct ctdb_context *ctdb, ctdb_sock_addr *addr)
1188 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1189 struct ctdb_all_public_ips *ips;
1190 struct ctdb_node_map *nodemap=NULL;
1193 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1195 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1196 talloc_free(tmp_ctx);
1200 for(i=0;i<nodemap->num;i++){
1201 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1204 if (nodemap->nodes[i].pnn == options.pnn) {
1208 /* read the public ip list from this node */
1209 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips);
1211 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", nodemap->nodes[i].pnn));
1215 for (j=0;j<ips->num;j++) {
1216 if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1217 talloc_free(tmp_ctx);
1218 return nodemap->nodes[i].pnn;
1224 talloc_free(tmp_ctx);
1229 add a public ip address to a node
1231 static int control_addip(struct ctdb_context *ctdb, int argc, const char **argv)
1237 ctdb_sock_addr addr;
1238 struct ctdb_control_ip_iface *pub;
1239 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1240 struct ctdb_all_public_ips *ips;
1244 talloc_free(tmp_ctx);
1248 if (!parse_ip_mask(argv[0], argv[1], &addr, &mask)) {
1249 DEBUG(DEBUG_ERR, ("Badly formed ip/mask : %s\n", argv[0]));
1250 talloc_free(tmp_ctx);
1254 ret = control_get_all_public_ips(ctdb, tmp_ctx, &ips);
1256 DEBUG(DEBUG_ERR, ("Unable to get public ip list from cluster\n"));
1257 talloc_free(tmp_ctx);
1262 /* check if some other node is already serving this ip, if not,
1265 for (i=0;i<ips->num;i++) {
1266 if (ctdb_same_ip(&addr, &ips->ips[i].addr)) {
1271 len = offsetof(struct ctdb_control_ip_iface, iface) + strlen(argv[1]) + 1;
1272 pub = talloc_size(tmp_ctx, len);
1273 CTDB_NO_MEMORY(ctdb, pub);
1277 pub->len = strlen(argv[1])+1;
1278 memcpy(&pub->iface[0], argv[1], strlen(argv[1])+1);
1280 ret = ctdb_ctrl_add_public_ip(ctdb, TIMELIMIT(), options.pnn, pub);
1282 DEBUG(DEBUG_ERR, ("Unable to add public ip to node %u\n", options.pnn));
1283 talloc_free(tmp_ctx);
1287 if (i == ips->num) {
1288 /* no one has this ip so we claim it */
1291 pnn = ips->ips[i].pnn;
1294 if (move_ip(ctdb, &addr, pnn) != 0) {
1295 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", pnn));
1299 talloc_free(tmp_ctx);
1303 static int control_delip(struct ctdb_context *ctdb, int argc, const char **argv);
1305 static int control_delip_all(struct ctdb_context *ctdb, int argc, const char **argv, ctdb_sock_addr *addr)
1307 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1308 struct ctdb_node_map *nodemap=NULL;
1309 struct ctdb_all_public_ips *ips;
1312 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1314 DEBUG(DEBUG_ERR, ("Unable to get nodemap from current node\n"));
1318 /* remove it from the nodes that are not hosting the ip currently */
1319 for(i=0;i<nodemap->num;i++){
1320 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1323 if (ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips) != 0) {
1324 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %d\n", nodemap->nodes[i].pnn));
1328 for (j=0;j<ips->num;j++) {
1329 if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1337 if (ips->ips[j].pnn == nodemap->nodes[i].pnn) {
1341 options.pnn = nodemap->nodes[i].pnn;
1342 control_delip(ctdb, argc, argv);
1346 /* remove it from every node (also the one hosting it) */
1347 for(i=0;i<nodemap->num;i++){
1348 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1351 if (ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips) != 0) {
1352 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %d\n", nodemap->nodes[i].pnn));
1356 for (j=0;j<ips->num;j++) {
1357 if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1365 options.pnn = nodemap->nodes[i].pnn;
1366 control_delip(ctdb, argc, argv);
1369 talloc_free(tmp_ctx);
1374 delete a public ip address from a node
1376 static int control_delip(struct ctdb_context *ctdb, int argc, const char **argv)
1379 ctdb_sock_addr addr;
1380 struct ctdb_control_ip_iface pub;
1381 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1382 struct ctdb_all_public_ips *ips;
1385 talloc_free(tmp_ctx);
1389 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1390 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1394 if (options.pnn == CTDB_BROADCAST_ALL) {
1395 return control_delip_all(ctdb, argc, argv, &addr);
1402 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &ips);
1404 DEBUG(DEBUG_ERR, ("Unable to get public ip list from cluster\n"));
1405 talloc_free(tmp_ctx);
1409 for (i=0;i<ips->num;i++) {
1410 if (ctdb_same_ip(&addr, &ips->ips[i].addr)) {
1416 DEBUG(DEBUG_ERR, ("This node does not support this public address '%s'\n",
1417 ctdb_addr_to_str(&addr)));
1418 talloc_free(tmp_ctx);
1422 if (ips->ips[i].pnn == options.pnn) {
1423 ret = find_other_host_for_public_ip(ctdb, &addr);
1425 if (move_ip(ctdb, &addr, ret) != 0) {
1426 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", ret));
1432 ret = ctdb_ctrl_del_public_ip(ctdb, TIMELIMIT(), options.pnn, &pub);
1434 DEBUG(DEBUG_ERR, ("Unable to del public ip from node %u\n", options.pnn));
1435 talloc_free(tmp_ctx);
1439 talloc_free(tmp_ctx);
1444 kill a tcp connection
1446 static int kill_tcp(struct ctdb_context *ctdb, int argc, const char **argv)
1449 struct ctdb_control_killtcp killtcp;
1455 if (!parse_ip_port(argv[0], &killtcp.src_addr)) {
1456 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[0]));
1460 if (!parse_ip_port(argv[1], &killtcp.dst_addr)) {
1461 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[1]));
1465 ret = ctdb_ctrl_killtcp(ctdb, TIMELIMIT(), options.pnn, &killtcp);
1467 DEBUG(DEBUG_ERR, ("Unable to killtcp from node %u\n", options.pnn));
1478 static int control_gratious_arp(struct ctdb_context *ctdb, int argc, const char **argv)
1481 ctdb_sock_addr addr;
1487 if (!parse_ip(argv[0], NULL, 0, &addr)) {
1488 DEBUG(DEBUG_ERR, ("Bad IP '%s'\n", argv[0]));
1492 ret = ctdb_ctrl_gratious_arp(ctdb, TIMELIMIT(), options.pnn, &addr, argv[1]);
1494 DEBUG(DEBUG_ERR, ("Unable to send gratious_arp from node %u\n", options.pnn));
1502 register a server id
1504 static int regsrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1507 struct ctdb_server_id server_id;
1513 server_id.pnn = strtoul(argv[0], NULL, 0);
1514 server_id.type = strtoul(argv[1], NULL, 0);
1515 server_id.server_id = strtoul(argv[2], NULL, 0);
1517 ret = ctdb_ctrl_register_server_id(ctdb, TIMELIMIT(), &server_id);
1519 DEBUG(DEBUG_ERR, ("Unable to register server_id from node %u\n", options.pnn));
1526 unregister a server id
1528 static int unregsrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1531 struct ctdb_server_id server_id;
1537 server_id.pnn = strtoul(argv[0], NULL, 0);
1538 server_id.type = strtoul(argv[1], NULL, 0);
1539 server_id.server_id = strtoul(argv[2], NULL, 0);
1541 ret = ctdb_ctrl_unregister_server_id(ctdb, TIMELIMIT(), &server_id);
1543 DEBUG(DEBUG_ERR, ("Unable to unregister server_id from node %u\n", options.pnn));
1550 check if a server id exists
1552 static int chksrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1556 struct ctdb_server_id server_id;
1562 server_id.pnn = strtoul(argv[0], NULL, 0);
1563 server_id.type = strtoul(argv[1], NULL, 0);
1564 server_id.server_id = strtoul(argv[2], NULL, 0);
1566 ret = ctdb_ctrl_check_server_id(ctdb, TIMELIMIT(), options.pnn, &server_id, &status);
1568 DEBUG(DEBUG_ERR, ("Unable to check server_id from node %u\n", options.pnn));
1573 printf("Server id %d:%d:%d EXISTS\n", server_id.pnn, server_id.type, server_id.server_id);
1575 printf("Server id %d:%d:%d does NOT exist\n", server_id.pnn, server_id.type, server_id.server_id);
1581 get a list of all server ids that are registered on a node
1583 static int getsrvids(struct ctdb_context *ctdb, int argc, const char **argv)
1586 struct ctdb_server_id_list *server_ids;
1588 ret = ctdb_ctrl_get_server_id_list(ctdb, ctdb, TIMELIMIT(), options.pnn, &server_ids);
1590 DEBUG(DEBUG_ERR, ("Unable to get server_id list from node %u\n", options.pnn));
1594 for (i=0; i<server_ids->num; i++) {
1595 printf("Server id %d:%d:%d\n",
1596 server_ids->server_ids[i].pnn,
1597 server_ids->server_ids[i].type,
1598 server_ids->server_ids[i].server_id);
1605 send a tcp tickle ack
1607 static int tickle_tcp(struct ctdb_context *ctdb, int argc, const char **argv)
1610 ctdb_sock_addr src, dst;
1616 if (!parse_ip_port(argv[0], &src)) {
1617 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[0]));
1621 if (!parse_ip_port(argv[1], &dst)) {
1622 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[1]));
1626 ret = ctdb_sys_send_tcp(&src, &dst, 0, 0, 0);
1630 DEBUG(DEBUG_ERR, ("Error while sending tickle ack\n"));
1637 display public ip status
1639 static int control_ip(struct ctdb_context *ctdb, int argc, const char **argv)
1642 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1643 struct ctdb_all_public_ips *ips;
1645 if (options.pnn == CTDB_BROADCAST_ALL) {
1646 /* read the list of public ips from all nodes */
1647 ret = control_get_all_public_ips(ctdb, tmp_ctx, &ips);
1649 /* read the public ip list from this node */
1650 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &ips);
1653 DEBUG(DEBUG_ERR, ("Unable to get public ips from node %u\n", options.pnn));
1654 talloc_free(tmp_ctx);
1658 if (options.machinereadable){
1659 printf(":Public IP:Node:\n");
1661 if (options.pnn == CTDB_BROADCAST_ALL) {
1662 printf("Public IPs on ALL nodes\n");
1664 printf("Public IPs on node %u\n", options.pnn);
1668 for (i=1;i<=ips->num;i++) {
1669 if (options.machinereadable){
1670 printf(":%s:%d:\n", ctdb_addr_to_str(&ips->ips[ips->num-i].addr), ips->ips[ips->num-i].pnn);
1672 printf("%s %d\n", ctdb_addr_to_str(&ips->ips[ips->num-i].addr), ips->ips[ips->num-i].pnn);
1676 talloc_free(tmp_ctx);
1681 display pid of a ctdb daemon
1683 static int control_getpid(struct ctdb_context *ctdb, int argc, const char **argv)
1688 ret = ctdb_ctrl_getpid(ctdb, TIMELIMIT(), options.pnn, &pid);
1690 DEBUG(DEBUG_ERR, ("Unable to get daemon pid from node %u\n", options.pnn));
1693 printf("Pid:%d\n", pid);
1699 handler for receiving the response to ipreallocate
1701 static void ip_reallocate_handler(struct ctdb_context *ctdb, uint64_t srvid,
1702 TDB_DATA data, void *private_data)
1707 static void ctdb_every_second(struct event_context *ev, struct timed_event *te, struct timeval t, void *p)
1709 struct ctdb_context *ctdb = talloc_get_type(p, struct ctdb_context);
1711 event_add_timed(ctdb->ev, ctdb,
1712 timeval_current_ofs(1, 0),
1713 ctdb_every_second, ctdb);
1717 ask the recovery daemon on the recovery master to perform a ip reallocation
1719 static int control_ipreallocate(struct ctdb_context *ctdb, int argc, const char **argv)
1723 struct takeover_run_reply rd;
1725 struct ctdb_node_map *nodemap=NULL;
1727 struct timeval tv = timeval_current();
1729 /* we need some events to trigger so we can timeout and restart
1732 event_add_timed(ctdb->ev, ctdb,
1733 timeval_current_ofs(1, 0),
1734 ctdb_every_second, ctdb);
1736 rd.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
1738 DEBUG(DEBUG_ERR, ("Failed to get pnn of local node\n"));
1741 rd.srvid = getpid();
1743 /* register a message port for receiveing the reply so that we
1744 can receive the reply
1746 ctdb_set_message_handler(ctdb, rd.srvid, ip_reallocate_handler, NULL);
1748 data.dptr = (uint8_t *)&rd;
1749 data.dsize = sizeof(rd);
1753 DEBUG(DEBUG_ERR,("Failed waiting for cluster convergense\n"));
1757 /* check that there are valid nodes available */
1758 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap) != 0) {
1759 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
1762 for (i=0; i<nodemap->num;i++) {
1763 if ((nodemap->nodes[i].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) == 0) {
1767 if (i==nodemap->num) {
1768 DEBUG(DEBUG_ERR,("No recmaster available, no need to wait for cluster convergence\n"));
1773 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
1775 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
1779 /* verify the node exists */
1780 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), recmaster, ctdb, &nodemap) != 0) {
1781 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
1786 /* check tha there are nodes available that can act as a recmaster */
1787 for (i=0; i<nodemap->num; i++) {
1788 if (nodemap->nodes[i].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
1793 if (i == nodemap->num) {
1794 DEBUG(DEBUG_ERR,("No possible nodes to host addresses.\n"));
1798 /* verify the recovery master is not STOPPED, nor BANNED */
1799 if (nodemap->nodes[recmaster].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
1800 DEBUG(DEBUG_ERR,("No suitable recmaster found. Try again\n"));
1807 /* verify the recovery master is not STOPPED, nor BANNED */
1808 if (nodemap->nodes[recmaster].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
1809 DEBUG(DEBUG_ERR,("No suitable recmaster found. Try again\n"));
1815 ret = ctdb_send_message(ctdb, recmaster, CTDB_SRVID_TAKEOVER_RUN, data);
1817 DEBUG(DEBUG_ERR,("Failed to send ip takeover run request message to %u\n", options.pnn));
1821 tv = timeval_current();
1822 /* this loop will terminate when we have received the reply */
1823 while (timeval_elapsed(&tv) < 3.0) {
1824 event_loop_once(ctdb->ev);
1827 DEBUG(DEBUG_INFO,("Timed out waiting for recmaster ipreallocate. Trying again\n"));
1837 disable a remote node
1839 static int control_disable(struct ctdb_context *ctdb, int argc, const char **argv)
1842 struct ctdb_node_map *nodemap=NULL;
1845 ret = ctdb_ctrl_modflags(ctdb, TIMELIMIT(), options.pnn, NODE_FLAGS_PERMANENTLY_DISABLED, 0);
1847 DEBUG(DEBUG_ERR, ("Unable to disable node %u\n", options.pnn));
1853 /* read the nodemap and verify the change took effect */
1854 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
1855 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
1859 } while (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED));
1860 ret = control_ipreallocate(ctdb, argc, argv);
1862 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
1870 enable a disabled remote node
1872 static int control_enable(struct ctdb_context *ctdb, int argc, const char **argv)
1876 struct ctdb_node_map *nodemap=NULL;
1879 ret = ctdb_ctrl_modflags(ctdb, TIMELIMIT(), options.pnn, 0, NODE_FLAGS_PERMANENTLY_DISABLED);
1881 DEBUG(DEBUG_ERR, ("Unable to enable node %u\n", options.pnn));
1887 /* read the nodemap and verify the change took effect */
1888 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
1889 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
1893 } while (nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED);
1894 ret = control_ipreallocate(ctdb, argc, argv);
1896 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
1906 static int control_stop(struct ctdb_context *ctdb, int argc, const char **argv)
1909 struct ctdb_node_map *nodemap=NULL;
1912 ret = ctdb_ctrl_stop_node(ctdb, TIMELIMIT(), options.pnn);
1914 DEBUG(DEBUG_ERR, ("Unable to stop node %u try again\n", options.pnn));
1919 /* read the nodemap and verify the change took effect */
1920 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
1921 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
1925 } while (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_STOPPED));
1926 ret = control_ipreallocate(ctdb, argc, argv);
1928 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
1936 restart a stopped remote node
1938 static int control_continue(struct ctdb_context *ctdb, int argc, const char **argv)
1942 struct ctdb_node_map *nodemap=NULL;
1945 ret = ctdb_ctrl_continue_node(ctdb, TIMELIMIT(), options.pnn);
1947 DEBUG(DEBUG_ERR, ("Unable to continue node %u\n", options.pnn));
1953 /* read the nodemap and verify the change took effect */
1954 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
1955 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
1959 } while (nodemap->nodes[options.pnn].flags & NODE_FLAGS_STOPPED);
1960 ret = control_ipreallocate(ctdb, argc, argv);
1962 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
1969 static uint32_t get_generation(struct ctdb_context *ctdb)
1971 struct ctdb_vnn_map *vnnmap=NULL;
1974 /* wait until the recmaster is not in recovery mode */
1976 uint32_t recmode, recmaster;
1978 if (vnnmap != NULL) {
1979 talloc_free(vnnmap);
1983 /* get the recmaster */
1984 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, &recmaster);
1986 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
1990 /* get recovery mode */
1991 ret = ctdb_ctrl_getrecmode(ctdb, ctdb, TIMELIMIT(), recmaster, &recmode);
1993 DEBUG(DEBUG_ERR, ("Unable to get recmode from node %u\n", options.pnn));
1997 /* get the current generation number */
1998 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), recmaster, ctdb, &vnnmap);
2000 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from recmaster (%u)\n", recmaster));
2004 if ((recmode == CTDB_RECOVERY_NORMAL)
2005 && (vnnmap->generation != 1)){
2006 return vnnmap->generation;
2013 ban a node from the cluster
2015 static int control_ban(struct ctdb_context *ctdb, int argc, const char **argv)
2018 struct ctdb_node_map *nodemap=NULL;
2019 struct ctdb_ban_time bantime;
2025 /* verify the node exists */
2026 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
2028 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2032 if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_BANNED) {
2033 DEBUG(DEBUG_ERR,("Node %u is already banned.\n", options.pnn));
2037 bantime.pnn = options.pnn;
2038 bantime.time = strtoul(argv[0], NULL, 0);
2040 ret = ctdb_ctrl_set_ban(ctdb, TIMELIMIT(), options.pnn, &bantime);
2042 DEBUG(DEBUG_ERR,("Banning node %d for %d seconds failed.\n", bantime.pnn, bantime.time));
2046 ret = control_ipreallocate(ctdb, argc, argv);
2048 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2057 unban a node from the cluster
2059 static int control_unban(struct ctdb_context *ctdb, int argc, const char **argv)
2062 struct ctdb_node_map *nodemap=NULL;
2063 struct ctdb_ban_time bantime;
2065 /* verify the node exists */
2066 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
2068 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2072 if (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_BANNED)) {
2073 DEBUG(DEBUG_ERR,("Node %u is not banned.\n", options.pnn));
2077 bantime.pnn = options.pnn;
2080 ret = ctdb_ctrl_set_ban(ctdb, TIMELIMIT(), options.pnn, &bantime);
2082 DEBUG(DEBUG_ERR,("Unbanning node %d failed.\n", bantime.pnn));
2086 ret = control_ipreallocate(ctdb, argc, argv);
2088 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2097 show ban information for a node
2099 static int control_showban(struct ctdb_context *ctdb, int argc, const char **argv)
2102 struct ctdb_node_map *nodemap=NULL;
2103 struct ctdb_ban_time *bantime;
2105 /* verify the node exists */
2106 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
2108 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2112 ret = ctdb_ctrl_get_ban(ctdb, TIMELIMIT(), options.pnn, ctdb, &bantime);
2114 DEBUG(DEBUG_ERR,("Showing ban info for node %d failed.\n", options.pnn));
2118 if (bantime->time == 0) {
2119 printf("Node %u is not banned\n", bantime->pnn);
2121 printf("Node %u is banned banned for %d seconds\n", bantime->pnn, bantime->time);
2130 static int control_shutdown(struct ctdb_context *ctdb, int argc, const char **argv)
2134 ret = ctdb_ctrl_shutdown(ctdb, TIMELIMIT(), options.pnn);
2136 DEBUG(DEBUG_ERR, ("Unable to shutdown node %u\n", options.pnn));
2146 static int control_recover(struct ctdb_context *ctdb, int argc, const char **argv)
2149 uint32_t generation, next_generation;
2151 /* record the current generation number */
2152 generation = get_generation(ctdb);
2154 ret = ctdb_ctrl_freeze_priority(ctdb, TIMELIMIT(), options.pnn, 1);
2156 DEBUG(DEBUG_ERR, ("Unable to freeze node\n"));
2160 ret = ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
2162 DEBUG(DEBUG_ERR, ("Unable to set recovery mode\n"));
2166 /* wait until we are in a new generation */
2168 next_generation = get_generation(ctdb);
2169 if (next_generation != generation) {
2180 display monitoring mode of a remote node
2182 static int control_getmonmode(struct ctdb_context *ctdb, int argc, const char **argv)
2187 ret = ctdb_ctrl_getmonmode(ctdb, TIMELIMIT(), options.pnn, &monmode);
2189 DEBUG(DEBUG_ERR, ("Unable to get monmode from node %u\n", options.pnn));
2192 if (!options.machinereadable){
2193 printf("Monitoring mode:%s (%d)\n",monmode==CTDB_MONITORING_ACTIVE?"ACTIVE":"DISABLED",monmode);
2196 printf(":%d:\n",monmode);
2203 display capabilities of a remote node
2205 static int control_getcapabilities(struct ctdb_context *ctdb, int argc, const char **argv)
2207 uint32_t capabilities;
2210 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), options.pnn, &capabilities);
2212 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", options.pnn));
2216 if (!options.machinereadable){
2217 printf("RECMASTER: %s\n", (capabilities&CTDB_CAP_RECMASTER)?"YES":"NO");
2218 printf("LMASTER: %s\n", (capabilities&CTDB_CAP_LMASTER)?"YES":"NO");
2219 printf("LVS: %s\n", (capabilities&CTDB_CAP_LVS)?"YES":"NO");
2220 printf("NATGW: %s\n", (capabilities&CTDB_CAP_NATGW)?"YES":"NO");
2222 printf(":RECMASTER:LMASTER:LVS:NATGW:\n");
2223 printf(":%d:%d:%d:%d:\n",
2224 !!(capabilities&CTDB_CAP_RECMASTER),
2225 !!(capabilities&CTDB_CAP_LMASTER),
2226 !!(capabilities&CTDB_CAP_LVS),
2227 !!(capabilities&CTDB_CAP_NATGW));
2233 display lvs configuration
2235 static int control_lvs(struct ctdb_context *ctdb, int argc, const char **argv)
2237 uint32_t *capabilities;
2238 struct ctdb_node_map *nodemap=NULL;
2240 int healthy_count = 0;
2242 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
2244 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
2248 capabilities = talloc_array(ctdb, uint32_t, nodemap->num);
2249 CTDB_NO_MEMORY(ctdb, capabilities);
2251 /* collect capabilities for all connected nodes */
2252 for (i=0; i<nodemap->num; i++) {
2253 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2256 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2260 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), i, &capabilities[i]);
2262 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", i));
2266 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2270 if (!(nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY)) {
2275 /* Print all LVS nodes */
2276 for (i=0; i<nodemap->num; i++) {
2277 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2280 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2283 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2287 if (healthy_count != 0) {
2288 if (nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY) {
2293 printf("%d:%s\n", i,
2294 ctdb_addr_to_str(&nodemap->nodes[i].addr));
2301 display who is the lvs master
2303 static int control_lvsmaster(struct ctdb_context *ctdb, int argc, const char **argv)
2305 uint32_t *capabilities;
2306 struct ctdb_node_map *nodemap=NULL;
2308 int healthy_count = 0;
2310 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
2312 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
2316 capabilities = talloc_array(ctdb, uint32_t, nodemap->num);
2317 CTDB_NO_MEMORY(ctdb, capabilities);
2319 /* collect capabilities for all connected nodes */
2320 for (i=0; i<nodemap->num; i++) {
2321 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2324 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2328 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), i, &capabilities[i]);
2330 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", i));
2334 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2338 if (!(nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY)) {
2343 /* find and show the lvsmaster */
2344 for (i=0; i<nodemap->num; i++) {
2345 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2348 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2351 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2355 if (healthy_count != 0) {
2356 if (nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY) {
2361 if (options.machinereadable){
2364 printf("Node %d is LVS master\n", i);
2369 printf("There is no LVS master\n");
2374 disable monitoring on a node
2376 static int control_disable_monmode(struct ctdb_context *ctdb, int argc, const char **argv)
2381 ret = ctdb_ctrl_disable_monmode(ctdb, TIMELIMIT(), options.pnn);
2383 DEBUG(DEBUG_ERR, ("Unable to disable monmode on node %u\n", options.pnn));
2386 printf("Monitoring mode:%s\n","DISABLED");
2392 enable monitoring on a node
2394 static int control_enable_monmode(struct ctdb_context *ctdb, int argc, const char **argv)
2399 ret = ctdb_ctrl_enable_monmode(ctdb, TIMELIMIT(), options.pnn);
2401 DEBUG(DEBUG_ERR, ("Unable to enable monmode on node %u\n", options.pnn));
2404 printf("Monitoring mode:%s\n","ACTIVE");
2410 display remote list of keys/data for a db
2412 static int control_catdb(struct ctdb_context *ctdb, int argc, const char **argv)
2414 const char *db_name;
2415 struct ctdb_db_context *ctdb_db;
2425 if (db_exists(ctdb, db_name)) {
2426 DEBUG(DEBUG_ERR,("Database '%s' does not exist\n", db_name));
2430 ctdb_db = ctdb_attach(ctdb, db_name, false, 0);
2432 if (ctdb_db == NULL) {
2433 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
2437 /* traverse and dump the cluster tdb */
2438 ret = ctdb_dump_db(ctdb_db, stdout);
2440 DEBUG(DEBUG_ERR, ("Unable to dump database\n"));
2443 talloc_free(ctdb_db);
2445 printf("Dumped %d records\n", ret);
2450 static void log_handler(struct ctdb_context *ctdb, uint64_t srvid,
2451 TDB_DATA data, void *private_data)
2453 DEBUG(DEBUG_ERR,("Log data received\n"));
2454 if (data.dsize > 0) {
2455 printf("%s", data.dptr);
2462 display a list of log messages from the in memory ringbuffer
2464 static int control_getlog(struct ctdb_context *ctdb, int argc, const char **argv)
2468 struct ctdb_get_log_addr log_addr;
2470 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2475 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
2476 talloc_free(tmp_ctx);
2480 log_addr.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
2481 log_addr.srvid = getpid();
2482 if (isalpha(argv[0][0]) || argv[0][0] == '-') {
2483 log_addr.level = get_debug_by_desc(argv[0]);
2485 log_addr.level = strtol(argv[0], NULL, 0);
2489 data.dptr = (unsigned char *)&log_addr;
2490 data.dsize = sizeof(log_addr);
2492 DEBUG(DEBUG_ERR, ("Pulling logs from node %u\n", options.pnn));
2494 ctdb_set_message_handler(ctdb, log_addr.srvid, log_handler, NULL);
2497 DEBUG(DEBUG_ERR,("Listen for response on %d\n", (int)log_addr.srvid));
2499 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_GET_LOG,
2500 0, data, tmp_ctx, NULL, &res, NULL, &errmsg);
2501 if (ret != 0 || res != 0) {
2502 DEBUG(DEBUG_ERR,("Failed to get logs - %s\n", errmsg));
2503 talloc_free(tmp_ctx);
2508 tv = timeval_current();
2509 /* this loop will terminate when we have received the reply */
2510 while (timeval_elapsed(&tv) < 3.0) {
2511 event_loop_once(ctdb->ev);
2514 DEBUG(DEBUG_INFO,("Timed out waiting for log data.\n"));
2516 talloc_free(tmp_ctx);
2521 clear the in memory log area
2523 static int control_clearlog(struct ctdb_context *ctdb, int argc, const char **argv)
2528 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2530 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_CLEAR_LOG,
2531 0, tdb_null, tmp_ctx, NULL, &res, NULL, &errmsg);
2532 if (ret != 0 || res != 0) {
2533 DEBUG(DEBUG_ERR,("Failed to clear logs\n"));
2534 talloc_free(tmp_ctx);
2538 talloc_free(tmp_ctx);
2545 display a list of the databases on a remote ctdb
2547 static int control_getdbmap(struct ctdb_context *ctdb, int argc, const char **argv)
2550 struct ctdb_dbid_map *dbmap=NULL;
2552 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
2554 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
2558 printf("Number of databases:%d\n", dbmap->num);
2559 for(i=0;i<dbmap->num;i++){
2565 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &path);
2566 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
2567 ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &health);
2568 persistent = dbmap->dbs[i].persistent;
2569 printf("dbid:0x%08x name:%s path:%s%s%s\n",
2570 dbmap->dbs[i].dbid, name, path,
2571 persistent?" PERSISTENT":"",
2572 health?" UNHEALTHY":"");
2579 display the status of a database on a remote ctdb
2581 static int control_getdbstatus(struct ctdb_context *ctdb, int argc, const char **argv)
2584 struct ctdb_dbid_map *dbmap=NULL;
2585 const char *db_name;
2593 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
2595 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
2599 for(i=0;i<dbmap->num;i++){
2605 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
2606 if (strcmp(name, db_name) != 0) {
2610 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &path);
2611 ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &health);
2612 persistent = dbmap->dbs[i].persistent;
2613 printf("dbid: 0x%08x\nname: %s\npath: %s\nPERSISTENT: %s\nHEALTH: %s\n",
2614 dbmap->dbs[i].dbid, name, path,
2615 persistent?"yes":"no",
2616 health?health:"OK");
2620 DEBUG(DEBUG_ERR, ("db %s doesn't exist on node %u\n", db_name, options.pnn));
2625 check if the local node is recmaster or not
2626 it will return 1 if this node is the recmaster and 0 if it is not
2627 or if the local ctdb daemon could not be contacted
2629 static int control_isnotrecmaster(struct ctdb_context *ctdb, int argc, const char **argv)
2631 uint32_t mypnn, recmaster;
2634 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
2636 printf("Failed to get pnn of node\n");
2640 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
2642 printf("Failed to get the recmaster\n");
2646 if (recmaster != mypnn) {
2647 printf("this node is not the recmaster\n");
2651 printf("this node is the recmaster\n");
2658 static int control_ping(struct ctdb_context *ctdb, int argc, const char **argv)
2661 struct timeval tv = timeval_current();
2662 ret = ctdb_ctrl_ping(ctdb, options.pnn);
2664 printf("Unable to get ping response from node %u\n", options.pnn);
2667 printf("response from %u time=%.6f sec (%d clients)\n",
2668 options.pnn, timeval_elapsed(&tv), ret);
2677 static int control_getvar(struct ctdb_context *ctdb, int argc, const char **argv)
2688 ret = ctdb_ctrl_get_tunable(ctdb, TIMELIMIT(), options.pnn, name, &value);
2690 DEBUG(DEBUG_ERR, ("Unable to get tunable variable '%s'\n", name));
2694 printf("%-19s = %u\n", name, value);
2701 static int control_setvar(struct ctdb_context *ctdb, int argc, const char **argv)
2712 value = strtoul(argv[1], NULL, 0);
2714 ret = ctdb_ctrl_set_tunable(ctdb, TIMELIMIT(), options.pnn, name, value);
2716 DEBUG(DEBUG_ERR, ("Unable to set tunable variable '%s'\n", name));
2725 static int control_listvars(struct ctdb_context *ctdb, int argc, const char **argv)
2731 ret = ctdb_ctrl_list_tunables(ctdb, TIMELIMIT(), options.pnn, ctdb, &list, &count);
2733 DEBUG(DEBUG_ERR, ("Unable to list tunable variables\n"));
2737 for (i=0;i<count;i++) {
2738 control_getvar(ctdb, 1, &list[i]);
2747 display debug level on a node
2749 static int control_getdebug(struct ctdb_context *ctdb, int argc, const char **argv)
2754 ret = ctdb_ctrl_get_debuglevel(ctdb, options.pnn, &level);
2756 DEBUG(DEBUG_ERR, ("Unable to get debuglevel response from node %u\n", options.pnn));
2759 if (options.machinereadable){
2760 printf(":Name:Level:\n");
2761 printf(":%s:%d:\n",get_debug_by_level(level),level);
2763 printf("Node %u is at debug level %s (%d)\n", options.pnn, get_debug_by_level(level), level);
2770 display reclock file of a node
2772 static int control_getreclock(struct ctdb_context *ctdb, int argc, const char **argv)
2775 const char *reclock;
2777 ret = ctdb_ctrl_getreclock(ctdb, TIMELIMIT(), options.pnn, ctdb, &reclock);
2779 DEBUG(DEBUG_ERR, ("Unable to get reclock file from node %u\n", options.pnn));
2782 if (options.machinereadable){
2783 if (reclock != NULL) {
2784 printf("%s", reclock);
2787 if (reclock == NULL) {
2788 printf("No reclock file used.\n");
2790 printf("Reclock file:%s\n", reclock);
2798 set the reclock file of a node
2800 static int control_setreclock(struct ctdb_context *ctdb, int argc, const char **argv)
2803 const char *reclock;
2807 } else if (argc == 1) {
2813 ret = ctdb_ctrl_setreclock(ctdb, TIMELIMIT(), options.pnn, reclock);
2815 DEBUG(DEBUG_ERR, ("Unable to get reclock file from node %u\n", options.pnn));
2822 set the natgw state on/off
2824 static int control_setnatgwstate(struct ctdb_context *ctdb, int argc, const char **argv)
2827 uint32_t natgwstate;
2833 if (!strcmp(argv[0], "on")) {
2835 } else if (!strcmp(argv[0], "off")) {
2841 ret = ctdb_ctrl_setnatgwstate(ctdb, TIMELIMIT(), options.pnn, natgwstate);
2843 DEBUG(DEBUG_ERR, ("Unable to set the natgw state for node %u\n", options.pnn));
2851 set the lmaster role on/off
2853 static int control_setlmasterrole(struct ctdb_context *ctdb, int argc, const char **argv)
2856 uint32_t lmasterrole;
2862 if (!strcmp(argv[0], "on")) {
2864 } else if (!strcmp(argv[0], "off")) {
2870 ret = ctdb_ctrl_setlmasterrole(ctdb, TIMELIMIT(), options.pnn, lmasterrole);
2872 DEBUG(DEBUG_ERR, ("Unable to set the lmaster role for node %u\n", options.pnn));
2880 set the recmaster role on/off
2882 static int control_setrecmasterrole(struct ctdb_context *ctdb, int argc, const char **argv)
2885 uint32_t recmasterrole;
2891 if (!strcmp(argv[0], "on")) {
2893 } else if (!strcmp(argv[0], "off")) {
2899 ret = ctdb_ctrl_setrecmasterrole(ctdb, TIMELIMIT(), options.pnn, recmasterrole);
2901 DEBUG(DEBUG_ERR, ("Unable to set the recmaster role for node %u\n", options.pnn));
2909 set debug level on a node or all nodes
2911 static int control_setdebug(struct ctdb_context *ctdb, int argc, const char **argv)
2917 printf("You must specify the debug level. Valid levels are:\n");
2918 for (i=0; debug_levels[i].description != NULL; i++) {
2919 printf("%s (%d)\n", debug_levels[i].description, debug_levels[i].level);
2925 if (isalpha(argv[0][0]) || argv[0][0] == '-') {
2926 level = get_debug_by_desc(argv[0]);
2928 level = strtol(argv[0], NULL, 0);
2931 for (i=0; debug_levels[i].description != NULL; i++) {
2932 if (level == debug_levels[i].level) {
2936 if (debug_levels[i].description == NULL) {
2937 printf("Invalid debug level, must be one of\n");
2938 for (i=0; debug_levels[i].description != NULL; i++) {
2939 printf("%s (%d)\n", debug_levels[i].description, debug_levels[i].level);
2944 ret = ctdb_ctrl_set_debuglevel(ctdb, options.pnn, level);
2946 DEBUG(DEBUG_ERR, ("Unable to set debug level on node %u\n", options.pnn));
2955 static int control_freeze(struct ctdb_context *ctdb, int argc, const char **argv)
2961 priority = strtol(argv[0], NULL, 0);
2965 DEBUG(DEBUG_ERR,("Freeze by priority %u\n", priority));
2967 ret = ctdb_ctrl_freeze_priority(ctdb, TIMELIMIT(), options.pnn, priority);
2969 DEBUG(DEBUG_ERR, ("Unable to freeze node %u\n", options.pnn));
2977 static int control_thaw(struct ctdb_context *ctdb, int argc, const char **argv)
2983 priority = strtol(argv[0], NULL, 0);
2987 DEBUG(DEBUG_ERR,("Thaw by priority %u\n", priority));
2989 ret = ctdb_ctrl_thaw_priority(ctdb, TIMELIMIT(), options.pnn, priority);
2991 DEBUG(DEBUG_ERR, ("Unable to thaw node %u\n", options.pnn));
2998 attach to a database
3000 static int control_attach(struct ctdb_context *ctdb, int argc, const char **argv)
3002 const char *db_name;
3003 struct ctdb_db_context *ctdb_db;
3010 ctdb_db = ctdb_attach(ctdb, db_name, false, 0);
3011 if (ctdb_db == NULL) {
3012 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
3022 static int control_setdbprio(struct ctdb_context *ctdb, int argc, const char **argv)
3024 struct ctdb_db_priority db_prio;
3031 db_prio.db_id = strtoul(argv[0], NULL, 0);
3032 db_prio.priority = strtoul(argv[1], NULL, 0);
3034 ret = ctdb_ctrl_set_db_priority(ctdb, TIMELIMIT(), options.pnn, &db_prio);
3036 DEBUG(DEBUG_ERR,("Unable to set db prio\n"));
3046 static int control_getdbprio(struct ctdb_context *ctdb, int argc, const char **argv)
3048 uint32_t db_id, priority;
3055 db_id = strtoul(argv[0], NULL, 0);
3057 ret = ctdb_ctrl_get_db_priority(ctdb, TIMELIMIT(), options.pnn, db_id, &priority);
3059 DEBUG(DEBUG_ERR,("Unable to get db prio\n"));
3063 DEBUG(DEBUG_ERR,("Priority:%u\n", priority));
3069 run an eventscript on a node
3071 static int control_eventscript(struct ctdb_context *ctdb, int argc, const char **argv)
3077 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3080 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3084 data.dptr = (unsigned char *)discard_const(argv[0]);
3085 data.dsize = strlen((char *)data.dptr) + 1;
3087 DEBUG(DEBUG_ERR, ("Running eventscripts with arguments \"%s\" on node %u\n", data.dptr, options.pnn));
3089 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_RUN_EVENTSCRIPTS,
3090 0, data, tmp_ctx, NULL, &res, NULL, &errmsg);
3091 if (ret != 0 || res != 0) {
3092 DEBUG(DEBUG_ERR,("Failed to run eventscripts - %s\n", errmsg));
3093 talloc_free(tmp_ctx);
3096 talloc_free(tmp_ctx);
3100 #define DB_VERSION 1
3101 #define MAX_DB_NAME 64
3102 struct db_file_header {
3103 unsigned long version;
3105 unsigned long persistent;
3107 const char name[MAX_DB_NAME];
3110 struct backup_data {
3111 struct ctdb_marshall_buffer *records;
3114 bool traverse_error;
3117 static int backup_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *private)
3119 struct backup_data *bd = talloc_get_type(private, struct backup_data);
3120 struct ctdb_rec_data *rec;
3122 /* add the record */
3123 rec = ctdb_marshall_record(bd->records, 0, key, NULL, data);
3125 bd->traverse_error = true;
3126 DEBUG(DEBUG_ERR,("Failed to marshall record\n"));
3129 bd->records = talloc_realloc_size(NULL, bd->records, rec->length + bd->len);
3130 if (bd->records == NULL) {
3131 DEBUG(DEBUG_ERR,("Failed to expand marshalling buffer\n"));
3132 bd->traverse_error = true;
3135 bd->records->count++;
3136 memcpy(bd->len+(uint8_t *)bd->records, rec, rec->length);
3137 bd->len += rec->length;
3145 * backup a database to a file
3147 static int control_backupdb(struct ctdb_context *ctdb, int argc, const char **argv)
3150 struct ctdb_dbid_map *dbmap=NULL;
3151 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3152 struct db_file_header dbhdr;
3153 struct ctdb_db_context *ctdb_db;
3154 struct backup_data *bd;
3159 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3163 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &dbmap);
3165 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
3169 for(i=0;i<dbmap->num;i++){
3172 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, tmp_ctx, &name);
3173 if(!strcmp(argv[0], name)){
3174 talloc_free(discard_const(name));
3177 talloc_free(discard_const(name));
3179 if (i == dbmap->num) {
3180 DEBUG(DEBUG_ERR,("No database with name '%s' found\n", argv[0]));
3181 talloc_free(tmp_ctx);
3186 ctdb_db = ctdb_attach(ctdb, argv[0], dbmap->dbs[i].persistent, 0);
3187 if (ctdb_db == NULL) {
3188 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", argv[0]));
3189 talloc_free(tmp_ctx);
3194 ret = tdb_transaction_start(ctdb_db->ltdb->tdb);
3196 DEBUG(DEBUG_ERR,("Failed to start transaction\n"));
3197 talloc_free(tmp_ctx);
3202 bd = talloc_zero(tmp_ctx, struct backup_data);
3204 DEBUG(DEBUG_ERR,("Failed to allocate backup_data\n"));
3205 talloc_free(tmp_ctx);
3209 bd->records = talloc_zero(bd, struct ctdb_marshall_buffer);
3210 if (bd->records == NULL) {
3211 DEBUG(DEBUG_ERR,("Failed to allocate ctdb_marshall_buffer\n"));
3212 talloc_free(tmp_ctx);
3216 bd->len = offsetof(struct ctdb_marshall_buffer, data);
3217 bd->records->db_id = ctdb_db->db_id;
3218 /* traverse the database collecting all records */
3219 if (tdb_traverse_read(ctdb_db->ltdb->tdb, backup_traverse, bd) == -1 ||
3220 bd->traverse_error) {
3221 DEBUG(DEBUG_ERR,("Traverse error\n"));
3222 talloc_free(tmp_ctx);
3226 tdb_transaction_cancel(ctdb_db->ltdb->tdb);
3229 fh = open(argv[1], O_RDWR|O_CREAT, 0600);
3231 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[1]));
3232 talloc_free(tmp_ctx);
3236 dbhdr.version = DB_VERSION;
3237 dbhdr.timestamp = time(NULL);
3238 dbhdr.persistent = dbmap->dbs[i].persistent;
3239 dbhdr.size = bd->len;
3240 if (strlen(argv[0]) >= MAX_DB_NAME) {
3241 DEBUG(DEBUG_ERR,("Too long dbname\n"));
3244 strncpy(discard_const(dbhdr.name), argv[0], MAX_DB_NAME);
3245 ret = write(fh, &dbhdr, sizeof(dbhdr));
3247 DEBUG(DEBUG_ERR,("write failed: %s\n", strerror(errno)));
3250 ret = write(fh, bd->records, bd->len);
3252 DEBUG(DEBUG_ERR,("write failed: %s\n", strerror(errno)));
3261 DEBUG(DEBUG_ERR,("close failed: %s\n", strerror(errno)));
3264 talloc_free(tmp_ctx);
3269 * restore a database from a file
3271 static int control_restoredb(struct ctdb_context *ctdb, int argc, const char **argv)
3274 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3277 struct db_file_header dbhdr;
3278 struct ctdb_db_context *ctdb_db;
3279 struct ctdb_node_map *nodemap=NULL;
3280 struct ctdb_vnn_map *vnnmap=NULL;
3282 struct ctdb_control_wipe_database w;
3284 uint32_t generation;
3289 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3293 fh = open(argv[0], O_RDONLY);
3295 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[0]));
3296 talloc_free(tmp_ctx);
3300 read(fh, &dbhdr, sizeof(dbhdr));
3301 if (dbhdr.version != DB_VERSION) {
3302 DEBUG(DEBUG_ERR,("Invalid version of database dump. File is version %lu but expected version was %u\n", dbhdr.version, DB_VERSION));
3303 talloc_free(tmp_ctx);
3307 outdata.dsize = dbhdr.size;
3308 outdata.dptr = talloc_size(tmp_ctx, outdata.dsize);
3309 if (outdata.dptr == NULL) {
3310 DEBUG(DEBUG_ERR,("Failed to allocate data of size '%lu'\n", dbhdr.size));
3312 talloc_free(tmp_ctx);
3315 read(fh, outdata.dptr, outdata.dsize);
3318 tm = localtime(&dbhdr.timestamp);
3319 strftime(tbuf,sizeof(tbuf)-1,"%Y/%m/%d %H:%M:%S", tm);
3320 printf("Restoring database '%s' from backup @ %s\n",
3324 ctdb_db = ctdb_attach(ctdb, dbhdr.name, dbhdr.persistent, 0);
3325 if (ctdb_db == NULL) {
3326 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", dbhdr.name));
3327 talloc_free(tmp_ctx);
3331 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
3333 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
3334 talloc_free(tmp_ctx);
3339 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &vnnmap);
3341 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n", options.pnn));
3342 talloc_free(tmp_ctx);
3346 /* freeze all nodes */
3347 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3348 for (i=1; i<=NUM_DB_PRIORITIES; i++) {
3349 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_FREEZE,
3355 DEBUG(DEBUG_ERR, ("Unable to freeze nodes.\n"));
3356 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3357 talloc_free(tmp_ctx);
3362 generation = vnnmap->generation;
3363 data.dptr = (void *)&generation;
3364 data.dsize = sizeof(generation);
3366 /* start a cluster wide transaction */
3367 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3368 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_START,
3370 TIMELIMIT(), false, data,
3373 DEBUG(DEBUG_ERR, ("Unable to start cluster wide transactions.\n"));
3378 w.db_id = ctdb_db->db_id;
3379 w.transaction_id = generation;
3381 data.dptr = (void *)&w;
3382 data.dsize = sizeof(w);
3384 /* wipe all the remote databases. */
3385 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3386 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_WIPE_DATABASE,
3388 TIMELIMIT(), false, data,
3391 DEBUG(DEBUG_ERR, ("Unable to wipe database.\n"));
3392 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3393 talloc_free(tmp_ctx);
3397 /* push the database */
3398 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3399 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_PUSH_DB,
3401 TIMELIMIT(), false, outdata,
3404 DEBUG(DEBUG_ERR, ("Failed to push database.\n"));
3405 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3406 talloc_free(tmp_ctx);
3410 data.dptr = (void *)&ctdb_db->db_id;
3411 data.dsize = sizeof(ctdb_db->db_id);
3413 /* mark the database as healthy */
3414 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3415 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_DB_SET_HEALTHY,
3417 TIMELIMIT(), false, data,
3420 DEBUG(DEBUG_ERR, ("Failed to mark database as healthy.\n"));
3421 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3422 talloc_free(tmp_ctx);
3426 data.dptr = (void *)&generation;
3427 data.dsize = sizeof(generation);
3429 /* commit all the changes */
3430 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_COMMIT,
3432 TIMELIMIT(), false, data,
3435 DEBUG(DEBUG_ERR, ("Unable to commit databases.\n"));
3436 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3437 talloc_free(tmp_ctx);
3442 /* thaw all nodes */
3443 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3444 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_THAW,
3450 DEBUG(DEBUG_ERR, ("Unable to thaw nodes.\n"));
3451 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3452 talloc_free(tmp_ctx);
3457 talloc_free(tmp_ctx);
3462 * dump a database backup from a file
3464 static int control_dumpdbbackup(struct ctdb_context *ctdb, int argc, const char **argv)
3466 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3468 struct db_file_header dbhdr;
3472 struct ctdb_rec_data *rec = NULL;
3473 struct ctdb_marshall_buffer *m;
3476 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3480 fh = open(argv[0], O_RDONLY);
3482 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[0]));
3483 talloc_free(tmp_ctx);
3487 read(fh, &dbhdr, sizeof(dbhdr));
3488 if (dbhdr.version != DB_VERSION) {
3489 DEBUG(DEBUG_ERR,("Invalid version of database dump. File is version %lu but expected version was %u\n", dbhdr.version, DB_VERSION));
3490 talloc_free(tmp_ctx);
3494 outdata.dsize = dbhdr.size;
3495 outdata.dptr = talloc_size(tmp_ctx, outdata.dsize);
3496 if (outdata.dptr == NULL) {
3497 DEBUG(DEBUG_ERR,("Failed to allocate data of size '%lu'\n", dbhdr.size));
3499 talloc_free(tmp_ctx);
3502 read(fh, outdata.dptr, outdata.dsize);
3504 m = (struct ctdb_marshall_buffer *)outdata.dptr;
3506 tm = localtime(&dbhdr.timestamp);
3507 strftime(tbuf,sizeof(tbuf)-1,"%Y/%m/%d %H:%M:%S", tm);
3508 printf("Backup of database name:'%s' dbid:0x%x08x from @ %s\n",
3509 dbhdr.name, m->db_id, tbuf);
3511 for (i=0; i < m->count; i++) {
3515 /* we do not want the header splitted, so we pass NULL*/
3516 rec = ctdb_marshall_loop_next(m, rec, &reqid,
3519 ctdb_dumpdb_record(ctdb, key, data, stdout);
3522 printf("Dumped %d records\n", i);
3523 talloc_free(tmp_ctx);
3528 * wipe a database from a file
3530 static int control_wipedb(struct ctdb_context *ctdb, int argc,
3534 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3536 struct ctdb_db_context *ctdb_db;
3537 struct ctdb_node_map *nodemap = NULL;
3538 struct ctdb_vnn_map *vnnmap = NULL;
3540 struct ctdb_control_wipe_database w;
3542 uint32_t generation;
3543 struct ctdb_dbid_map *dbmap = NULL;
3546 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3550 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx,
3553 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n",
3558 for(i=0;i<dbmap->num;i++){
3561 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn,
3562 dbmap->dbs[i].dbid, tmp_ctx, &name);
3563 if(!strcmp(argv[0], name)){
3564 talloc_free(discard_const(name));
3567 talloc_free(discard_const(name));
3569 if (i == dbmap->num) {
3570 DEBUG(DEBUG_ERR, ("No database with name '%s' found\n",
3572 talloc_free(tmp_ctx);
3576 ctdb_db = ctdb_attach(ctdb, argv[0], dbmap->dbs[i].persistent, 0);
3577 if (ctdb_db == NULL) {
3578 DEBUG(DEBUG_ERR, ("Unable to attach to database '%s'\n",
3580 talloc_free(tmp_ctx);
3584 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb,
3587 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n",
3589 talloc_free(tmp_ctx);
3593 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx,
3596 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n",
3598 talloc_free(tmp_ctx);
3602 /* freeze all nodes */
3603 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3604 for (i=1; i<=NUM_DB_PRIORITIES; i++) {
3605 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_FREEZE,
3612 DEBUG(DEBUG_ERR, ("Unable to freeze nodes.\n"));
3613 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn,
3614 CTDB_RECOVERY_ACTIVE);
3615 talloc_free(tmp_ctx);
3620 generation = vnnmap->generation;
3621 data.dptr = (void *)&generation;
3622 data.dsize = sizeof(generation);
3624 /* start a cluster wide transaction */
3625 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3626 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_START,
3628 TIMELIMIT(), false, data,
3632 DEBUG(DEBUG_ERR, ("Unable to start cluster wide "
3633 "transactions.\n"));
3637 w.db_id = ctdb_db->db_id;
3638 w.transaction_id = generation;
3640 data.dptr = (void *)&w;
3641 data.dsize = sizeof(w);
3643 /* wipe all the remote databases. */
3644 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3645 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_WIPE_DATABASE,
3647 TIMELIMIT(), false, data,
3650 DEBUG(DEBUG_ERR, ("Unable to wipe database.\n"));
3651 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3652 talloc_free(tmp_ctx);
3656 data.dptr = (void *)&ctdb_db->db_id;
3657 data.dsize = sizeof(ctdb_db->db_id);
3659 /* mark the database as healthy */
3660 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3661 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_DB_SET_HEALTHY,
3663 TIMELIMIT(), false, data,
3666 DEBUG(DEBUG_ERR, ("Failed to mark database as healthy.\n"));
3667 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3668 talloc_free(tmp_ctx);
3672 data.dptr = (void *)&generation;
3673 data.dsize = sizeof(generation);
3675 /* commit all the changes */
3676 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_COMMIT,
3678 TIMELIMIT(), false, data,
3681 DEBUG(DEBUG_ERR, ("Unable to commit databases.\n"));
3682 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3683 talloc_free(tmp_ctx);
3687 /* thaw all nodes */
3688 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3689 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_THAW,
3695 DEBUG(DEBUG_ERR, ("Unable to thaw nodes.\n"));
3696 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3697 talloc_free(tmp_ctx);
3701 talloc_free(tmp_ctx);
3706 * set flags of a node in the nodemap
3708 static int control_setflags(struct ctdb_context *ctdb, int argc, const char **argv)
3715 struct ctdb_node_flag_change c;
3722 if (sscanf(argv[0], "%d", &node) != 1) {
3723 DEBUG(DEBUG_ERR, ("Badly formed node\n"));
3727 if (sscanf(argv[1], "0x%x", &flags) != 1) {
3728 DEBUG(DEBUG_ERR, ("Badly formed flags\n"));
3735 c.new_flags = flags;
3737 data.dsize = sizeof(c);
3738 data.dptr = (unsigned char *)&c;
3740 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_MODIFY_FLAGS, 0,
3741 data, NULL, NULL, &status, NULL, NULL);
3742 if (ret != 0 || status != 0) {
3743 DEBUG(DEBUG_ERR,("Failed to modify flags\n"));
3752 static int control_dumpmemory(struct ctdb_context *ctdb, int argc, const char **argv)
3758 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3759 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_DUMP_MEMORY,
3760 0, tdb_null, tmp_ctx, &data, &res, NULL, &errmsg);
3761 if (ret != 0 || res != 0) {
3762 DEBUG(DEBUG_ERR,("Failed to dump memory - %s\n", errmsg));
3763 talloc_free(tmp_ctx);
3766 write(1, data.dptr, data.dsize);
3767 talloc_free(tmp_ctx);
3772 handler for memory dumps
3774 static void mem_dump_handler(struct ctdb_context *ctdb, uint64_t srvid,
3775 TDB_DATA data, void *private_data)
3777 write(1, data.dptr, data.dsize);
3782 dump memory usage on the recovery daemon
3784 static int control_rddumpmemory(struct ctdb_context *ctdb, int argc, const char **argv)
3788 struct rd_memdump_reply rd;
3790 rd.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
3792 DEBUG(DEBUG_ERR, ("Failed to get pnn of local node\n"));
3795 rd.srvid = getpid();
3797 /* register a message port for receiveing the reply so that we
3798 can receive the reply
3800 ctdb_set_message_handler(ctdb, rd.srvid, mem_dump_handler, NULL);
3803 data.dptr = (uint8_t *)&rd;
3804 data.dsize = sizeof(rd);
3806 ret = ctdb_send_message(ctdb, options.pnn, CTDB_SRVID_MEM_DUMP, data);
3808 DEBUG(DEBUG_ERR,("Failed to send memdump request message to %u\n", options.pnn));
3812 /* this loop will terminate when we have received the reply */
3814 event_loop_once(ctdb->ev);
3821 list all nodes in the cluster
3822 if the daemon is running, we read the data from the daemon.
3823 if the daemon is not running we parse the nodes file directly
3825 static int control_listnodes(struct ctdb_context *ctdb, int argc, const char **argv)
3828 struct ctdb_node_map *nodemap=NULL;
3831 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
3833 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
3837 for(i=0;i<nodemap->num;i++){
3838 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
3841 if (options.machinereadable){
3842 printf(":%d:%s:\n", nodemap->nodes[i].pnn, ctdb_addr_to_str(&nodemap->nodes[i].addr));
3844 printf("%s\n", ctdb_addr_to_str(&nodemap->nodes[i].addr));
3848 TALLOC_CTX *mem_ctx = talloc_new(NULL);
3849 struct pnn_node *pnn_nodes;
3850 struct pnn_node *pnn_node;
3852 pnn_nodes = read_nodes_file(mem_ctx);
3853 if (pnn_nodes == NULL) {
3854 DEBUG(DEBUG_ERR,("Failed to read nodes file\n"));
3855 talloc_free(mem_ctx);
3859 for(pnn_node=pnn_nodes;pnn_node;pnn_node=pnn_node->next) {
3860 ctdb_sock_addr addr;
3862 if (parse_ip(pnn_node->addr, NULL, 63999, &addr) == 0) {
3863 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s' in nodes file\n", pnn_node->addr));
3864 talloc_free(mem_ctx);
3868 if (options.machinereadable){
3869 printf(":%d:%s:\n", pnn_node->pnn, pnn_node->addr);
3871 printf("%s\n", pnn_node->addr);
3874 talloc_free(mem_ctx);
3881 reload the nodes file on the local node
3883 static int control_reload_nodes_file(struct ctdb_context *ctdb, int argc, const char **argv)
3887 struct ctdb_node_map *nodemap=NULL;
3889 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
3891 DEBUG(DEBUG_ERR, ("Failed to read pnn of local node\n"));
3895 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
3897 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
3901 /* reload the nodes file on all remote nodes */
3902 for (i=0;i<nodemap->num;i++) {
3903 if (nodemap->nodes[i].pnn == mypnn) {
3906 DEBUG(DEBUG_NOTICE, ("Reloading nodes file on node %u\n", nodemap->nodes[i].pnn));
3907 ret = ctdb_ctrl_reload_nodes_file(ctdb, TIMELIMIT(),
3908 nodemap->nodes[i].pnn);
3910 DEBUG(DEBUG_ERR, ("ERROR: Failed to reload nodes file on node %u. You MUST fix that node manually!\n", nodemap->nodes[i].pnn));
3914 /* reload the nodes file on the local node */
3915 DEBUG(DEBUG_NOTICE, ("Reloading nodes file on node %u\n", mypnn));
3916 ret = ctdb_ctrl_reload_nodes_file(ctdb, TIMELIMIT(), mypnn);
3918 DEBUG(DEBUG_ERR, ("ERROR: Failed to reload nodes file on node %u. You MUST fix that node manually!\n", mypnn));
3921 /* initiate a recovery */
3922 control_recover(ctdb, argc, argv);
3928 static const struct {
3930 int (*fn)(struct ctdb_context *, int, const char **);
3932 bool without_daemon; /* can be run without daemon running ? */
3935 } ctdb_commands[] = {
3937 { "version", control_version, true, false, "show version of ctdb" },
3939 { "status", control_status, true, false, "show node status" },
3940 { "uptime", control_uptime, true, false, "show node uptime" },
3941 { "ping", control_ping, true, false, "ping all nodes" },
3942 { "getvar", control_getvar, true, false, "get a tunable variable", "<name>"},
3943 { "setvar", control_setvar, true, false, "set a tunable variable", "<name> <value>"},
3944 { "listvars", control_listvars, true, false, "list tunable variables"},
3945 { "statistics", control_statistics, false, false, "show statistics" },
3946 { "statisticsreset", control_statistics_reset, true, false, "reset statistics"},
3947 { "ip", control_ip, false, false, "show which public ip's that ctdb manages" },
3948 { "process-exists", control_process_exists, true, false, "check if a process exists on a node", "<pid>"},
3949 { "getdbmap", control_getdbmap, true, false, "show the database map" },
3950 { "getdbstatus", control_getdbstatus, true, false, "show the status of a database", "<dbname>" },
3951 { "catdb", control_catdb, true, false, "dump a database" , "<dbname>"},
3952 { "getmonmode", control_getmonmode, true, false, "show monitoring mode" },
3953 { "getcapabilities", control_getcapabilities, true, false, "show node capabilities" },
3954 { "pnn", control_pnn, true, false, "show the pnn of the currnet node" },
3955 { "lvs", control_lvs, true, false, "show lvs configuration" },
3956 { "lvsmaster", control_lvsmaster, true, false, "show which node is the lvs master" },
3957 { "disablemonitor", control_disable_monmode,true, false, "set monitoring mode to DISABLE" },
3958 { "enablemonitor", control_enable_monmode, true, false, "set monitoring mode to ACTIVE" },
3959 { "setdebug", control_setdebug, true, false, "set debug level", "<EMERG|ALERT|CRIT|ERR|WARNING|NOTICE|INFO|DEBUG>" },
3960 { "getdebug", control_getdebug, true, false, "get debug level" },
3961 { "getlog", control_getlog, true, false, "get the log data from the in memory ringbuffer", "<level>" },
3962 { "clearlog", control_clearlog, true, false, "clear the log data from the in memory ringbuffer" },
3963 { "attach", control_attach, true, false, "attach to a database", "<dbname>" },
3964 { "dumpmemory", control_dumpmemory, true, false, "dump memory map to stdout" },
3965 { "rddumpmemory", control_rddumpmemory, true, false, "dump memory map from the recovery daemon to stdout" },
3966 { "getpid", control_getpid, true, false, "get ctdbd process ID" },
3967 { "disable", control_disable, true, false, "disable a nodes public IP" },
3968 { "enable", control_enable, true, false, "enable a nodes public IP" },
3969 { "stop", control_stop, true, false, "stop a node" },
3970 { "continue", control_continue, true, false, "re-start a stopped node" },
3971 { "ban", control_ban, true, false, "ban a node from the cluster", "<bantime|0>"},
3972 { "unban", control_unban, true, false, "unban a node" },
3973 { "showban", control_showban, true, false, "show ban information"},
3974 { "shutdown", control_shutdown, true, false, "shutdown ctdbd" },
3975 { "recover", control_recover, true, false, "force recovery" },
3976 { "ipreallocate", control_ipreallocate, true, false, "force the recovery daemon to perform a ip reallocation procedure" },
3977 { "freeze", control_freeze, true, false, "freeze databases", "[priority:1-3]" },
3978 { "thaw", control_thaw, true, false, "thaw databases", "[priority:1-3]" },
3979 { "isnotrecmaster", control_isnotrecmaster, false, false, "check if the local node is recmaster or not" },
3980 { "killtcp", kill_tcp, false, false, "kill a tcp connection.", "<srcip:port> <dstip:port>" },
3981 { "gratiousarp", control_gratious_arp, false, false, "send a gratious arp", "<ip> <interface>" },
3982 { "tickle", tickle_tcp, false, false, "send a tcp tickle ack", "<srcip:port> <dstip:port>" },
3983 { "gettickles", control_get_tickles, false, false, "get the list of tickles registered for this ip", "<ip>" },
3985 { "regsrvid", regsrvid, false, false, "register a server id", "<pnn> <type> <id>" },
3986 { "unregsrvid", unregsrvid, false, false, "unregister a server id", "<pnn> <type> <id>" },
3987 { "chksrvid", chksrvid, false, false, "check if a server id exists", "<pnn> <type> <id>" },
3988 { "getsrvids", getsrvids, false, false, "get a list of all server ids"},
3989 { "vacuum", ctdb_vacuum, false, false, "vacuum the databases of empty records", "[max_records]"},
3990 { "repack", ctdb_repack, false, false, "repack all databases", "[max_freelist]"},
3991 { "listnodes", control_listnodes, false, true, "list all nodes in the cluster"},
3992 { "reloadnodes", control_reload_nodes_file, false, false, "reload the nodes file and restart the transport on all nodes"},
3993 { "moveip", control_moveip, false, false, "move/failover an ip address to another node", "<ip> <node>"},
3994 { "addip", control_addip, true, false, "add a ip address to a node", "<ip/mask> <iface>"},
3995 { "delip", control_delip, false, false, "delete an ip address from a node", "<ip>"},
3996 { "eventscript", control_eventscript, true, false, "run the eventscript with the given parameters on a node", "<arguments>"},
3997 { "backupdb", control_backupdb, false, false, "backup the database into a file.", "<database> <file>"},
3998 { "restoredb", control_restoredb, false, false, "restore the database from a file.", "<file>"},
3999 { "dumpdbbackup", control_dumpdbbackup, false, true, "dump database backup from a file.", "<file>"},
4000 { "wipedb", control_wipedb, false, false, "wipe the contents of a database.", "<dbname>"},
4001 { "recmaster", control_recmaster, false, false, "show the pnn for the recovery master."},
4002 { "setflags", control_setflags, false, false, "set flags for a node in the nodemap.", "<node> <flags>"},
4003 { "scriptstatus", control_scriptstatus, false, false, "show the status of the monitoring scripts (or all scripts)", "[all]"},
4004 { "enablescript", control_enablescript, false, false, "enable an eventscript", "<script>"},
4005 { "disablescript", control_disablescript, false, false, "disable an eventscript", "<script>"},
4006 { "natgwlist", control_natgwlist, false, false, "show the nodes belonging to this natgw configuration"},
4007 { "xpnn", control_xpnn, true, true, "find the pnn of the local node without talking to the daemon (unreliable)" },
4008 { "getreclock", control_getreclock, false, false, "Show the reclock file of a node"},
4009 { "setreclock", control_setreclock, false, false, "Set/clear the reclock file of a node", "[filename]"},
4010 { "setnatgwstate", control_setnatgwstate, false, false, "Set NATGW state to on/off", "{on|off}"},
4011 { "setlmasterrole", control_setlmasterrole, false, false, "Set LMASTER role to on/off", "{on|off}"},
4012 { "setrecmasterrole", control_setrecmasterrole, false, false, "Set RECMASTER role to on/off", "{on|off}"},
4013 { "setdbprio", control_setdbprio, false, false, "Set DB priority", "<dbid> <prio:1-3>"},
4014 { "getdbprio", control_getdbprio, false, false, "Get DB priority", "<dbid>"},
4020 static void usage(void)
4024 "Usage: ctdb [options] <control>\n" \
4026 " -n <node> choose node number, or 'all' (defaults to local node)\n"
4027 " -Y generate machinereadable output\n"
4028 " -t <timelimit> set timelimit for control in seconds (default %u)\n", options.timelimit);
4029 printf("Controls:\n");
4030 for (i=0;i<ARRAY_SIZE(ctdb_commands);i++) {
4031 printf(" %-15s %-27s %s\n",
4032 ctdb_commands[i].name,
4033 ctdb_commands[i].args?ctdb_commands[i].args:"",
4034 ctdb_commands[i].msg);
4040 static void ctdb_alarm(int sig)
4042 printf("Maximum runtime exceeded - exiting\n");
4049 int main(int argc, const char *argv[])
4051 struct ctdb_context *ctdb;
4052 char *nodestring = NULL;
4053 struct poptOption popt_options[] = {
4056 { "timelimit", 't', POPT_ARG_INT, &options.timelimit, 0, "timelimit", "integer" },
4057 { "node", 'n', POPT_ARG_STRING, &nodestring, 0, "node", "integer|all" },
4058 { "machinereadable", 'Y', POPT_ARG_NONE, &options.machinereadable, 0, "enable machinereadable output", NULL },
4059 { "maxruntime", 'T', POPT_ARG_INT, &options.maxruntime, 0, "die if runtime exceeds this limit (in seconds)", "integer" },
4063 const char **extra_argv;
4067 struct event_context *ev;
4068 const char *control;
4072 /* set some defaults */
4073 options.maxruntime = 0;
4074 options.timelimit = 3;
4075 options.pnn = CTDB_CURRENT_NODE;
4077 pc = poptGetContext(argv[0], argc, argv, popt_options, POPT_CONTEXT_KEEP_FIRST);
4079 while ((opt = poptGetNextOpt(pc)) != -1) {
4082 DEBUG(DEBUG_ERR, ("Invalid option %s: %s\n",
4083 poptBadOption(pc, 0), poptStrerror(opt)));
4088 /* setup the remaining options for the main program to use */
4089 extra_argv = poptGetArgs(pc);
4092 while (extra_argv[extra_argc]) extra_argc++;
4095 if (extra_argc < 1) {
4099 if (options.maxruntime == 0) {
4100 const char *ctdb_timeout;
4101 ctdb_timeout = getenv("CTDB_TIMEOUT");
4102 if (ctdb_timeout != NULL) {
4103 options.maxruntime = strtoul(ctdb_timeout, NULL, 0);
4105 /* default timeout is 120 seconds */
4106 options.maxruntime = 120;
4110 signal(SIGALRM, ctdb_alarm);
4111 alarm(options.maxruntime);
4113 /* setup the node number to contact */
4114 if (nodestring != NULL) {
4115 if (strcmp(nodestring, "all") == 0) {
4116 options.pnn = CTDB_BROADCAST_ALL;
4118 options.pnn = strtoul(nodestring, NULL, 0);
4122 control = extra_argv[0];
4124 ev = event_context_init(NULL);
4126 for (i=0;i<ARRAY_SIZE(ctdb_commands);i++) {
4127 if (strcmp(control, ctdb_commands[i].name) == 0) {
4130 if (ctdb_commands[i].without_daemon == true) {
4134 /* initialise ctdb */
4135 ctdb = ctdb_cmdline_client(ev);
4137 if (ctdb_commands[i].without_daemon == false) {
4139 DEBUG(DEBUG_ERR, ("Failed to init ctdb\n"));
4143 /* verify the node exists */
4146 if (options.pnn == CTDB_CURRENT_NODE) {
4148 pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
4156 if (ctdb_commands[i].auto_all &&
4157 options.pnn == CTDB_BROADCAST_ALL) {
4162 nodes = ctdb_get_connected_nodes(ctdb, TIMELIMIT(), ctdb, &num_nodes);
4163 CTDB_NO_MEMORY(ctdb, nodes);
4165 for (j=0;j<num_nodes;j++) {
4166 options.pnn = nodes[j];
4167 ret |= ctdb_commands[i].fn(ctdb, extra_argc-1, extra_argv+1);
4171 ret = ctdb_commands[i].fn(ctdb, extra_argc-1, extra_argv+1);
4177 if (i == ARRAY_SIZE(ctdb_commands)) {
4178 DEBUG(DEBUG_ERR, ("Unknown control '%s'\n", control));