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);
2860 fetch a record from a persistent database
2862 static int control_pfetch(struct ctdb_context *ctdb, int argc, const char **argv)
2864 const char *db_name;
2865 struct ctdb_db_context *ctdb_db;
2866 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2867 struct ctdb_transaction_handle *h;
2872 talloc_free(tmp_ctx);
2879 if (db_exists(ctdb, db_name)) {
2880 DEBUG(DEBUG_ERR,("Database '%s' does not exist\n", db_name));
2881 talloc_free(tmp_ctx);
2885 ctdb_db = ctdb_attach(ctdb, db_name, true, 0);
2887 if (ctdb_db == NULL) {
2888 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
2889 talloc_free(tmp_ctx);
2893 h = ctdb_transaction_start(ctdb_db, tmp_ctx);
2895 DEBUG(DEBUG_ERR,("Failed to start transaction on database %s\n", db_name));
2896 talloc_free(tmp_ctx);
2900 key.dptr = discard_const(argv[1]);
2901 key.dsize = strlen(argv[1]);
2902 ret = ctdb_transaction_fetch(h, tmp_ctx, key, &data);
2904 DEBUG(DEBUG_ERR,("Failed to fetch record\n"));
2905 talloc_free(tmp_ctx);
2909 if (data.dsize == 0 || data.dptr == NULL) {
2910 DEBUG(DEBUG_ERR,("Record is empty\n"));
2911 talloc_free(tmp_ctx);
2916 fd = open(argv[2], O_WRONLY|O_CREAT|O_TRUNC, 0600);
2918 DEBUG(DEBUG_ERR,("Failed to open output file %s\n", argv[2]));
2919 talloc_free(tmp_ctx);
2922 write(fd, data.dptr, data.dsize);
2925 write(1, data.dptr, data.dsize);
2928 /* abort the transaction */
2932 talloc_free(tmp_ctx);
2937 write a record to a persistent database
2939 static int control_pstore(struct ctdb_context *ctdb, int argc, const char **argv)
2941 const char *db_name;
2942 struct ctdb_db_context *ctdb_db;
2943 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
2944 struct ctdb_transaction_handle *h;
2950 talloc_free(tmp_ctx);
2954 fd = open(argv[2], O_RDONLY);
2956 DEBUG(DEBUG_ERR,("Failed to open file containing record data : %s %s\n", argv[2], strerror(errno)));
2957 talloc_free(tmp_ctx);
2961 ret = fstat(fd, &st);
2963 DEBUG(DEBUG_ERR,("fstat of file %s failed: %s\n", argv[2], strerror(errno)));
2965 talloc_free(tmp_ctx);
2969 if (!S_ISREG(st.st_mode)) {
2970 DEBUG(DEBUG_ERR,("Not a regular file %s\n", argv[2]));
2972 talloc_free(tmp_ctx);
2976 data.dsize = st.st_size;
2977 if (data.dsize == 0) {
2980 data.dptr = talloc_size(tmp_ctx, data.dsize);
2981 if (data.dptr == NULL) {
2982 DEBUG(DEBUG_ERR,("Failed to talloc %d of memory to store record data\n", (int)data.dsize));
2984 talloc_free(tmp_ctx);
2987 ret = read(fd, data.dptr, data.dsize);
2988 if (ret != data.dsize) {
2989 DEBUG(DEBUG_ERR,("Failed to read %d bytes of record data\n", (int)data.dsize));
2991 talloc_free(tmp_ctx);
3000 ctdb_db = ctdb_attach(ctdb, db_name, true, 0);
3002 if (ctdb_db == NULL) {
3003 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
3004 talloc_free(tmp_ctx);
3008 h = ctdb_transaction_start(ctdb_db, tmp_ctx);
3010 DEBUG(DEBUG_ERR,("Failed to start transaction on database %s\n", db_name));
3011 talloc_free(tmp_ctx);
3015 key.dptr = discard_const(argv[1]);
3016 key.dsize = strlen(argv[1]);
3017 ret = ctdb_transaction_store(h, key, data);
3019 DEBUG(DEBUG_ERR,("Failed to store record\n"));
3020 talloc_free(tmp_ctx);
3024 ret = ctdb_transaction_commit(h);
3026 DEBUG(DEBUG_ERR,("Failed to commit transaction\n"));
3027 talloc_free(tmp_ctx);
3032 talloc_free(tmp_ctx);
3036 static void log_handler(struct ctdb_context *ctdb, uint64_t srvid,
3037 TDB_DATA data, void *private_data)
3039 DEBUG(DEBUG_ERR,("Log data received\n"));
3040 if (data.dsize > 0) {
3041 printf("%s", data.dptr);
3048 display a list of log messages from the in memory ringbuffer
3050 static int control_getlog(struct ctdb_context *ctdb, int argc, const char **argv)
3054 struct ctdb_get_log_addr log_addr;
3056 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3061 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3062 talloc_free(tmp_ctx);
3066 log_addr.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
3067 log_addr.srvid = getpid();
3068 if (isalpha(argv[0][0]) || argv[0][0] == '-') {
3069 log_addr.level = get_debug_by_desc(argv[0]);
3071 log_addr.level = strtol(argv[0], NULL, 0);
3075 data.dptr = (unsigned char *)&log_addr;
3076 data.dsize = sizeof(log_addr);
3078 DEBUG(DEBUG_ERR, ("Pulling logs from node %u\n", options.pnn));
3080 ctdb_client_set_message_handler(ctdb, log_addr.srvid, log_handler, NULL);
3083 DEBUG(DEBUG_ERR,("Listen for response on %d\n", (int)log_addr.srvid));
3085 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_GET_LOG,
3086 0, data, tmp_ctx, NULL, &res, NULL, &errmsg);
3087 if (ret != 0 || res != 0) {
3088 DEBUG(DEBUG_ERR,("Failed to get logs - %s\n", errmsg));
3089 talloc_free(tmp_ctx);
3094 tv = timeval_current();
3095 /* this loop will terminate when we have received the reply */
3096 while (timeval_elapsed(&tv) < 3.0) {
3097 event_loop_once(ctdb->ev);
3100 DEBUG(DEBUG_INFO,("Timed out waiting for log data.\n"));
3102 talloc_free(tmp_ctx);
3107 clear the in memory log area
3109 static int control_clearlog(struct ctdb_context *ctdb, int argc, const char **argv)
3114 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3116 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_CLEAR_LOG,
3117 0, tdb_null, tmp_ctx, NULL, &res, NULL, &errmsg);
3118 if (ret != 0 || res != 0) {
3119 DEBUG(DEBUG_ERR,("Failed to clear logs\n"));
3120 talloc_free(tmp_ctx);
3124 talloc_free(tmp_ctx);
3131 display a list of the databases on a remote ctdb
3133 static int control_getdbmap(struct ctdb_context *ctdb, int argc, const char **argv)
3136 struct ctdb_dbid_map *dbmap=NULL;
3138 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
3140 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
3144 if(options.machinereadable){
3145 printf(":ID:Name:Path:Persistent:Unhealthy:\n");
3146 for(i=0;i<dbmap->num;i++){
3152 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn,
3153 dbmap->dbs[i].dbid, ctdb, &path);
3154 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn,
3155 dbmap->dbs[i].dbid, ctdb, &name);
3156 ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn,
3157 dbmap->dbs[i].dbid, ctdb, &health);
3158 persistent = dbmap->dbs[i].persistent;
3159 printf(":0x%08X:%s:%s:%d:%d:\n",
3160 dbmap->dbs[i].dbid, name, path,
3161 !!(persistent), !!(health));
3166 printf("Number of databases:%d\n", dbmap->num);
3167 for(i=0;i<dbmap->num;i++){
3173 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &path);
3174 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
3175 ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &health);
3176 persistent = dbmap->dbs[i].persistent;
3177 printf("dbid:0x%08x name:%s path:%s%s%s\n",
3178 dbmap->dbs[i].dbid, name, path,
3179 persistent?" PERSISTENT":"",
3180 health?" UNHEALTHY":"");
3187 display the status of a database on a remote ctdb
3189 static int control_getdbstatus(struct ctdb_context *ctdb, int argc, const char **argv)
3192 struct ctdb_dbid_map *dbmap=NULL;
3193 const char *db_name;
3201 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, ctdb, &dbmap);
3203 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
3207 for(i=0;i<dbmap->num;i++){
3213 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &name);
3214 if (strcmp(name, db_name) != 0) {
3218 ctdb_ctrl_getdbpath(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &path);
3219 ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, ctdb, &health);
3220 persistent = dbmap->dbs[i].persistent;
3221 printf("dbid: 0x%08x\nname: %s\npath: %s\nPERSISTENT: %s\nHEALTH: %s\n",
3222 dbmap->dbs[i].dbid, name, path,
3223 persistent?"yes":"no",
3224 health?health:"OK");
3228 DEBUG(DEBUG_ERR, ("db %s doesn't exist on node %u\n", db_name, options.pnn));
3233 check if the local node is recmaster or not
3234 it will return 1 if this node is the recmaster and 0 if it is not
3235 or if the local ctdb daemon could not be contacted
3237 static int control_isnotrecmaster(struct ctdb_context *ctdb, int argc, const char **argv)
3239 uint32_t mypnn, recmaster;
3242 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
3244 printf("Failed to get pnn of node\n");
3248 ret = ctdb_ctrl_getrecmaster(ctdb, ctdb, TIMELIMIT(), options.pnn, &recmaster);
3250 printf("Failed to get the recmaster\n");
3254 if (recmaster != mypnn) {
3255 printf("this node is not the recmaster\n");
3259 printf("this node is the recmaster\n");
3266 static int control_ping(struct ctdb_context *ctdb, int argc, const char **argv)
3269 struct timeval tv = timeval_current();
3270 ret = ctdb_ctrl_ping(ctdb, options.pnn);
3272 printf("Unable to get ping response from node %u\n", options.pnn);
3275 printf("response from %u time=%.6f sec (%d clients)\n",
3276 options.pnn, timeval_elapsed(&tv), ret);
3285 static int control_getvar(struct ctdb_context *ctdb, int argc, const char **argv)
3296 ret = ctdb_ctrl_get_tunable(ctdb, TIMELIMIT(), options.pnn, name, &value);
3298 DEBUG(DEBUG_ERR, ("Unable to get tunable variable '%s'\n", name));
3302 printf("%-19s = %u\n", name, value);
3309 static int control_setvar(struct ctdb_context *ctdb, int argc, const char **argv)
3320 value = strtoul(argv[1], NULL, 0);
3322 ret = ctdb_ctrl_set_tunable(ctdb, TIMELIMIT(), options.pnn, name, value);
3324 DEBUG(DEBUG_ERR, ("Unable to set tunable variable '%s'\n", name));
3333 static int control_listvars(struct ctdb_context *ctdb, int argc, const char **argv)
3339 ret = ctdb_ctrl_list_tunables(ctdb, TIMELIMIT(), options.pnn, ctdb, &list, &count);
3341 DEBUG(DEBUG_ERR, ("Unable to list tunable variables\n"));
3345 for (i=0;i<count;i++) {
3346 control_getvar(ctdb, 1, &list[i]);
3355 display debug level on a node
3357 static int control_getdebug(struct ctdb_context *ctdb, int argc, const char **argv)
3362 ret = ctdb_ctrl_get_debuglevel(ctdb, options.pnn, &level);
3364 DEBUG(DEBUG_ERR, ("Unable to get debuglevel response from node %u\n", options.pnn));
3367 if (options.machinereadable){
3368 printf(":Name:Level:\n");
3369 printf(":%s:%d:\n",get_debug_by_level(level),level);
3371 printf("Node %u is at debug level %s (%d)\n", options.pnn, get_debug_by_level(level), level);
3378 display reclock file of a node
3380 static int control_getreclock(struct ctdb_context *ctdb, int argc, const char **argv)
3383 const char *reclock;
3385 ret = ctdb_ctrl_getreclock(ctdb, TIMELIMIT(), options.pnn, ctdb, &reclock);
3387 DEBUG(DEBUG_ERR, ("Unable to get reclock file from node %u\n", options.pnn));
3390 if (options.machinereadable){
3391 if (reclock != NULL) {
3392 printf("%s", reclock);
3395 if (reclock == NULL) {
3396 printf("No reclock file used.\n");
3398 printf("Reclock file:%s\n", reclock);
3406 set the reclock file of a node
3408 static int control_setreclock(struct ctdb_context *ctdb, int argc, const char **argv)
3411 const char *reclock;
3415 } else if (argc == 1) {
3421 ret = ctdb_ctrl_setreclock(ctdb, TIMELIMIT(), options.pnn, reclock);
3423 DEBUG(DEBUG_ERR, ("Unable to get reclock file from node %u\n", options.pnn));
3430 set the natgw state on/off
3432 static int control_setnatgwstate(struct ctdb_context *ctdb, int argc, const char **argv)
3435 uint32_t natgwstate;
3441 if (!strcmp(argv[0], "on")) {
3443 } else if (!strcmp(argv[0], "off")) {
3449 ret = ctdb_ctrl_setnatgwstate(ctdb, TIMELIMIT(), options.pnn, natgwstate);
3451 DEBUG(DEBUG_ERR, ("Unable to set the natgw state for node %u\n", options.pnn));
3459 set the lmaster role on/off
3461 static int control_setlmasterrole(struct ctdb_context *ctdb, int argc, const char **argv)
3464 uint32_t lmasterrole;
3470 if (!strcmp(argv[0], "on")) {
3472 } else if (!strcmp(argv[0], "off")) {
3478 ret = ctdb_ctrl_setlmasterrole(ctdb, TIMELIMIT(), options.pnn, lmasterrole);
3480 DEBUG(DEBUG_ERR, ("Unable to set the lmaster role for node %u\n", options.pnn));
3488 set the recmaster role on/off
3490 static int control_setrecmasterrole(struct ctdb_context *ctdb, int argc, const char **argv)
3493 uint32_t recmasterrole;
3499 if (!strcmp(argv[0], "on")) {
3501 } else if (!strcmp(argv[0], "off")) {
3507 ret = ctdb_ctrl_setrecmasterrole(ctdb, TIMELIMIT(), options.pnn, recmasterrole);
3509 DEBUG(DEBUG_ERR, ("Unable to set the recmaster role for node %u\n", options.pnn));
3517 set debug level on a node or all nodes
3519 static int control_setdebug(struct ctdb_context *ctdb, int argc, const char **argv)
3525 printf("You must specify the debug level. Valid levels are:\n");
3526 for (i=0; debug_levels[i].description != NULL; i++) {
3527 printf("%s (%d)\n", debug_levels[i].description, debug_levels[i].level);
3533 if (isalpha(argv[0][0]) || argv[0][0] == '-') {
3534 level = get_debug_by_desc(argv[0]);
3536 level = strtol(argv[0], NULL, 0);
3539 for (i=0; debug_levels[i].description != NULL; i++) {
3540 if (level == debug_levels[i].level) {
3544 if (debug_levels[i].description == NULL) {
3545 printf("Invalid debug level, must be one of\n");
3546 for (i=0; debug_levels[i].description != NULL; i++) {
3547 printf("%s (%d)\n", debug_levels[i].description, debug_levels[i].level);
3552 ret = ctdb_ctrl_set_debuglevel(ctdb, options.pnn, level);
3554 DEBUG(DEBUG_ERR, ("Unable to set debug level on node %u\n", options.pnn));
3563 static int control_thaw(struct ctdb_context *ctdb, int argc, const char **argv)
3569 priority = strtol(argv[0], NULL, 0);
3573 DEBUG(DEBUG_ERR,("Thaw by priority %u\n", priority));
3575 ret = ctdb_ctrl_thaw_priority(ctdb, TIMELIMIT(), options.pnn, priority);
3577 DEBUG(DEBUG_ERR, ("Unable to thaw node %u\n", options.pnn));
3584 attach to a database
3586 static int control_attach(struct ctdb_context *ctdb, int argc, const char **argv)
3588 const char *db_name;
3589 struct ctdb_db_context *ctdb_db;
3596 ctdb_db = ctdb_attach(ctdb, db_name, false, 0);
3597 if (ctdb_db == NULL) {
3598 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", db_name));
3608 static int control_setdbprio(struct ctdb_context *ctdb, int argc, const char **argv)
3610 struct ctdb_db_priority db_prio;
3617 db_prio.db_id = strtoul(argv[0], NULL, 0);
3618 db_prio.priority = strtoul(argv[1], NULL, 0);
3620 ret = ctdb_ctrl_set_db_priority(ctdb, TIMELIMIT(), options.pnn, &db_prio);
3622 DEBUG(DEBUG_ERR,("Unable to set db prio\n"));
3632 static int control_getdbprio(struct ctdb_context *ctdb, int argc, const char **argv)
3634 uint32_t db_id, priority;
3641 db_id = strtoul(argv[0], NULL, 0);
3643 ret = ctdb_ctrl_get_db_priority(ctdb, TIMELIMIT(), options.pnn, db_id, &priority);
3645 DEBUG(DEBUG_ERR,("Unable to get db prio\n"));
3649 DEBUG(DEBUG_ERR,("Priority:%u\n", priority));
3655 run an eventscript on a node
3657 static int control_eventscript(struct ctdb_context *ctdb, int argc, const char **argv)
3663 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3666 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3670 data.dptr = (unsigned char *)discard_const(argv[0]);
3671 data.dsize = strlen((char *)data.dptr) + 1;
3673 DEBUG(DEBUG_ERR, ("Running eventscripts with arguments \"%s\" on node %u\n", data.dptr, options.pnn));
3675 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_RUN_EVENTSCRIPTS,
3676 0, data, tmp_ctx, NULL, &res, NULL, &errmsg);
3677 if (ret != 0 || res != 0) {
3678 DEBUG(DEBUG_ERR,("Failed to run eventscripts - %s\n", errmsg));
3679 talloc_free(tmp_ctx);
3682 talloc_free(tmp_ctx);
3686 #define DB_VERSION 1
3687 #define MAX_DB_NAME 64
3688 struct db_file_header {
3689 unsigned long version;
3691 unsigned long persistent;
3693 const char name[MAX_DB_NAME];
3696 struct backup_data {
3697 struct ctdb_marshall_buffer *records;
3700 bool traverse_error;
3703 static int backup_traverse(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *private)
3705 struct backup_data *bd = talloc_get_type(private, struct backup_data);
3706 struct ctdb_rec_data *rec;
3708 /* add the record */
3709 rec = ctdb_marshall_record(bd->records, 0, key, NULL, data);
3711 bd->traverse_error = true;
3712 DEBUG(DEBUG_ERR,("Failed to marshall record\n"));
3715 bd->records = talloc_realloc_size(NULL, bd->records, rec->length + bd->len);
3716 if (bd->records == NULL) {
3717 DEBUG(DEBUG_ERR,("Failed to expand marshalling buffer\n"));
3718 bd->traverse_error = true;
3721 bd->records->count++;
3722 memcpy(bd->len+(uint8_t *)bd->records, rec, rec->length);
3723 bd->len += rec->length;
3731 * backup a database to a file
3733 static int control_backupdb(struct ctdb_context *ctdb, int argc, const char **argv)
3736 struct ctdb_dbid_map *dbmap=NULL;
3737 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3738 struct db_file_header dbhdr;
3739 struct ctdb_db_context *ctdb_db;
3740 struct backup_data *bd;
3743 const char *reason = NULL;
3746 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3750 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &dbmap);
3752 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n", options.pnn));
3756 for(i=0;i<dbmap->num;i++){
3759 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn, dbmap->dbs[i].dbid, tmp_ctx, &name);
3760 if(!strcmp(argv[0], name)){
3761 talloc_free(discard_const(name));
3764 talloc_free(discard_const(name));
3766 if (i == dbmap->num) {
3767 DEBUG(DEBUG_ERR,("No database with name '%s' found\n", argv[0]));
3768 talloc_free(tmp_ctx);
3772 ret = ctdb_ctrl_getdbhealth(ctdb, TIMELIMIT(), options.pnn,
3773 dbmap->dbs[i].dbid, tmp_ctx, &reason);
3775 DEBUG(DEBUG_ERR,("Unable to get dbhealth for database '%s'\n",
3777 talloc_free(tmp_ctx);
3781 uint32_t allow_unhealthy = 0;
3783 ctdb_ctrl_get_tunable(ctdb, TIMELIMIT(), options.pnn,
3784 "AllowUnhealthyDBRead",
3787 if (allow_unhealthy != 1) {
3788 DEBUG(DEBUG_ERR,("database '%s' is unhealthy: %s\n",
3791 DEBUG(DEBUG_ERR,("disallow backup : tunnable AllowUnhealthyDBRead = %u\n",
3793 talloc_free(tmp_ctx);
3797 DEBUG(DEBUG_WARNING,("WARNING database '%s' is unhealthy - see 'ctdb getdbstatus %s'\n",
3799 DEBUG(DEBUG_WARNING,("WARNING! allow backup of unhealthy database: "
3800 "tunnable AllowUnhealthyDBRead = %u\n",
3804 ctdb_db = ctdb_attach(ctdb, argv[0], dbmap->dbs[i].persistent, 0);
3805 if (ctdb_db == NULL) {
3806 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", argv[0]));
3807 talloc_free(tmp_ctx);
3812 ret = tdb_transaction_start(ctdb_db->ltdb->tdb);
3814 DEBUG(DEBUG_ERR,("Failed to start transaction\n"));
3815 talloc_free(tmp_ctx);
3820 bd = talloc_zero(tmp_ctx, struct backup_data);
3822 DEBUG(DEBUG_ERR,("Failed to allocate backup_data\n"));
3823 talloc_free(tmp_ctx);
3827 bd->records = talloc_zero(bd, struct ctdb_marshall_buffer);
3828 if (bd->records == NULL) {
3829 DEBUG(DEBUG_ERR,("Failed to allocate ctdb_marshall_buffer\n"));
3830 talloc_free(tmp_ctx);
3834 bd->len = offsetof(struct ctdb_marshall_buffer, data);
3835 bd->records->db_id = ctdb_db->db_id;
3836 /* traverse the database collecting all records */
3837 if (tdb_traverse_read(ctdb_db->ltdb->tdb, backup_traverse, bd) == -1 ||
3838 bd->traverse_error) {
3839 DEBUG(DEBUG_ERR,("Traverse error\n"));
3840 talloc_free(tmp_ctx);
3844 tdb_transaction_cancel(ctdb_db->ltdb->tdb);
3847 fh = open(argv[1], O_RDWR|O_CREAT, 0600);
3849 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[1]));
3850 talloc_free(tmp_ctx);
3854 dbhdr.version = DB_VERSION;
3855 dbhdr.timestamp = time(NULL);
3856 dbhdr.persistent = dbmap->dbs[i].persistent;
3857 dbhdr.size = bd->len;
3858 if (strlen(argv[0]) >= MAX_DB_NAME) {
3859 DEBUG(DEBUG_ERR,("Too long dbname\n"));
3862 strncpy(discard_const(dbhdr.name), argv[0], MAX_DB_NAME);
3863 ret = write(fh, &dbhdr, sizeof(dbhdr));
3865 DEBUG(DEBUG_ERR,("write failed: %s\n", strerror(errno)));
3868 ret = write(fh, bd->records, bd->len);
3870 DEBUG(DEBUG_ERR,("write failed: %s\n", strerror(errno)));
3879 DEBUG(DEBUG_ERR,("close failed: %s\n", strerror(errno)));
3882 talloc_free(tmp_ctx);
3887 * restore a database from a file
3889 static int control_restoredb(struct ctdb_context *ctdb, int argc, const char **argv)
3892 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
3895 struct db_file_header dbhdr;
3896 struct ctdb_db_context *ctdb_db;
3897 struct ctdb_node_map *nodemap=NULL;
3898 struct ctdb_vnn_map *vnnmap=NULL;
3900 struct ctdb_control_wipe_database w;
3902 uint32_t generation;
3907 if (argc < 1 || argc > 2) {
3908 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
3912 fh = open(argv[0], O_RDONLY);
3914 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[0]));
3915 talloc_free(tmp_ctx);
3919 read(fh, &dbhdr, sizeof(dbhdr));
3920 if (dbhdr.version != DB_VERSION) {
3921 DEBUG(DEBUG_ERR,("Invalid version of database dump. File is version %lu but expected version was %u\n", dbhdr.version, DB_VERSION));
3922 talloc_free(tmp_ctx);
3926 dbname = discard_const(dbhdr.name);
3928 dbname = discard_const(argv[1]);
3931 outdata.dsize = dbhdr.size;
3932 outdata.dptr = talloc_size(tmp_ctx, outdata.dsize);
3933 if (outdata.dptr == NULL) {
3934 DEBUG(DEBUG_ERR,("Failed to allocate data of size '%lu'\n", dbhdr.size));
3936 talloc_free(tmp_ctx);
3939 read(fh, outdata.dptr, outdata.dsize);
3942 tm = localtime(&dbhdr.timestamp);
3943 strftime(tbuf,sizeof(tbuf)-1,"%Y/%m/%d %H:%M:%S", tm);
3944 printf("Restoring database '%s' from backup @ %s\n",
3948 ctdb_db = ctdb_attach(ctdb, dbname, dbhdr.persistent, 0);
3949 if (ctdb_db == NULL) {
3950 DEBUG(DEBUG_ERR,("Unable to attach to database '%s'\n", dbname));
3951 talloc_free(tmp_ctx);
3955 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
3957 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
3958 talloc_free(tmp_ctx);
3963 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx, &vnnmap);
3965 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n", options.pnn));
3966 talloc_free(tmp_ctx);
3970 /* freeze all nodes */
3971 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3972 for (i=1; i<=NUM_DB_PRIORITIES; i++) {
3973 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_FREEZE,
3979 DEBUG(DEBUG_ERR, ("Unable to freeze nodes.\n"));
3980 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
3981 talloc_free(tmp_ctx);
3986 generation = vnnmap->generation;
3987 data.dptr = (void *)&generation;
3988 data.dsize = sizeof(generation);
3990 /* start a cluster wide transaction */
3991 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
3992 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_START,
3994 TIMELIMIT(), false, data,
3997 DEBUG(DEBUG_ERR, ("Unable to start cluster wide transactions.\n"));
4002 w.db_id = ctdb_db->db_id;
4003 w.transaction_id = generation;
4005 data.dptr = (void *)&w;
4006 data.dsize = sizeof(w);
4008 /* wipe all the remote databases. */
4009 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4010 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_WIPE_DATABASE,
4012 TIMELIMIT(), false, data,
4015 DEBUG(DEBUG_ERR, ("Unable to wipe database.\n"));
4016 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4017 talloc_free(tmp_ctx);
4021 /* push the database */
4022 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4023 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_PUSH_DB,
4025 TIMELIMIT(), false, outdata,
4028 DEBUG(DEBUG_ERR, ("Failed to push database.\n"));
4029 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4030 talloc_free(tmp_ctx);
4034 data.dptr = (void *)&ctdb_db->db_id;
4035 data.dsize = sizeof(ctdb_db->db_id);
4037 /* mark the database as healthy */
4038 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4039 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_DB_SET_HEALTHY,
4041 TIMELIMIT(), false, data,
4044 DEBUG(DEBUG_ERR, ("Failed to mark database as healthy.\n"));
4045 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4046 talloc_free(tmp_ctx);
4050 data.dptr = (void *)&generation;
4051 data.dsize = sizeof(generation);
4053 /* commit all the changes */
4054 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_COMMIT,
4056 TIMELIMIT(), false, data,
4059 DEBUG(DEBUG_ERR, ("Unable to commit databases.\n"));
4060 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4061 talloc_free(tmp_ctx);
4066 /* thaw all nodes */
4067 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4068 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_THAW,
4074 DEBUG(DEBUG_ERR, ("Unable to thaw nodes.\n"));
4075 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4076 talloc_free(tmp_ctx);
4081 talloc_free(tmp_ctx);
4086 * dump a database backup from a file
4088 static int control_dumpdbbackup(struct ctdb_context *ctdb, int argc, const char **argv)
4090 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
4092 struct db_file_header dbhdr;
4096 struct ctdb_rec_data *rec = NULL;
4097 struct ctdb_marshall_buffer *m;
4100 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
4104 fh = open(argv[0], O_RDONLY);
4106 DEBUG(DEBUG_ERR,("Failed to open file '%s'\n", argv[0]));
4107 talloc_free(tmp_ctx);
4111 read(fh, &dbhdr, sizeof(dbhdr));
4112 if (dbhdr.version != DB_VERSION) {
4113 DEBUG(DEBUG_ERR,("Invalid version of database dump. File is version %lu but expected version was %u\n", dbhdr.version, DB_VERSION));
4114 talloc_free(tmp_ctx);
4118 outdata.dsize = dbhdr.size;
4119 outdata.dptr = talloc_size(tmp_ctx, outdata.dsize);
4120 if (outdata.dptr == NULL) {
4121 DEBUG(DEBUG_ERR,("Failed to allocate data of size '%lu'\n", dbhdr.size));
4123 talloc_free(tmp_ctx);
4126 read(fh, outdata.dptr, outdata.dsize);
4128 m = (struct ctdb_marshall_buffer *)outdata.dptr;
4130 tm = localtime(&dbhdr.timestamp);
4131 strftime(tbuf,sizeof(tbuf)-1,"%Y/%m/%d %H:%M:%S", tm);
4132 printf("Backup of database name:'%s' dbid:0x%x08x from @ %s\n",
4133 dbhdr.name, m->db_id, tbuf);
4135 for (i=0; i < m->count; i++) {
4139 /* we do not want the header splitted, so we pass NULL*/
4140 rec = ctdb_marshall_loop_next(m, rec, &reqid,
4143 ctdb_dumpdb_record(ctdb, key, data, stdout);
4146 printf("Dumped %d records\n", i);
4147 talloc_free(tmp_ctx);
4152 * wipe a database from a file
4154 static int control_wipedb(struct ctdb_context *ctdb, int argc,
4158 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
4160 struct ctdb_db_context *ctdb_db;
4161 struct ctdb_node_map *nodemap = NULL;
4162 struct ctdb_vnn_map *vnnmap = NULL;
4164 struct ctdb_control_wipe_database w;
4166 uint32_t generation;
4167 struct ctdb_dbid_map *dbmap = NULL;
4170 DEBUG(DEBUG_ERR,("Invalid arguments\n"));
4174 ret = ctdb_ctrl_getdbmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx,
4177 DEBUG(DEBUG_ERR, ("Unable to get dbids from node %u\n",
4182 for(i=0;i<dbmap->num;i++){
4185 ctdb_ctrl_getdbname(ctdb, TIMELIMIT(), options.pnn,
4186 dbmap->dbs[i].dbid, tmp_ctx, &name);
4187 if(!strcmp(argv[0], name)){
4188 talloc_free(discard_const(name));
4191 talloc_free(discard_const(name));
4193 if (i == dbmap->num) {
4194 DEBUG(DEBUG_ERR, ("No database with name '%s' found\n",
4196 talloc_free(tmp_ctx);
4200 ctdb_db = ctdb_attach(ctdb, argv[0], dbmap->dbs[i].persistent, 0);
4201 if (ctdb_db == NULL) {
4202 DEBUG(DEBUG_ERR, ("Unable to attach to database '%s'\n",
4204 talloc_free(tmp_ctx);
4208 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb,
4211 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n",
4213 talloc_free(tmp_ctx);
4217 ret = ctdb_ctrl_getvnnmap(ctdb, TIMELIMIT(), options.pnn, tmp_ctx,
4220 DEBUG(DEBUG_ERR, ("Unable to get vnnmap from node %u\n",
4222 talloc_free(tmp_ctx);
4226 /* freeze all nodes */
4227 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4228 for (i=1; i<=NUM_DB_PRIORITIES; i++) {
4229 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_FREEZE,
4236 DEBUG(DEBUG_ERR, ("Unable to freeze nodes.\n"));
4237 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn,
4238 CTDB_RECOVERY_ACTIVE);
4239 talloc_free(tmp_ctx);
4244 generation = vnnmap->generation;
4245 data.dptr = (void *)&generation;
4246 data.dsize = sizeof(generation);
4248 /* start a cluster wide transaction */
4249 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4250 ret = ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_START,
4252 TIMELIMIT(), false, data,
4256 DEBUG(DEBUG_ERR, ("Unable to start cluster wide "
4257 "transactions.\n"));
4261 w.db_id = ctdb_db->db_id;
4262 w.transaction_id = generation;
4264 data.dptr = (void *)&w;
4265 data.dsize = sizeof(w);
4267 /* wipe all the remote databases. */
4268 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4269 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_WIPE_DATABASE,
4271 TIMELIMIT(), false, data,
4274 DEBUG(DEBUG_ERR, ("Unable to wipe database.\n"));
4275 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4276 talloc_free(tmp_ctx);
4280 data.dptr = (void *)&ctdb_db->db_id;
4281 data.dsize = sizeof(ctdb_db->db_id);
4283 /* mark the database as healthy */
4284 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4285 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_DB_SET_HEALTHY,
4287 TIMELIMIT(), false, data,
4290 DEBUG(DEBUG_ERR, ("Failed to mark database as healthy.\n"));
4291 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4292 talloc_free(tmp_ctx);
4296 data.dptr = (void *)&generation;
4297 data.dsize = sizeof(generation);
4299 /* commit all the changes */
4300 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_TRANSACTION_COMMIT,
4302 TIMELIMIT(), false, data,
4305 DEBUG(DEBUG_ERR, ("Unable to commit databases.\n"));
4306 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4307 talloc_free(tmp_ctx);
4311 /* thaw all nodes */
4312 nodes = list_of_active_nodes(ctdb, nodemap, tmp_ctx, true);
4313 if (ctdb_client_async_control(ctdb, CTDB_CONTROL_THAW,
4319 DEBUG(DEBUG_ERR, ("Unable to thaw nodes.\n"));
4320 ctdb_ctrl_setrecmode(ctdb, TIMELIMIT(), options.pnn, CTDB_RECOVERY_ACTIVE);
4321 talloc_free(tmp_ctx);
4325 talloc_free(tmp_ctx);
4330 * set flags of a node in the nodemap
4332 static int control_setflags(struct ctdb_context *ctdb, int argc, const char **argv)
4339 struct ctdb_node_flag_change c;
4346 if (sscanf(argv[0], "%d", &node) != 1) {
4347 DEBUG(DEBUG_ERR, ("Badly formed node\n"));
4351 if (sscanf(argv[1], "0x%x", &flags) != 1) {
4352 DEBUG(DEBUG_ERR, ("Badly formed flags\n"));
4359 c.new_flags = flags;
4361 data.dsize = sizeof(c);
4362 data.dptr = (unsigned char *)&c;
4364 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_MODIFY_FLAGS, 0,
4365 data, NULL, NULL, &status, NULL, NULL);
4366 if (ret != 0 || status != 0) {
4367 DEBUG(DEBUG_ERR,("Failed to modify flags\n"));
4376 static int control_dumpmemory(struct ctdb_context *ctdb, int argc, const char **argv)
4382 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
4383 ret = ctdb_control(ctdb, options.pnn, 0, CTDB_CONTROL_DUMP_MEMORY,
4384 0, tdb_null, tmp_ctx, &data, &res, NULL, &errmsg);
4385 if (ret != 0 || res != 0) {
4386 DEBUG(DEBUG_ERR,("Failed to dump memory - %s\n", errmsg));
4387 talloc_free(tmp_ctx);
4390 write(1, data.dptr, data.dsize);
4391 talloc_free(tmp_ctx);
4396 handler for memory dumps
4398 static void mem_dump_handler(struct ctdb_context *ctdb, uint64_t srvid,
4399 TDB_DATA data, void *private_data)
4401 write(1, data.dptr, data.dsize);
4406 dump memory usage on the recovery daemon
4408 static int control_rddumpmemory(struct ctdb_context *ctdb, int argc, const char **argv)
4412 struct rd_memdump_reply rd;
4414 rd.pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
4416 DEBUG(DEBUG_ERR, ("Failed to get pnn of local node\n"));
4419 rd.srvid = getpid();
4421 /* register a message port for receiveing the reply so that we
4422 can receive the reply
4424 ctdb_client_set_message_handler(ctdb, rd.srvid, mem_dump_handler, NULL);
4427 data.dptr = (uint8_t *)&rd;
4428 data.dsize = sizeof(rd);
4430 ret = ctdb_client_send_message(ctdb, options.pnn, CTDB_SRVID_MEM_DUMP, data);
4432 DEBUG(DEBUG_ERR,("Failed to send memdump request message to %u\n", options.pnn));
4436 /* this loop will terminate when we have received the reply */
4438 event_loop_once(ctdb->ev);
4445 send a message to a srvid
4447 static int control_msgsend(struct ctdb_context *ctdb, int argc, const char **argv)
4449 unsigned long srvid;
4457 srvid = strtoul(argv[0], NULL, 0);
4459 data.dptr = (uint8_t *)discard_const(argv[1]);
4460 data.dsize= strlen(argv[1]);
4462 ret = ctdb_client_send_message(ctdb, CTDB_BROADCAST_CONNECTED, srvid, data);
4464 DEBUG(DEBUG_ERR,("Failed to send memdump request message to %u\n", options.pnn));
4472 handler for msglisten
4474 static void msglisten_handler(struct ctdb_context *ctdb, uint64_t srvid,
4475 TDB_DATA data, void *private_data)
4479 printf("Message received: ");
4480 for (i=0;i<data.dsize;i++) {
4481 printf("%c", data.dptr[i]);
4487 listen for messages on a messageport
4489 static int control_msglisten(struct ctdb_context *ctdb, int argc, const char **argv)
4495 /* register a message port and listen for messages
4497 ctdb_client_set_message_handler(ctdb, srvid, msglisten_handler, NULL);
4498 printf("Listening for messages on srvid:%d\n", (int)srvid);
4501 event_loop_once(ctdb->ev);
4508 list all nodes in the cluster
4509 if the daemon is running, we read the data from the daemon.
4510 if the daemon is not running we parse the nodes file directly
4512 static int control_listnodes(struct ctdb_context *ctdb, int argc, const char **argv)
4515 struct ctdb_node_map *nodemap=NULL;
4518 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), options.pnn, ctdb, &nodemap);
4520 DEBUG(DEBUG_ERR, ("Unable to get nodemap from node %u\n", options.pnn));
4524 for(i=0;i<nodemap->num;i++){
4525 if (nodemap->nodes[i].flags & NODE_FLAGS_DELETED) {
4528 if (options.machinereadable){
4529 printf(":%d:%s:\n", nodemap->nodes[i].pnn, ctdb_addr_to_str(&nodemap->nodes[i].addr));
4531 printf("%s\n", ctdb_addr_to_str(&nodemap->nodes[i].addr));
4535 TALLOC_CTX *mem_ctx = talloc_new(NULL);
4536 struct pnn_node *pnn_nodes;
4537 struct pnn_node *pnn_node;
4539 pnn_nodes = read_nodes_file(mem_ctx);
4540 if (pnn_nodes == NULL) {
4541 DEBUG(DEBUG_ERR,("Failed to read nodes file\n"));
4542 talloc_free(mem_ctx);
4546 for(pnn_node=pnn_nodes;pnn_node;pnn_node=pnn_node->next) {
4547 ctdb_sock_addr addr;
4549 if (parse_ip(pnn_node->addr, NULL, 63999, &addr) == 0) {
4550 DEBUG(DEBUG_ERR,("Wrongly formed ip address '%s' in nodes file\n", pnn_node->addr));
4551 talloc_free(mem_ctx);
4555 if (options.machinereadable){
4556 printf(":%d:%s:\n", pnn_node->pnn, pnn_node->addr);
4558 printf("%s\n", pnn_node->addr);
4561 talloc_free(mem_ctx);
4568 reload the nodes file on the local node
4570 static int control_reload_nodes_file(struct ctdb_context *ctdb, int argc, const char **argv)
4574 struct ctdb_node_map *nodemap=NULL;
4576 mypnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE);
4578 DEBUG(DEBUG_ERR, ("Failed to read pnn of local node\n"));
4582 ret = ctdb_ctrl_getnodemap(ctdb, TIMELIMIT(), CTDB_CURRENT_NODE, ctdb, &nodemap);
4584 DEBUG(DEBUG_ERR, ("Unable to get nodemap from local node\n"));
4588 /* reload the nodes file on all remote nodes */
4589 for (i=0;i<nodemap->num;i++) {
4590 if (nodemap->nodes[i].pnn == mypnn) {
4593 DEBUG(DEBUG_NOTICE, ("Reloading nodes file on node %u\n", nodemap->nodes[i].pnn));
4594 ret = ctdb_ctrl_reload_nodes_file(ctdb, TIMELIMIT(),
4595 nodemap->nodes[i].pnn);
4597 DEBUG(DEBUG_ERR, ("ERROR: Failed to reload nodes file on node %u. You MUST fix that node manually!\n", nodemap->nodes[i].pnn));
4601 /* reload the nodes file on the local node */
4602 DEBUG(DEBUG_NOTICE, ("Reloading nodes file on node %u\n", mypnn));
4603 ret = ctdb_ctrl_reload_nodes_file(ctdb, TIMELIMIT(), mypnn);
4605 DEBUG(DEBUG_ERR, ("ERROR: Failed to reload nodes file on node %u. You MUST fix that node manually!\n", mypnn));
4608 /* initiate a recovery */
4609 control_recover(ctdb, argc, argv);
4615 static const struct {
4617 int (*fn)(struct ctdb_context *, int, const char **);
4619 bool without_daemon; /* can be run without daemon running ? */
4622 } ctdb_commands[] = {
4624 { "version", control_version, true, false, "show version of ctdb" },
4626 { "status", control_status, true, false, "show node status" },
4627 { "uptime", control_uptime, true, false, "show node uptime" },
4628 { "ping", control_ping, true, false, "ping all nodes" },
4629 { "getvar", control_getvar, true, false, "get a tunable variable", "<name>"},
4630 { "setvar", control_setvar, true, false, "set a tunable variable", "<name> <value>"},
4631 { "listvars", control_listvars, true, false, "list tunable variables"},
4632 { "statistics", control_statistics, false, false, "show statistics" },
4633 { "statisticsreset", control_statistics_reset, true, false, "reset statistics"},
4634 { "ip", control_ip, false, false, "show which public ip's that ctdb manages" },
4635 { "ipinfo", control_ipinfo, true, false, "show details about a public ip that ctdb manages", "<ip>" },
4636 { "ifaces", control_ifaces, true, false, "show which interfaces that ctdb manages" },
4637 { "setifacelink", control_setifacelink, true, false, "set interface link status", "<iface> <status>" },
4638 { "process-exists", control_process_exists, true, false, "check if a process exists on a node", "<pid>"},
4639 { "getdbmap", control_getdbmap, true, false, "show the database map" },
4640 { "getdbstatus", control_getdbstatus, true, false, "show the status of a database", "<dbname>" },
4641 { "catdb", control_catdb, true, false, "dump a database" , "<dbname>"},
4642 { "getmonmode", control_getmonmode, true, false, "show monitoring mode" },
4643 { "getcapabilities", control_getcapabilities, true, false, "show node capabilities" },
4644 { "pnn", control_pnn, true, false, "show the pnn of the currnet node" },
4645 { "lvs", control_lvs, true, false, "show lvs configuration" },
4646 { "lvsmaster", control_lvsmaster, true, false, "show which node is the lvs master" },
4647 { "disablemonitor", control_disable_monmode,true, false, "set monitoring mode to DISABLE" },
4648 { "enablemonitor", control_enable_monmode, true, false, "set monitoring mode to ACTIVE" },
4649 { "setdebug", control_setdebug, true, false, "set debug level", "<EMERG|ALERT|CRIT|ERR|WARNING|NOTICE|INFO|DEBUG>" },
4650 { "getdebug", control_getdebug, true, false, "get debug level" },
4651 { "getlog", control_getlog, true, false, "get the log data from the in memory ringbuffer", "<level>" },
4652 { "clearlog", control_clearlog, true, false, "clear the log data from the in memory ringbuffer" },
4653 { "attach", control_attach, true, false, "attach to a database", "<dbname>" },
4654 { "dumpmemory", control_dumpmemory, true, false, "dump memory map to stdout" },
4655 { "rddumpmemory", control_rddumpmemory, true, false, "dump memory map from the recovery daemon to stdout" },
4656 { "getpid", control_getpid, true, false, "get ctdbd process ID" },
4657 { "disable", control_disable, true, false, "disable a nodes public IP" },
4658 { "enable", control_enable, true, false, "enable a nodes public IP" },
4659 { "stop", control_stop, true, false, "stop a node" },
4660 { "continue", control_continue, true, false, "re-start a stopped node" },
4661 { "ban", control_ban, true, false, "ban a node from the cluster", "<bantime|0>"},
4662 { "unban", control_unban, true, false, "unban a node" },
4663 { "showban", control_showban, true, false, "show ban information"},
4664 { "shutdown", control_shutdown, true, false, "shutdown ctdbd" },
4665 { "recover", control_recover, true, false, "force recovery" },
4666 { "sync", control_ipreallocate, true, false, "wait until ctdbd has synced all state changes" },
4667 { "ipreallocate", control_ipreallocate, true, false, "force the recovery daemon to perform a ip reallocation procedure" },
4668 { "thaw", control_thaw, true, false, "thaw databases", "[priority:1-3]" },
4669 { "isnotrecmaster", control_isnotrecmaster, false, false, "check if the local node is recmaster or not" },
4670 { "killtcp", kill_tcp, false, false, "kill a tcp connection.", "<srcip:port> <dstip:port>" },
4671 { "gratiousarp", control_gratious_arp, false, false, "send a gratious arp", "<ip> <interface>" },
4672 { "tickle", tickle_tcp, false, false, "send a tcp tickle ack", "<srcip:port> <dstip:port>" },
4673 { "gettickles", control_get_tickles, false, false, "get the list of tickles registered for this ip", "<ip> [<port>]" },
4674 { "addtickle", control_add_tickle, false, false, "add a tickle for this ip", "<ip>:<port> <ip>:<port>" },
4676 { "deltickle", control_del_tickle, false, false, "delete a tickle from this ip", "<ip>:<port> <ip>:<port>" },
4678 { "regsrvid", regsrvid, false, false, "register a server id", "<pnn> <type> <id>" },
4679 { "unregsrvid", unregsrvid, false, false, "unregister a server id", "<pnn> <type> <id>" },
4680 { "chksrvid", chksrvid, false, false, "check if a server id exists", "<pnn> <type> <id>" },
4681 { "getsrvids", getsrvids, false, false, "get a list of all server ids"},
4682 { "vacuum", ctdb_vacuum, false, false, "vacuum the databases of empty records", "[max_records]"},
4683 { "repack", ctdb_repack, false, false, "repack all databases", "[max_freelist]"},
4684 { "listnodes", control_listnodes, false, true, "list all nodes in the cluster"},
4685 { "reloadnodes", control_reload_nodes_file, false, false, "reload the nodes file and restart the transport on all nodes"},
4686 { "moveip", control_moveip, false, false, "move/failover an ip address to another node", "<ip> <node>"},
4687 { "addip", control_addip, true, false, "add a ip address to a node", "<ip/mask> <iface>"},
4688 { "delip", control_delip, false, false, "delete an ip address from a node", "<ip>"},
4689 { "eventscript", control_eventscript, true, false, "run the eventscript with the given parameters on a node", "<arguments>"},
4690 { "backupdb", control_backupdb, false, false, "backup the database into a file.", "<database> <file>"},
4691 { "restoredb", control_restoredb, false, false, "restore the database from a file.", "<file> [dbname]"},
4692 { "dumpdbbackup", control_dumpdbbackup, false, true, "dump database backup from a file.", "<file>"},
4693 { "wipedb", control_wipedb, false, false, "wipe the contents of a database.", "<dbname>"},
4694 { "recmaster", control_recmaster, false, false, "show the pnn for the recovery master."},
4695 { "setflags", control_setflags, false, false, "set flags for a node in the nodemap.", "<node> <flags>"},
4696 { "scriptstatus", control_scriptstatus, false, false, "show the status of the monitoring scripts (or all scripts)", "[all]"},
4697 { "enablescript", control_enablescript, false, false, "enable an eventscript", "<script>"},
4698 { "disablescript", control_disablescript, false, false, "disable an eventscript", "<script>"},
4699 { "natgwlist", control_natgwlist, false, false, "show the nodes belonging to this natgw configuration"},
4700 { "xpnn", control_xpnn, true, true, "find the pnn of the local node without talking to the daemon (unreliable)" },
4701 { "getreclock", control_getreclock, false, false, "Show the reclock file of a node"},
4702 { "setreclock", control_setreclock, false, false, "Set/clear the reclock file of a node", "[filename]"},
4703 { "setnatgwstate", control_setnatgwstate, false, false, "Set NATGW state to on/off", "{on|off}"},
4704 { "setlmasterrole", control_setlmasterrole, false, false, "Set LMASTER role to on/off", "{on|off}"},
4705 { "setrecmasterrole", control_setrecmasterrole, false, false, "Set RECMASTER role to on/off", "{on|off}"},
4706 { "setdbprio", control_setdbprio, false, false, "Set DB priority", "<dbid> <prio:1-3>"},
4707 { "getdbprio", control_getdbprio, false, false, "Get DB priority", "<dbid>"},
4708 { "msglisten", control_msglisten, false, false, "Listen on a srvid port for messages", "<msg srvid>"},
4709 { "msgsend", control_msgsend, false, false, "Send a message to srvid", "<srvid> <message>"},
4710 { "sync", control_ipreallocate, true, false, "wait until ctdbd has synced all state changes" },
4711 { "pfetch", control_pfetch, true, false, "fetch a record from a persistent database", "<db> <key> [<file>]" },
4712 { "pstore", control_pstore, true, false, "write a record to a persistent database", "<db> <key> <file containing record>" },
4718 static void usage(void)
4722 "Usage: ctdb [options] <control>\n" \
4724 " -n <node> choose node number, or 'all' (defaults to local node)\n"
4725 " -Y generate machinereadable output\n"
4726 " -v generate verbose output\n"
4727 " -t <timelimit> set timelimit for control in seconds (default %u)\n", options.timelimit);
4728 printf("Controls:\n");
4729 for (i=0;i<ARRAY_SIZE(ctdb_commands);i++) {
4730 printf(" %-15s %-27s %s\n",
4731 ctdb_commands[i].name,
4732 ctdb_commands[i].args?ctdb_commands[i].args:"",
4733 ctdb_commands[i].msg);
4739 static void ctdb_alarm(int sig)
4741 printf("Maximum runtime exceeded - exiting\n");
4748 int main(int argc, const char *argv[])
4750 struct ctdb_context *ctdb;
4751 char *nodestring = NULL;
4752 struct poptOption popt_options[] = {
4755 { "timelimit", 't', POPT_ARG_INT, &options.timelimit, 0, "timelimit", "integer" },
4756 { "node", 'n', POPT_ARG_STRING, &nodestring, 0, "node", "integer|all" },
4757 { "machinereadable", 'Y', POPT_ARG_NONE, &options.machinereadable, 0, "enable machinereadable output", NULL },
4758 { "verbose", 'v', POPT_ARG_NONE, &options.verbose, 0, "enable verbose output", NULL },
4759 { "maxruntime", 'T', POPT_ARG_INT, &options.maxruntime, 0, "die if runtime exceeds this limit (in seconds)", "integer" },
4763 const char **extra_argv;
4767 struct event_context *ev;
4768 const char *control;
4772 /* set some defaults */
4773 options.maxruntime = 0;
4774 options.timelimit = 3;
4775 options.pnn = CTDB_CURRENT_NODE;
4777 pc = poptGetContext(argv[0], argc, argv, popt_options, POPT_CONTEXT_KEEP_FIRST);
4779 while ((opt = poptGetNextOpt(pc)) != -1) {
4782 DEBUG(DEBUG_ERR, ("Invalid option %s: %s\n",
4783 poptBadOption(pc, 0), poptStrerror(opt)));
4788 /* setup the remaining options for the main program to use */
4789 extra_argv = poptGetArgs(pc);
4792 while (extra_argv[extra_argc]) extra_argc++;
4795 if (extra_argc < 1) {
4799 if (options.maxruntime == 0) {
4800 const char *ctdb_timeout;
4801 ctdb_timeout = getenv("CTDB_TIMEOUT");
4802 if (ctdb_timeout != NULL) {
4803 options.maxruntime = strtoul(ctdb_timeout, NULL, 0);
4805 /* default timeout is 120 seconds */
4806 options.maxruntime = 120;
4810 signal(SIGALRM, ctdb_alarm);
4811 alarm(options.maxruntime);
4813 /* setup the node number to contact */
4814 if (nodestring != NULL) {
4815 if (strcmp(nodestring, "all") == 0) {
4816 options.pnn = CTDB_BROADCAST_ALL;
4818 options.pnn = strtoul(nodestring, NULL, 0);
4822 control = extra_argv[0];
4824 ev = event_context_init(NULL);
4826 DEBUG(DEBUG_ERR, ("Failed to initialize event system\n"));
4829 tevent_loop_allow_nesting(ev);
4831 for (i=0;i<ARRAY_SIZE(ctdb_commands);i++) {
4832 if (strcmp(control, ctdb_commands[i].name) == 0) {
4835 if (ctdb_commands[i].without_daemon == true) {
4839 /* initialise ctdb */
4840 ctdb = ctdb_cmdline_client(ev);
4842 if (ctdb_commands[i].without_daemon == false) {
4843 const char *socket_name;
4846 DEBUG(DEBUG_ERR, ("Failed to init ctdb\n"));
4850 /* initialize a libctdb connection as well */
4851 socket_name = ctdb_get_socketname(ctdb);
4852 ctdb_connection = ctdb_connect(socket_name,
4853 ctdb_log_file, stderr);
4854 if (ctdb_connection == NULL) {
4855 fprintf(stderr, "Failed to connect to daemon from libctdb\n");
4859 /* verify the node exists */
4862 if (options.pnn == CTDB_CURRENT_NODE) {
4864 pnn = ctdb_ctrl_getpnn(ctdb, TIMELIMIT(), options.pnn);
4872 if (ctdb_commands[i].auto_all &&
4873 options.pnn == CTDB_BROADCAST_ALL) {
4878 nodes = ctdb_get_connected_nodes(ctdb, TIMELIMIT(), ctdb, &num_nodes);
4879 CTDB_NO_MEMORY(ctdb, nodes);
4881 for (j=0;j<num_nodes;j++) {
4882 options.pnn = nodes[j];
4883 ret |= ctdb_commands[i].fn(ctdb, extra_argc-1, extra_argv+1);
4887 ret = ctdb_commands[i].fn(ctdb, extra_argc-1, extra_argv+1);
4893 if (i == ARRAY_SIZE(ctdb_commands)) {
4894 DEBUG(DEBUG_ERR, ("Unknown control '%s'\n", control));