4 Copyright (C) Andrew Tridgell 2007
5 Copyright (C) Ronnie Sahlberg 2007
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, see <http://www.gnu.org/licenses/>.
22 #include "lib/tevent/tevent.h"
23 #include "system/time.h"
24 #include "system/filesys.h"
25 #include "system/network.h"
26 #include "system/locale.h"
29 #include "../include/ctdb.h"
30 #include "../include/ctdb_client.h"
31 #include "../include/ctdb_private.h"
32 #include "../common/rb_tree.h"
35 #define ERR_TIMEOUT 20 /* timed out trying to reach node */
36 #define ERR_NONODE 21 /* node does not exist */
37 #define ERR_DISNODE 22 /* node is disconnected */
39 struct ctdb_connection *ctdb_connection;
41 static void usage(void);
51 #define TIMELIMIT() timeval_current_ofs(options.timelimit, 0)
52 #define LONGTIMELIMIT() timeval_current_ofs(options.timelimit*10, 0)
55 static int control_version(struct ctdb_context *ctdb, int argc, const char **argv)
58 #define XSTR(x) STR(x)
59 printf("CTDB version: %s\n", XSTR(CTDB_VERS));
66 verify that a node exists and is reachable
68 static void verify_node(struct ctdb_context *ctdb)
71 struct ctdb_node_map *nodemap=NULL;
73 if (options.pnn == CTDB_CURRENT_NODE) {
76 if (options.pnn == CTDB_BROADCAST_ALL) {
80 /* verify the node exists */
81 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
82 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
85 if (options.pnn >= nodemap->num) {
86 DEBUG(DEBUG_ERR, ("Node %u does not exist\n", options.pnn));
89 if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_DELETED) {
90 DEBUG(DEBUG_ERR, ("Node %u is DELETED\n", options.pnn));
93 if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_DISCONNECTED) {
94 DEBUG(DEBUG_ERR, ("Node %u is DISCONNECTED\n", options.pnn));
98 /* verify we can access the node */
99 ret = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
101 DEBUG(DEBUG_ERR,("Can not access node. Node is not operational.\n"));
107 check if a database exists
109 static int db_exists(struct ctdb_context *ctdb, const char *db_name)
112 struct ctdb_dbid_map *dbmap=NULL;
114 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
116 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
120 for(i=0;i<dbmap->num;i++){
123 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
124 if (!strcmp(name, db_name)) {
133 see if a process exists
135 static int control_process_exists(struct ctdb_context *ctdb, int argc, const char **argv)
143 if (sscanf(argv[0], "%u:%u", &pnn, &pid) != 2) {
144 DEBUG(DEBUG_ERR, ("Badly formed pnn:pid\n"));
148 ret = ctdb_ctrl_process_exists(ctdb, pnn, pid);
150 printf("%u:%u exists\n", pnn, pid);
152 printf("%u:%u does not exist\n", pnn, pid);
158 display statistics structure
160 static void show_statistics(struct ctdb_statistics *s)
162 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
164 const char *prefix=NULL;
166 int tmp, days, hours, minutes, seconds;
171 #define STATISTICS_FIELD(n) { #n, offsetof(struct ctdb_statistics, n) }
172 STATISTICS_FIELD(num_clients),
173 STATISTICS_FIELD(frozen),
174 STATISTICS_FIELD(recovering),
175 STATISTICS_FIELD(num_recoveries),
176 STATISTICS_FIELD(client_packets_sent),
177 STATISTICS_FIELD(client_packets_recv),
178 STATISTICS_FIELD(node_packets_sent),
179 STATISTICS_FIELD(node_packets_recv),
180 STATISTICS_FIELD(keepalive_packets_sent),
181 STATISTICS_FIELD(keepalive_packets_recv),
182 STATISTICS_FIELD(node.req_call),
183 STATISTICS_FIELD(node.reply_call),
184 STATISTICS_FIELD(node.req_dmaster),
185 STATISTICS_FIELD(node.reply_dmaster),
186 STATISTICS_FIELD(node.reply_error),
187 STATISTICS_FIELD(node.req_message),
188 STATISTICS_FIELD(node.req_control),
189 STATISTICS_FIELD(node.reply_control),
190 STATISTICS_FIELD(client.req_call),
191 STATISTICS_FIELD(client.req_message),
192 STATISTICS_FIELD(client.req_control),
193 STATISTICS_FIELD(timeouts.call),
194 STATISTICS_FIELD(timeouts.control),
195 STATISTICS_FIELD(timeouts.traverse),
196 STATISTICS_FIELD(total_calls),
197 STATISTICS_FIELD(pending_calls),
198 STATISTICS_FIELD(lockwait_calls),
199 STATISTICS_FIELD(pending_lockwait_calls),
200 STATISTICS_FIELD(childwrite_calls),
201 STATISTICS_FIELD(pending_childwrite_calls),
202 STATISTICS_FIELD(memory_used),
203 STATISTICS_FIELD(max_hop_count),
205 tmp = s->statistics_current_time.tv_sec - s->statistics_start_time.tv_sec;
214 printf("CTDB version %u\n", CTDB_VERSION);
215 printf("Current time of statistics : %s", ctime(&s->statistics_current_time.tv_sec));
216 printf("Statistics collected since : (%03d %02d:%02d:%02d) %s", days, hours, minutes, seconds, ctime(&s->statistics_start_time.tv_sec));
218 for (i=0;i<ARRAY_SIZE(fields);i++) {
219 if (strchr(fields[i].name, '.')) {
220 preflen = strcspn(fields[i].name, ".")+1;
221 if (!prefix || strncmp(prefix, fields[i].name, preflen) != 0) {
222 prefix = fields[i].name;
223 printf(" %*.*s\n", preflen-1, preflen-1, fields[i].name);
228 printf(" %*s%-22s%*s%10u\n",
230 fields[i].name+preflen,
232 *(uint32_t *)(fields[i].offset+(uint8_t *)s));
234 printf(" %-30s %.6f sec\n", "max_reclock_ctdbd", s->reclock.ctdbd);
235 printf(" %-30s %.6f sec\n", "max_reclock_recd", s->reclock.recd);
237 printf(" %-30s %.6f sec\n", "max_call_latency", s->max_call_latency);
238 printf(" %-30s %.6f sec\n", "max_lockwait_latency", s->max_lockwait_latency);
239 printf(" %-30s %.6f sec\n", "max_childwrite_latency", s->max_childwrite_latency);
240 printf(" %-30s %.6f sec\n", "max_childwrite_latency", s->max_childwrite_latency);
242 talloc_free(tmp_ctx);
246 display remote ctdb statistics combined from all nodes
248 static int control_statistics_all(struct ctdb_context *ctdb)
251 struct ctdb_statistics statistics;
255 nodes = ctdb_get_connected_nodes(ctdb, TIMELIMIT(), ctdb, &num_nodes);
256 CTDB_NO_MEMORY(ctdb, nodes);
258 ZERO_STRUCT(statistics);
260 for (i=0;i<num_nodes;i++) {
261 struct ctdb_statistics s1;
263 uint32_t *v1 = (uint32_t *)&s1;
264 uint32_t *v2 = (uint32_t *)&statistics;
266 offsetof(struct ctdb_statistics, __last_counter) / sizeof(uint32_t);
267 ret = ctdb_ctrl_statistics(ctdb, nodes[i], &s1);
269 DEBUG(DEBUG_ERR, ("Unable to get statistics from node %u\n", nodes[i]));
272 for (j=0;j<num_ints;j++) {
275 statistics.max_hop_count =
276 MAX(statistics.max_hop_count, s1.max_hop_count);
277 statistics.max_call_latency =
278 MAX(statistics.max_call_latency, s1.max_call_latency);
279 statistics.max_lockwait_latency =
280 MAX(statistics.max_lockwait_latency, s1.max_lockwait_latency);
283 printf("Gathered statistics for %u nodes\n", num_nodes);
284 show_statistics(&statistics);
289 display remote ctdb statistics
291 static int control_statistics(struct ctdb_context *ctdb, int argc, const char **argv)
294 struct ctdb_statistics statistics;
296 if (options.pnn == CTDB_BROADCAST_ALL) {
297 return control_statistics_all(ctdb);
300 ret = ctdb_ctrl_statistics(ctdb, options.pnn, &statistics);
302 DEBUG(DEBUG_ERR, ("Unable to get statistics from node %u\n", options.pnn));
305 show_statistics(&statistics);
311 reset remote ctdb statistics
313 static int control_statistics_reset(struct ctdb_context *ctdb, int argc, const char **argv)
317 ret = ctdb_statistics_reset(ctdb, options.pnn);
319 DEBUG(DEBUG_ERR, ("Unable to reset statistics on node %u\n", options.pnn));
327 display uptime of remote node
329 static int control_uptime(struct ctdb_context *ctdb, int argc, const char **argv)
332 struct ctdb_uptime *uptime = NULL;
333 int tmp, days, hours, minutes, seconds;
335 ret = ctdb_ctrl_uptime(ctdb, ctdb, TIMELIMIT(), options.pnn, &uptime);
337 DEBUG(DEBUG_ERR, ("Unable to get uptime from node %u\n", options.pnn));
341 if (options.machinereadable){
342 printf(":Current Node Time:Ctdb Start Time:Last Recovery/Failover Time:Last Recovery/IPFailover Duration:\n");
343 printf(":%u:%u:%u:%lf\n",
344 (unsigned int)uptime->current_time.tv_sec,
345 (unsigned int)uptime->ctdbd_start_time.tv_sec,
346 (unsigned int)uptime->last_recovery_finished.tv_sec,
347 timeval_delta(&uptime->last_recovery_finished,
348 &uptime->last_recovery_started)
353 printf("Current time of node : %s", ctime(&uptime->current_time.tv_sec));
355 tmp = uptime->current_time.tv_sec - uptime->ctdbd_start_time.tv_sec;
363 printf("Ctdbd start time : (%03d %02d:%02d:%02d) %s", days, hours, minutes, seconds, ctime(&uptime->ctdbd_start_time.tv_sec));
365 tmp = uptime->current_time.tv_sec - uptime->last_recovery_finished.tv_sec;
373 printf("Time of last recovery/failover: (%03d %02d:%02d:%02d) %s", days, hours, minutes, seconds, ctime(&uptime->last_recovery_finished.tv_sec));
375 printf("Duration of last recovery/failover: %lf seconds\n",
376 timeval_delta(&uptime->last_recovery_finished,
377 &uptime->last_recovery_started));
383 show the PNN of the current node
385 static int control_pnn(struct ctdb_context *ctdb, int argc, const char **argv)
390 ret = ctdb_getpnn(ctdb_connection, options.pnn, &mypnn);
392 DEBUG(DEBUG_ERR, ("Unable to get pnn from node."));
396 printf("PNN:%d\n", mypnn);
402 struct pnn_node *next;
407 static struct pnn_node *read_nodes_file(TALLOC_CTX *mem_ctx)
409 const char *nodes_list;
413 struct pnn_node *pnn_nodes = NULL;
414 struct pnn_node *pnn_node;
415 struct pnn_node *tmp_node;
417 /* read the nodes file */
418 nodes_list = getenv("CTDB_NODES");
419 if (nodes_list == NULL) {
420 nodes_list = "/etc/ctdb/nodes";
422 lines = file_lines_load(nodes_list, &nlines, mem_ctx);
426 while (nlines > 0 && strcmp(lines[nlines-1], "") == 0) {
429 for (i=0, pnn=0; i<nlines; i++) {
433 /* strip leading spaces */
434 while((*node == ' ') || (*node == '\t')) {
441 if (strcmp(node, "") == 0) {
444 pnn_node = talloc(mem_ctx, struct pnn_node);
445 pnn_node->pnn = pnn++;
446 pnn_node->addr = talloc_strdup(pnn_node, node);
447 pnn_node->next = pnn_nodes;
448 pnn_nodes = pnn_node;
451 /* swap them around so we return them in incrementing order */
452 pnn_node = pnn_nodes;
456 pnn_node = pnn_node->next;
458 tmp_node->next = pnn_nodes;
459 pnn_nodes = tmp_node;
466 show the PNN of the current node
467 discover the pnn by loading the nodes file and try to bind to all
468 addresses one at a time until the ip address is found.
470 static int control_xpnn(struct ctdb_context *ctdb, int argc, const char **argv)
472 TALLOC_CTX *mem_ctx = talloc_new(NULL);
473 struct pnn_node *pnn_nodes;
474 struct pnn_node *pnn_node;
476 pnn_nodes = read_nodes_file(mem_ctx);
477 if (pnn_nodes == NULL) {
478 DEBUG(DEBUG_ERR,("Failed to read nodes file\n"));
479 talloc_free(mem_ctx);
483 for(pnn_node=pnn_nodes;pnn_node;pnn_node=pnn_node->next) {
486 if (parse_ip(pnn_node->addr, NULL, 63999, &addr) == 0) {
487 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s' in nodes file\n", pnn_node->addr));
488 talloc_free(mem_ctx);
492 if (ctdb_sys_have_ip(&addr)) {
493 printf("PNN:%d\n", pnn_node->pnn);
494 talloc_free(mem_ctx);
499 printf("Failed to detect which PNN this node is\n");
500 talloc_free(mem_ctx);
505 display remote ctdb status
507 static int control_status(struct ctdb_context *ctdb, int argc, const char **argv)
510 struct ctdb_vnn_map *vnnmap=NULL;
511 struct ctdb_node_map *nodemap=NULL;
512 uint32_t recmode, recmaster;
515 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
520 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
522 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
526 if(options.machinereadable){
527 printf(":Node:IP:Disconnected:Banned:Disabled:Unhealthy:Stopped:Inactive:PartiallyOnline:\n");
528 for(i=0;i<nodemap->num;i++){
529 int partially_online = 0;
532 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
535 if (nodemap->nodes[i].flags == 0) {
536 struct ctdb_control_get_ifaces *ifaces;
538 ret = ctdb_ctrl_get_ifaces(ctdb, TIMELIMIT(),
539 nodemap->nodes[i].pnn,
542 for (j=0; j < ifaces->num; j++) {
543 if (ifaces->ifaces[j].link_state != 0) {
546 partially_online = 1;
552 printf(":%d:%s:%d:%d:%d:%d:%d:%d:%d:\n", nodemap->nodes[i].pnn,
553 ctdb_addr_to_str(&nodemap->nodes[i].addr),
554 !!(nodemap->nodes[i].flags&NODE_FLAGS_DISCONNECTED),
555 !!(nodemap->nodes[i].flags&NODE_FLAGS_BANNED),
556 !!(nodemap->nodes[i].flags&NODE_FLAGS_PERMANENTLY_DISABLED),
557 !!(nodemap->nodes[i].flags&NODE_FLAGS_UNHEALTHY),
558 !!(nodemap->nodes[i].flags&NODE_FLAGS_STOPPED),
559 !!(nodemap->nodes[i].flags&NODE_FLAGS_INACTIVE),
565 printf("Number of nodes:%d\n", nodemap->num);
566 for(i=0;i<nodemap->num;i++){
567 static const struct {
571 { NODE_FLAGS_DISCONNECTED, "DISCONNECTED" },
572 { NODE_FLAGS_PERMANENTLY_DISABLED, "DISABLED" },
573 { NODE_FLAGS_BANNED, "BANNED" },
574 { NODE_FLAGS_UNHEALTHY, "UNHEALTHY" },
575 { NODE_FLAGS_DELETED, "DELETED" },
576 { NODE_FLAGS_STOPPED, "STOPPED" },
577 { NODE_FLAGS_INACTIVE, "INACTIVE" },
579 char *flags_str = NULL;
582 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
585 if (nodemap->nodes[i].flags == 0) {
586 struct ctdb_control_get_ifaces *ifaces;
588 ret = ctdb_ctrl_get_ifaces(ctdb, TIMELIMIT(),
589 nodemap->nodes[i].pnn,
592 for (j=0; j < ifaces->num; j++) {
593 if (ifaces->ifaces[j].link_state != 0) {
596 flags_str = talloc_strdup(ctdb, "PARTIALLYONLINE");
602 for (j=0;j<ARRAY_SIZE(flag_names);j++) {
603 if (nodemap->nodes[i].flags & flag_names[j].flag) {
604 if (flags_str == NULL) {
605 flags_str = talloc_strdup(ctdb, flag_names[j].name);
607 flags_str = talloc_asprintf_append(flags_str, "|%s",
610 CTDB_NO_MEMORY_FATAL(ctdb, flags_str);
613 if (flags_str == NULL) {
614 flags_str = talloc_strdup(ctdb, "OK");
615 CTDB_NO_MEMORY_FATAL(ctdb, flags_str);
617 printf("pnn:%d %-16s %s%s\n", nodemap->nodes[i].pnn,
618 ctdb_addr_to_str(&nodemap->nodes[i].addr),
620 nodemap->nodes[i].pnn == mypnn?" (THIS NODE)":"");
621 talloc_free(flags_str);
624 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &vnnmap);
626 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n", options.pnn));
629 if (vnnmap->generation == INVALID_GENERATION) {
630 printf("Generation:INVALID\n");
632 printf("Generation:%d\n",vnnmap->generation);
634 printf("Size:%d\n",vnnmap->size);
635 for(i=0;i<vnnmap->size;i++){
636 printf("hash:%d lmaster:%d\n", i, vnnmap->map[i]);
639 ret = ctdb_ctrl_getrecmode(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmode);
641 DEBUG(DEBUG_ERR, ("Unable to get recmode from node %u\n", options.pnn));
644 printf("Recovery mode:%s (%d)\n",recmode==CTDB_RECOVERY_NORMAL?"NORMAL":"RECOVERY",recmode);
646 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
648 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
651 printf("Recovery master:%d\n",recmaster);
658 struct natgw_node *next;
663 display the list of nodes belonging to this natgw configuration
665 static int control_natgwlist(struct ctdb_context *ctdb, int argc, const char **argv)
668 const char *natgw_list;
671 struct natgw_node *natgw_nodes = NULL;
672 struct natgw_node *natgw_node;
673 struct ctdb_node_map *nodemap=NULL;
676 /* read the natgw nodes file into a linked list */
677 natgw_list = getenv("NATGW_NODES");
678 if (natgw_list == NULL) {
679 natgw_list = "/etc/ctdb/natgw_nodes";
681 lines = file_lines_load(natgw_list, &nlines, ctdb);
683 ctdb_set_error(ctdb, "Failed to load natgw node list '%s'\n", natgw_list);
686 while (nlines > 0 && strcmp(lines[nlines-1], "") == 0) {
689 for (i=0;i<nlines;i++) {
693 /* strip leading spaces */
694 while((*node == ' ') || (*node == '\t')) {
700 if (strcmp(node, "") == 0) {
703 natgw_node = talloc(ctdb, struct natgw_node);
704 natgw_node->addr = talloc_strdup(natgw_node, node);
705 CTDB_NO_MEMORY(ctdb, natgw_node->addr);
706 natgw_node->next = natgw_nodes;
707 natgw_nodes = natgw_node;
710 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
712 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node.\n"));
717 while(i<nodemap->num) {
718 for(natgw_node=natgw_nodes;natgw_node;natgw_node=natgw_node->next) {
719 if (!strcmp(natgw_node->addr, ctdb_addr_to_str(&nodemap->nodes[i].addr))) {
724 /* this node was not in the natgw so we just remove it from
727 if ((natgw_node == NULL)
728 || (nodemap->nodes[i].flags & NODE_FLAGS_DISCONNECTED) ) {
731 for (j=i+1; j<nodemap->num; j++) {
732 nodemap->nodes[j-1] = nodemap->nodes[j];
741 /* pick a node to be natgwmaster
742 * we dont allow STOPPED, DELETED, BANNED or UNHEALTHY nodes to become the natgwmaster
744 for(i=0;i<nodemap->num;i++){
745 if (!(nodemap->nodes[i].flags & (NODE_FLAGS_DISCONNECTED|NODE_FLAGS_STOPPED|NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_UNHEALTHY))) {
746 printf("%d %s\n", nodemap->nodes[i].pnn,ctdb_addr_to_str(&nodemap->nodes[i].addr));
750 /* we couldnt find any healthy node, try unhealthy ones */
751 if (i == nodemap->num) {
752 for(i=0;i<nodemap->num;i++){
753 if (!(nodemap->nodes[i].flags & (NODE_FLAGS_DISCONNECTED|NODE_FLAGS_STOPPED|NODE_FLAGS_DELETED))) {
754 printf("%d %s\n", nodemap->nodes[i].pnn,ctdb_addr_to_str(&nodemap->nodes[i].addr));
759 /* unless all nodes are STOPPED, when we pick one anyway */
760 if (i == nodemap->num) {
761 for(i=0;i<nodemap->num;i++){
762 if (!(nodemap->nodes[i].flags & (NODE_FLAGS_DISCONNECTED|NODE_FLAGS_DELETED))) {
763 printf("%d %s\n", nodemap->nodes[i].pnn, ctdb_addr_to_str(&nodemap->nodes[i].addr));
767 /* or if we still can not find any */
768 if (i == nodemap->num) {
769 printf("-1 0.0.0.0\n");
773 /* print the pruned list of nodes belonging to this natgw list */
774 for(i=0;i<nodemap->num;i++){
775 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
778 printf(":%d:%s:%d:%d:%d:%d:%d\n", nodemap->nodes[i].pnn,
779 ctdb_addr_to_str(&nodemap->nodes[i].addr),
780 !!(nodemap->nodes[i].flags&NODE_FLAGS_DISCONNECTED),
781 !!(nodemap->nodes[i].flags&NODE_FLAGS_BANNED),
782 !!(nodemap->nodes[i].flags&NODE_FLAGS_PERMANENTLY_DISABLED),
783 !!(nodemap->nodes[i].flags&NODE_FLAGS_UNHEALTHY),
784 !!(nodemap->nodes[i].flags&NODE_FLAGS_STOPPED));
791 display the status of the scripts for monitoring (or other events)
793 static int control_one_scriptstatus(struct ctdb_context *ctdb,
794 enum ctdb_eventscript_call type)
796 struct ctdb_scripts_wire *script_status;
799 ret = ctdb_ctrl_getscriptstatus(ctdb, TIMELIMIT(), options.pnn, ctdb, type, &script_status);
801 DEBUG(DEBUG_ERR, ("Unable to get script status from node %u\n", options.pnn));
805 if (script_status == NULL) {
806 if (!options.machinereadable) {
807 printf("%s cycle never run\n",
808 ctdb_eventscript_call_names[type]);
813 if (!options.machinereadable) {
814 printf("%d scripts were executed last %s cycle\n",
815 script_status->num_scripts,
816 ctdb_eventscript_call_names[type]);
818 for (i=0; i<script_status->num_scripts; i++) {
819 const char *status = NULL;
821 switch (script_status->scripts[i].status) {
832 if (script_status->scripts[i].status > 0)
836 if (options.machinereadable) {
837 printf("%s:%s:%i:%s:%lu.%06lu:%lu.%06lu:%s:\n",
838 ctdb_eventscript_call_names[type],
839 script_status->scripts[i].name,
840 script_status->scripts[i].status,
842 (long)script_status->scripts[i].start.tv_sec,
843 (long)script_status->scripts[i].start.tv_usec,
844 (long)script_status->scripts[i].finished.tv_sec,
845 (long)script_status->scripts[i].finished.tv_usec,
846 script_status->scripts[i].output);
850 printf("%-20s Status:%s ",
851 script_status->scripts[i].name, status);
853 /* Some other error, eg from stat. */
854 printf("%-20s Status:CANNOT RUN (%s)",
855 script_status->scripts[i].name,
856 strerror(-script_status->scripts[i].status));
858 if (script_status->scripts[i].status >= 0) {
859 printf("Duration:%.3lf ",
860 timeval_delta(&script_status->scripts[i].finished,
861 &script_status->scripts[i].start));
863 if (script_status->scripts[i].status != -ENOEXEC) {
865 ctime(&script_status->scripts[i].start.tv_sec));
866 if (script_status->scripts[i].status != 0) {
867 printf(" OUTPUT:%s\n",
868 script_status->scripts[i].output);
878 static int control_scriptstatus(struct ctdb_context *ctdb,
879 int argc, const char **argv)
882 enum ctdb_eventscript_call type, min, max;
886 DEBUG(DEBUG_ERR, ("Unknown arguments to scriptstatus\n"));
891 arg = ctdb_eventscript_call_names[CTDB_EVENT_MONITOR];
895 for (type = 0; type < CTDB_EVENT_MAX; type++) {
896 if (strcmp(arg, ctdb_eventscript_call_names[type]) == 0) {
902 if (type == CTDB_EVENT_MAX) {
903 if (strcmp(arg, "all") == 0) {
905 max = CTDB_EVENT_MAX;
907 DEBUG(DEBUG_ERR, ("Unknown event type %s\n", argv[0]));
912 if (options.machinereadable) {
913 printf(":Type:Name:Code:Status:Start:End:Error Output...:\n");
916 for (type = min; type < max; type++) {
917 ret = control_one_scriptstatus(ctdb, type);
927 enable an eventscript
929 static int control_enablescript(struct ctdb_context *ctdb, int argc, const char **argv)
937 ret = ctdb_ctrl_enablescript(ctdb, TIMELIMIT(), options.pnn, argv[0]);
939 DEBUG(DEBUG_ERR, ("Unable to enable script %s on node %u\n", argv[0], options.pnn));
947 disable an eventscript
949 static int control_disablescript(struct ctdb_context *ctdb, int argc, const char **argv)
957 ret = ctdb_ctrl_disablescript(ctdb, TIMELIMIT(), options.pnn, argv[0]);
959 DEBUG(DEBUG_ERR, ("Unable to disable script %s on node %u\n", argv[0], options.pnn));
967 display the pnn of the recovery master
969 static int control_recmaster(struct ctdb_context *ctdb, int argc, const char **argv)
974 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
976 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
979 printf("%d\n",recmaster);
985 add a tickle to a public address
987 static int control_add_tickle(struct ctdb_context *ctdb, int argc, const char **argv)
989 struct ctdb_tcp_connection t;
997 if (parse_ip_port(argv[0], &t.src_addr) == 0) {
998 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1001 if (parse_ip_port(argv[1], &t.dst_addr) == 0) {
1002 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[1]));
1006 data.dptr = (uint8_t *)&t;
1007 data.dsize = sizeof(t);
1009 /* tell all nodes about this tcp connection */
1010 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_TCP_ADD_DELAYED_UPDATE,
1011 0, data, ctdb, NULL, NULL, NULL, NULL);
1013 DEBUG(DEBUG_ERR,("Failed to add tickle\n"));
1022 delete a tickle from a node
1024 static int control_del_tickle(struct ctdb_context *ctdb, int argc, const char **argv)
1026 struct ctdb_tcp_connection t;
1034 if (parse_ip_port(argv[0], &t.src_addr) == 0) {
1035 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1038 if (parse_ip_port(argv[1], &t.dst_addr) == 0) {
1039 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[1]));
1043 data.dptr = (uint8_t *)&t;
1044 data.dsize = sizeof(t);
1046 /* tell all nodes about this tcp connection */
1047 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_TCP_REMOVE,
1048 0, data, ctdb, NULL, NULL, NULL, NULL);
1050 DEBUG(DEBUG_ERR,("Failed to remove tickle\n"));
1059 get a list of all tickles for this pnn
1061 static int control_get_tickles(struct ctdb_context *ctdb, int argc, const char **argv)
1063 struct ctdb_control_tcp_tickle_list *list;
1064 ctdb_sock_addr addr;
1073 port = atoi(argv[1]);
1076 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1077 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1081 ret = ctdb_ctrl_get_tcp_tickles(ctdb, TIMELIMIT(), options.pnn, ctdb, &addr, &list);
1083 DEBUG(DEBUG_ERR, ("Unable to list tickles\n"));
1087 if (options.machinereadable){
1088 printf(":source ip:port:destination ip:port:\n");
1089 for (i=0;i<list->tickles.num;i++) {
1090 if (port && port != ntohs(list->tickles.connections[i].dst_addr.ip.sin_port)) {
1093 printf(":%s:%u", ctdb_addr_to_str(&list->tickles.connections[i].src_addr), ntohs(list->tickles.connections[i].src_addr.ip.sin_port));
1094 printf(":%s:%u:\n", ctdb_addr_to_str(&list->tickles.connections[i].dst_addr), ntohs(list->tickles.connections[i].dst_addr.ip.sin_port));
1097 printf("Tickles for ip:%s\n", ctdb_addr_to_str(&list->addr));
1098 printf("Num tickles:%u\n", list->tickles.num);
1099 for (i=0;i<list->tickles.num;i++) {
1100 if (port && port != ntohs(list->tickles.connections[i].dst_addr.ip.sin_port)) {
1103 printf("SRC: %s:%u ", ctdb_addr_to_str(&list->tickles.connections[i].src_addr), ntohs(list->tickles.connections[i].src_addr.ip.sin_port));
1104 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));
1114 static int move_ip(struct ctdb_context *ctdb, ctdb_sock_addr *addr, uint32_t pnn)
1116 struct ctdb_all_public_ips *ips;
1117 struct ctdb_public_ip ip;
1120 uint32_t disable_time;
1122 struct ctdb_node_map *nodemap=NULL;
1123 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1126 data.dptr = (uint8_t*)&disable_time;
1127 data.dsize = sizeof(disable_time);
1128 ret = ctdb_client_send_message(ctdb, CTDB_BROADCAST_CONNECTED, CTDB_SRVID_DISABLE_IP_CHECK, data);
1130 DEBUG(DEBUG_ERR,("Failed to send message to disable ipcheck\n"));
1136 /* read the public ip list from the node */
1137 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), pnn, ctdb, &ips);
1139 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", pnn));
1140 talloc_free(tmp_ctx);
1144 for (i=0;i<ips->num;i++) {
1145 if (ctdb_same_ip(addr, &ips->ips[i].addr)) {
1150 DEBUG(DEBUG_ERR, ("Node %u can not host ip address '%s'\n",
1151 pnn, ctdb_addr_to_str(addr)));
1152 talloc_free(tmp_ctx);
1159 data.dptr = (uint8_t *)&ip;
1160 data.dsize = sizeof(ip);
1162 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &nodemap);
1164 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1165 talloc_free(tmp_ctx);
1169 nodes = list_of_active_nodes_except_pnn(ctdb, nodemap, tmp_ctx, pnn);
1170 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_RELEASE_IP,
1177 DEBUG(DEBUG_ERR,("Failed to release IP on nodes\n"));
1178 talloc_free(tmp_ctx);
1182 ret = ctdb_ctrl_takeover_ip(ctdb, LONGTIMELIMIT(), pnn, &ip);
1184 DEBUG(DEBUG_ERR,("Failed to take over IP on node %d\n", pnn));
1185 talloc_free(tmp_ctx);
1189 /* update the recovery daemon so it now knows to expect the new
1190 node assignment for this ip.
1192 ret = ctdb_client_send_message(ctdb, CTDB_BROADCAST_CONNECTED, CTDB_SRVID_RECD_UPDATE_IP, data);
1194 DEBUG(DEBUG_ERR,("Failed to send message to update the ip on the recovery master.\n"));
1198 talloc_free(tmp_ctx);
1203 move/failover an ip address to a specific node
1205 static int control_moveip(struct ctdb_context *ctdb, int argc, const char **argv)
1208 ctdb_sock_addr addr;
1215 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1216 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1221 if (sscanf(argv[1], "%u", &pnn) != 1) {
1222 DEBUG(DEBUG_ERR, ("Badly formed pnn\n"));
1226 if (move_ip(ctdb, &addr, pnn) != 0) {
1227 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", pnn));
1234 void getips_store_callback(void *param, void *data)
1236 struct ctdb_public_ip *node_ip = (struct ctdb_public_ip *)data;
1237 struct ctdb_all_public_ips *ips = param;
1241 ips->ips[i].pnn = node_ip->pnn;
1242 ips->ips[i].addr = node_ip->addr;
1245 void getips_count_callback(void *param, void *data)
1247 uint32_t *count = param;
1253 static uint32_t *ip_key(ctdb_sock_addr *ip)
1255 static uint32_t key[IP_KEYLEN];
1257 bzero(key, sizeof(key));
1259 switch (ip->sa.sa_family) {
1261 key[0] = ip->ip.sin_addr.s_addr;
1264 key[0] = ip->ip6.sin6_addr.s6_addr32[3];
1265 key[1] = ip->ip6.sin6_addr.s6_addr32[2];
1266 key[2] = ip->ip6.sin6_addr.s6_addr32[1];
1267 key[3] = ip->ip6.sin6_addr.s6_addr32[0];
1270 DEBUG(DEBUG_ERR, (__location__ " ERROR, unknown family passed :%u\n", ip->sa.sa_family));
1277 static void *add_ip_callback(void *parm, void *data)
1283 control_get_all_public_ips(struct ctdb_context *ctdb, TALLOC_CTX *tmp_ctx, struct ctdb_all_public_ips **ips)
1285 struct ctdb_all_public_ips *tmp_ips;
1286 struct ctdb_node_map *nodemap=NULL;
1287 trbt_tree_t *ip_tree;
1291 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1293 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1297 ip_tree = trbt_create(tmp_ctx, 0);
1299 for(i=0;i<nodemap->num;i++){
1300 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
1303 if (nodemap->nodes[i].flags & NODE_FLAGS_DISCONNECTED) {
1307 /* read the public ip list from this node */
1308 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &tmp_ips);
1310 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", nodemap->nodes[i].pnn));
1314 for (j=0; j<tmp_ips->num;j++) {
1315 struct ctdb_public_ip *node_ip;
1317 node_ip = talloc(tmp_ctx, struct ctdb_public_ip);
1318 node_ip->pnn = tmp_ips->ips[j].pnn;
1319 node_ip->addr = tmp_ips->ips[j].addr;
1321 trbt_insertarray32_callback(ip_tree,
1322 IP_KEYLEN, ip_key(&tmp_ips->ips[j].addr),
1326 talloc_free(tmp_ips);
1331 trbt_traversearray32(ip_tree, IP_KEYLEN, getips_count_callback, &count);
1333 len = offsetof(struct ctdb_all_public_ips, ips) +
1334 count*sizeof(struct ctdb_public_ip);
1335 tmp_ips = talloc_zero_size(tmp_ctx, len);
1336 trbt_traversearray32(ip_tree, IP_KEYLEN, getips_store_callback, tmp_ips);
1345 * scans all other nodes and returns a pnn for another node that can host this
1349 find_other_host_for_public_ip(struct ctdb_context *ctdb, ctdb_sock_addr *addr)
1351 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1352 struct ctdb_all_public_ips *ips;
1353 struct ctdb_node_map *nodemap=NULL;
1356 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1358 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
1359 talloc_free(tmp_ctx);
1363 for(i=0;i<nodemap->num;i++){
1364 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1367 if (nodemap->nodes[i].pnn == options.pnn) {
1371 /* read the public ip list from this node */
1372 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips);
1374 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %u\n", nodemap->nodes[i].pnn));
1378 for (j=0;j<ips->num;j++) {
1379 if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1380 talloc_free(tmp_ctx);
1381 return nodemap->nodes[i].pnn;
1387 talloc_free(tmp_ctx);
1392 add a public ip address to a node
1394 static int control_addip(struct ctdb_context *ctdb, int argc, const char **argv)
1400 ctdb_sock_addr addr;
1401 struct ctdb_control_ip_iface *pub;
1402 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1403 struct ctdb_all_public_ips *ips;
1407 talloc_free(tmp_ctx);
1411 if (!parse_ip_mask(argv[0], argv[1], &addr, &mask)) {
1412 DEBUG(DEBUG_ERR, ("Badly formed ip/mask : %s\n", argv[0]));
1413 talloc_free(tmp_ctx);
1417 ret = control_get_all_public_ips(ctdb, tmp_ctx, &ips);
1419 DEBUG(DEBUG_ERR, ("Unable to get public ip list from cluster\n"));
1420 talloc_free(tmp_ctx);
1425 /* check if some other node is already serving this ip, if not,
1428 for (i=0;i<ips->num;i++) {
1429 if (ctdb_same_ip(&addr, &ips->ips[i].addr)) {
1434 len = offsetof(struct ctdb_control_ip_iface, iface) + strlen(argv[1]) + 1;
1435 pub = talloc_size(tmp_ctx, len);
1436 CTDB_NO_MEMORY(ctdb, pub);
1440 pub->len = strlen(argv[1])+1;
1441 memcpy(&pub->iface[0], argv[1], strlen(argv[1])+1);
1443 ret = ctdb_ctrl_add_public_ip(ctdb, TIMELIMIT(), options.pnn, pub);
1445 DEBUG(DEBUG_ERR, ("Unable to add public ip to node %u\n", options.pnn));
1446 talloc_free(tmp_ctx);
1450 if (i == ips->num) {
1451 /* no one has this ip so we claim it */
1454 pnn = ips->ips[i].pnn;
1457 if (move_ip(ctdb, &addr, pnn) != 0) {
1458 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", pnn));
1462 talloc_free(tmp_ctx);
1466 static int control_delip(struct ctdb_context *ctdb, int argc, const char **argv);
1468 static int control_delip_all(struct ctdb_context *ctdb, int argc, const char **argv, ctdb_sock_addr *addr)
1470 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1471 struct ctdb_node_map *nodemap=NULL;
1472 struct ctdb_all_public_ips *ips;
1475 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, tmp_ctx, &nodemap);
1477 DEBUG(DEBUG_ERR, ("Unable to get nodemap from current node\n"));
1481 /* remove it from the nodes that are not hosting the ip currently */
1482 for(i=0;i<nodemap->num;i++){
1483 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1486 if (ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips) != 0) {
1487 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %d\n", nodemap->nodes[i].pnn));
1491 for (j=0;j<ips->num;j++) {
1492 if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1500 if (ips->ips[j].pnn == nodemap->nodes[i].pnn) {
1504 options.pnn = nodemap->nodes[i].pnn;
1505 control_delip(ctdb, argc, argv);
1509 /* remove it from every node (also the one hosting it) */
1510 for(i=0;i<nodemap->num;i++){
1511 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
1514 if (ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), nodemap->nodes[i].pnn, tmp_ctx, &ips) != 0) {
1515 DEBUG(DEBUG_ERR, ("Unable to get public ip list from node %d\n", nodemap->nodes[i].pnn));
1519 for (j=0;j<ips->num;j++) {
1520 if (ctdb_same_ip(addr, &ips->ips[j].addr)) {
1528 options.pnn = nodemap->nodes[i].pnn;
1529 control_delip(ctdb, argc, argv);
1532 talloc_free(tmp_ctx);
1537 delete a public ip address from a node
1539 static int control_delip(struct ctdb_context *ctdb, int argc, const char **argv)
1542 ctdb_sock_addr addr;
1543 struct ctdb_control_ip_iface pub;
1544 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1545 struct ctdb_all_public_ips *ips;
1548 talloc_free(tmp_ctx);
1552 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1553 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1557 if (options.pnn == CTDB_BROADCAST_ALL) {
1558 return control_delip_all(ctdb, argc, argv, &addr);
1565 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &ips);
1567 DEBUG(DEBUG_ERR, ("Unable to get public ip list from cluster\n"));
1568 talloc_free(tmp_ctx);
1572 for (i=0;i<ips->num;i++) {
1573 if (ctdb_same_ip(&addr, &ips->ips[i].addr)) {
1579 DEBUG(DEBUG_ERR, ("This node does not support this public address '%s'\n",
1580 ctdb_addr_to_str(&addr)));
1581 talloc_free(tmp_ctx);
1585 if (ips->ips[i].pnn == options.pnn) {
1586 ret = find_other_host_for_public_ip(ctdb, &addr);
1588 if (move_ip(ctdb, &addr, ret) != 0) {
1589 DEBUG(DEBUG_ERR,("Failed to move ip to node %d\n", ret));
1595 ret = ctdb_ctrl_del_public_ip(ctdb, TIMELIMIT(), options.pnn, &pub);
1597 DEBUG(DEBUG_ERR, ("Unable to del public ip from node %u\n", options.pnn));
1598 talloc_free(tmp_ctx);
1602 talloc_free(tmp_ctx);
1607 kill a tcp connection
1609 static int kill_tcp(struct ctdb_context *ctdb, int argc, const char **argv)
1612 struct ctdb_control_killtcp killtcp;
1618 if (!parse_ip_port(argv[0], &killtcp.src_addr)) {
1619 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[0]));
1623 if (!parse_ip_port(argv[1], &killtcp.dst_addr)) {
1624 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[1]));
1628 ret = ctdb_ctrl_killtcp(ctdb, TIMELIMIT(), options.pnn, &killtcp);
1630 DEBUG(DEBUG_ERR, ("Unable to killtcp from node %u\n", options.pnn));
1641 static int control_gratious_arp(struct ctdb_context *ctdb, int argc, const char **argv)
1644 ctdb_sock_addr addr;
1650 if (!parse_ip(argv[0], NULL, 0, &addr)) {
1651 DEBUG(DEBUG_ERR, ("Bad IP '%s'\n", argv[0]));
1655 ret = ctdb_ctrl_gratious_arp(ctdb, TIMELIMIT(), options.pnn, &addr, argv[1]);
1657 DEBUG(DEBUG_ERR, ("Unable to send gratious_arp from node %u\n", options.pnn));
1665 register a server id
1667 static int regsrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1670 struct ctdb_server_id server_id;
1676 server_id.pnn = strtoul(argv[0], NULL, 0);
1677 server_id.type = strtoul(argv[1], NULL, 0);
1678 server_id.server_id = strtoul(argv[2], NULL, 0);
1680 ret = ctdb_ctrl_register_server_id(ctdb, TIMELIMIT(), &server_id);
1682 DEBUG(DEBUG_ERR, ("Unable to register server_id from node %u\n", options.pnn));
1685 DEBUG(DEBUG_ERR,("Srvid registered. Sleeping for 999 seconds\n"));
1691 unregister a server id
1693 static int unregsrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1696 struct ctdb_server_id server_id;
1702 server_id.pnn = strtoul(argv[0], NULL, 0);
1703 server_id.type = strtoul(argv[1], NULL, 0);
1704 server_id.server_id = strtoul(argv[2], NULL, 0);
1706 ret = ctdb_ctrl_unregister_server_id(ctdb, TIMELIMIT(), &server_id);
1708 DEBUG(DEBUG_ERR, ("Unable to unregister server_id from node %u\n", options.pnn));
1715 check if a server id exists
1717 static int chksrvid(struct ctdb_context *ctdb, int argc, const char **argv)
1721 struct ctdb_server_id server_id;
1727 server_id.pnn = strtoul(argv[0], NULL, 0);
1728 server_id.type = strtoul(argv[1], NULL, 0);
1729 server_id.server_id = strtoul(argv[2], NULL, 0);
1731 ret = ctdb_ctrl_check_server_id(ctdb, TIMELIMIT(), options.pnn, &server_id, &status);
1733 DEBUG(DEBUG_ERR, ("Unable to check server_id from node %u\n", options.pnn));
1738 printf("Server id %d:%d:%d EXISTS\n", server_id.pnn, server_id.type, server_id.server_id);
1740 printf("Server id %d:%d:%d does NOT exist\n", server_id.pnn, server_id.type, server_id.server_id);
1746 get a list of all server ids that are registered on a node
1748 static int getsrvids(struct ctdb_context *ctdb, int argc, const char **argv)
1751 struct ctdb_server_id_list *server_ids;
1753 ret = ctdb_ctrl_get_server_id_list(ctdb, ctdb, TIMELIMIT(), options.pnn, &server_ids);
1755 DEBUG(DEBUG_ERR, ("Unable to get server_id list from node %u\n", options.pnn));
1759 for (i=0; i<server_ids->num; i++) {
1760 printf("Server id %d:%d:%d\n",
1761 server_ids->server_ids[i].pnn,
1762 server_ids->server_ids[i].type,
1763 server_ids->server_ids[i].server_id);
1770 send a tcp tickle ack
1772 static int tickle_tcp(struct ctdb_context *ctdb, int argc, const char **argv)
1775 ctdb_sock_addr src, dst;
1781 if (!parse_ip_port(argv[0], &src)) {
1782 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[0]));
1786 if (!parse_ip_port(argv[1], &dst)) {
1787 DEBUG(DEBUG_ERR, ("Bad IP:port '%s'\n", argv[1]));
1791 ret = ctdb_sys_send_tcp(&src, &dst, 0, 0, 0);
1795 DEBUG(DEBUG_ERR, ("Error while sending tickle ack\n"));
1802 display public ip status
1804 static int control_ip(struct ctdb_context *ctdb, int argc, const char **argv)
1807 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1808 struct ctdb_all_public_ips *ips;
1810 if (options.pnn == CTDB_BROADCAST_ALL) {
1811 /* read the list of public ips from all nodes */
1812 ret = control_get_all_public_ips(ctdb, tmp_ctx, &ips);
1814 /* read the public ip list from this node */
1815 ret = ctdb_ctrl_get_public_ips(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &ips);
1818 DEBUG(DEBUG_ERR, ("Unable to get public ips from node %u\n", options.pnn));
1819 talloc_free(tmp_ctx);
1823 if (options.machinereadable){
1824 printf(":Public IP:Node:");
1825 if (options.verbose){
1826 printf("ActiveInterface:AvailableInterfaces:ConfiguredInterfaces:");
1830 if (options.pnn == CTDB_BROADCAST_ALL) {
1831 printf("Public IPs on ALL nodes\n");
1833 printf("Public IPs on node %u\n", options.pnn);
1837 for (i=1;i<=ips->num;i++) {
1838 struct ctdb_control_public_ip_info *info = NULL;
1840 char *aciface = NULL;
1841 char *avifaces = NULL;
1842 char *cifaces = NULL;
1844 if (options.pnn == CTDB_BROADCAST_ALL) {
1845 pnn = ips->ips[ips->num-i].pnn;
1851 ret = ctdb_ctrl_get_public_ip_info(ctdb, TIMELIMIT(), pnn, ctdb,
1852 &ips->ips[ips->num-i].addr, &info);
1859 for (j=0; j < info->num; j++) {
1860 if (cifaces == NULL) {
1861 cifaces = talloc_strdup(info,
1862 info->ifaces[j].name);
1864 cifaces = talloc_asprintf_append(cifaces,
1866 info->ifaces[j].name);
1869 if (info->active_idx == j) {
1870 aciface = info->ifaces[j].name;
1873 if (info->ifaces[j].link_state == 0) {
1877 if (avifaces == NULL) {
1878 avifaces = talloc_strdup(info, info->ifaces[j].name);
1880 avifaces = talloc_asprintf_append(avifaces,
1882 info->ifaces[j].name);
1887 if (options.machinereadable){
1889 ctdb_addr_to_str(&ips->ips[ips->num-i].addr),
1890 ips->ips[ips->num-i].pnn);
1891 if (options.verbose){
1894 avifaces?avifaces:"",
1895 cifaces?cifaces:"");
1899 if (options.verbose) {
1900 printf("%s node[%d] active[%s] available[%s] configured[%s]\n",
1901 ctdb_addr_to_str(&ips->ips[ips->num-i].addr),
1902 ips->ips[ips->num-i].pnn,
1904 avifaces?avifaces:"",
1905 cifaces?cifaces:"");
1908 ctdb_addr_to_str(&ips->ips[ips->num-i].addr),
1909 ips->ips[ips->num-i].pnn);
1915 talloc_free(tmp_ctx);
1922 static int control_ipinfo(struct ctdb_context *ctdb, int argc, const char **argv)
1925 ctdb_sock_addr addr;
1926 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1927 struct ctdb_control_public_ip_info *info;
1930 talloc_free(tmp_ctx);
1934 if (parse_ip(argv[0], NULL, 0, &addr) == 0) {
1935 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s'\n", argv[0]));
1939 /* read the public ip info from this node */
1940 ret = ctdb_ctrl_get_public_ip_info(ctdb, TIMELIMIT(), options.pnn,
1941 tmp_ctx, &addr, &info);
1943 DEBUG(DEBUG_ERR, ("Unable to get public ip[%s]info from node %u\n",
1944 argv[0], options.pnn));
1945 talloc_free(tmp_ctx);
1949 printf("Public IP[%s] info on node %u\n",
1950 ctdb_addr_to_str(&info->ip.addr),
1953 printf("IP:%s\nCurrentNode:%d\nNumInterfaces:%u\n",
1954 ctdb_addr_to_str(&info->ip.addr),
1955 info->ip.pnn, info->num);
1957 for (i=0; i<info->num; i++) {
1958 info->ifaces[i].name[CTDB_IFACE_SIZE] = '\0';
1960 printf("Interface[%u]: Name:%s Link:%s References:%u%s\n",
1961 i+1, info->ifaces[i].name,
1962 info->ifaces[i].link_state?"up":"down",
1963 (unsigned int)info->ifaces[i].references,
1964 (i==info->active_idx)?" (active)":"");
1967 talloc_free(tmp_ctx);
1972 display interfaces status
1974 static int control_ifaces(struct ctdb_context *ctdb, int argc, const char **argv)
1977 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
1978 struct ctdb_control_get_ifaces *ifaces;
1980 /* read the public ip list from this node */
1981 ret = ctdb_ctrl_get_ifaces(ctdb, TIMELIMIT(), options.pnn,
1984 DEBUG(DEBUG_ERR, ("Unable to get interfaces from node %u\n",
1986 talloc_free(tmp_ctx);
1990 if (options.machinereadable){
1991 printf(":Name:LinkStatus:References:\n");
1993 printf("Interfaces on node %u\n", options.pnn);
1996 for (i=0; i<ifaces->num; i++) {
1997 if (options.machinereadable){
1998 printf(":%s:%s:%u\n",
1999 ifaces->ifaces[i].name,
2000 ifaces->ifaces[i].link_state?"1":"0",
2001 (unsigned int)ifaces->ifaces[i].references);
2003 printf("name:%s link:%s references:%u\n",
2004 ifaces->ifaces[i].name,
2005 ifaces->ifaces[i].link_state?"up":"down",
2006 (unsigned int)ifaces->ifaces[i].references);
2010 talloc_free(tmp_ctx);
2016 set link status of an interface
2018 static int control_setifacelink(struct ctdb_context *ctdb, int argc, const char **argv)
2021 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2022 struct ctdb_control_iface_info info;
2030 if (strlen(argv[0]) > CTDB_IFACE_SIZE) {
2031 DEBUG(DEBUG_ERR, ("interfaces name '%s' too long\n",
2033 talloc_free(tmp_ctx);
2036 strcpy(info.name, argv[0]);
2038 if (strcmp(argv[1], "up") == 0) {
2039 info.link_state = 1;
2040 } else if (strcmp(argv[1], "down") == 0) {
2041 info.link_state = 0;
2043 DEBUG(DEBUG_ERR, ("link state invalid '%s' should be 'up' or 'down'\n",
2045 talloc_free(tmp_ctx);
2049 /* read the public ip list from this node */
2050 ret = ctdb_ctrl_set_iface_link(ctdb, TIMELIMIT(), options.pnn,
2053 DEBUG(DEBUG_ERR, ("Unable to set link state for interfaces %s node %u\n",
2054 argv[0], options.pnn));
2055 talloc_free(tmp_ctx);
2059 talloc_free(tmp_ctx);
2064 display pid of a ctdb daemon
2066 static int control_getpid(struct ctdb_context *ctdb, int argc, const char **argv)
2071 ret = ctdb_ctrl_getpid(ctdb, TIMELIMIT(), options.pnn, &pid);
2073 DEBUG(DEBUG_ERR, ("Unable to get daemon pid from node %u\n", options.pnn));
2076 printf("Pid:%d\n", pid);
2081 static uint32_t ipreallocate_finished;
2084 handler for receiving the response to ipreallocate
2086 static void ip_reallocate_handler(struct ctdb_context *ctdb, uint64_t srvid,
2087 TDB_DATA data, void *private_data)
2089 ipreallocate_finished = 1;
2092 static void ctdb_every_second(struct event_context *ev, struct timed_event *te, struct timeval t, void *p)
2094 struct ctdb_context *ctdb = talloc_get_type(p, struct ctdb_context);
2096 event_add_timed(ctdb->ev, ctdb,
2097 timeval_current_ofs(1, 0),
2098 ctdb_every_second, ctdb);
2102 ask the recovery daemon on the recovery master to perform a ip reallocation
2104 static int control_ipreallocate(struct ctdb_context *ctdb, int argc, const char **argv)
2108 struct takeover_run_reply rd;
2110 struct ctdb_node_map *nodemap=NULL;
2112 struct timeval tv = timeval_current();
2114 /* we need some events to trigger so we can timeout and restart
2117 event_add_timed(ctdb->ev, ctdb,
2118 timeval_current_ofs(1, 0),
2119 ctdb_every_second, ctdb);
2121 rd.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
2123 DEBUG(DEBUG_ERR, ("Failed to get pnn of local node\n"));
2126 rd.srvid = getpid();
2128 /* register a message port for receiveing the reply so that we
2129 can receive the reply
2131 ctdb_client_set_message_handler(ctdb, rd.srvid, ip_reallocate_handler, NULL);
2133 data.dptr = (uint8_t *)&rd;
2134 data.dsize = sizeof(rd);
2137 /* check that there are valid nodes available */
2138 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap) != 0) {
2139 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2142 for (i=0; i<nodemap->num;i++) {
2143 if ((nodemap->nodes[i].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) == 0) {
2147 if (i==nodemap->num) {
2148 DEBUG(DEBUG_ERR,("No recmaster available, no need to wait for cluster convergence\n"));
2153 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
2155 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
2159 /* verify the node exists */
2160 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), recmaster, ctdb, &nodemap) != 0) {
2161 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2166 /* check tha there are nodes available that can act as a recmaster */
2167 for (i=0; i<nodemap->num; i++) {
2168 if (nodemap->nodes[i].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
2173 if (i == nodemap->num) {
2174 DEBUG(DEBUG_ERR,("No possible nodes to host addresses.\n"));
2178 /* verify the recovery master is not STOPPED, nor BANNED */
2179 if (nodemap->nodes[recmaster].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
2180 DEBUG(DEBUG_ERR,("No suitable recmaster found. Try again\n"));
2187 /* verify the recovery master is not STOPPED, nor BANNED */
2188 if (nodemap->nodes[recmaster].flags & (NODE_FLAGS_DELETED|NODE_FLAGS_BANNED|NODE_FLAGS_STOPPED)) {
2189 DEBUG(DEBUG_ERR,("No suitable recmaster found. Try again\n"));
2195 ipreallocate_finished = 0;
2196 ret = ctdb_client_send_message(ctdb, recmaster, CTDB_SRVID_TAKEOVER_RUN, data);
2198 DEBUG(DEBUG_ERR,("Failed to send ip takeover run request message to %u\n", options.pnn));
2202 tv = timeval_current();
2203 /* this loop will terminate when we have received the reply */
2204 while (timeval_elapsed(&tv) < 3.0) {
2205 event_loop_once(ctdb->ev);
2207 if (ipreallocate_finished == 1) {
2211 DEBUG(DEBUG_ERR,("Timed out waiting for recmaster ipreallocate. Trying again\n"));
2221 disable a remote node
2223 static int control_disable(struct ctdb_context *ctdb, int argc, const char **argv)
2226 struct ctdb_node_map *nodemap=NULL;
2228 /* check if the node is already disabled */
2229 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2230 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2233 if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2234 DEBUG(DEBUG_ERR,("Node %d is already disabled.\n", options.pnn));
2239 ret = ctdb_ctrl_modflags(ctdb, TIMELIMIT(), options.pnn, NODE_FLAGS_PERMANENTLY_DISABLED, 0);
2241 DEBUG(DEBUG_ERR, ("Unable to disable node %u\n", options.pnn));
2247 /* read the nodemap and verify the change took effect */
2248 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2249 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2253 } while (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED));
2254 ret = control_ipreallocate(ctdb, argc, argv);
2256 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2264 enable a disabled remote node
2266 static int control_enable(struct ctdb_context *ctdb, int argc, const char **argv)
2270 struct ctdb_node_map *nodemap=NULL;
2273 /* check if the node is already enabled */
2274 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2275 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2278 if (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED)) {
2279 DEBUG(DEBUG_ERR,("Node %d is already enabled.\n", options.pnn));
2284 ret = ctdb_ctrl_modflags(ctdb, TIMELIMIT(), options.pnn, 0, NODE_FLAGS_PERMANENTLY_DISABLED);
2286 DEBUG(DEBUG_ERR, ("Unable to enable node %u\n", options.pnn));
2292 /* read the nodemap and verify the change took effect */
2293 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2294 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2298 } while (nodemap->nodes[options.pnn].flags & NODE_FLAGS_PERMANENTLY_DISABLED);
2300 ret = control_ipreallocate(ctdb, argc, argv);
2302 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2312 static int control_stop(struct ctdb_context *ctdb, int argc, const char **argv)
2315 struct ctdb_node_map *nodemap=NULL;
2318 ret = ctdb_ctrl_stop_node(ctdb, TIMELIMIT(), options.pnn);
2320 DEBUG(DEBUG_ERR, ("Unable to stop node %u try again\n", options.pnn));
2325 /* read the nodemap and verify the change took effect */
2326 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2327 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2331 } while (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_STOPPED));
2332 ret = control_ipreallocate(ctdb, argc, argv);
2334 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2342 restart a stopped remote node
2344 static int control_continue(struct ctdb_context *ctdb, int argc, const char **argv)
2348 struct ctdb_node_map *nodemap=NULL;
2351 ret = ctdb_ctrl_continue_node(ctdb, TIMELIMIT(), options.pnn);
2353 DEBUG(DEBUG_ERR, ("Unable to continue node %u\n", options.pnn));
2359 /* read the nodemap and verify the change took effect */
2360 if (ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap) != 0) {
2361 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2365 } while (nodemap->nodes[options.pnn].flags & NODE_FLAGS_STOPPED);
2366 ret = control_ipreallocate(ctdb, argc, argv);
2368 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2375 static uint32_t get_generation(struct ctdb_context *ctdb)
2377 struct ctdb_vnn_map *vnnmap=NULL;
2380 /* wait until the recmaster is not in recovery mode */
2382 uint32_t recmode, recmaster;
2384 if (vnnmap != NULL) {
2385 talloc_free(vnnmap);
2389 /* get the recmaster */
2390 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, &recmaster);
2392 DEBUG(DEBUG_ERR, ("Unable to get recmaster from node %u\n", options.pnn));
2396 /* get recovery mode */
2397 ret = ctdb_ctrl_getrecmode(ctdb, ctdb, TIMELIMIT(), recmaster, &recmode);
2399 DEBUG(DEBUG_ERR, ("Unable to get recmode from node %u\n", options.pnn));
2403 /* get the current generation number */
2404 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), recmaster, ctdb, &vnnmap);
2406 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from recmaster (%u)\n", recmaster));
2410 if ((recmode == CTDB_RECOVERY_NORMAL)
2411 && (vnnmap->generation != 1)){
2412 return vnnmap->generation;
2419 ban a node from the cluster
2421 static int control_ban(struct ctdb_context *ctdb, int argc, const char **argv)
2424 struct ctdb_node_map *nodemap=NULL;
2425 struct ctdb_ban_time bantime;
2431 /* verify the node exists */
2432 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
2434 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2438 if (nodemap->nodes[options.pnn].flags & NODE_FLAGS_BANNED) {
2439 DEBUG(DEBUG_ERR,("Node %u is already banned.\n", options.pnn));
2443 bantime.pnn = options.pnn;
2444 bantime.time = strtoul(argv[0], NULL, 0);
2446 ret = ctdb_ctrl_set_ban(ctdb, TIMELIMIT(), options.pnn, &bantime);
2448 DEBUG(DEBUG_ERR,("Banning node %d for %d seconds failed.\n", bantime.pnn, bantime.time));
2452 ret = control_ipreallocate(ctdb, argc, argv);
2454 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2463 unban a node from the cluster
2465 static int control_unban(struct ctdb_context *ctdb, int argc, const char **argv)
2468 struct ctdb_node_map *nodemap=NULL;
2469 struct ctdb_ban_time bantime;
2471 /* verify the node exists */
2472 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
2474 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2478 if (!(nodemap->nodes[options.pnn].flags & NODE_FLAGS_BANNED)) {
2479 DEBUG(DEBUG_ERR,("Node %u is not banned.\n", options.pnn));
2483 bantime.pnn = options.pnn;
2486 ret = ctdb_ctrl_set_ban(ctdb, TIMELIMIT(), options.pnn, &bantime);
2488 DEBUG(DEBUG_ERR,("Unbanning node %d failed.\n", bantime.pnn));
2492 ret = control_ipreallocate(ctdb, argc, argv);
2494 DEBUG(DEBUG_ERR, ("IP Reallocate failed on node %u\n", options.pnn));
2503 show ban information for a node
2505 static int control_showban(struct ctdb_context *ctdb, int argc, const char **argv)
2508 struct ctdb_node_map *nodemap=NULL;
2509 struct ctdb_ban_time *bantime;
2511 /* verify the node exists */
2512 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
2514 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
2518 ret = ctdb_ctrl_get_ban(ctdb, TIMELIMIT(), options.pnn, ctdb, &bantime);
2520 DEBUG(DEBUG_ERR,("Showing ban info for node %d failed.\n", options.pnn));
2524 if (bantime->time == 0) {
2525 printf("Node %u is not banned\n", bantime->pnn);
2527 printf("Node %u is banned banned for %d seconds\n", bantime->pnn, bantime->time);
2536 static int control_shutdown(struct ctdb_context *ctdb, int argc, const char **argv)
2540 ret = ctdb_ctrl_shutdown(ctdb, TIMELIMIT(), options.pnn);
2542 DEBUG(DEBUG_ERR, ("Unable to shutdown node %u\n", options.pnn));
2552 static int control_recover(struct ctdb_context *ctdb, int argc, const char **argv)
2555 uint32_t generation, next_generation;
2557 /* record the current generation number */
2558 generation = get_generation(ctdb);
2560 ret = ctdb_ctrl_freeze_priority(ctdb, TIMELIMIT(), options.pnn, 1);
2562 DEBUG(DEBUG_ERR, ("Unable to freeze node\n"));
2566 ret = ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
2568 DEBUG(DEBUG_ERR, ("Unable to set recovery mode\n"));
2572 /* wait until we are in a new generation */
2574 next_generation = get_generation(ctdb);
2575 if (next_generation != generation) {
2586 display monitoring mode of a remote node
2588 static int control_getmonmode(struct ctdb_context *ctdb, int argc, const char **argv)
2593 ret = ctdb_ctrl_getmonmode(ctdb, TIMELIMIT(), options.pnn, &monmode);
2595 DEBUG(DEBUG_ERR, ("Unable to get monmode from node %u\n", options.pnn));
2598 if (!options.machinereadable){
2599 printf("Monitoring mode:%s (%d)\n",monmode==CTDB_MONITORING_ACTIVE?"ACTIVE":"DISABLED",monmode);
2602 printf(":%d:\n",monmode);
2609 display capabilities of a remote node
2611 static int control_getcapabilities(struct ctdb_context *ctdb, int argc, const char **argv)
2613 uint32_t capabilities;
2616 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), options.pnn, &capabilities);
2618 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", options.pnn));
2622 if (!options.machinereadable){
2623 printf("RECMASTER: %s\n", (capabilities&CTDB_CAP_RECMASTER)?"YES":"NO");
2624 printf("LMASTER: %s\n", (capabilities&CTDB_CAP_LMASTER)?"YES":"NO");
2625 printf("LVS: %s\n", (capabilities&CTDB_CAP_LVS)?"YES":"NO");
2626 printf("NATGW: %s\n", (capabilities&CTDB_CAP_NATGW)?"YES":"NO");
2628 printf(":RECMASTER:LMASTER:LVS:NATGW:\n");
2629 printf(":%d:%d:%d:%d:\n",
2630 !!(capabilities&CTDB_CAP_RECMASTER),
2631 !!(capabilities&CTDB_CAP_LMASTER),
2632 !!(capabilities&CTDB_CAP_LVS),
2633 !!(capabilities&CTDB_CAP_NATGW));
2639 display lvs configuration
2641 static int control_lvs(struct ctdb_context *ctdb, int argc, const char **argv)
2643 uint32_t *capabilities;
2644 struct ctdb_node_map *nodemap=NULL;
2646 int healthy_count = 0;
2648 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
2650 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
2654 capabilities = talloc_array(ctdb, uint32_t, nodemap->num);
2655 CTDB_NO_MEMORY(ctdb, capabilities);
2657 /* collect capabilities for all connected nodes */
2658 for (i=0; i<nodemap->num; i++) {
2659 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2662 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2666 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), i, &capabilities[i]);
2668 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", i));
2672 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2676 if (!(nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY)) {
2681 /* Print all LVS nodes */
2682 for (i=0; i<nodemap->num; i++) {
2683 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2686 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2689 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2693 if (healthy_count != 0) {
2694 if (nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY) {
2699 printf("%d:%s\n", i,
2700 ctdb_addr_to_str(&nodemap->nodes[i].addr));
2707 display who is the lvs master
2709 static int control_lvsmaster(struct ctdb_context *ctdb, int argc, const char **argv)
2711 uint32_t *capabilities;
2712 struct ctdb_node_map *nodemap=NULL;
2714 int healthy_count = 0;
2716 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
2718 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
2722 capabilities = talloc_array(ctdb, uint32_t, nodemap->num);
2723 CTDB_NO_MEMORY(ctdb, capabilities);
2725 /* collect capabilities for all connected nodes */
2726 for (i=0; i<nodemap->num; i++) {
2727 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2730 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2734 ret = ctdb_ctrl_getcapabilities(ctdb, TIMELIMIT(), i, &capabilities[i]);
2736 DEBUG(DEBUG_ERR, ("Unable to get capabilities from node %u\n", i));
2740 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2744 if (!(nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY)) {
2749 /* find and show the lvsmaster */
2750 for (i=0; i<nodemap->num; i++) {
2751 if (nodemap->nodes[i].flags & NODE_FLAGS_INACTIVE) {
2754 if (nodemap->nodes[i].flags & NODE_FLAGS_PERMANENTLY_DISABLED) {
2757 if (!(capabilities[i] & CTDB_CAP_LVS)) {
2761 if (healthy_count != 0) {
2762 if (nodemap->nodes[i].flags & NODE_FLAGS_UNHEALTHY) {
2767 if (options.machinereadable){
2770 printf("Node %d is LVS master\n", i);
2775 printf("There is no LVS master\n");
2780 disable monitoring on a node
2782 static int control_disable_monmode(struct ctdb_context *ctdb, int argc, const char **argv)
2787 ret = ctdb_ctrl_disable_monmode(ctdb, TIMELIMIT(), options.pnn);
2789 DEBUG(DEBUG_ERR, ("Unable to disable monmode on node %u\n", options.pnn));
2792 printf("Monitoring mode:%s\n","DISABLED");
2798 enable monitoring on a node
2800 static int control_enable_monmode(struct ctdb_context *ctdb, int argc, const char **argv)
2805 ret = ctdb_ctrl_enable_monmode(ctdb, TIMELIMIT(), options.pnn);
2807 DEBUG(DEBUG_ERR, ("Unable to enable monmode on node %u\n", options.pnn));
2810 printf("Monitoring mode:%s\n","ACTIVE");
2816 display remote list of keys/data for a db
2818 static int control_catdb(struct ctdb_context *ctdb, int argc, const char **argv)
2820 const char *db_name;
2821 struct ctdb_db_context *ctdb_db;
2831 if (db_exists(ctdb, db_name)) {
2832 DEBUG(DEBUG_ERR,("Database '%s' does not exist\n", db_name));
2836 ctdb_db = ctdb_attach(ctdb, db_name, false, 0);
2838 if (ctdb_db == NULL) {
2839 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
2843 /* traverse and dump the cluster tdb */
2844 ret = ctdb_dump_db(ctdb_db, stdout);
2846 DEBUG(DEBUG_ERR, ("Unable to dump database\n"));
2847 DEBUG(DEBUG_ERR, ("Maybe try 'ctdb getdbstatus %s'"
2848 " and 'ctdb getvar AllowUnhealthyDBRead'\n",
2852 talloc_free(ctdb_db);
2854 printf("Dumped %d records\n", ret);
2859 static void log_handler(struct ctdb_context *ctdb, uint64_t srvid,
2860 TDB_DATA data, void *private_data)
2862 DEBUG(DEBUG_ERR,("Log data received\n"));
2863 if (data.dsize > 0) {
2864 printf("%s", data.dptr);
2871 display a list of log messages from the in memory ringbuffer
2873 static int control_getlog(struct ctdb_context *ctdb, int argc, const char **argv)
2877 struct ctdb_get_log_addr log_addr;
2879 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2884 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
2885 talloc_free(tmp_ctx);
2889 log_addr.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
2890 log_addr.srvid = getpid();
2891 if (isalpha(argv[0][0]) || argv[0][0] == '-') {
2892 log_addr.level = get_debug_by_desc(argv[0]);
2894 log_addr.level = strtol(argv[0], NULL, 0);
2898 data.dptr = (unsigned char *)&log_addr;
2899 data.dsize = sizeof(log_addr);
2901 DEBUG(DEBUG_ERR, ("Pulling logs from node %u\n", options.pnn));
2903 ctdb_client_set_message_handler(ctdb, log_addr.srvid, log_handler, NULL);
2906 DEBUG(DEBUG_ERR,("Listen for response on %d\n", (int)log_addr.srvid));
2908 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_GET_LOG,
2909 0, data, tmp_ctx, NULL, &res, NULL, &errmsg);
2910 if (ret != 0 || res != 0) {
2911 DEBUG(DEBUG_ERR,("Failed to get logs - %s\n", errmsg));
2912 talloc_free(tmp_ctx);
2917 tv = timeval_current();
2918 /* this loop will terminate when we have received the reply */
2919 while (timeval_elapsed(&tv) < 3.0) {
2920 event_loop_once(ctdb->ev);
2923 DEBUG(DEBUG_INFO,("Timed out waiting for log data.\n"));
2925 talloc_free(tmp_ctx);
2930 clear the in memory log area
2932 static int control_clearlog(struct ctdb_context *ctdb, int argc, const char **argv)
2937 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2939 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_CLEAR_LOG,
2940 0, tdb_null, tmp_ctx, NULL, &res, NULL, &errmsg);
2941 if (ret != 0 || res != 0) {
2942 DEBUG(DEBUG_ERR,("Failed to clear logs\n"));
2943 talloc_free(tmp_ctx);
2947 talloc_free(tmp_ctx);
2954 display a list of the databases on a remote ctdb
2956 static int control_getdbmap(struct ctdb_context *ctdb, int argc, const char **argv)
2959 struct ctdb_dbid_map *dbmap=NULL;
2961 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
2963 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
2967 if(options.machinereadable){
2968 printf(":ID:Name:Path:Persistent:Unhealthy:\n");
2969 for(i=0;i<dbmap->num;i++){
2975 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn,
2976 dbmap->dbs[i].dbid, ctdb, &path);
2977 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn,
2978 dbmap->dbs[i].dbid, ctdb, &name);
2979 ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn,
2980 dbmap->dbs[i].dbid, ctdb, &health);
2981 persistent = dbmap->dbs[i].persistent;
2982 printf(":0x%08X:%s:%s:%d:%d:\n",
2983 dbmap->dbs[i].dbid, name, path,
2984 !!(persistent), !!(health));
2989 printf("Number of databases:%d\n", dbmap->num);
2990 for(i=0;i<dbmap->num;i++){
2996 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &path);
2997 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
2998 ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &health);
2999 persistent = dbmap->dbs[i].persistent;
3000 printf("dbid:0x%08x name:%s path:%s%s%s\n",
3001 dbmap->dbs[i].dbid, name, path,
3002 persistent?" PERSISTENT":"",
3003 health?" UNHEALTHY":"");
3010 display the status of a database on a remote ctdb
3012 static int control_getdbstatus(struct ctdb_context *ctdb, int argc, const char **argv)
3015 struct ctdb_dbid_map *dbmap=NULL;
3016 const char *db_name;
3024 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
3026 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
3030 for(i=0;i<dbmap->num;i++){
3036 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
3037 if (strcmp(name, db_name) != 0) {
3041 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &path);
3042 ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &health);
3043 persistent = dbmap->dbs[i].persistent;
3044 printf("dbid: 0x%08x\nname: %s\npath: %s\nPERSISTENT: %s\nHEALTH: %s\n",
3045 dbmap->dbs[i].dbid, name, path,
3046 persistent?"yes":"no",
3047 health?health:"OK");
3051 DEBUG(DEBUG_ERR, ("db %s doesn't exist on node %u\n", db_name, options.pnn));
3056 check if the local node is recmaster or not
3057 it will return 1 if this node is the recmaster and 0 if it is not
3058 or if the local ctdb daemon could not be contacted
3060 static int control_isnotrecmaster(struct ctdb_context *ctdb, int argc, const char **argv)
3062 uint32_t mypnn, recmaster;
3065 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
3067 printf("Failed to get pnn of node\n");
3071 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
3073 printf("Failed to get the recmaster\n");
3077 if (recmaster != mypnn) {
3078 printf("this node is not the recmaster\n");
3082 printf("this node is the recmaster\n");
3089 static int control_ping(struct ctdb_context *ctdb, int argc, const char **argv)
3092 struct timeval tv = timeval_current();
3093 ret = ctdb_ctrl_ping(ctdb, options.pnn);
3095 printf("Unable to get ping response from node %u\n", options.pnn);
3098 printf("response from %u time=%.6f sec (%d clients)\n",
3099 options.pnn, timeval_elapsed(&tv), ret);
3108 static int control_getvar(struct ctdb_context *ctdb, int argc, const char **argv)
3119 ret = ctdb_ctrl_get_tunable(ctdb, TIMELIMIT(), options.pnn, name, &value);
3121 DEBUG(DEBUG_ERR, ("Unable to get tunable variable '%s'\n", name));
3125 printf("%-19s = %u\n", name, value);
3132 static int control_setvar(struct ctdb_context *ctdb, int argc, const char **argv)
3143 value = strtoul(argv[1], NULL, 0);
3145 ret = ctdb_ctrl_set_tunable(ctdb, TIMELIMIT(), options.pnn, name, value);
3147 DEBUG(DEBUG_ERR, ("Unable to set tunable variable '%s'\n", name));
3156 static int control_listvars(struct ctdb_context *ctdb, int argc, const char **argv)
3162 ret = ctdb_ctrl_list_tunables(ctdb, TIMELIMIT(), options.pnn, ctdb, &list, &count);
3164 DEBUG(DEBUG_ERR, ("Unable to list tunable variables\n"));
3168 for (i=0;i<count;i++) {
3169 control_getvar(ctdb, 1, &list[i]);
3178 display debug level on a node
3180 static int control_getdebug(struct ctdb_context *ctdb, int argc, const char **argv)
3185 ret = ctdb_ctrl_get_debuglevel(ctdb, options.pnn, &level);
3187 DEBUG(DEBUG_ERR, ("Unable to get debuglevel response from node %u\n", options.pnn));
3190 if (options.machinereadable){
3191 printf(":Name:Level:\n");
3192 printf(":%s:%d:\n",get_debug_by_level(level),level);
3194 printf("Node %u is at debug level %s (%d)\n", options.pnn, get_debug_by_level(level), level);
3201 display reclock file of a node
3203 static int control_getreclock(struct ctdb_context *ctdb, int argc, const char **argv)
3206 const char *reclock;
3208 ret = ctdb_ctrl_getreclock(ctdb, TIMELIMIT(), options.pnn, ctdb, &reclock);
3210 DEBUG(DEBUG_ERR, ("Unable to get reclock file from node %u\n", options.pnn));
3213 if (options.machinereadable){
3214 if (reclock != NULL) {
3215 printf("%s", reclock);
3218 if (reclock == NULL) {
3219 printf("No reclock file used.\n");
3221 printf("Reclock file:%s\n", reclock);
3229 set the reclock file of a node
3231 static int control_setreclock(struct ctdb_context *ctdb, int argc, const char **argv)
3234 const char *reclock;
3238 } else if (argc == 1) {
3244 ret = ctdb_ctrl_setreclock(ctdb, TIMELIMIT(), options.pnn, reclock);
3246 DEBUG(DEBUG_ERR, ("Unable to get reclock file from node %u\n", options.pnn));
3253 set the natgw state on/off
3255 static int control_setnatgwstate(struct ctdb_context *ctdb, int argc, const char **argv)
3258 uint32_t natgwstate;
3264 if (!strcmp(argv[0], "on")) {
3266 } else if (!strcmp(argv[0], "off")) {
3272 ret = ctdb_ctrl_setnatgwstate(ctdb, TIMELIMIT(), options.pnn, natgwstate);
3274 DEBUG(DEBUG_ERR, ("Unable to set the natgw state for node %u\n", options.pnn));
3282 set the lmaster role on/off
3284 static int control_setlmasterrole(struct ctdb_context *ctdb, int argc, const char **argv)
3287 uint32_t lmasterrole;
3293 if (!strcmp(argv[0], "on")) {
3295 } else if (!strcmp(argv[0], "off")) {
3301 ret = ctdb_ctrl_setlmasterrole(ctdb, TIMELIMIT(), options.pnn, lmasterrole);
3303 DEBUG(DEBUG_ERR, ("Unable to set the lmaster role for node %u\n", options.pnn));
3311 set the recmaster role on/off
3313 static int control_setrecmasterrole(struct ctdb_context *ctdb, int argc, const char **argv)
3316 uint32_t recmasterrole;
3322 if (!strcmp(argv[0], "on")) {
3324 } else if (!strcmp(argv[0], "off")) {
3330 ret = ctdb_ctrl_setrecmasterrole(ctdb, TIMELIMIT(), options.pnn, recmasterrole);
3332 DEBUG(DEBUG_ERR, ("Unable to set the recmaster role for node %u\n", options.pnn));
3340 set debug level on a node or all nodes
3342 static int control_setdebug(struct ctdb_context *ctdb, int argc, const char **argv)
3348 printf("You must specify the debug level. Valid levels are:\n");
3349 for (i=0; debug_levels[i].description != NULL; i++) {
3350 printf("%s (%d)\n", debug_levels[i].description, debug_levels[i].level);
3356 if (isalpha(argv[0][0]) || argv[0][0] == '-') {
3357 level = get_debug_by_desc(argv[0]);
3359 level = strtol(argv[0], NULL, 0);
3362 for (i=0; debug_levels[i].description != NULL; i++) {
3363 if (level == debug_levels[i].level) {
3367 if (debug_levels[i].description == NULL) {
3368 printf("Invalid debug level, must be one of\n");
3369 for (i=0; debug_levels[i].description != NULL; i++) {
3370 printf("%s (%d)\n", debug_levels[i].description, debug_levels[i].level);
3375 ret = ctdb_ctrl_set_debuglevel(ctdb, options.pnn, level);
3377 DEBUG(DEBUG_ERR, ("Unable to set debug level on node %u\n", options.pnn));
3386 static int control_thaw(struct ctdb_context *ctdb, int argc, const char **argv)
3392 priority = strtol(argv[0], NULL, 0);
3396 DEBUG(DEBUG_ERR,("Thaw by priority %u\n", priority));
3398 ret = ctdb_ctrl_thaw_priority(ctdb, TIMELIMIT(), options.pnn, priority);
3400 DEBUG(DEBUG_ERR, ("Unable to thaw node %u\n", options.pnn));
3407 attach to a database
3409 static int control_attach(struct ctdb_context *ctdb, int argc, const char **argv)
3411 const char *db_name;
3412 struct ctdb_db_context *ctdb_db;
3419 ctdb_db = ctdb_attach(ctdb, db_name, false, 0);
3420 if (ctdb_db == NULL) {
3421 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
3431 static int control_setdbprio(struct ctdb_context *ctdb, int argc, const char **argv)
3433 struct ctdb_db_priority db_prio;
3440 db_prio.db_id = strtoul(argv[0], NULL, 0);
3441 db_prio.priority = strtoul(argv[1], NULL, 0);
3443 ret = ctdb_ctrl_set_db_priority(ctdb, TIMELIMIT(), options.pnn, &db_prio);
3445 DEBUG(DEBUG_ERR,("Unable to set db prio\n"));
3455 static int control_getdbprio(struct ctdb_context *ctdb, int argc, const char **argv)
3457 uint32_t db_id, priority;
3464 db_id = strtoul(argv[0], NULL, 0);
3466 ret = ctdb_ctrl_get_db_priority(ctdb, TIMELIMIT(), options.pnn, db_id, &priority);
3468 DEBUG(DEBUG_ERR,("Unable to get db prio\n"));
3472 DEBUG(DEBUG_ERR,("Priority:%u\n", priority));
3478 run an eventscript on a node
3480 static int control_eventscript(struct ctdb_context *ctdb, int argc, const char **argv)
3486 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3489 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3493 data.dptr = (unsigned char *)discard_const(argv[0]);
3494 data.dsize = strlen((char *)data.dptr) + 1;
3496 DEBUG(DEBUG_ERR, ("Running eventscripts with arguments \"%s\" on node %u\n", data.dptr, options.pnn));
3498 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_RUN_EVENTSCRIPTS,
3499 0, data, tmp_ctx, NULL, &res, NULL, &errmsg);
3500 if (ret != 0 || res != 0) {
3501 DEBUG(DEBUG_ERR,("Failed to run eventscripts - %s\n", errmsg));
3502 talloc_free(tmp_ctx);
3505 talloc_free(tmp_ctx);
3509 #define DB_VERSION 1
3510 #define MAX_DB_NAME 64
3511 struct db_file_header {
3512 unsigned long version;
3514 unsigned long persistent;
3516 const char name[MAX_DB_NAME];
3519 struct backup_data {
3520 struct ctdb_marshall_buffer *records;
3523 bool traverse_error;
3526 static int backup_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *private)
3528 struct backup_data *bd = talloc_get_type(private, struct backup_data);
3529 struct ctdb_rec_data *rec;
3531 /* add the record */
3532 rec = ctdb_marshall_record(bd->records, 0, key, NULL, data);
3534 bd->traverse_error = true;
3535 DEBUG(DEBUG_ERR,("Failed to marshall record\n"));
3538 bd->records = talloc_realloc_size(NULL, bd->records, rec->length + bd->len);
3539 if (bd->records == NULL) {
3540 DEBUG(DEBUG_ERR,("Failed to expand marshalling buffer\n"));
3541 bd->traverse_error = true;
3544 bd->records->count++;
3545 memcpy(bd->len+(uint8_t *)bd->records, rec, rec->length);
3546 bd->len += rec->length;
3554 * backup a database to a file
3556 static int control_backupdb(struct ctdb_context *ctdb, int argc, const char **argv)
3559 struct ctdb_dbid_map *dbmap=NULL;
3560 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3561 struct db_file_header dbhdr;
3562 struct ctdb_db_context *ctdb_db;
3563 struct backup_data *bd;
3566 const char *reason = NULL;
3569 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3573 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &dbmap);
3575 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
3579 for(i=0;i<dbmap->num;i++){
3582 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, tmp_ctx, &name);
3583 if(!strcmp(argv[0], name)){
3584 talloc_free(discard_const(name));
3587 talloc_free(discard_const(name));
3589 if (i == dbmap->num) {
3590 DEBUG(DEBUG_ERR,("No database with name '%s' found\n", argv[0]));
3591 talloc_free(tmp_ctx);
3595 ret = ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn,
3596 dbmap->dbs[i].dbid, tmp_ctx, &reason);
3598 DEBUG(DEBUG_ERR,("Unable to get dbhealth for database '%s'\n",
3600 talloc_free(tmp_ctx);
3604 uint32_t allow_unhealthy = 0;
3606 ctdb_ctrl_get_tunable(ctdb, TIMELIMIT(), options.pnn,
3607 "AllowUnhealthyDBRead",
3610 if (allow_unhealthy != 1) {
3611 DEBUG(DEBUG_ERR,("database '%s' is unhealthy: %s\n",
3614 DEBUG(DEBUG_ERR,("disallow backup : tunnable AllowUnhealthyDBRead = %u\n",
3616 talloc_free(tmp_ctx);
3620 DEBUG(DEBUG_WARNING,("WARNING database '%s' is unhealthy - see 'ctdb getdbstatus %s'\n",
3622 DEBUG(DEBUG_WARNING,("WARNING! allow backup of unhealthy database: "
3623 "tunnable AllowUnhealthyDBRead = %u\n",
3627 ctdb_db = ctdb_attach(ctdb, argv[0], dbmap->dbs[i].persistent, 0);
3628 if (ctdb_db == NULL) {
3629 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", argv[0]));
3630 talloc_free(tmp_ctx);
3635 ret = tdb_transaction_start(ctdb_db->ltdb->tdb);
3637 DEBUG(DEBUG_ERR,("Failed to start transaction\n"));
3638 talloc_free(tmp_ctx);
3643 bd = talloc_zero(tmp_ctx, struct backup_data);
3645 DEBUG(DEBUG_ERR,("Failed to allocate backup_data\n"));
3646 talloc_free(tmp_ctx);
3650 bd->records = talloc_zero(bd, struct ctdb_marshall_buffer);
3651 if (bd->records == NULL) {
3652 DEBUG(DEBUG_ERR,("Failed to allocate ctdb_marshall_buffer\n"));
3653 talloc_free(tmp_ctx);
3657 bd->len = offsetof(struct ctdb_marshall_buffer, data);
3658 bd->records->db_id = ctdb_db->db_id;
3659 /* traverse the database collecting all records */
3660 if (tdb_traverse_read(ctdb_db->ltdb->tdb, backup_traverse, bd) == -1 ||
3661 bd->traverse_error) {
3662 DEBUG(DEBUG_ERR,("Traverse error\n"));
3663 talloc_free(tmp_ctx);
3667 tdb_transaction_cancel(ctdb_db->ltdb->tdb);
3670 fh = open(argv[1], O_RDWR|O_CREAT, 0600);
3672 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[1]));
3673 talloc_free(tmp_ctx);
3677 dbhdr.version = DB_VERSION;
3678 dbhdr.timestamp = time(NULL);
3679 dbhdr.persistent = dbmap->dbs[i].persistent;
3680 dbhdr.size = bd->len;
3681 if (strlen(argv[0]) >= MAX_DB_NAME) {
3682 DEBUG(DEBUG_ERR,("Too long dbname\n"));
3685 strncpy(discard_const(dbhdr.name), argv[0], MAX_DB_NAME);
3686 ret = write(fh, &dbhdr, sizeof(dbhdr));
3688 DEBUG(DEBUG_ERR,("write failed: %s\n", strerror(errno)));
3691 ret = write(fh, bd->records, bd->len);
3693 DEBUG(DEBUG_ERR,("write failed: %s\n", strerror(errno)));
3702 DEBUG(DEBUG_ERR,("close failed: %s\n", strerror(errno)));
3705 talloc_free(tmp_ctx);
3710 * restore a database from a file
3712 static int control_restoredb(struct ctdb_context *ctdb, int argc, const char **argv)
3715 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3718 struct db_file_header dbhdr;
3719 struct ctdb_db_context *ctdb_db;
3720 struct ctdb_node_map *nodemap=NULL;
3721 struct ctdb_vnn_map *vnnmap=NULL;
3723 struct ctdb_control_wipe_database w;
3725 uint32_t generation;
3730 if (argc < 1 || argc > 2) {
3731 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3735 fh = open(argv[0], O_RDONLY);
3737 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[0]));
3738 talloc_free(tmp_ctx);
3742 read(fh, &dbhdr, sizeof(dbhdr));
3743 if (dbhdr.version != DB_VERSION) {
3744 DEBUG(DEBUG_ERR,("Invalid version of database dump. File is version %lu but expected version was %u\n", dbhdr.version, DB_VERSION));
3745 talloc_free(tmp_ctx);
3749 dbname = dbhdr.name;
3754 outdata.dsize = dbhdr.size;
3755 outdata.dptr = talloc_size(tmp_ctx, outdata.dsize);
3756 if (outdata.dptr == NULL) {
3757 DEBUG(DEBUG_ERR,("Failed to allocate data of size '%lu'\n", dbhdr.size));
3759 talloc_free(tmp_ctx);
3762 read(fh, outdata.dptr, outdata.dsize);
3765 tm = localtime(&dbhdr.timestamp);
3766 strftime(tbuf,sizeof(tbuf)-1,"%Y/%m/%d %H:%M:%S", tm);
3767 printf("Restoring database '%s' from backup @ %s\n",
3771 ctdb_db = ctdb_attach(ctdb, dbname, dbhdr.persistent, 0);
3772 if (ctdb_db == NULL) {
3773 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", dbname));
3774 talloc_free(tmp_ctx);
3778 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
3780 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
3781 talloc_free(tmp_ctx);
3786 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &vnnmap);
3788 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n", options.pnn));
3789 talloc_free(tmp_ctx);
3793 /* freeze all nodes */
3794 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3795 for (i=1; i<=NUM_DB_PRIORITIES; i++) {
3796 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_FREEZE,
3802 DEBUG(DEBUG_ERR, ("Unable to freeze nodes.\n"));
3803 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3804 talloc_free(tmp_ctx);
3809 generation = vnnmap->generation;
3810 data.dptr = (void *)&generation;
3811 data.dsize = sizeof(generation);
3813 /* start a cluster wide transaction */
3814 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3815 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_START,
3817 TIMELIMIT(), false, data,
3820 DEBUG(DEBUG_ERR, ("Unable to start cluster wide transactions.\n"));
3825 w.db_id = ctdb_db->db_id;
3826 w.transaction_id = generation;
3828 data.dptr = (void *)&w;
3829 data.dsize = sizeof(w);
3831 /* wipe all the remote databases. */
3832 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3833 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_WIPE_DATABASE,
3835 TIMELIMIT(), false, data,
3838 DEBUG(DEBUG_ERR, ("Unable to wipe database.\n"));
3839 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3840 talloc_free(tmp_ctx);
3844 /* push the database */
3845 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3846 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_PUSH_DB,
3848 TIMELIMIT(), false, outdata,
3851 DEBUG(DEBUG_ERR, ("Failed to push database.\n"));
3852 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3853 talloc_free(tmp_ctx);
3857 data.dptr = (void *)&ctdb_db->db_id;
3858 data.dsize = sizeof(ctdb_db->db_id);
3860 /* mark the database as healthy */
3861 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3862 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_DB_SET_HEALTHY,
3864 TIMELIMIT(), false, data,
3867 DEBUG(DEBUG_ERR, ("Failed to mark database as healthy.\n"));
3868 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3869 talloc_free(tmp_ctx);
3873 data.dptr = (void *)&generation;
3874 data.dsize = sizeof(generation);
3876 /* commit all the changes */
3877 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_COMMIT,
3879 TIMELIMIT(), false, data,
3882 DEBUG(DEBUG_ERR, ("Unable to commit databases.\n"));
3883 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3884 talloc_free(tmp_ctx);
3889 /* thaw all nodes */
3890 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3891 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_THAW,
3897 DEBUG(DEBUG_ERR, ("Unable to thaw nodes.\n"));
3898 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3899 talloc_free(tmp_ctx);
3904 talloc_free(tmp_ctx);
3909 * dump a database backup from a file
3911 static int control_dumpdbbackup(struct ctdb_context *ctdb, int argc, const char **argv)
3913 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3915 struct db_file_header dbhdr;
3919 struct ctdb_rec_data *rec = NULL;
3920 struct ctdb_marshall_buffer *m;
3923 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3927 fh = open(argv[0], O_RDONLY);
3929 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[0]));
3930 talloc_free(tmp_ctx);
3934 read(fh, &dbhdr, sizeof(dbhdr));
3935 if (dbhdr.version != DB_VERSION) {
3936 DEBUG(DEBUG_ERR,("Invalid version of database dump. File is version %lu but expected version was %u\n", dbhdr.version, DB_VERSION));
3937 talloc_free(tmp_ctx);
3941 outdata.dsize = dbhdr.size;
3942 outdata.dptr = talloc_size(tmp_ctx, outdata.dsize);
3943 if (outdata.dptr == NULL) {
3944 DEBUG(DEBUG_ERR,("Failed to allocate data of size '%lu'\n", dbhdr.size));
3946 talloc_free(tmp_ctx);
3949 read(fh, outdata.dptr, outdata.dsize);
3951 m = (struct ctdb_marshall_buffer *)outdata.dptr;
3953 tm = localtime(&dbhdr.timestamp);
3954 strftime(tbuf,sizeof(tbuf)-1,"%Y/%m/%d %H:%M:%S", tm);
3955 printf("Backup of database name:'%s' dbid:0x%x08x from @ %s\n",
3956 dbhdr.name, m->db_id, tbuf);
3958 for (i=0; i < m->count; i++) {
3962 /* we do not want the header splitted, so we pass NULL*/
3963 rec = ctdb_marshall_loop_next(m, rec, &reqid,
3966 ctdb_dumpdb_record(ctdb, key, data, stdout);
3969 printf("Dumped %d records\n", i);
3970 talloc_free(tmp_ctx);
3975 * wipe a database from a file
3977 static int control_wipedb(struct ctdb_context *ctdb, int argc,
3981 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3983 struct ctdb_db_context *ctdb_db;
3984 struct ctdb_node_map *nodemap = NULL;
3985 struct ctdb_vnn_map *vnnmap = NULL;
3987 struct ctdb_control_wipe_database w;
3989 uint32_t generation;
3990 struct ctdb_dbid_map *dbmap = NULL;
3993 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3997 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx,
4000 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n",
4005 for(i=0;i<dbmap->num;i++){
4008 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn,
4009 dbmap->dbs[i].dbid, tmp_ctx, &name);
4010 if(!strcmp(argv[0], name)){
4011 talloc_free(discard_const(name));
4014 talloc_free(discard_const(name));
4016 if (i == dbmap->num) {
4017 DEBUG(DEBUG_ERR, ("No database with name '%s' found\n",
4019 talloc_free(tmp_ctx);
4023 ctdb_db = ctdb_attach(ctdb, argv[0], dbmap->dbs[i].persistent, 0);
4024 if (ctdb_db == NULL) {
4025 DEBUG(DEBUG_ERR, ("Unable to attach to database '%s'\n",
4027 talloc_free(tmp_ctx);
4031 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb,
4034 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n",
4036 talloc_free(tmp_ctx);
4040 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx,
4043 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n",
4045 talloc_free(tmp_ctx);
4049 /* freeze all nodes */
4050 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4051 for (i=1; i<=NUM_DB_PRIORITIES; i++) {
4052 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_FREEZE,
4059 DEBUG(DEBUG_ERR, ("Unable to freeze nodes.\n"));
4060 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn,
4061 CTDB_RECOVERY_ACTIVE);
4062 talloc_free(tmp_ctx);
4067 generation = vnnmap->generation;
4068 data.dptr = (void *)&generation;
4069 data.dsize = sizeof(generation);
4071 /* start a cluster wide transaction */
4072 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4073 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_START,
4075 TIMELIMIT(), false, data,
4079 DEBUG(DEBUG_ERR, ("Unable to start cluster wide "
4080 "transactions.\n"));
4084 w.db_id = ctdb_db->db_id;
4085 w.transaction_id = generation;
4087 data.dptr = (void *)&w;
4088 data.dsize = sizeof(w);
4090 /* wipe all the remote databases. */
4091 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4092 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_WIPE_DATABASE,
4094 TIMELIMIT(), false, data,
4097 DEBUG(DEBUG_ERR, ("Unable to wipe database.\n"));
4098 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4099 talloc_free(tmp_ctx);
4103 data.dptr = (void *)&ctdb_db->db_id;
4104 data.dsize = sizeof(ctdb_db->db_id);
4106 /* mark the database as healthy */
4107 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4108 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_DB_SET_HEALTHY,
4110 TIMELIMIT(), false, data,
4113 DEBUG(DEBUG_ERR, ("Failed to mark database as healthy.\n"));
4114 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4115 talloc_free(tmp_ctx);
4119 data.dptr = (void *)&generation;
4120 data.dsize = sizeof(generation);
4122 /* commit all the changes */
4123 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_COMMIT,
4125 TIMELIMIT(), false, data,
4128 DEBUG(DEBUG_ERR, ("Unable to commit databases.\n"));
4129 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4130 talloc_free(tmp_ctx);
4134 /* thaw all nodes */
4135 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4136 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_THAW,
4142 DEBUG(DEBUG_ERR, ("Unable to thaw nodes.\n"));
4143 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4144 talloc_free(tmp_ctx);
4148 talloc_free(tmp_ctx);
4153 * set flags of a node in the nodemap
4155 static int control_setflags(struct ctdb_context *ctdb, int argc, const char **argv)
4162 struct ctdb_node_flag_change c;
4169 if (sscanf(argv[0], "%d", &node) != 1) {
4170 DEBUG(DEBUG_ERR, ("Badly formed node\n"));
4174 if (sscanf(argv[1], "0x%x", &flags) != 1) {
4175 DEBUG(DEBUG_ERR, ("Badly formed flags\n"));
4182 c.new_flags = flags;
4184 data.dsize = sizeof(c);
4185 data.dptr = (unsigned char *)&c;
4187 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_MODIFY_FLAGS, 0,
4188 data, NULL, NULL, &status, NULL, NULL);
4189 if (ret != 0 || status != 0) {
4190 DEBUG(DEBUG_ERR,("Failed to modify flags\n"));
4199 static int control_dumpmemory(struct ctdb_context *ctdb, int argc, const char **argv)
4205 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
4206 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_DUMP_MEMORY,
4207 0, tdb_null, tmp_ctx, &data, &res, NULL, &errmsg);
4208 if (ret != 0 || res != 0) {
4209 DEBUG(DEBUG_ERR,("Failed to dump memory - %s\n", errmsg));
4210 talloc_free(tmp_ctx);
4213 write(1, data.dptr, data.dsize);
4214 talloc_free(tmp_ctx);
4219 handler for memory dumps
4221 static void mem_dump_handler(struct ctdb_context *ctdb, uint64_t srvid,
4222 TDB_DATA data, void *private_data)
4224 write(1, data.dptr, data.dsize);
4229 dump memory usage on the recovery daemon
4231 static int control_rddumpmemory(struct ctdb_context *ctdb, int argc, const char **argv)
4235 struct rd_memdump_reply rd;
4237 rd.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
4239 DEBUG(DEBUG_ERR, ("Failed to get pnn of local node\n"));
4242 rd.srvid = getpid();
4244 /* register a message port for receiveing the reply so that we
4245 can receive the reply
4247 ctdb_client_set_message_handler(ctdb, rd.srvid, mem_dump_handler, NULL);
4250 data.dptr = (uint8_t *)&rd;
4251 data.dsize = sizeof(rd);
4253 ret = ctdb_client_send_message(ctdb, options.pnn, CTDB_SRVID_MEM_DUMP, data);
4255 DEBUG(DEBUG_ERR,("Failed to send memdump request message to %u\n", options.pnn));
4259 /* this loop will terminate when we have received the reply */
4261 event_loop_once(ctdb->ev);
4268 send a message to a srvid
4270 static int control_msgsend(struct ctdb_context *ctdb, int argc, const char **argv)
4272 unsigned long srvid;
4280 srvid = strtoul(argv[0], NULL, 0);
4282 data.dptr = (uint8_t *)discard_const(argv[1]);
4283 data.dsize= strlen(argv[1]);
4285 ret = ctdb_client_send_message(ctdb, CTDB_BROADCAST_CONNECTED, srvid, data);
4287 DEBUG(DEBUG_ERR,("Failed to send memdump request message to %u\n", options.pnn));
4295 handler for msglisten
4297 static void msglisten_handler(struct ctdb_context *ctdb, uint64_t srvid,
4298 TDB_DATA data, void *private_data)
4302 printf("Message received: ");
4303 for (i=0;i<data.dsize;i++) {
4304 printf("%c", data.dptr[i]);
4310 listen for messages on a messageport
4312 static int control_msglisten(struct ctdb_context *ctdb, int argc, const char **argv)
4318 /* register a message port and listen for messages
4320 ctdb_client_set_message_handler(ctdb, srvid, msglisten_handler, NULL);
4321 printf("Listening for messages on srvid:%d\n", (int)srvid);
4324 event_loop_once(ctdb->ev);
4331 list all nodes in the cluster
4332 if the daemon is running, we read the data from the daemon.
4333 if the daemon is not running we parse the nodes file directly
4335 static int control_listnodes(struct ctdb_context *ctdb, int argc, const char **argv)
4338 struct ctdb_node_map *nodemap=NULL;
4341 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
4343 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
4347 for(i=0;i<nodemap->num;i++){
4348 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
4351 if (options.machinereadable){
4352 printf(":%d:%s:\n", nodemap->nodes[i].pnn, ctdb_addr_to_str(&nodemap->nodes[i].addr));
4354 printf("%s\n", ctdb_addr_to_str(&nodemap->nodes[i].addr));
4358 TALLOC_CTX *mem_ctx = talloc_new(NULL);
4359 struct pnn_node *pnn_nodes;
4360 struct pnn_node *pnn_node;
4362 pnn_nodes = read_nodes_file(mem_ctx);
4363 if (pnn_nodes == NULL) {
4364 DEBUG(DEBUG_ERR,("Failed to read nodes file\n"));
4365 talloc_free(mem_ctx);
4369 for(pnn_node=pnn_nodes;pnn_node;pnn_node=pnn_node->next) {
4370 ctdb_sock_addr addr;
4372 if (parse_ip(pnn_node->addr, NULL, 63999, &addr) == 0) {
4373 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s' in nodes file\n", pnn_node->addr));
4374 talloc_free(mem_ctx);
4378 if (options.machinereadable){
4379 printf(":%d:%s:\n", pnn_node->pnn, pnn_node->addr);
4381 printf("%s\n", pnn_node->addr);
4384 talloc_free(mem_ctx);
4391 reload the nodes file on the local node
4393 static int control_reload_nodes_file(struct ctdb_context *ctdb, int argc, const char **argv)
4397 struct ctdb_node_map *nodemap=NULL;
4399 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
4401 DEBUG(DEBUG_ERR, ("Failed to read pnn of local node\n"));
4405 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
4407 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
4411 /* reload the nodes file on all remote nodes */
4412 for (i=0;i<nodemap->num;i++) {
4413 if (nodemap->nodes[i].pnn == mypnn) {
4416 DEBUG(DEBUG_NOTICE, ("Reloading nodes file on node %u\n", nodemap->nodes[i].pnn));
4417 ret = ctdb_ctrl_reload_nodes_file(ctdb, TIMELIMIT(),
4418 nodemap->nodes[i].pnn);
4420 DEBUG(DEBUG_ERR, ("ERROR: Failed to reload nodes file on node %u. You MUST fix that node manually!\n", nodemap->nodes[i].pnn));
4424 /* reload the nodes file on the local node */
4425 DEBUG(DEBUG_NOTICE, ("Reloading nodes file on node %u\n", mypnn));
4426 ret = ctdb_ctrl_reload_nodes_file(ctdb, TIMELIMIT(), mypnn);
4428 DEBUG(DEBUG_ERR, ("ERROR: Failed to reload nodes file on node %u. You MUST fix that node manually!\n", mypnn));
4431 /* initiate a recovery */
4432 control_recover(ctdb, argc, argv);
4438 static const struct {
4440 int (*fn)(struct ctdb_context *, int, const char **);
4442 bool without_daemon; /* can be run without daemon running ? */
4445 } ctdb_commands[] = {
4447 { "version", control_version, true, false, "show version of ctdb" },
4449 { "status", control_status, true, false, "show node status" },
4450 { "uptime", control_uptime, true, false, "show node uptime" },
4451 { "ping", control_ping, true, false, "ping all nodes" },
4452 { "getvar", control_getvar, true, false, "get a tunable variable", "<name>"},
4453 { "setvar", control_setvar, true, false, "set a tunable variable", "<name> <value>"},
4454 { "listvars", control_listvars, true, false, "list tunable variables"},
4455 { "statistics", control_statistics, false, false, "show statistics" },
4456 { "statisticsreset", control_statistics_reset, true, false, "reset statistics"},
4457 { "ip", control_ip, false, false, "show which public ip's that ctdb manages" },
4458 { "ipinfo", control_ipinfo, true, false, "show details about a public ip that ctdb manages", "<ip>" },
4459 { "ifaces", control_ifaces, true, false, "show which interfaces that ctdb manages" },
4460 { "setifacelink", control_setifacelink, true, false, "set interface link status", "<iface> <status>" },
4461 { "process-exists", control_process_exists, true, false, "check if a process exists on a node", "<pid>"},
4462 { "getdbmap", control_getdbmap, true, false, "show the database map" },
4463 { "getdbstatus", control_getdbstatus, true, false, "show the status of a database", "<dbname>" },
4464 { "catdb", control_catdb, true, false, "dump a database" , "<dbname>"},
4465 { "getmonmode", control_getmonmode, true, false, "show monitoring mode" },
4466 { "getcapabilities", control_getcapabilities, true, false, "show node capabilities" },
4467 { "pnn", control_pnn, true, false, "show the pnn of the currnet node" },
4468 { "lvs", control_lvs, true, false, "show lvs configuration" },
4469 { "lvsmaster", control_lvsmaster, true, false, "show which node is the lvs master" },
4470 { "disablemonitor", control_disable_monmode,true, false, "set monitoring mode to DISABLE" },
4471 { "enablemonitor", control_enable_monmode, true, false, "set monitoring mode to ACTIVE" },
4472 { "setdebug", control_setdebug, true, false, "set debug level", "<EMERG|ALERT|CRIT|ERR|WARNING|NOTICE|INFO|DEBUG>" },
4473 { "getdebug", control_getdebug, true, false, "get debug level" },
4474 { "getlog", control_getlog, true, false, "get the log data from the in memory ringbuffer", "<level>" },
4475 { "clearlog", control_clearlog, true, false, "clear the log data from the in memory ringbuffer" },
4476 { "attach", control_attach, true, false, "attach to a database", "<dbname>" },
4477 { "dumpmemory", control_dumpmemory, true, false, "dump memory map to stdout" },
4478 { "rddumpmemory", control_rddumpmemory, true, false, "dump memory map from the recovery daemon to stdout" },
4479 { "getpid", control_getpid, true, false, "get ctdbd process ID" },
4480 { "disable", control_disable, true, false, "disable a nodes public IP" },
4481 { "enable", control_enable, true, false, "enable a nodes public IP" },
4482 { "stop", control_stop, true, false, "stop a node" },
4483 { "continue", control_continue, true, false, "re-start a stopped node" },
4484 { "ban", control_ban, true, false, "ban a node from the cluster", "<bantime|0>"},
4485 { "unban", control_unban, true, false, "unban a node" },
4486 { "showban", control_showban, true, false, "show ban information"},
4487 { "shutdown", control_shutdown, true, false, "shutdown ctdbd" },
4488 { "recover", control_recover, true, false, "force recovery" },
4489 { "sync", control_ipreallocate, true, false, "wait until ctdbd has synced all state changes" },
4490 { "ipreallocate", control_ipreallocate, true, false, "force the recovery daemon to perform a ip reallocation procedure" },
4491 { "thaw", control_thaw, true, false, "thaw databases", "[priority:1-3]" },
4492 { "isnotrecmaster", control_isnotrecmaster, false, false, "check if the local node is recmaster or not" },
4493 { "killtcp", kill_tcp, false, false, "kill a tcp connection.", "<srcip:port> <dstip:port>" },
4494 { "gratiousarp", control_gratious_arp, false, false, "send a gratious arp", "<ip> <interface>" },
4495 { "tickle", tickle_tcp, false, false, "send a tcp tickle ack", "<srcip:port> <dstip:port>" },
4496 { "gettickles", control_get_tickles, false, false, "get the list of tickles registered for this ip", "<ip> [<port>]" },
4497 { "addtickle", control_add_tickle, false, false, "add a tickle for this ip", "<ip>:<port> <ip>:<port>" },
4499 { "deltickle", control_del_tickle, false, false, "delete a tickle from this ip", "<ip>:<port> <ip>:<port>" },
4501 { "regsrvid", regsrvid, false, false, "register a server id", "<pnn> <type> <id>" },
4502 { "unregsrvid", unregsrvid, false, false, "unregister a server id", "<pnn> <type> <id>" },
4503 { "chksrvid", chksrvid, false, false, "check if a server id exists", "<pnn> <type> <id>" },
4504 { "getsrvids", getsrvids, false, false, "get a list of all server ids"},
4505 { "vacuum", ctdb_vacuum, false, false, "vacuum the databases of empty records", "[max_records]"},
4506 { "repack", ctdb_repack, false, false, "repack all databases", "[max_freelist]"},
4507 { "listnodes", control_listnodes, false, true, "list all nodes in the cluster"},
4508 { "reloadnodes", control_reload_nodes_file, false, false, "reload the nodes file and restart the transport on all nodes"},
4509 { "moveip", control_moveip, false, false, "move/failover an ip address to another node", "<ip> <node>"},
4510 { "addip", control_addip, true, false, "add a ip address to a node", "<ip/mask> <iface>"},
4511 { "delip", control_delip, false, false, "delete an ip address from a node", "<ip>"},
4512 { "eventscript", control_eventscript, true, false, "run the eventscript with the given parameters on a node", "<arguments>"},
4513 { "backupdb", control_backupdb, false, false, "backup the database into a file.", "<database> <file>"},
4514 { "restoredb", control_restoredb, false, false, "restore the database from a file.", "<file> [dbname]"},
4515 { "dumpdbbackup", control_dumpdbbackup, false, true, "dump database backup from a file.", "<file>"},
4516 { "wipedb", control_wipedb, false, false, "wipe the contents of a database.", "<dbname>"},
4517 { "recmaster", control_recmaster, false, false, "show the pnn for the recovery master."},
4518 { "setflags", control_setflags, false, false, "set flags for a node in the nodemap.", "<node> <flags>"},
4519 { "scriptstatus", control_scriptstatus, false, false, "show the status of the monitoring scripts (or all scripts)", "[all]"},
4520 { "enablescript", control_enablescript, false, false, "enable an eventscript", "<script>"},
4521 { "disablescript", control_disablescript, false, false, "disable an eventscript", "<script>"},
4522 { "natgwlist", control_natgwlist, false, false, "show the nodes belonging to this natgw configuration"},
4523 { "xpnn", control_xpnn, true, true, "find the pnn of the local node without talking to the daemon (unreliable)" },
4524 { "getreclock", control_getreclock, false, false, "Show the reclock file of a node"},
4525 { "setreclock", control_setreclock, false, false, "Set/clear the reclock file of a node", "[filename]"},
4526 { "setnatgwstate", control_setnatgwstate, false, false, "Set NATGW state to on/off", "{on|off}"},
4527 { "setlmasterrole", control_setlmasterrole, false, false, "Set LMASTER role to on/off", "{on|off}"},
4528 { "setrecmasterrole", control_setrecmasterrole, false, false, "Set RECMASTER role to on/off", "{on|off}"},
4529 { "setdbprio", control_setdbprio, false, false, "Set DB priority", "<dbid> <prio:1-3>"},
4530 { "getdbprio", control_getdbprio, false, false, "Get DB priority", "<dbid>"},
4531 { "msglisten", control_msglisten, false, false, "Listen on a srvid port for messages", "<msg srvid>"},
4532 { "msgsend", control_msgsend, false, false, "Send a message to srvid", "<srvid> <message>"},
4533 { "sync", control_ipreallocate, true, false, "wait until ctdbd has synced all state changes" },
4539 static void usage(void)
4543 "Usage: ctdb [options] <control>\n" \
4545 " -n <node> choose node number, or 'all' (defaults to local node)\n"
4546 " -Y generate machinereadable output\n"
4547 " -v generate verbose output\n"
4548 " -t <timelimit> set timelimit for control in seconds (default %u)\n", options.timelimit);
4549 printf("Controls:\n");
4550 for (i=0;i<ARRAY_SIZE(ctdb_commands);i++) {
4551 printf(" %-15s %-27s %s\n",
4552 ctdb_commands[i].name,
4553 ctdb_commands[i].args?ctdb_commands[i].args:"",
4554 ctdb_commands[i].msg);
4560 static void ctdb_alarm(int sig)
4562 printf("Maximum runtime exceeded - exiting\n");
4569 int main(int argc, const char *argv[])
4571 struct ctdb_context *ctdb;
4572 char *nodestring = NULL;
4573 struct poptOption popt_options[] = {
4576 { "timelimit", 't', POPT_ARG_INT, &options.timelimit, 0, "timelimit", "integer" },
4577 { "node", 'n', POPT_ARG_STRING, &nodestring, 0, "node", "integer|all" },
4578 { "machinereadable", 'Y', POPT_ARG_NONE, &options.machinereadable, 0, "enable machinereadable output", NULL },
4579 { "verbose", 'v', POPT_ARG_NONE, &options.verbose, 0, "enable verbose output", NULL },
4580 { "maxruntime", 'T', POPT_ARG_INT, &options.maxruntime, 0, "die if runtime exceeds this limit (in seconds)", "integer" },
4584 const char **extra_argv;
4588 struct event_context *ev;
4589 const char *control;
4593 /* set some defaults */
4594 options.maxruntime = 0;
4595 options.timelimit = 3;
4596 options.pnn = CTDB_CURRENT_NODE;
4598 pc = poptGetContext(argv[0], argc, argv, popt_options, POPT_CONTEXT_KEEP_FIRST);
4600 while ((opt = poptGetNextOpt(pc)) != -1) {
4603 DEBUG(DEBUG_ERR, ("Invalid option %s: %s\n",
4604 poptBadOption(pc, 0), poptStrerror(opt)));
4609 /* setup the remaining options for the main program to use */
4610 extra_argv = poptGetArgs(pc);
4613 while (extra_argv[extra_argc]) extra_argc++;
4616 if (extra_argc < 1) {
4620 if (options.maxruntime == 0) {
4621 const char *ctdb_timeout;
4622 ctdb_timeout = getenv("CTDB_TIMEOUT");
4623 if (ctdb_timeout != NULL) {
4624 options.maxruntime = strtoul(ctdb_timeout, NULL, 0);
4626 /* default timeout is 120 seconds */
4627 options.maxruntime = 120;
4631 signal(SIGALRM, ctdb_alarm);
4632 alarm(options.maxruntime);
4634 /* setup the node number to contact */
4635 if (nodestring != NULL) {
4636 if (strcmp(nodestring, "all") == 0) {
4637 options.pnn = CTDB_BROADCAST_ALL;
4639 options.pnn = strtoul(nodestring, NULL, 0);
4643 control = extra_argv[0];
4645 ev = event_context_init(NULL);
4647 DEBUG(DEBUG_ERR, ("Failed to initialize event system\n"));
4650 tevent_loop_allow_nesting(ev);
4652 for (i=0;i<ARRAY_SIZE(ctdb_commands);i++) {
4653 if (strcmp(control, ctdb_commands[i].name) == 0) {
4656 if (ctdb_commands[i].without_daemon == true) {
4660 /* initialise ctdb */
4661 ctdb = ctdb_cmdline_client(ev);
4663 if (ctdb_commands[i].without_daemon == false) {
4664 const char *socket_name;
4667 DEBUG(DEBUG_ERR, ("Failed to init ctdb\n"));
4671 /* initialize a libctdb connection as well */
4672 socket_name = ctdb_get_socketname(ctdb);
4673 ctdb_connection = ctdb_connect(socket_name,
4674 ctdb_log_file, stderr);
4675 if (ctdb_connection == NULL) {
4676 fprintf(stderr, "Failed to connect to daemon from libctdb\n");
4680 /* verify the node exists */
4683 if (options.pnn == CTDB_CURRENT_NODE) {
4685 pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
4693 if (ctdb_commands[i].auto_all &&
4694 options.pnn == CTDB_BROADCAST_ALL) {
4699 nodes = ctdb_get_connected_nodes(ctdb, TIMELIMIT(), ctdb, &num_nodes);
4700 CTDB_NO_MEMORY(ctdb, nodes);
4702 for (j=0;j<num_nodes;j++) {
4703 options.pnn = nodes[j];
4704 ret |= ctdb_commands[i].fn(ctdb, extra_argc-1, extra_argv+1);
4708 ret = ctdb_commands[i].fn(ctdb, extra_argc-1, extra_argv+1);
4714 if (i == ARRAY_SIZE(ctdb_commands)) {
4715 DEBUG(DEBUG_ERR, ("Unknown control '%s'\n", control));